Alarm events and status
This page is for integration developers who read Sentinel alarms from MQTT. Limit settings are in Alarms.
Celestian ──(1) config: alarm limits + cfg_ver──▶ gateway ──▶ nodeCelestian ◀──(2) config/reported: effective values, cfg_ver, rejected── nodeCelestian ◀──(3) event: alarm start / end + trigger value── nodeCelestian ◀──(4) telemetry: status of each alarm + alarm_level── nodeEvents
Section titled “Events”Sent to …/<mac>/event (QoS 1) when status changes, without waiting for telemetry. The format follows payload_format. Example: temperature t1 passes the alarm limit, in flat:
{"f":"flat","v":1,"id":"001a2b3c4d5e","t":1790000123,"m":{"alarm_t1_high":true,"alarm_t1_high_value":35.4}}In senml:
[{"bn":"001a2b3c4d5e:","bt":1790000123,"n":"alarm_t1_high","vb":true}, {"n":"alarm_t1_high_value","u":"Cel","v":35.4}]Ending: the same metric with false and the last value.
- The examples use the default name (
t1). Ift1_name=rack_top, the names arealarm_rack_top_highandalarm_rack_top_high_value. …_valueis always in the same packet as its status metric; if the sensor cannot be read when the event is sent,…_valueis not included.- A temperature warning and alarm are two separate alarms;
alarm_t1_warnstaystruewhilealarm_t1_highis active. - Maintenance mode has its own event:
maintenance(trueat start,falseat end).
Status in telemetry
Section titled “Status in telemetry”Telemetry carries the status of each alarm whose limit is set (for digital inputs: dN_alarm = true) on active slots, plus the combined level:
{"n":"alarm_t1_warn","vb":true},{"n":"alarm_t1_high","vb":false},{"n":"alarm_level","v":1}alarm_level is always sent: 0 = normal, 1 = a warning exists, 2 = an alarm exists. Telemetry is sent immediately when alarm_level changes. A message carrying alarm_level closes alarms that are not included; a message with alarm_* but without alarm_level closes nothing.
Behavior rules
Section titled “Behavior rules”| Situation | Behavior |
|---|---|
| Delay | an alarm starts after the condition persists for alarm_delay_s. If the value returns to normal before that, there is no event |
| Hysteresis | temperature: temp_alarm_hyst_c; power: 2%. Ending uses no delay |
| Sensor read failure | alarm status does not change and there is no event; the sensor’s metric disappears from telemetry |
| Limit changed while an alarm is active | re-evaluated; if the condition ended, an end event is sent |
Alarm disabled (0) while active |
an end event is sent once, then that alarm’s metric disappears from telemetry |
| Node reboots while an alarm is active | no end event; after boot and the delay, a start event is sent again. Treat it as an update, not a new incident |
| MQTT down when status changes | the event is held and sent once connected (the last status, not every change) |
| BACK (silence) | a local matter; produces no event |
alarm_buzzer = false or maintenance |
events and status are still sent |
| Clock not synchronized | events without t / bt; the server uses receive time |
Server implementation suggestions
Section titled “Server implementation suggestions”- Recognize alarms from boolean metrics prefixed
alarm_.trueopens,falsecloses;<name>_valuein the same packet is the value at that time. - Keep status per device and per alarm (active since when, last value). Update it from telemetry too, because events can be missed, and make it idempotent.
- Severity: the table in Alarms, or
alarm_levelfor a per-device summary. - Show sync status from
cfg_verandrejected(Config and reports). - Slot names come from configuration; renaming starts a new series. Read labels and types from
config/reported(tN_label,dN_label,dN_type,dN_active).
Test cases
Section titled “Test cases”- A start then end event produces one incident with a start and end time.
- A start event sent twice in a row: one incident.
- Telemetry
alarm_*: truewithout a prior start event: the alarm is still recorded as active. - The end event is lost but the next telemetry has
alarm_*: false: the incident is closed. - The alarm metric disappears from telemetry (limit zeroed): the incident is closed.
cfg_verdiffers from the one sent: status “pending”;rejectednon-empty: “partially rejected”.
Test without a device using the simulator: celestianctl.py config … temp_alarm_c=25 and watch with watch.