Rules
A rule turns observations into events (architecture 15). Rules are versioned documents: every event references the exact version that created it, and a version can be tested against history before it is enabled. Rules live per project under Rules in the sidebar.
What a rule is
| Part | Meaning |
|---|---|
| Trigger | What starts an evaluation: a new position, a new measurement (optionally one metric), a device state change, or a schedule (every N seconds) |
| Scope | Which entities the rule applies to; empty means every entity of the project |
| Conditions | One condition, or several that must all hold |
| For | How long the condition must hold before the rule fires (0 fires at once) |
| Cooldown | While the condition stays true, fire again as a reminder after this long; 0 never |
| Event | The event type, severity, title template and whether an alert is created |
The subject of a rule is the entity the data belongs to, or the device when no entity is assigned. A rule's scope names entities, entity types or devices; a type in the scope takes its sub-types, so a rule for Vehicles judges every car and 4x4 of the project. State is kept per rule and subject: whether the condition is active, since when it holds, when it last fired and which geofences the subject was inside of.
Conditions
| Type | Fields | Meaning |
|---|---|---|
| Threshold | metric, operator, value | The triggering measurement, a derived position metric (speed_kmh, speed_mps, altitude_m) or the latest value of another metric of the subject (within seven days) compared with the value. speed_kmh is the speed the device reported with its fix (an OpenCollar with active tracking on, a Traccar tracker); a fix without a speed carries none and a speed rule stays quiet on it |
| Geofence or area | relation (enter, exit, inside, outside), features by type or by selection | Enter and exit fire on the crossing and need a position trigger; inside and outside are checked on every sample |
| Near a feature or entity | metres, features by type or by selection, or entities | The subject's position is within the distance of the nearest of them (decision D140); the distance is the event's value and the nearest one its feature |
| Far from every feature | metres, features by type (routes by default) or by selection | The subject's position is farther than the distance from every one of them (phase 38, decision D300): a vehicle off the known roads. The nearest route and the distance to it are the event's feature and value. A fix whose own accuracy is worse than the distance does not count, and the document's for guards against one bad fix beside the road |
| No data | duration | The subject has not been seen for this long; needs a schedule trigger. A subject that never reported does not count |
| Window aggregate | metric, aggregate (avg, min, max, sum, count), window, operator, value | The aggregate over the last window of the metric compared with the value |
Reserved for a later release, accepted by the schema but not by the evaluator: dwell, crossed, baseline, correlation, event_chain. A rule that uses one can be saved but not enabled.
Firing
Firing is edge-triggered. The rule fires when the condition becomes true, and while it stays true it fires again only after the cooldown. A battery rule with battery_voltage < 3.2 and a cooldown of one day therefore sends one event when the battery drops and one reminder per day, not one per measurement. A rule with a for of 30 seconds fires when the samples show the condition holding for at least 30 seconds without a break.
The title is a template: {entity}, {device}, {feature}, {metric}, {value} and {rule} are filled in; an unknown placeholder renders as ?.
Templates
| Template | Trigger | Conditions | Event |
|---|---|---|---|
| Geofence exit | position | exit any geofence | GEOFENCE_EXIT, warning, alert |
| Geofence enter | position | enter any geofence | GEOFENCE_ENTER, info |
| Speed limit inside an area | position | speed_kmh > 40 and inside any zone, for 30 s, cooldown 10 min |
SPEED_LIMIT_VIOLATION, warning, alert |
| Speeding | position | speed_kmh > 60 anywhere, cooldown 10 min; scope it to the Vehicles type so a collar is never judged (a type in the scope takes its sub-types) |
SPEED_LIMIT_VIOLATION, warning, alert |
| Off the roads | position | farther than 50 m from every route for 120 s, cooldown 30 min; scope it to the Vehicles type; the routes are the roads imported from a file, drawn or combined (phase 38) | OFF_ROAD, warning, alert |
| No data for 12 hours | schedule, every 5 min | no data for 12 h, cooldown 24 h | NO_DATA, warning, alert |
| Battery low | measurement battery_voltage |
battery_voltage < 3.2, cooldown 24 h |
BATTERY_LOW, warning, alert |
| Collar not moving | schedule, hourly | max(activity, 12 h) < 1.0 with at least three status messages in the window and battery_voltage > 3.2, cooldown 12 h; activity is the change of the accelerometer vector between status messages (m/s²) |
POSSIBLE_IMMOBILITY, critical, alert |
Testing on history
The editor's Test tab replays the definition over the project's positions and measurements in a time range, with in-memory state, and lists the events it would have produced. Nothing is created. A replay reads at most 50,000 rows and returns at most 500 events; a schedule rule steps through the range at its interval, at most 5,000 steps. The API: POST /projects/{id}/rules/{rule_id}/test for a saved version, POST /projects/{id}/rules/test-document for a draft.
The document
Rules are JSON documents validated by shared/rules/schema.py; the JSON schema is served at GET /projects/{id}/rules/schema. The example from architecture 15.3:
{
"trigger": {"kind": "position"},
"scope": {"entity_type_ids": ["<vehicle type>"]},
"conditions": {
"all": [
{"type": "threshold", "metric": "speed_kmh", "op": ">", "value": 40},
{"type": "spatial", "relation": "inside", "feature_type": "zone"}
]
},
"for_seconds": 30,
"event": {
"event_type": "SPEED_LIMIT_VIOLATION",
"severity": "warning",
"title": "{entity} at {value} km/h inside {feature}",
"create_alert": true
}
}
all, any and not nest. The form in the editor shows one condition or an all of conditions; anything else is edited as JSON.
Events and alerts
An event is a fact: a geofence exit, a low battery, a species detection from a device or an integration. An alert is an event that needs a person; it is open, acknowledged or resolved, with the actor, time and a note recorded. Alerts live in the Alerts inbox; every event has a detail page with its context, alert and the deliveries of the automations that acted on it, and in the live map's feed, where an open alert can be acknowledged from its row and a new one announces itself with a toast while the map is open (ADR 0028). Events with a location show on the live map for the last 24 hours with the event marker family, so an event never looks like an entity.
Late data: every event carries the age of the sample that produced it. Rules evaluate offloaded history for completeness; automations skip events older than their freshness bound so a log upload never pages anyone about last month.
Failures
A rule that fails to evaluate (a reserved condition, a bug) does not stop the other rules. The failure is recorded on the rule (last_error, shown in the Rules list) and as a failed processing trace; the rule fires again normally once the cause is fixed. A rule that fires writes a compact trace with the matched subject, the evaluated values and the created event and alert; silent evaluations write nothing.