Device Stuck
The Device Stuck trigger fires when an active-shift device is still reporting locations but has not moved beyond a configured distance threshold inside a recent time window. Use it to catch vehicles immobilized in traffic, workers stalled at a job site, or trackers stuck at a location where they should not be lingering.
Unlike Device Offline, Device Stuck assumes the tracker is healthy and communicating — the anomaly is that the device has stopped moving, not that it has stopped reporting.
What It Does
A scheduled scanner inspects every active-shift device in your workspace and measures the total ground distance the device has moved inside the most recent window_minutes. When that distance falls below the configured distance_meters threshold, the workflow fires with a payload that includes the actual meters moved, the threshold, and the device's current location.
When to Use
- Detect delivery vehicles stuck in heavy traffic beyond an acceptable dwell
- Alert when a field worker has been stationary at a job site for longer than expected
- Catch immobilized equipment (e.g., a stuck forklift still pinging GPS but not moving)
- Surface devices that have been parked or abandoned without the shift being ended
Configuration
| Knob | Type | Default | Min / Max | Description |
|---|---|---|---|---|
distance_meters | integer | (required) | 1 / 100000 (100 km) | The device is considered "stuck" if it has moved less than this distance in the window. |
window_minutes | integer | (required) | 2 / 10080 (1 week) | The trailing time window over which movement is summed. |
repeat_policy | string | once_until_seen | enum | once_until_seen fires once per stuck episode and re-arms after the device moves again. every_interval re-fires every cooldown. |
cooldown_minutes | integer | none | 1 / 10080 | Required when repeat_policy is every_interval. Minutes between repeat fires for the same still-stuck device. |
device_filters | object | {} (all devices) | — | Optional filter: device_ids, exclude_device_ids, device_types (mobile, vehicle, iot, tracker, other), metadata_match. |
A common starting point is distance_meters: 50 with window_minutes: 15 for vehicles in urban environments. For field workers walking job sites, try distance_meters: 20 with window_minutes: 30. Tune based on observed false-positive rates in your fleet.
Trigger Payload
When the trigger fires, the following trigger_data envelope is delivered to every downstream action. Optional fields are only present when the underlying data is available.
{
"event_type": "device_stuck",
"signal_type": "device_stuck",
"device_id": "van-07",
"device_name": "Van 07",
"device_type": "vehicle",
"workspace_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"threshold_distance_meters": 50,
"window_minutes": 15,
"meters_moved_in_window": 8,
"is_in_geofence": false,
"repeat_policy": "once_until_seen",
"shift_status": "active",
"location": {
"latitude": 37.7749,
"longitude": -122.4194
}
}
Template Variables
Reference these in any action body using the standard {{trigger.xxx}} syntax.
| Variable | Resolved Value |
|---|---|
{{trigger.event_type}} | "device_stuck" |
{{trigger.signal_type}} | "device_stuck" (mirrors event_type for signal-aware consumers) |
{{trigger.device_id}} | External device identifier (customer-assigned) |
{{trigger.device_name}} | Human-readable device name |
{{trigger.device_type}} | "mobile", "vehicle", "iot", "tracker", or "other" |
{{trigger.workspace_id}} | UUID of the workspace that owns the device |
{{trigger.threshold_distance_meters}} | The distance threshold the trigger was configured with (echoed back) |
{{trigger.window_minutes}} | The window the trigger was configured with (echoed back) |
{{trigger.meters_moved_in_window}} | Integer meters moved in the trailing window (the actual measurement) |
{{trigger.is_in_geofence}} | Reserved boolean — currently always false |
{{trigger.repeat_policy}} | "once_until_seen" or "every_interval" |
{{trigger.shift_status}} | Current shift status (when present) — typically "active" |
{{trigger.location.latitude}} | Current latitude (only present when a location is available) |
{{trigger.location.longitude}} | Current longitude (only present when a location is available) |
Example Use Case
Scenario. A same-day courier service runs 80 vans in a dense metro. Idle time over 20 minutes during business hours usually means a driver is dealing with a problem (a customer dispute, a building access issue, an accident) and dispatch wants a heads-up before the SLA clock runs out.
Workflow.
- Trigger: Device Stuck with
distance_meters: 50,window_minutes: 20, andrepeat_policy: once_until_seen, filtered todevice_types: ["vehicle"]. - Action 1 — PagerDuty: Open a low-severity incident on the dispatch service so the on-call dispatcher gets paged through the existing PD escalation chain.
- Action 2 — Slack: Post a contextual message to
#fleet-opswith the driver name and a map link to the stuck location.
The once_until_seen policy ensures dispatch is paged once per stuck episode — when the van starts moving again, the workflow re-arms.
Related Recipes
End-to-end runnable guides for routing this trigger to external systems:
- Slack Alerting — incoming webhook + copy-pasteable JSON
- PagerDuty Alerting — Events API v2 incident payload
- Generic HTTP Alerting — minimal curl-testable pattern
See Also
- Device Offline — device has stopped reporting entirely
- Shift Overdue — shift has run longer than expected
- Workflows In Depth — actions, templates, and execution model