Reset Logic
How the Occupancy Data Engine corrects count drift using inactivity-based and manual resets
The Occupancy Data Engine is Haltian’s backend processing service that transforms raw sensor events from a device group’s member sensors into unified, accurate occupancy measurements. It takes entry/exit counts and presence detections as input and produces a single authoritative occupancy state for the space the device group represents.
The engine runs automatically — once you create a device group with supported sensors, the Occupancy Data Engine begins processing their data and publishing occupancy measurements under the device group’s identity.
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#F6FAFA', 'primaryTextColor': '#143633', 'primaryBorderColor': '#143633', 'lineColor': '#143633', 'secondaryColor': '#C7FDE6', 'tertiaryColor': '#73F9C1', 'clusterBkg': '#ffffff', 'clusterBorder': '#143633', 'edgeLabelBackground': '#ffffff'}}}%%
graph TB
subgraph Input["Member Sensors"]
A[Entryway sensor<br/>entries + exits]
C[Presence sensor<br/>occupied + movementDetections]
end
subgraph DG["Device Group"]
D[Virtual Device<br/>aggregation point]
end
subgraph ODE["Occupancy Data Engine"]
E[Event Correlation]
F[Count Algorithm]
G[Reset Logic]
end
subgraph Output["Output Measurements"]
H[occupantsCount]
I[directionalMovement]
J[occupancyStatus]
end
A --> D
C --> D
D --> E
E --> F
F --> G
G --> H
G --> I
G --> JThe Occupancy Data Engine processes data on every sensor event — it does not poll or run on a schedule. Each time a member sensor reports a new measurement, the engine recalculates the device group’s occupancy state immediately.
Individual sensor measurements are not duplicated to the device group. Each member device’s data stays on the device itself. The device group only stores its own computed measurements — occupantsCount, directionalMovement, and occupancyStatus — which are the aggregated output of the engine. This means:
The Occupancy Data Engine produces three measurement types, all attributed to the device group:
Current number of people in the space.
Schema Type: measurementOccupantsCount
{
"deviceId": "550e8400-e29b-41d4-a716-446655440000",
"measuredAt": "2026-02-05T10:30:00.000Z",
"occupantsCount": 5
}
| Field | Type | Description |
|---|---|---|
measuredAt | ISO 8601 timestamp | When count was calculated |
occupantsCount | Integer | Number of occupants (≥ 0) |
Entry and exit tracking.
Schema Type: measurementDirectionalMovement
{
"deviceId": "550e8400-e29b-41d4-a716-446655440000",
"measuredAt": "2026-02-05T10:30:00.000Z",
"entries": 3,
"exits": 1
}
| Field | Type | Description |
|---|---|---|
entries | Integer | Number of entries since last reset |
exits | Integer | Number of exits since last reset |
Binary occupied/vacant status.
Schema Type: measurementOccupancyStatus
{
"deviceId": "550e8400-e29b-41d4-a716-446655440000",
"measuredAt": "2026-02-05T10:30:00.000Z",
"isOccupied": true
}
| Field | Type | Description |
|---|---|---|
isOccupied | Boolean | true if space is occupied, false if vacant |
Occupancy Data Engine measurements are accessed through the same APIs as any device measurement — using the device group’s UUID.
query MeasurementLastOccupantsCount($device: uuid) {
measurementLastOccupantsCount(where: { deviceId: { _eq: $device } }) {
measuredAt
occupantsCount
}
}
query MeasurementLastDirectionalMovement($device: uuid) {
measurementLastDirectionalMovement(where: { deviceId: { _eq: $device } }) {
measuredAt
entries
exits
}
}
query MeasurementLastOccupancyStatus($device: uuid) {
measurementLastOccupancyStatus(where: { deviceId: { _eq: $device } }) {
measuredAt
isOccupied
}
}
Note: Pass the device group’s UUID as the
$deviceparameter — device groups use the same UUID structure as physical devices.
Occupancy Data Engine measurements are published on the same topic structure as physical devices:
haltian-iot/events/{integration-id}/{api-key-id}/measurements/occupantsCount/{device-group-id}
haltian-iot/events/{integration-id}/{api-key-id}/measurements/directionalMovement/{device-group-id}
haltian-iot/events/{integration-id}/{api-key-id}/measurements/occupancyStatus/{device-group-id}
Occupancy measurements from device groups appear in Parquet exports alongside regular device measurements. The devicegroups and devicegroupdevices tables provide the group structure for joining.
How the Occupancy Data Engine corrects count drift using inactivity-based and manual resets
Common issues and solutions when working with the Occupancy Data Engine.