mqtt_bus / home_bus.md
Newer Older
310 lines | 9.282kb
Bogdan Timofte authored 2 weeks ago
1
# Home Bus
2

            
3
## Purpose
4

            
5
The `home` bus exposes room-centric and user-facing telemetry, state, and control topics for the living environment.
6

            
7
Typical systems connected to this bus include:
8

            
9
- environmental sensors
10
- lighting and switches
11
- motion/contact/presence sensors
12
- thermostats and climate devices
13
- smart sockets for on/off control semantics
14

            
15
The `home` bus models living-space behavior, not electrical topology.
16

            
17
This document defines the `home`-specific topic grammar and semantic ownership.
18

            
19
Shared rules for payload profiles, metadata, time semantics, quality, and operational topics are defined in `mqtt_contract.md`.
20

            
21

            
22
## Scope and Ownership
23

            
24
The `home` bus owns room and automation semantics.
25

            
26
The `energy` bus owns electrical accounting semantics.
27

            
28
Examples:
29

            
30
- `vad/home/living-room/power/tv/value` is room control state
31
- `vad/home/living-room/power/tv/set` is room control command
32
- `vad/energy/load/living-room-entertainment/active_power/value` is electrical telemetry
33

            
34
Rule:
35

            
36
- publish user-oriented control/state on `home`
37
- publish electrical measurement and accounting on `energy`
38

            
39

            
40
## Normative Topic Contract (v1)
41

            
42
All home topics MUST follow:
43

            
44
`<site>/home/<location>/<capability>/<device_id>/<stream>`
45

            
46
Where:
47

            
48
- `<site>`: deployment/site id, for example `vad`
49
- `<location>`: normalized area identifier in kebab-case
50
- `<capability>`: semantic capability in snake_case
51
- `<device_id>`: stable device/entity identifier in kebab-case
52
- `<stream>`: one of `value`, `last`, `set`, `meta`, `availability`
53

            
54
Examples:
55

            
56
- `vad/home/bedroom/temperature/bedroom-sensor/value`
57
- `vad/home/living-room/motion/radar-south/value`
58
- `vad/home/kitchen/light/ceiling-switch/value`
59
- `vad/home/living-room/power/tv/set`
60

            
61

            
62
## Canonical Identity Model
63

            
64
The `home` bus is built around stable room semantics.
65

            
66
Rules:
67

            
68
- `<location>` MUST describe the living-space area, not the vendor room name if the two differ
69
- `<device_id>` MUST identify the logical endpoint exposed to consumers
70
- one physical device MAY publish multiple capabilities under the same `<device_id>`
71
- replacing a physical Zigbee sensor SHOULD keep the same canonical `<device_id>` when the logical endpoint remains the same
72

            
73
Examples:
74

            
75
- `bedroom-sensor` is a logical endpoint
76
- `0x00158d0008aa1111` is a vendor identity and belongs in `meta.source_ref`, not in the topic path
77

            
78
This keeps HomeKit, historian, and automations insulated from vendor identity churn.
79

            
80

            
81
## Stream Semantics
82

            
83
- `value`: live semantic sample, whether measurement, held state, or transition notification
84
- `last`: retained last-known timestamped sample for startup/bootstrap decisions
85
- `set`: command/request topic for controllable capabilities
86
- `meta`: static or slowly-changing metadata
87
- `availability`: online/offline state
88

            
89
Rules:
90

            
91
- adapters SHOULD emit live hot-path data only on `value`
92
- adapters SHOULD deduplicate repeated `value` samples when the semantic value did not change
93
- adapters SHOULD publish retained `last` for the latest known timestamped sample
94
- legacy `state` and `event` topics SHOULD be treated as compatibility-only during migration
95

            
96
Command safety:
97

            
98
- `set` MUST NOT be retained
99
- stateful devices SHOULD acknowledge commands via `value`
100
- payload profile and time semantics follow `mqtt_contract.md`
101

            
102

            
103
## Payload Contract
104

            
105
To keep Node-RED flows efficient, two payload profiles are allowed.
106

            
107
### Profile A: Hot Path Scalar (recommended)
108

            
109
For frequent updates, payload SHOULD be scalar.
110

            
111
Examples:
112

            
113
- `vad/home/bedroom/temperature/bedroom-sensor/value` -> `23.6`
114
- `vad/home/living-room/motion/radar-south/value` -> `true`
115

            
116
Metadata is published separately on retained `meta`.
117

            
118
Example:
119

            
120
- Topic: `vad/home/bedroom/temperature/bedroom-sensor/meta`
121
- Payload:
122

            
123
```json
124
{
125
  "unit": "C",
126
  "source": "zigbee_adapter",
127
  "precision": 0.1
128
}
129
```
130

            
131
### Profile B: Envelope JSON (optional)
132

            
133
For streams that need inline quality/timestamp:
134

            
135
```json
136
{
137
  "value": 23.6,
138
  "unit": "C",
139
  "observed_at": "2026-03-08T10:15:12Z",
140
  "quality": "good"
141
}
142
```
143

            
144
Recommendation:
145

            
146
- prefer Profile A on high-frequency paths
147
- use Profile B where source quality/time must travel with each sample
148
- if exact source timestamp must be preserved, use Profile B
149
- use `last` with Profile B and `observed_at` when control consumers need a startup sample with freshness information
150
- do not repeat metadata or adapter internals in `value` payloads
151
- keep Profile B envelopes small and canonical
152

            
153

            
154
## Capability Catalog (initial)
155

            
156
Environmental capabilities:
157

            
158
- `temperature`
159
- `humidity`
160
- `pressure`
161
- `illuminance`
162
- `co2`
163
- `voc`
164
- `pm25`
165
- `pm10`
166

            
167
Presence and safety capabilities:
168

            
169
- `motion`
170
- `presence`
171
- `contact`
172
- `water_leak`
173
- `smoke`
174
- `gas`
175
- `tamper`
176

            
177
Control and user-facing capabilities:
178

            
179
- `light`
180
- `power`
181
- `lock`
182
- `cover_position`
183
- `thermostat_mode`
184
- `target_temperature`
185
- `fan_mode`
186
- `button`
187

            
188
Device health capabilities that are still user-relevant:
189

            
190
- `battery`
191
- `battery_low`
192

            
193
Rules:
194

            
195
- use `power` on `home` only for control semantics
196
- use electrical telemetry such as `active_power` and cumulative counters such as `energy_total` on `energy`
197
- radio diagnostics such as `linkquality` SHOULD NOT go on `home` by default
198
- `presence` SHOULD normally be a higher-level derived state, not a raw single-device detection
199
- raw mmWave detection, including Zigbee `presence` with `fading_time=0`, SHOULD be published as `motion`
200

            
201

            
202
## MQTT Delivery Policy
203

            
204
Default policy:
205

            
206
- `value`: QoS 1, retain false
207
- `last`: QoS 1, retain true
208
- `set`: QoS 1, retain false
209
- `meta`: QoS 1, retain true
210
- `availability`: QoS 1, retain true (LWT preferred)
211

            
212
Cold-start rule:
213

            
214
- control consumers such as thermostats SHOULD subscribe to retained `last` to obtain the latest known sample at startup
215
- `last` SHOULD include `observed_at` so staleness can be evaluated immediately after subscribe
216
- consumers MAY unsubscribe from `last` after bootstrap and continue consuming lightweight live updates on `value`
217
- consumers that depend on deterministic retained bootstrap SHOULD use a dedicated MQTT client session instead of sharing the same broker config with unrelated subscribers
218

            
219
If uncertain, choose QoS 1.
220

            
221

            
222
## Node-RED Implementation Optimizations
223

            
224
Translation is done in Node-RED, so the contract is optimized for low processing overhead.
225

            
226
Guidelines:
227

            
228
- keep topic shape stable to simplify wildcard routing and switch nodes
229
- avoid unnecessary JSON parse/build in high-rate pipelines
230
- publish device metadata on retained `meta` to avoid payload repetition
231
- publish canonical MQTT-ready messages as early as possible after normalization
232
- emit MQTT-ready messages only at the publish boundary
233
- do not carry adapter-internal normalization structures on forwarded `msg` objects
234
- discard temporary normalization fields before publish
235
- keep `value` streams extremely lightweight
236
- centralize mapping rules (location, capability, device_id) in reusable subflows
237
- keep one ingress subflow per protocol and one normalization subflow shared by all
238
- avoid broad `#` subscriptions in hot paths
239

            
240
Suggested Node-RED subscriptions:
241

            
242
- `+/home/+/+/+/value`
243
- `+/home/+/+/+/last`
244
- `+/home/+/+/+/set`
245

            
246

            
247
## Interaction with Other Buses
248

            
249
Cross-bus correlations are implemented by consumers, not by changing bus semantics.
250

            
251
Examples:
252

            
253
- combine `home` presence with `energy` load telemetry for occupancy-aware energy decisions
254
- combine `home` climate data with `network` device state for diagnostics
255

            
256

            
257
## Historian Relationship
258

            
259
The `home` bus is a major historian source.
260

            
261
For ingestion worker compatibility, each message should map to:
262

            
263
- `metric_name`
264
- `device_id`
265
- `value`
266
- `observed_at`
267

            
268
`device_id` recommendation:
269

            
270
- `<location>.<device_id>`
271

            
272
Historian defaults:
273

            
274
- `value` streams SHOULD be ingested by default
275
- `last` streams SHOULD NOT be ingested as normal telemetry samples
276
- `meta.historian.mode` SHOULD describe whether a `value` stream represents `sample`, `state`, or `event` semantics
277
- when Profile A scalar is used, `observed_at` will usually fall back to ingestion time
278
- string enum states are semantically valid, but the current PostgreSQL ingestion API directly supports only numeric and boolean samples
279

            
280
Example:
281

            
282
- Topic: `vad/home/bedroom/temperature/bedroom-sensor/value`
283
- `metric_name = temperature`
284
- `device_id = bedroom.bedroom-sensor`
285

            
286
Zigbee2MQTT projection examples:
287

            
288
- `zigbee2mqtt/bedroom_sensor.temperature` -> `vad/home/bedroom/temperature/bedroom-sensor/value`
289
- `zigbee2mqtt/front_door_contact.contact` -> `vad/home/entrance/contact/front-door/value`
290
- `zigbee2mqtt/bedside_remote.action` -> `vad/home/bedroom/button/bedside-remote/value`
291

            
292

            
293
## Relationship with HomeKit
294

            
295
The `home` bus is a primary source for HomeKit adapters.
296

            
297
HomeKit integration remains a consumer layer concern:
298

            
299
- Device -> Protocol Adapter -> MQTT Bus -> HomeKit Adapter -> HomeKit
300

            
301
The `home` bus contract SHOULD remain independent from HomeKit-specific modeling constraints.
302

            
303

            
304
## Design Principles
305

            
306
- keep room-centric semantics explicit and stable
307
- separate control semantics (`home`) from electrical accounting (`energy`)
308
- optimize for deterministic, low-cost Node-RED translation
309
- keep topic grammar strict and payload overhead low
310
- keep canonical IDs independent from vendor identifiers