Events, state, commands, and time
Events record changes, state describes the current view of a system, and commands request an action. Keep those records distinct when building an integration.
Sources and scopeSource record 25 August 2026
Technical source record: 25 August 2026. Check the linked documentation for current product requirements.
Generic semantic model; each protocol defines its own delivery and state machine.
On this page
Overview#
Treating an event as current state, or an acknowledgement as physical completion, is one of the most dangerous integration errors.
Four distinct records#
| Record | Meaning | Example |
|---|---|---|
| Observation/event | Something was reported at a point in time | Door contact changed to open |
| State estimate | Best current model assembled from evidence | Door is believed open as of sequence 884 |
| Command | Requested intent | Unlock door for five seconds |
| Outcome/confirmation | Evidence of acceptance or physical result | Controller accepted; lock monitor later reported unlocked |
An access granted event says a decision was granted, not necessarily that the door opened. A relay activated response says an output was driven, not that a lock moved. Confirmations should identify what was actually measured.
Event envelope#
A useful canonical event contains:
event_id: source-or-derived-unique-id
event_type: access.door.contact.changed
entity_id: site-a/building-1/door-004
source_time: 2026-08-25T10:04:17.314+10:00
received_time: 2026-08-25T10:04:17.402+10:00
sequence: 884
value: open
quality: confirmed
source: controller-2
schema_version: 2
If the source doesn't provide a stable event ID, a derived ID is a local deduplication aid, not source truth. Hashing mutable serialisation can produce different IDs for the same semantic event.
Ordering and duplicates#
Across reconnects, queues, gateways, and redundant paths, expect:
- duplicate delivery;
- events arriving out of source order;
- gaps in sequence;
- reset or wrap of counters;
- same timestamp for multiple events;
- clock stepping backward or forward;
- late delivery after a newer snapshot;
- replay of retained or cached messages.
Prefer source local sequence when documented. Don't impose a false global order by receive time. Track an ordering key such as (source, boot/session epoch, sequence) and define what happens when one component is missing.
Reconstructing state#
Use snapshots to establish a baseline and events to advance it:
subscribe/buffer -> fetch snapshot -> reconcile boundary -> apply later events
The exact safe ordering is protocol specific. If the API can't provide a sequence consistent boundary, mark the state uncertain during reconciliation. Periodic authoritative snapshots can detect silent event loss.
State should include quality:
confirmed: direct recent authoritative evidence;derived: calculated from other fields;stale: age exceeds policy;unknown: insufficient or contradictory evidence;unsupported: source can't express the property.
Unknown must not silently become a safe/normal value.
Command lifecycle#
Model at least:
requested -> authorized -> accepted/rejected -> dispatched
-> physically-confirmed | timed-out | indeterminate | compensated
Use an idempotency or command ID where the protocol supports one. After a timeout, query authoritative state before retrying an actuation. Automatic compensation is itself an actuation and may be unsafe when the first result is unknown.
Time fields#
Keep source occurrence time, device monotonic/order value, receipt time, normalisation time, and storage time separate. Use an unambiguous offset or Z following the Internet timestamp profile in RFC 3339. Also retain clock uncertainty, synchronisation status, or device reported quality when available.
Wall clock time is for correlation; monotonic time is for local durations and timeouts. Don't calculate a five second unlock or retry interval from a clock that can step.
Alarm lifecycle#
An alarm, acknowledgement, restore, cancel, and operator closure are distinct events. “Restore” means the source condition cleared; it doesn't prove the alarm was handled. Preserve the original alarm and append lifecycle facts rather than overwriting history.