Changes
Commits
Commit title | Date | Hash |
---|---|---|
Merge pull request #71 from homieiot/rolling-releases | 2018-03-25 08:55:18 +1100 | 96c3086 |
Add info regarding rolling releases | 2018-03-24 15:18:37 +0100 | c5ad0b2 |
Add NodeJS implementation | 2018-03-24 11:25:36 +1100 | 110b68f |
Small Readme version fix | 2018-03-21 09:00:35 +1100 | 508f6ae |
Fix Versioning. | 2018-03-16 07:55:10 +1100 | 09c84e4 |
Merge pull request #67 from marvinroger/v2 | 2018-03-12 12:01:13 +1100 | 0b90e74 |
Update Version | 2018-03-12 12:00:15 +1100 | be4d750 |
Merge branch ‘redesign’ into v2 | 2018-03-12 11:59:28 +1100 | e25c5dc |
added micropython-homie | 2018-03-12 11:54:43 +1100 | 00285cb |
Merge pull request #64 from microhomie/v2 | 2018-02-17 21:12:45 +1100 | 0a9e88b |
Remove WIP state | 2018-02-12 10:49:02 +0100 | 85d6a1f |
Add MicroPython implementation | 2018-02-10 11:56:40 +0100 | d7392c0 |
Merge pull request #63 from nerdfirefighter/redesign | 2018-02-03 18:44:59 +1100 | b071d29 |
Typo Fix | 2018-02-02 20:46:05 +1100 | 25b727f |
Merge pull request #1 from marvinroger/redesign | 2018-02-02 20:43:27 +1100 | 71b15b9 |
Update Branch | 2018-01-24 12:08:45 +1100 | 755b994 |
Merge pull request #60 from nerdfirefighter/v2 | 2018-01-24 11:50:03 +1100 | 0482588 |
Update README.md | 2018-01-17 22:10:47 +1100 | 97e5ec9 |
:bug: Fix typos (#55) | 2018-01-02 15:25:25 +0100 | 2247839 |
:art: Update ToC | 2017-11-13 16:34:15 +0100 | 8d33c76 |
:art: Clean up MQTT restrictions (#47) | 2017-11-13 16:30:32 +0100 | 3e51c9e |
:art: Cosmetic change | 2017-11-13 16:22:54 +0100 | d977ceb |
:fire: Make properties optional with default (#48) | 2017-11-10 12:12:22 +0100 | a19b81a |
:art: Add TOC | 2017-11-06 15:39:44 +0100 | 1b60390 |
:sparkles: Add $state topic (#50) | 2017-11-06 15:11:13 +0100 | e355f4e |
:art: Small comestic change | 2017-09-25 22:00:16 +0200 | ddbe9c9 |
:sparkles: Add a link to the tags | 2017-09-25 21:57:58 +0200 | e0e3bad |
:memo: Add Node.js implementation (#42) | 2017-09-21 03:22:32 -0700 | e5dcd7e |
:sparkles: Allow possibility to know when a device is fully discovered | 2017-08-11 20:02:20 +0200 | 0003daa |
:bug: Fix node attributes array | 2017-08-11 12:55:26 +0200 | 90f94c6 |
:memo: Make clear all values are string | 2017-08-11 12:40:44 +0200 | 11cd9ff |
:sparkles: Add color datatype | 2017-08-11 12:34:47 +0200 | a17b8b3 |
:fire: Replace property arrays to node arrays | 2017-08-11 12:14:11 +0200 | 460e547 |
:memo: Change to a car example | 2017-08-11 11:46:49 +0200 | 949ad7d |
:art: Moved statistics to seperate section and made some clarifications, when to send device attributes. (#40) | 2017-08-10 17:43:27 +0200 | 7ab2e87 |
:fire: $unit should not be mandatory (#39) | 2017-08-08 11:14:43 +0200 | 1a5d314 |
:art: Improve example presentation with strings and java syntax (#36) | 2017-08-07 18:39:11 +0200 | d81a00a |
:memo: Add example for implementation (#37) | 2017-08-07 17:35:18 +0200 | 2be405c |
:fire: $unit should not be mandatory (#35) | 2017-08-07 15:43:33 +0200 | 04441dc |
:sparkles: Add optional stats properties | 2017-08-06 14:29:31 +0200 | 08666c3 |
:art: Rearrange and clarify topology (#31) | 2017-08-06 14:17:35 +0200 | 15e8df0 |
:memo: Add Motivation chapter (#29) | 2017-08-05 19:16:02 +0200 | 1e33ab8 |
:memo: Add implementations file | 2017-08-04 16:38:43 +0200 | e87738f |
:fire: Move implementations on another page | 2017-08-04 16:38:00 +0200 | cf92268 |
:bug: Fix all examples | 2017-08-04 16:30:26 +0200 | 65a91f9 |
:bug: Use more adequate examples for nodes | 2017-08-04 16:05:25 +0200 | d10e380 |
:sparkles: Add shared array attributes | 2017-08-04 15:58:41 +0200 | b7e1b6b |
:art: Make the $format regex simple | 2017-08-04 15:43:33 +0200 | 20c0c13 |
:fire: Remove $signal and | 2017-08-04 15:39:59 +0200 | 081c5af |
:art: Make the structure more consistent | 2017-08-04 15:33:49 +0200 | 4d49797 |
:art: Clarify background | 2017-08-04 15:17:09 +0200 | c8a270a |
:art: Make each paragraph line on a newline | 2017-08-04 15:10:11 +0200 | cae1fa5 |
:sparkles: Make properties discoverable (#27) | 2017-08-04 13:56:14 +0200 | 779093a |
Differences
v2.0.1 | v3.0.0 | ||||
---|---|---|---|---|---|
n | 3 | version: v2.0.1 | n | 3 | version: v3.0.0 |
4 | releasedate: 24. March 2018 | 4 | releasedate: 25. March 2018 | ||
n | 11 | ## Background | n | 11 | ## Table of Contents |
n | 13 | An instance of a physical piece of hardware (an Arduino, an ESP8266...) is called a **device**. A device has **device properties**, like the current local IP, the Wi-Fi signal, etc. A device can expose multiple **nodes**. For example, a weather device might expose a `temperature` node and an `humidity` node. A node can have multiple **node properties**. The `temperature` node might for example expose a `degrees` property containing the actual temperature, and an `unit` property. Node properties can be **ranges**. For example, if you have a LED strip, you can have a node property `led` ranging from `1` to `10`, to control LEDs independently. Node properties can be **settable**. For example, you don't want your `degrees` property to be settable in case of a temperature sensor: this depends on the environment and it would not make sense to change it. However, you will want the `degrees` property to be settable in case of a thermostat. | n | 13 | * [Motivation](#motivation) |
14 | * [MQTT restrictions](#mqtt-restrictions) | ||||
15 | * [Topic IDs](#topic-ids) | ||||
16 | * [Payload](#payload) | ||||
17 | * [QoS and retained messages](#qos-and-retained-messages) | ||||
18 | * [Topology](#topology) | ||||
19 | * [Base topic](#base-topic) | ||||
20 | * [Devices](#devices) | ||||
21 | * [Device attributes](#device-attributes) | ||||
22 | * [Device behavior](#device-behavior) | ||||
23 | * [Device statistics](#device-statistics) | ||||
24 | * [Nodes](#nodes) | ||||
25 | * [Node attributes](#node-attributes) | ||||
26 | * [Properties](#properties) | ||||
27 | * [Property attributes](#property-attributes) | ||||
28 | * [Arrays](#arrays) | ||||
29 | * [Broadcast channel](#broadcast-channel) | ||||
n | n | 31 | ## Motivation | ||
32 | |||||
33 | The Homie convention strives to be a **communication definition on top of MQTT** between IoT devices and controlling entities. | ||||
34 | |||||
35 | > [MQTT](http://mqtt.org) is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol. | ||||
36 | > It was designed as an extremely lightweight publish/subscribe messaging transport. | ||||
37 | |||||
38 | MQTT supports easy and unrestricted message-based communication. | ||||
39 | However, MQTT doesn't define the structure and content of these messages and their relation. | ||||
40 | An IoT device publishes data and provides interaction possibilities but a controlling entity will need to be specifically configured to be able to interface with the device. | ||||
41 | |||||
42 | The Homie convention defines a **standardized way** of how IoT devices and services announce themselves and their data on the communication channel. | ||||
43 | The Homie convention is thereby a crucial aspect in the support of **automatic discovery, configuration and usage** of devices and services over the MQTT protocol. | ||||
44 | |||||
45 | ---- | ||||
46 | |||||
47 | ## MQTT Restrictions | ||||
48 | |||||
49 | Homie communicates through [MQTT](http://mqtt.org) and is hence based on the basic principles of MQTT topic publication and subscription. | ||||
50 | |||||
51 | ### Topic IDs | ||||
52 | |||||
53 | An MQTT topic consists of one or more topic levels, separated by the slash character (`/`). | ||||
54 | A topic level ID MAY contain lowercase letters from `a` to `z`, numbers from `0` to `9` as well as the hyphen character (`-`). | ||||
55 | |||||
56 | A topic level ID MUST NOT start or end with a hyphen (`-`). | ||||
57 | The special character `$` is used and reserved for Homie *attributes*. | ||||
58 | The underscore (`_`) is used and reserved for Homie *node arrays*. | ||||
59 | |||||
60 | ### Payload | ||||
61 | |||||
62 | Every MQTT message payload MUST be sent as string. | ||||
63 | If a value is of a numeric data type, it MUST be converted to string. | ||||
64 | Booleans MUST be converted to "true" or "false". | ||||
65 | All values MUST be encoded as UTF-8 strings. | ||||
66 | |||||
15 | ## QoS and retained messages | 67 | ### QoS and retained messages | ||
n | 17 | Homie devices communicate through MQTT. | n | ||
18 | |||||
19 | The nature of the Homie convention makes it safe about duplicate messages, so the recommended QoS for reliability is **QoS 1**. All messages MUST be sent as **retained**, UNLESS stated otherwise. | 69 | The nature of the Homie convention makes it safe about duplicate messages, so the recommended QoS for reliability is **QoS 1**. | ||
70 | All messages MUST be sent as **retained**, UNLESS stated otherwise. | ||||
n | 21 | ## ID format | n | 72 | ## Topology |
n | 23 | An ID MAY contain only lowercase letters from `a` to `z`, numbers from `0` to `9`, and it MAY contain `-`, but MUST NOT start or end with a `-`. | n | 74 | **Devices:** |
75 | An instance of a physical piece of hardware is called a *device*. | ||||
76 | For example, a car, an Arduino/ESP8266 or a coffee machine. | ||||
n | 25 | ## Convention | n | 78 | **Nodes:** |
79 | A *device* can expose multiple *nodes*. | ||||
80 | Nodes are independent or logically separable parts of a device. | ||||
81 | For example, a car might expose a `wheels` node, an `engine` node and a `lights` node. | ||||
n | 27 | To efficiently parse messages, Homie defines a few rules related to topic names. The base topic you will see in the following convention will be `homie/`. You can however choose whatever base topic you want. | n | 83 | Nodes can be **arrays**. |
84 | For example, instead of creating two `lights` node to control front lights and back lights independently, we can set the `lights` node to be an array with two elements. | ||||
n | 29 | * `homie` / **`device ID`**: this is the base topic of a device. Each device must have an unique device ID which adhere to the [ID format](#id-format). | n | 86 | **Properties:** |
87 | A *node* can have multiple *properties*. | ||||
88 | Properties represent basic characteristics of the node/device, often given as numbers or finite states. | ||||
89 | For example the `wheels` node might expose an `angle` property. | ||||
90 | The `engine` node might expose a `speed`, `direction` and `temperature` property. | ||||
91 | The `lights` node might expose an `intensity` and a `color` property. | ||||
n | 31 | ### Device properties | n | 93 | Properties can be **settable**. |
94 | For example, you don't want your `temperature` property to be settable in case of a temperature sensor (like the car example), but to be settable in case of a thermostat. | ||||
n | 33 | * `homie` / **`device ID`** / `$` **`device property`**: a topic starting with a `$` after the base topic of a device represents a device property. A device property MUST be one of these: | n | 96 | **Attributes:** |
97 | *Devices, nodes and properties* have specific *attributes* characterizing them. | ||||
98 | Attributes are represented by topic identifier starting with `$`. | ||||
99 | The precise definition of attributes is important for the automatic discovery of devices following the Homie convention. | ||||
100 | |||||
101 | Examples: A device might have an `IP` attribute, a node will have a `name` attribute, and a property will have a `unit` attribute. | ||||
102 | |||||
103 | ---- | ||||
104 | |||||
105 | ### Base Topic | ||||
106 | |||||
107 | The base topic you will see in the following convention will be `homie/`. | ||||
108 | If this base topic does not suit your needs (in case of, e.g., a public broker), you can choose another. | ||||
109 | |||||
110 | Be aware, that only the default base topic `homie/` is eligible for automatic discovery by third party controllers. | ||||
111 | |||||
112 | ---- | ||||
113 | |||||
114 | ### Devices | ||||
115 | |||||
116 | * `homie` / **`device ID`**: this is the base topic of a device. | ||||
117 | Each device must have a unique device ID which adhere to the [ID format](#topic-ids). | ||||
118 | |||||
119 | #### Device Attributes | ||||
120 | |||||
121 | * `homie` / `device ID` / **`$device-attribute`**: | ||||
122 | When the MQTT connection to the broker is established or re-established, the device MUST send its attributes to the broker immediately. | ||||
n | 37 | <th>Property</th> | n | 126 | <th>Topic</th> |
n | 51 | <td>$online</td> | n | ||
52 | <td>Device → Controller</td> | ||||
53 | <td><code>true</code> when the device is online, <code>false</code> when the device is offline (through LWT). When sending the device is online, this message must be sent last, to indicate every other required messages are sent and the device is ready</td> | ||||
54 | <td>Yes</td> | ||||
55 | <td>Yes</td> | ||||
56 | </tr> | ||||
57 | <tr> | ||||
n | n | 147 | <td>$state</td> | ||
148 | <td>Device → Controller</td> | ||||
149 | <td> | ||||
150 | See <a href="#device-behavior">Device behavior</a> | ||||
151 | </td> | ||||
152 | <td>Yes</td> | ||||
153 | <td>Yes</td> | ||||
154 | </tr> | ||||
155 | <tr> | ||||
n | 79 | <td>$stats/uptime</td> | n | ||
80 | <td>Device → Controller</td> | ||||
81 | <td>Time elapsed in seconds since the boot of the device</td> | ||||
82 | <td>Yes</td> | ||||
83 | <td>Yes</td> | ||||
84 | </tr> | ||||
85 | <tr> | ||||
86 | <td>$stats/signal</td> | ||||
87 | <td>Device → Controller</td> | ||||
88 | <td>Integer representing the Wi-Fi signal quality in percentage if applicable</td> | ||||
89 | <td>Yes</td> | ||||
90 | <td>No, this is not applicable to an Ethernet connected device for example</td> | ||||
91 | </tr> | ||||
92 | <tr> | ||||
93 | <td>$stats/interval</td> | ||||
94 | <td>Device → Controller</td> | ||||
95 | <td>Interval in seconds at which the <code>$stats/uptime</code> and <code>$stats/signal</code> are refreshed</td> | ||||
96 | <td>Yes</td> | ||||
97 | <td>Yes</td> | ||||
98 | </tr> | ||||
99 | <tr> | ||||
n | 114 | <td>$fw/checksum</td> | n | ||
115 | <td>Device → Controller</td> | ||||
116 | <td>MD5 checksum of the firmware running on the device</td> | ||||
117 | <td>Yes</td> | 184 | <td>$nodes</td> | ||
118 | <td>No, depending of your implementation</td> | 185 | <td>Device → Controller</td> | ||
186 | <td> | ||||
187 | Nodes the device exposes, with format <code>id</code> separated by a <code>,</code> if there are multiple nodes. | ||||
188 | To make a node an array, append <code>[]</code> to the ID. | ||||
189 | </td> | ||||
190 | <td>Yes</td> | ||||
191 | <td>Yes</td> | ||||
n | n | 208 | <td>$stats</td> | ||
209 | <td>Device → Controller</td> | ||||
210 | <td>Specify all optional stats that the device will announce, with format <code>stats</code> separated by a <code>,</code> if there are multiple stats. See next section for an example</td> | ||||
135 | <td>$nodes</td> | 211 | <td>Yes</td> | ||
212 | <td>Yes</td> | ||||
213 | </tr> | ||||
214 | <tr> | ||||
215 | <td>$stats/interval</td> | ||||
n | 137 | <td>Nodes the device exposes, with format <code>id</code> separated by a <code>,</code> if there are multiple nodes.</td> | n | 217 | <td>Interval in seconds at which the device refreshes its <code>$stats/+</code>: See next section for details about statistical attributes</td> |
n | 143 | For example, a device with an ID of `686f6d6965` with a temperature and an humidity sensor would send: | n | 223 | For example, a device with an ID of `super-car` that comprises off a `wheels`, `engine` and a `lights` node would send: |
n | n | 225 | ```java | ||
226 | homie/super-car/$homie → "2.1.0" | ||||
227 | homie/super-car/$name → "Super car" | ||||
228 | homie/super-car/$localip → "192.168.0.10" | ||||
229 | homie/super-car/$mac → "DE:AD:BE:EF:FE:ED" | ||||
230 | homie/super-car/$fw/name → "weatherstation-firmware" | ||||
231 | homie/super-car/$fw/version → "1.0.0" | ||||
232 | homie/super-car/$nodes → "wheels,engine,lights[]" | ||||
233 | homie/super-car/$implementation → "esp8266" | ||||
234 | homie/super-car/$stats/interval → "60" | ||||
235 | homie/super-car/$state → "ready" | ||||
n | 146 | homie/686f6d6965/$online → true | n | ||
147 | homie/686f6d6965/$name → Bedroom temperature sensor | ||||
148 | homie/686f6d6965/$localip → 192.168.0.10 | ||||
149 | homie/686f6d6965/$signal → 72 | ||||
150 | homie/686f6d6965/$fw/name → 1.0.0 | ||||
151 | homie/686f6d6965/$fw/version → 1.0.0 | ||||
152 | ``` | ||||
n | 154 | ### Node properties | n | 238 | #### Device Behavior |
n | 156 | * `homie` / **`device ID`** / **`node ID`** / **`property`**: `node ID` is the ID of the node, which must be unique on a per-device basis, and which adhere to the [ID format](#id-format). `property` is the property of the node that is getting updated, which must be unique on a per-node basis, and which adhere to the [ID format](#id-format). | n | 240 | The `$state` device attribute represents, as the name suggests, the current state of the device. |
241 | There are 6 different states: | ||||
n | 158 | Properties starting with a `$` are special properties. It must be one of the following: | n | 243 | * **`init`**: this is the state the device is in when it is connected to the MQTT broker, but has not yet sent all Homie messages and is not yet ready to operate. |
244 | This is the first message that must that must be sent. | ||||
245 | * **`ready`**: this is the state the device is in when it is connected to the MQTT broker, has sent all Homie messages and is ready to operate. | ||||
246 | You have to send this message after all other announcements message have been sent. | ||||
247 | * **`disconnected`**: this is the state the device is in when it is cleanly disconnected from the MQTT broker. | ||||
248 | You must send this message before cleanly disconnecting. | ||||
249 | * **`sleeping`**: this is the state the device is in when the device is sleeping. | ||||
250 | You have to send this message before sleeping. | ||||
251 | * **`lost`**: this is the state the device is in when the device has been "badly" disconnected. | ||||
252 | You must define this message as LWT. | ||||
253 | * **`alert`**: this is the state the device is when connected to the MQTT broker, but something wrong is happening. E.g. a sensor is not providing data and needs human intervention. | ||||
254 | You have to send this message when something is wrong. | ||||
255 | |||||
256 | #### Device Statistics | ||||
257 | |||||
258 | * `homie` / `device ID` / `$stats`/ **`$device-statistic-attribute`**: | ||||
259 | The `$stats/` hierarchy allows to send device attributes that change over time. The device MUST send them every `$stats/interval` seconds. | ||||
n | 162 | <th>Property</th> | n | 263 | <th>Topic</th> |
n | n | 270 | <td>$stats/uptime</td> | ||
271 | <td>Device → Controller</td> | ||||
272 | <td>Time elapsed in seconds since the boot of the device</td> | ||||
273 | <td>Yes</td> | ||||
274 | <td>Yes</td> | ||||
275 | </tr> | ||||
276 | <tr> | ||||
277 | <td>$stats/signal</td> | ||||
278 | <td>Device → Controller</td> | ||||
279 | <td>Signal strength in %</td> | ||||
280 | <td>Yes</td> | ||||
281 | <td>No</td> | ||||
282 | </tr> | ||||
283 | <tr> | ||||
284 | <td>$stats/cputemp</td> | ||||
285 | <td>Device → Controller</td> | ||||
286 | <td>CPU Temperature in °C</td> | ||||
287 | <td>Yes</td> | ||||
288 | <td>No</td> | ||||
289 | </tr> | ||||
290 | <tr> | ||||
291 | <td>$stats/cpuload</td> | ||||
292 | <td>Device → Controller</td> | ||||
293 | <td> | ||||
294 | CPU Load in %. | ||||
295 | Average of last <code>$interval</code> including all CPUs | ||||
296 | </td> | ||||
297 | <td>Yes</td> | ||||
298 | <td>No</td> | ||||
299 | </tr> | ||||
300 | <tr> | ||||
301 | <td>$stats/battery</td> | ||||
302 | <td>Device → Controller</td> | ||||
303 | <td>Battery level in %</td> | ||||
304 | <td>Yes</td> | ||||
305 | <td>No</td> | ||||
306 | </tr> | ||||
307 | <tr> | ||||
308 | <td>$stats/freeheap</td> | ||||
309 | <td>Device → Controller</td> | ||||
310 | <td>Free heap in bytes</td> | ||||
311 | <td>Yes</td> | ||||
312 | <td>No</td> | ||||
313 | </tr> | ||||
314 | <tr> | ||||
315 | <td>$stats/supply</td> | ||||
316 | <td>Device → Controller</td> | ||||
317 | <td>Supply Voltage in V</td> | ||||
318 | <td>Yes</td> | ||||
319 | <td>No</td> | ||||
320 | </tr> | ||||
321 | </table> | ||||
322 | |||||
323 | For example, our `super-car` device with `$stats/interval` value "60" is supposed to send its current values every 60 seconds: | ||||
324 | |||||
325 | ```java | ||||
326 | homie/super-car/$stats → "uptime,cputemp,signal,battery" | ||||
327 | homie/super-car/$stats/uptime → "120" | ||||
328 | homie/super-car/$stats/cputemp → "48" | ||||
329 | homie/super-car/$stats/signal → "24" | ||||
330 | homie/super-car/$stats/battery → "80" | ||||
331 | ``` | ||||
332 | |||||
333 | ---- | ||||
334 | |||||
335 | ### Nodes | ||||
336 | |||||
337 | * `homie` / `device ID` / **`node ID`**: this is the base topic of a node. | ||||
338 | Each node must have a unique node ID on a per-device basis which adhere to the [ID format](#topic-ids). | ||||
339 | |||||
340 | #### Node Attributes | ||||
341 | |||||
342 | * `homie` / `device ID` / `node ID` / **`$node-attribute`**: | ||||
343 | A node attribute MUST be one of these: | ||||
344 | |||||
345 | <table> | ||||
346 | <tr> | ||||
347 | <th>Topic</th> | ||||
348 | <th>Direction</th> | ||||
349 | <th>Description</th> | ||||
350 | <th>Retained</th> | ||||
351 | <th>Required</th> | ||||
352 | </tr> | ||||
353 | <tr> | ||||
354 | <td>$name</td> | ||||
355 | <td>Device → Controller</td> | ||||
356 | <td>Friendly name of the Node</td> | ||||
357 | <td>Yes</td> | ||||
358 | <td>Yes</td> | ||||
359 | </tr> | ||||
360 | <tr> | ||||
n | 178 | <td>Properties the node exposes, with format <code>id</code> separated by a <code>,</code> if there are multiple nodes. For ranges, define the range after the <code>id</code>, within <code>[]</code> and separated by a <code>-</code>. For settable properties, add <code>:settable</code> to the <code>id</code></td> | n | 370 | <td> |
371 | Properties the node exposes, with format <code>id</code> separated by a <code>,</code> if there are multiple nodes. | ||||
372 | </td> | ||||
373 | <td>Yes</td> | ||||
374 | <td>Yes</td> | ||||
375 | </tr> | ||||
376 | <tr> | ||||
377 | <td>$array</td> | ||||
378 | <td>Device → Controller</td> | ||||
379 | <td>Range separated by a <code>-</code>. e.g. <code>0-2</code> for an array with the indexes <code>0</code>, <code>1</code> and <code>2</code></td> | ||||
179 | <td>Yes</td> | 380 | <td>Yes</td> | ||
180 | <td>Yes</td> | 381 | <td>Yes, if the node is an array</td> | ||
181 | </tr> | 382 | </tr> | ||
n | 184 | For example, our `686f6d6965` above would send: | n | 385 | For example, our `engine` node would send: |
n | n | 387 | ```java | ||
388 | homie/super-car/engine/$name → "Car engine" | ||||
389 | homie/super-car/engine/$type → "V8" | ||||
390 | homie/super-car/engine/$properties → "speed,direction,temperature" | ||||
391 | ``` | ||||
392 | |||||
393 | ---- | ||||
394 | |||||
395 | ### Properties | ||||
396 | |||||
397 | * `homie` / `device ID` / `node ID` / **`property ID`**: this is the base topic of a property. | ||||
398 | Each property must have a unique property ID on a per-node basis which adhere to the [ID format](#topic-ids). | ||||
399 | |||||
400 | * A property value (e.g. a sensor reading) is directly published to the property topic, e.g.: | ||||
401 | ```java | ||||
402 | homie/super-car/engine/temperature → "21.5" | ||||
186 | ``` | 403 | ``` | ||
187 | homie/686f6d6965/temperature/$type → temperature | ||||
188 | homie/686f6d6965/temperature/$properties → degrees,unit | ||||
189 | homie/686f6d6965/temperature/unit → c | ||||
190 | homie/686f6d6965/temperature/degrees → 12.07 | ||||
n | 192 | homie/686f6d6965/humidity/$type → humidity | n | 405 | #### Property Attributes |
193 | homie/686f6d6965/humidity/$properties → percentage | ||||
194 | homie/686f6d6965/humidity/percentage → 79 | ||||
195 | ``` | ||||
n | 197 | A LED strip would look like this. Note that the topic for a range properties is the name of the property followed by a `_` and the index getting updated: | n | 407 | * `homie` / `device ID` / `node ID` / `property ID` / **`$property-attribute`**: |
408 | A property attribute MUST be one of these: | ||||
n | 199 | ``` | n | 410 | <table> |
200 | homie/ledstrip-device/ledstrip/$type → ledstrip | 411 | <tr> | ||
201 | homie/ledstrip-device/ledstrip/$properties → led[1-3]:settable | 412 | <th>Topic</th> | ||
202 | homie/ledstrip-device/ledstrip/led_1 → on | 413 | <th>Direction</th> | ||
203 | homie/ledstrip-device/ledstrip/led_2 → off | 414 | <th>Description</th> | ||
204 | homie/ledstrip-device/ledstrip/led_3 → on | 415 | <th>Valid values</th> | ||
205 | ``` | 416 | <th>Retained</th> | ||
417 | <th>Required (Default)</th> | ||||
418 | </tr> | ||||
419 | <tr> | ||||
420 | <td>$name</td> | ||||
421 | <td>Device → Controller</td> | ||||
422 | <td>Friendly name of the property.</td> | ||||
423 | <td>Any String</td> | ||||
424 | <td>Yes</td> | ||||
425 | <td>No ("")</td> | ||||
426 | </tr> | ||||
427 | <tr> | ||||
428 | <td>$settable</td> | ||||
429 | <td>Device → Controller</td> | ||||
430 | <td>Specifies whether the property is settable (<code>true</code>) or readonly (<code>false</code>)</td> | ||||
431 | <td><code>true</code> or <code>false</code></td> | ||||
432 | <td>Yes</td> | ||||
433 | <td>No (<code>false</code>)</td> | ||||
434 | </tr> | ||||
435 | <tr> | ||||
436 | <td>$unit</td> | ||||
437 | <td>Device → Controller</td> | ||||
438 | <td> | ||||
439 | A string containing the unit of this property. | ||||
440 | You are not limited to the recommended values, although they are the only well known ones that will have to be recognized by any Homie consumer. | ||||
441 | </td> | ||||
442 | <td> | ||||
443 | Recommended:<br> | ||||
444 | <code>°C</code> Degree Celsius<br> | ||||
445 | <code>°F</code> Degree Fahrenheit<br> | ||||
446 | <code>°</code> Degree<br> | ||||
447 | <code>L</code> Liter<br> | ||||
448 | <code>gal</code> Galon<br> | ||||
449 | <code>V</code> Volts<br> | ||||
450 | <code>W</code> Watt<br> | ||||
451 | <code>A</code> Ampere<br> | ||||
452 | <code>%</code> Percent<br> | ||||
453 | <code>m</code> Meter<br> | ||||
454 | <code>ft</code> Feet<br> | ||||
455 | <code>Pa</code> Pascal<br> | ||||
456 | <code>psi</code> PSI<br> | ||||
457 | <code>#</code> Count or Amount | ||||
458 | </td> | ||||
459 | <td>Yes</td> | ||||
460 | <td>No ("")</td> | ||||
461 | </tr> | ||||
462 | <tr> | ||||
463 | <td>$datatype</td> | ||||
464 | <td>Device → Controller</td> | ||||
465 | <td>Describes the format of data.</td> | ||||
466 | <td> | ||||
467 | <code>integer</code>, | ||||
468 | <code>float</code>, | ||||
469 | <code>boolean</code>, | ||||
470 | <code>string</code>, | ||||
471 | <code>enum</code>, | ||||
472 | <code>color</code> | ||||
473 | </td> | ||||
474 | <td>Yes</td> | ||||
475 | <td>No (<code>string</code>)</td> | ||||
476 | </tr> | ||||
477 | <tr> | ||||
478 | <td>$format</td> | ||||
479 | <td>Device → Controller</td> | ||||
480 | <td> | ||||
481 | Describes what are valid values for this property. | ||||
482 | </td> | ||||
483 | <td> | ||||
484 | <ul> | ||||
485 | <li> | ||||
486 | <code>from:to</code> Describes a range of values e.g. <code>10:15</code>. | ||||
487 | <br>Valid for datatypes <code>integer</code>, <code>float</code> | ||||
488 | </li> | ||||
489 | <li> | ||||
490 | <code>value,value,value</code> for enumerating all valid values. | ||||
491 | Escape <code>,</code> by using <code>,,</code>. e.g. <code>A,B,C</code> or <code>ON,OFF,PAUSE</code>. | ||||
492 | <br>Valid for datatypes <code>enum</code> | ||||
493 | </li> | ||||
494 | <li> | ||||
495 | <code>regex:pattern</code> to provide a regex that can be used to match the value. e.g. <code>regex:[A-Z][0-9]+</code>. | ||||
496 | <br>Valid for datatype <code>string</code> | ||||
497 | </li> | ||||
498 | <li> | ||||
499 | <code>rgb</code> to provide colors in RGB format e.g. <code>255,255,0</code> for yellow. | ||||
500 | <code>hsv</code> to provide colors in HSV format e.g. <code>60,100,100</code> for yellow. | ||||
501 | <br>Valid for datatype <code>color</code> | ||||
502 | </li> | ||||
503 | </ul> | ||||
504 | </td> | ||||
505 | <td>Yes</td> | ||||
506 | <td>Depends on $datatype</td> | ||||
507 | </tr> | ||||
508 | </table> | ||||
n | n | 510 | For example, our `temperature` property would send: | ||
511 | |||||
512 | ```java | ||||
513 | homie/super-car/engine/temperature/$name → "Engine temperature" | ||||
514 | homie/super-car/engine/temperature/$settable → "false" | ||||
515 | homie/super-car/engine/temperature/$unit → "°C" | ||||
516 | homie/super-car/engine/temperature/$datatype → "float" | ||||
517 | homie/super-car/engine/temperature/$format → "-20:120" | ||||
518 | homie/super-car/engine/temperature → "21.5" | ||||
519 | ``` | ||||
520 | |||||
207 | * `homie` / **`device ID`** / **`node ID`** / **`property`** / `set`: the device can subscribe to this topic if the property is **settable** from the controller, in case of actuators. | 521 | * `homie` / `device ID` / `node ID` / `property ID` / **`set`**: the device can subscribe to this topic if the property is **settable** from the controller, in case of actuators. | ||
n | 209 | Homie is state-based. You don't tell your smartlight to `turn on`, but you tell it to put it's `on` state to `true`. This especially fits well with MQTT, because of retained message. | n | 523 | Homie is state-based. |
524 | You don't tell your smartlight to `turn on`, but you tell it to put its `power` state to `on`. | ||||
525 | This especially fits well with MQTT, because of retained message. | ||||
n | 211 | For example, a `kitchen-light` device exposing a `light` node would subscribe to `homie/kitchen-light/light/on/set` and it would receive: | n | 527 | For example, a `kitchen-light` device exposing a `light` node would subscribe to `homie/kitchen-light/light/power/set` and it would receive: |
n | 213 | ``` | n | 529 | ```java |
214 | homie/kitchen-light/light/on/set ← true | 530 | homie/kitchen-light/light/power/set ← "on" | ||
n | 217 | The device would then turn on the light, and update its `on` state. This provides pessimistic feedback, which is important for home automation. | n | 533 | The device would then turn on the light, and update its `power` state. |
534 | This provides pessimistic feedback, which is important for home automation. | ||||
n | 219 | ``` | n | 536 | ```java |
220 | homie/kitchen-light/light/on → true | 537 | homie/kitchen-light/light/power → "true" | ||
n | n | 540 | ### Arrays | ||
541 | |||||
542 | A node can be an array if you've added `[]` to its ID in the `$nodes` device attribute, and if its `$array` attribute is set to the range of the array. | ||||
543 | Let's consider we want to control independently the front lights and back lights of our `super-car`. Our `lights` node array would look like this. Note that the topic for an element of the array node is the name of the node followed by a `_` and the index getting updated: | ||||
544 | |||||
545 | ```java | ||||
546 | homie/super-car/$nodes → "lights[]" | ||||
547 | |||||
548 | homie/super-car/lights/$name → "Lights" | ||||
549 | homie/super-car/lights/$properties → "intensity" | ||||
550 | homie/super-car/lights/$array → "0-1" | ||||
551 | |||||
552 | homie/super-car/lights/intensity/$name → "Intensity" | ||||
553 | homie/super-car/lights/intensity/$settable → "true" | ||||
554 | homie/super-car/lights/intensity/$unit → "%" | ||||
555 | homie/super-car/lights/intensity/$datatype → "integer" | ||||
556 | homie/super-car/lights/intensity/$format → "0:100" | ||||
557 | |||||
558 | homie/super-car/lights_0/$name → "Back lights" | ||||
559 | homie/super-car/lights_0/intensity → "0" | ||||
560 | homie/super-car/lights_1/$name → "Front lights" | ||||
561 | homie/super-car/lights_1/intensity → "100" | ||||
562 | ``` | ||||
563 | |||||
564 | Note that you can name each element in your array individually ("Back lights", etc.). | ||||
565 | |||||
566 | ---- | ||||
567 | |||||
223 | ### Broadcast channel | 568 | ### Broadcast Channel | ||
n | 227 | * `homie` / `$broadcast` / **`level`**: `level` is an arbitrary broadcast identifier. It must adhere to the [ID format](#id-format). | n | 572 | * `homie` / `$broadcast` / **`level`**: `level` is an arbitrary broadcast identifier. |
573 | It must adhere to the [ID format](#topic-ids). | ||||
n | 229 | For example, you might want to broadcast an `alert` event with the alert reason as the payload. Devices are then free to react or not. In our case, every buzzer of your home automation system would start buzzing. | n | 575 | For example, you might want to broadcast an `alert` event with the alert reason as the payload. |
576 | Devices are then free to react or not. | ||||
577 | In our case, every buzzer of your home automation system would start buzzing. | ||||
t | 231 | ``` | t | 579 | ```java |
232 | homie/$broadcast/alert ← Intruder detected | 580 | homie/$broadcast/alert ← "Intruder detected" |