Data Model
Haltian IoT organizes data in a hierarchical model that mirrors the physical world: organizations contain spaces, spaces contain zones, and devices are placed within spaces to produce measurements. This page explains each entity and how they relate.
Entity Overview
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#F6FAFA', 'primaryTextColor': '#143633', 'primaryBorderColor': '#143633', 'lineColor': '#143633', 'secondaryColor': '#C7FDE6', 'tertiaryColor': '#73F9C1', 'clusterBkg': '#ffffff', 'clusterBorder': '#143633', 'edgeLabelBackground': '#ffffff'}}}%%
flowchart TB
subgraph Org["fa:fa-building Organization"]
direction TB
subgraph SpaceHierarchy["Space Hierarchy"]
Location["fa:fa-map-marker-alt Location"]
Building["fa:fa-city Building"]
Floor["fa:fa-layer-group Floor"]
Location --> Building --> Floor
end
subgraph ZoneLayer["Zones"]
Zone["fa:fa-vector-square Zone"]
end
Floor --> Zone
subgraph DeviceLayer["Devices"]
Device["fa:fa-microchip Device"]
DeviceGroup["fa:fa-object-group Device Group"]
end
subgraph DataLayer["Data"]
Measurement["fa:fa-chart-line Measurement"]
end
Floor --- Device
Device --> DeviceGroup
Device --> Measurement
DeviceGroup --> Measurement
end
style Org fill:#ffffff,stroke:#143633,stroke-width:3px,color:#143633
style SpaceHierarchy fill:#ffffff,stroke:#143633,stroke-width:2px,color:#143633
style ZoneLayer fill:#ffffff,stroke:#143633,stroke-width:2px,color:#143633
style DeviceLayer fill:#ffffff,stroke:#143633,stroke-width:2px,color:#143633
style DataLayer fill:#ffffff,stroke:#143633,stroke-width:2px,color:#143633
style Location fill:#F6FAFA,stroke:#143633,stroke-width:2px,color:#143633
style Building fill:#F6FAFA,stroke:#143633,stroke-width:2px,color:#143633
style Floor fill:#F6FAFA,stroke:#143633,stroke-width:2px,color:#143633
style Zone fill:#C7FDE6,stroke:#143633,stroke-width:2px,color:#143633
style Device fill:#73F9C1,stroke:#143633,stroke-width:2px,color:#143633
style DeviceGroup fill:#73F9C1,stroke:#143633,stroke-width:2px,color:#143633
style Measurement fill:#F6FAFA,stroke:#143633,stroke-width:2px,color:#143633Organization
An organization is the top-level entity in Haltian IoT. Everything — spaces, devices, users, API keys — belongs to an organization.
| Field | Description |
|---|---|
id | Unique identifier (UUID) |
name | Organization name |
createdAt | Creation timestamp |
updatedAt | Last modification timestamp |
Organizations scope all access control. Users and API keys are assigned roles at the organization level, and permissions cascade down to spaces within the organization. See Roles and Access for RBAC details.
Space Hierarchy
Spaces represent the physical structure of your deployment. They form a tree hierarchy with three types:
| Space Type | Description | Example |
|---|---|---|
| Location | Top-level site or campus. Root of the space tree. | Oulu Headquarter, Helsinki Factory |
| Building | A building within a location. | Yrttipellontie 1, Parking Lot |
| Floor | A floor within a building. The most granular space level. | 1st floor, 3rd floor, Ground Floor |
Hierarchy Example
Organization: Haltian Sales Demo
├── Location: Oulu Headquarter
│ ├── Building: Yrttipellontie 1
│ │ ├── Floor: 1st floor
│ │ └── Floor: 3rd floor
│ └── Building: Parking Lot
│ └── Floor: Outdoor Parking Lot
├── Location: Helsinki Factory
│ └── Building: Factory
│ └── Floor: Ground Floor
└── Location: Kemijarvi Test Center
└── Building: Factory
└── Floor: 1st floor
Space Fields
| Field | Description |
|---|---|
id | Unique identifier (UUID) |
name | Display name |
type | One of: location, building, floor |
organizationId | Parent organization |
parentSpaceId | Parent space (null for locations) |
positionGlobal | Geographic coordinates |
northVector | North orientation for floor plans |
Each space can contain child spaces (via parentSpaceId), zones, and devices.
Zone
A zone is a named area within a floor. Zones represent functional areas such as meeting rooms, parking slots, open offices, or lobbies. Unlike spaces, zones do not form a hierarchy — they are flat, belonging directly to a single floor.
| Field | Description |
|---|---|
id | Unique identifier (UUID) |
name | Display name (e.g., Meeting Room Taika, Cafeteria) |
spaceId | The floor this zone belongs to |
organizationId | Parent organization |
type | Zone type classification |
polygonGlobal | Geographic polygon defining the zone boundary |
polygonLocal | Local coordinates polygon (relative to floor plan) |
Zones are used for positioning — when a device is located within a zone’s polygon, the platform reports its zone assignment.
Device
A device is a physical IoT sensor or gateway registered in the platform. Devices belong to an organization and are placed in a space (typically a floor).
| Field | Description |
|---|---|
id | Unique identifier (UUID) |
name | Device name |
deviceType | Hardware model/type |
organizationId | Parent organization |
spaceId | Space where the device is physically installed |
identifiers | Hardware identifiers (serial number, MAC address) |
availableMeasurements | List of measurement types this device produces |
lastSeen | Timestamp of last communication |
fixedPositionGlobal | Fixed geographic coordinates (for stationary devices) |
fixedPositionLocal | Fixed local coordinates (relative to floor plan) |
connectorProtocol | Communication protocol (e.g., Wirepas mesh) |
What Devices Produce
Each device generates measurements — time-stamped data points for the sensor types it supports. The availableMeasurements field lists what a device can report (e.g., measurementAmbientTemperature, measurementOccupancyStatus).
For details on specific device models, see the Device Catalog.
Device Group
A device group combines multiple devices into a single logical unit. Device groups are primarily used by the Occupancy Data Engine (ODE) to aggregate sensor events from several devices that monitor the same area.
| Field | Description |
|---|---|
id | Unique identifier (UUID) |
name | Group name |
organizationId | Parent organization |
spaceId | Space the group is assigned to |
modelType | ODE model type for aggregation logic |
devices | List of member devices |
lastOccupancyResetAt | Last occupancy counter reset timestamp |
lastSeen | Timestamp of last data from any member device |
Device groups produce their own measurements (aggregated from member devices), enabling unified occupancy metrics such as occupant count and directional movement.
Measurements
Measurements are the time-series data produced by devices and device groups. Each measurement type is stored as a separate data stream with a consistent structure.
Common Fields
Every measurement record contains:
| Field | Description |
|---|---|
deviceId | The device (or device group) that produced this measurement |
ts | Timestamp of the measurement event |
organizationId | Parent organization |
| value field | The measurement value (field name varies by type) |
Measurement Types
| Type | Value Field | Description |
|---|---|---|
measurementAmbientTemperature | ambientTemperature | Temperature reading (°C) |
measurementBatteryPercentage | batteryPercentage | Battery level (%) |
measurementBatteryVoltage | batteryVoltage | Battery voltage (V) |
measurementBootCount | bootCount | Device restart counter |
measurementCO2 | co2 | CO₂ concentration (ppm) |
measurementTVOC | tvoc | Total volatile organic compounds |
measurementDistance | distance | Distance sensor reading |
measurementOccupancyStatus | occupancyStatus | Binary presence (0 = vacant, 1 = occupied) |
measurementOccupancySeconds | occupancySeconds | Aggregated occupancy duration |
measurementOccupantsCount | occupantsCount | Number of people detected |
measurementDirectionalMovement | directionalMovement | Direction of movement (in/out) |
measurementPosition | position | Device position coordinates |
measurementPositionZone | zoneId | Zone where device is located |
Measurements are event-driven, not periodic samples. A value remains valid until the next event — gaps between events mean “no change,” not “no data.” See the Data API documentation for details on querying measurement data.
Entity Relationships
The following diagram summarizes how entities relate:
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#F6FAFA', 'primaryTextColor': '#143633', 'primaryBorderColor': '#143633', 'lineColor': '#143633', 'secondaryColor': '#C7FDE6', 'tertiaryColor': '#73F9C1', 'clusterBkg': '#ffffff', 'clusterBorder': '#143633', 'edgeLabelBackground': '#ffffff'}}}%%
erDiagram
Organization ||--o{ Space : contains
Organization ||--o{ Device : owns
Space ||--o{ Space : "parent of"
Space ||--o{ Zone : contains
Space ||--o{ Device : "installed in"
Device ||--o{ Measurement : produces
Device }o--o{ DeviceGroup : "member of"
DeviceGroup ||--o{ Measurement : produces
Zone }o--o{ Device : "located in"
Organization {
uuid id
string name
}
Space {
uuid id
string name
string type
uuid parentSpaceId
uuid organizationId
}
Zone {
uuid id
string name
uuid spaceId
string type
}
Device {
uuid id
string name
string deviceType
uuid spaceId
uuid organizationId
}
DeviceGroup {
uuid id
string name
string modelType
uuid spaceId
}
Measurement {
uuid deviceId
timestamp ts
uuid organizationId
}API Access
You can query and manage these entities through three APIs:
| API | Use Case | Protocol |
|---|---|---|
| Service API | Query and mutate spaces, devices, zones | GraphQL |
| Stream API | Subscribe to live measurement events | MQTT |
| Data API | Export historical measurement data | Parquet files |
Next Steps
- Roles and Access — Understand who can access what
- Occupancy Data Engine — How device groups produce aggregated occupancy data
- Service API — Query entities via GraphQL
- Glossary — Terminology reference