Files
plastic-hub-dev-node-saturn 538369cff7 latest
2021-05-12 18:35:18 +02:00

193 lines
7.3 KiB
Markdown

Overview
--------
This document describes an architectural concept for a Smart Home Automation system
which ties together heterogeneous hardware using a centralized message bus: MQTT.
_Effectively, it just defines a convention for exchanging messages, and a message format._
It's goal is to provide an interoperability layer close to the hardware level.
Logic and Visualization are to be implemented at a higher level, on top of the MQTT bus.
```
+---------------+
| | +----------------------+
| Logic Engine +-------+ +-----+ Hardware Interface A |
| | | | | (e.g. KNX) |
+---------------+ +--+----------+-+ +----------------------+
| |
| MQTT-Broker |
| |
+---------------+ +--+----------+-+ +----------------------+
| | | | | Hardware Interface B |
| Visualization +-------+ +-----+ (e.g. Homematic) |
| | +----------------------+
+---------------+
```
This convention does make no attempt at abstracting hardware messages into
higher level concepts like "Lights" or "Switches". Current home automation
hardware and their hardware interfaces have a wide range of different design
concepts, ranging from simply addressing devices directly (like many basic RF
protocols) over abstracting devices into channels and datapoints
(e.g. Homematic) to the link-orientied Group Address concept used by KNX.
This abstraction, if required, needs to happen at a higher level, e.g.
inside a logic engine.
Message Bus
-----------
A MQTT broker (http://en.wikipedia.org/wiki/MQTT) serves as the central message bus.
In short, MQTT allows applications to exchange messages under so-called "topics".
Applications which are interested in certain topics _subscribe_ to them,
and other applications _publish_ messages to them.
## Topic Hierarchy ##
MQTT topics are hierarchically structured, much like files and directories in a
file system. Example:
toplevelname/function/item...
By convention, in mqtt-smarthome the *toplevelname* will always refer to a specific
instance of a hardware interface or other participent in the system.
The second level *function* defines a function like _status_, _set_ etc.
The subsequent levels are defined by the specific interface.
For example, a KNX gateway might reflect the KNX Group Address hierarchy, which
might look like
knxgateway1/status/Kitchen/Lights/Front Left
whereas a Homematic interface may represent device/channel names and datapoints:
hm/status/Light Kitchen Front Left/LEVEL
The *toplevelname* should be configurable so that multiple instances of interfaces
can coexist on a single message bus.
### Status reports ###
Interfaces report states (values from sensors, feedback from actuators)
by publishing into the topic
toplevelname/status/itemname
The *retain* flag should be set depending on whether the status is a one-shot
event (e.g. a keypress) or a measurement or other state (e.g. a temperature).
One-shot events should not be retained, whereas states should have *retain*
set.
### Change/Action requests ###
Visualization UIs and Logic Engines request state changes by publishing
the requested new value into the topic
toplevelname/set/itemname
The _itemname_ hierarchy for _set_ should be the same as the one used for the _status_
function tree.
Messages published to this hierarchy should never have the MQTT *retain* flag set.
### Connected status ###
Each interface should maintain a topic
toplevelname/connected
which is an integer enum:
* 0 - disconnected from MQTT broker
* 1 - connected to MQTT, but disconnected from hardware
* 2 - connected to MQTT and hardware, i.e. fully operational
It should ensure that this is set to _0_ using MQTT's
_Last Will and Testament_ functionality upon a disconnect.
#### Active get ####
Interfaces which support active value requests from hardware
devices (like KNX or Homematic) may support a hierarchy
toplevelname/get/itemname
A write of any value to that hierarchy should trigger an active read
operation of the given _itemname_. The result of the read should be
published by the interface as a _status_ update.
Messages published to this hierarchy should never have the MQTT *retain*
flag set.
#### Command channel ####
Interfaces may support a command scheme which may not be representable
by the normal item hierarchy. In this case, the interface may listen to
toplevelname/command
to receive such commands.
Messages published to this hierarchy should never have the MQTT *retain*
flag set.
### QoS recommendations ###
MQTT supports various QoS (Quality of Service) levels for messages and
connections:
* 0 - no guaranteed delivery, no duplicates possible
* 1 - guaranteed delivery, *duplicates possible*
* 2 - guaranteed delivery, no duplicates possible
In the context of this proposal, it is recommended that QoS 1 is best avoided
due to the chance that messages may be delivered multiple times.
It should be assumed that duplicated messages in the _set_, _get_ and
_command_ hierarchies may cause unwanted repeated hardware interaction, and
that duplicated messages in the _status_ hierarchy may trigger unwanted
repeated events in a logic layer.
Message format
--------------
The message format for _status_ reports may either be a simple
value or a JSON encoded object which contains the simple value
and possible additional information.
The message format for _set_ operations is always a simple value.
The actual type of *simple value* depends on the underlying hardware.
It may be a boolean, a integer or floating point number, or a string.
If the _status_ message is a JSON encoded object, the object will
always have at least the field _val_, which holds aforementioned
simple value.
Additional possible fields:
* ts - the timestamp when the value was obtained. Milliseconds since Epoch.
* lc - the timestamp when the value last changed. Milliseconds since Epoch.
Example:
```
{
"val": 17.9,
"ts": 1421792677000,
"lc": 1421792677000
}
```
Interfaces may include additional fields in the object. Those fields
always should be prefixed with a mnemonic identifier denoting the
interface. For example, a KNX interface may include a field
"knx_src_addr" which holds the originating bus address of a KNX write
message.