Route map with alarms
Marks alarms along a device’s route and plays them back over the dashboard timewindow. Each marker takes its colour from the alarm’s severity — critical, major, minor, warning — and pulses while the alarm is active; cleared alarms turn grey and stop. Clicking one opens a card naming the originator, severity, status, type, time and coordinates. Latitude and longitude are read from the alarm details, so whatever raises the alarm has to write them there.
Who it’s for
Operators tracking a moving asset ask “where did this go wrong, not just that it did?”. The standard trip map already replays where a device has been; this version adds every alarm the trip raised, plotted at the place it happened, so a route with a problem looks different from a clean one at a glance.
What it does
A delivery van’s trip line crosses town while a temperature alarm sits as a pulsing red pin halfway along the route — clicking it opens a card naming the originator, the severity, and the time, without leaving the map.
- Alarms as markers, at the coordinates each alarm itself carries — not the device’s position, so an alarm still appears in the right place even if the device wasn’t reporting a position at that moment
- Colored by severity in the platform’s own severity colors, so the map agrees with any alarm table sitting next to it
- Active alarms pulse; a cleared one turns gray, goes still, and stays as a record instead of disappearing
- Live updates — escalate, acknowledge, or clear an alarm and its marker follows, with no reload
- A card on click naming the originator, severity, status, type, time, and coordinates
- Everything the trip map already does still works unchanged — tile providers, the route line, playback, and widget actions; this page covers only what’s added
How to set up
Data keys
The datasource is required: it’s how the alarm layer learns which entities to watch. It then subscribes to each entity’s own alarms itself — mixed entity types are fine, each is subscribed separately.
| Key | Role | Type | Description |
|---|---|---|---|
latitude | Route position X | Attribute or Timeseries | Required so the map’s own subscription finishes loading. The alarm layer itself doesn’t read this key — an alarm’s position comes from the alarm’s own details, described below |
longitude | Route position Y | Attribute or Timeseries | Same as above |
Everything else — map provider, route line, playback, default position and zoom, fit bounds, widget actions — is unchanged from the standard trip map.
Which alarms appear, and what they need to carry
An alarm shows up only if it was raised by an entity in the datasource, falls inside the dashboard time window, is one of the hundred most recent, and carries coordinates the map can read. The rest are skipped, not placed somewhere wrong.
Only the coordinates need preparing — everything else on the card comes from the alarm as usual. Put them in the alarm’s details:
{ "latitude": 50.45370225625024, "longitude": 30.521168243145887}Two places to write them:
An alarm rule on a device profile (ThingsBoard 4.3 and later) — the
rule’s Additional info field takes a JSON template, and
${argument} substitutes a value from the rule’s own condition:
{ "latitude": ${latitude}, "longitude": ${longitude}}Both arguments have to appear in that rule’s condition, or there’s nothing to substitute and the marker never gets a position.
A Create Alarm node in a rule chain, through its details script:
var details = {};details.latitude = msg.latitude;details.longitude = msg.longitude;return details;| Field | Used for |
|---|---|
details.latitude, details.longitude | Where the marker goes — the only requirement |
severity | Marker color; anything unrecognized counts as indeterminate |
status | Active or cleared, and whether acknowledged |
type | The card’s title |
originatorName | The Originator row; falls back to the entity’s own label or name |
Nested-under-data, a JSON string, or a JSON string nested under data
all work too. If the details don’t parse as JSON at all, the numbers are
read out of the raw text instead and a warning goes to the console —
that’s a safety net, not a format to rely on. The most common cause is a
semicolon instead of a comma in the template, which the Additional info
field will happily save without complaining:
{ "latitude":${latitude}; "longitude":${longitude};}No parser accepts that. It wants a comma between the two lines and nothing after the last one.
Framing the view
If the trip has drawn markers of its own, the route frames the view and the alarms appear on top of it — nothing moves. If it hasn’t (the keys are there, but the device reported no position in this window), the map fits itself to the alarms instead, once, the first time they arrive. A single alarm is centered rather than fitted, since fitting to one point would zoom all the way in. Later updates never pull the view back, so panning survives.
Tips
- The originator is always named on the card, even on a single-device dashboard; if it can’t be resolved, the row shows a dash instead of disappearing.
- Reduced-motion display settings turn the pulse off automatically — nothing here needs configuring for that.
- If a rule chain’s payload changes — a renamed field, a number that picked up quotes — alarms can stop appearing on the map with nothing on screen to explain why. Check the payload where it’s written first.
- Moving the dashboard time window changes which alarms are eligible, the same as it would in an alarm table.
Share Your Widget with the Community
Built a custom widget? Export it as a JSON from ThingsBoard and publish it to the IoT Hub through a simple 4-step wizard (Upload, Listing, Readme, Review & Submit). Share it with thousands of ThingsBoard developers worldwide and get featured in the catalog.