cmqttd¶
cmqttd allows you to expose a C-Bus network to an MQTT broker. This daemon replaces cdbusd (which required D-Bus) as the abstraction mechanism for all other components.
It uses Home Assistant style MQTT-JSON Light components, and supports MQTT discovery. It should also work with other software that supports MQTT.
It can also be run inside a Docker container.
This replaces sage (our custom web interface which replaced Wiser).
cmqttd with Home Assistant has many advantages over Wiser:
- No dependency on Flash Player or a mobile app
- No requirement for an Ethernet-based PCI (serial or USB are sufficient)
- Touch-friendly UI based on Material components
- Integrates with other Home Assistant supported devices
- No hard coded back-doors or outdated software from 2006
See also: Instructions for Wiser users.
Note
Only the default lighting application is supported by cmqttd. Patches welcome!
Running¶
cmqttd requires a MQTT Broker (server) to act as a message bus.
Note
For these examples, we’ll assume your MQTT Broker:
- is accessible via
192.0.2.1
on the default port (1883). - does not use transport security (TLS)
- does not require authentication
This setup is not secure; but securing your MQTT Broker is out of the scope of this document.
For more information, see MQTT options.
To connect to a serial or USB PCI connected on /dev/ttyUSB0
, run:
$ cmqttd --broker-address 192.0.2.1 --broker-disable-tls --serial /dev/ttyUSB0
To connect to a CNI (or PCI over TCP) listening at 192.0.2.2:10001
, run:
$ cmqttd --broker-address 192.0.2.1 --broker-disable-tls --tcp 192.0.2.2:10001
If you’re using Docker, the container also needs a route to the CNI’s IP address.
Tip
If you haven’t installed the library, you can run from a git clone
of
libcbus
source repository with:
$ python3 -m cbus.daemons.cmqttd -b 192.0.2.1 [...]
For Wiser users¶
This software is not compatible with Wiser Home Control (Clipsal’s web interface for C-Bus). Wiser and cmqttd both take full control the CNI, and will interfere with one another.
Additionally, using both on the same C-Bus network (with different PCI/CNIs) may cause issues, as both presume they are the sole source of network services such as time synchronisation.
Wiser Home Control Mk1 (5200PG)¶
The Wiser Home Control Mk1 has an external CNI which should be usable with cmqttd.
Switch off and completely disconnect the Wiser.
Disconnect the “busbar” between the Wiser and the CNI.
Connect the CNI to power and network directly.
You may need to use Toolkit to configure the CNI with an IP address which can be accessed from the host you’re running cmqttd on. The default IP address for the CNI is
192.168.2.2
.Continue setting up cmqttd.
Once you’ve verified cmqttd is working correctly, responsibly dispose of the Wiser 1 at your nearest e-waste facility.
Warning
The Wiser 1 has very outdated and insecure software (from 2006). You should not use it under any circumstances, or for any purpose.
Wiser Home Control Mk2 (5200WHC2)¶
The Wiser Home Control Mk2 has an internal CNI which cannot be used, because the Wiser’s software conflicts with cmqttd.
You will need to get a real, standalone PCI or CNI.
Tip
The author of this software does not have access to any Wiser hardware anymore, and the Wiser 2’s list price of 2000 AUD is far beyond the budget for this project.
Hint hint, Schneider Electric… we should talk :)
Configuration¶
cmqttd has many command-line configuration options.
A complete list can be found by running cmqttd --help
.
C-Bus PCI options¶
One of these must be specified:
-
--serial
DEVICE
¶ Serial device that the PCI is connected to, eg:
/dev/ttyUSB0
.USB PCIs (5500PCU) act as a SiLabs
cp210x
USB-Serial adapter, its serial device must be specified here.
-
--tcp
ADDR:PORT
¶ IP address and TCP port where the PCI or CNI is located, eg:
192.0.2.1:10001
.Both the address and the port are required. CNIs listen on port
10001
by default.See also: Instructions for Wiser users.
MQTT options¶
-
--broker-address
ADDR
¶ Address of the MQTT broker. This option is required.
-
--broker-port
PORT
¶ Port of the MQTT broker.
By default, this is 8883 if TLS is enabled, otherwise 1883.
-
--broker-disable-tls
¶
Disables all transport security (TLS). This option is insecure!
By default, transport security is enabled.
-
--broker-auth
FILE
¶ File containing the username and password to authenticate to the MQTT broker with.
This is a plain text file with two lines: the username, followed by the password.
If not specified, password authentication will not be used.
-
--broker-ca
DIRECTORY
¶ Path to a directory of CA certificates to trust, used for validating certificates presented in the TLS handshake.
If not specified, the default (Python) CA store is used instead.
-
--broker-client-cert
PEM
¶
-
--broker-client-key
PEM
¶ Path to a PEM-encoded client (public) certificate and (private) key for TLS authentication.
If not specified, certificate-based client authentication will not be used.
If the file is encrypted, Python will prompt for the password at the command-line.
Labels¶
-
--project-file
CBZ
¶ Path to a C-Bus Toolkit project backup file (CBZ) to use for labelling group addresses.
This doesn’t affect the entity paths or unique IDs published in MQTT.
Only single-network projects using the lighting application are supported. DLT labels are not supported.
For group addresses with unknown names, or if no project file is supplied, generated names like
C-Bus Light 001
will be used instead.
Tip
If you don’t have a project file backup from your installer, you can always rename entities from within Home Assistant itself.
This labels are not stored on C-Bus units, so Toolkit cannot download this information from the network.
Time synchronisation¶
By default, cmqttd will periodically provide a time signal to the C-Bus network, and respond to all time requests.
Local time is always used for time synchronisation. You can specify a different timezone with the TZ environment variable.
C-Bus’ time implementation has many limitations:
C-Bus date values and time values are two separate network variables – there is no analog to Python’s
datetime.datetime
type. This can trigger race conditions around midnight if the messages are not handled atomically by receivers.cmqttd will always send the date and time as a single message, in an attempt to mitigate this issue.
C-Bus time values have an optional “daylight saving time” flag, with three states: “no daylight saving offset applied”, “time advanced by 1 hour for daylight saving”, and “unknown”.
Because this is cannot be used to present daylight saving time properly (eg: Lord Howe Island turns their clocks forward 30 minutes for DST), and there are far too many edge cases with time zone handling, cmqttd will always report “unknown”, in an attempt to make sure C-Bus units do not attempt any time conversions.
C-Bus does not support leap seconds. You can mitigate this by synchronising your clock using an NTP server with leap second smearing.
To schedule scenes in C-Bus, you should use something like Home Assistant, rather than embedded controllers directly attached to the C-Bus network.
-
--timesync
SECONDS
¶ Periodically sends an unsolicited time signal to the C-Bus network.
By default, this is every 300 seconds (5 minutes).
If set to
0
, cmqttd will not send unsolicited time signals to the C-Bus network.
-
--no-clock
¶
Disables responding to time requests from the C-Bus network.
Using with Home Assistant¶
cmqttd supports Home Assistant’s MQTT discovery protocol.
To use it, just add a MQTT integration using the same MQTT Broker as cmqttd with discovery enabled (this is disabled by default). See Home Assistant’s documentation for more information and example configurations.
Once the integration and cmqttd are running, each group addresses (regardless of whether it is in use) will automatically appear in Home Assistant’s UI as two components:
lights:
light.cbus_{{GROUP_ADDRESS}}
(eg: GA 1 =light.cbus_1
)This implements read / write access to lighting controls on the default lighting application. “Lighting Ramp” commands can be sent via the standard
brightness
andtransition
extensions.By default, these will have names like
C-Bus Light 001
.binary sensors:
binary_sensor.cbus_{{GROUP_ADDRESS}}
(eg: GA 1 =binary_sensor.cbus_1
).This is a binary, read-only interface for all group addresses.
An example use case is a PIR (occupancy/motion) sensor that has been configured (in C-Bus Toolkit) to actuate two group addresses – one for the light in the room (shared with an ordinary wall switch), and which only reports recent movement.
cmqttd doesn’t assign any class to this component, so this can be used however you like. Any brightness value is ignored.
By default, these will have names like
C-Bus Light 001 (as binary sensor)
.
All elements can be renamed and customized from within Home Assistant.
Running in Docker¶
This repository includes a Dockerfile
, which uses a minimal Alpine Linux image as a
base, and contains the bare minimum needed to make cmqttd work.
On a system with Docker installed, clone the libcbus git repository and then run:
# docker build -t cmqttd .
This will download about 120 MiB of dependencies, and result in about 100 MiB image (named
cmqttd
).
The image’s startup script (entrypoint-cmqttd.sh
) uses the following environment variables:
-
TZ
¶ The timezone to use when sending a time signal to the C-Bus network.
This must be a tz database timezone name (eg:
Australia/Adelaide
). The default (and fall-back) timezone is UTC.
-
SERIAL_PORT
¶ The serial port that the PCI is connected to. USB PCIs appear as a serial device (
/dev/ttyUSB0
).Docker also requires the
--device
option so that it is forwarded into the container.This is equivalent to
cmqttd --serial
. Either this orCNI_ADDR
is required.
-
CNI_ADDR
¶ A TCP
host:port
where a CNI is located.This is equivalent to
cmqttd --tcp
. Either this orSERIAL_PORT
is required.See also: Instructions for Wiser users.
-
MQTT_SERVER
¶ IP address where the MQTT Broker is running.
This is equivalent to
cmqttd --broker-address
. This environment variable is required.
-
MQTT_PORT
¶ Port address where the MQTT Broker is running.
This is equivalent to
cmqttd --broker-port
.
-
MQTT_USE_TLS
¶ If set to
1
(default), this enables support for TLS.If set to
0
, TLS support will be disabled. This is equivalent tocmqttd --broker-disable-tls
.
-
CBUS_CLOCK
¶ If set to
1
(default), cmqttd will respond to time requests from the C-Bus network.If set to
0
, cmqttd will ignore time requests from the C-Bus network. This is equivalent tocmqttd --no-clock
.
-
CBUS_TIMESYNC
¶ Number of seconds to wait between sending an unsolicited time signal to the C-Bus network.
If set to
0
, cmqttd will not send unsolicited time signals to the C-Bus network.By default, this will be sent every 300 seconds (5 minutes).
This is equivalent to
cmqttd --timesync
.
The image is configured to read additional files from /etc/cmqttd
, if present. Use
Docker volume mounts to make the following files available:
/etc/cmqttd/auth
Username and password to use to connect to an MQTT broker, separated by a newline character.
If this file is not present, then cmqttd will try to use the MQTT broker without authentication.
This is equivalent to
cmqttd --broker-auth
./etc/cmqttd/certificates
A directory of CA certificates to trust when connecting with TLS.
If this directory is not present, the default (Python) CA store will be used instead.
This is equivalent to
cmqttd --broker-ca
./etc/cmqttd/client.pem
,/etc/cmqttd/client.key
Client certificate (
pem
) and private key (key
) to use to connect to the MQTT broker.This is equivalent to
cmqttd --broker-client-cert
andcmqttd --broker-client-key
./etc/cmqttd/project.cbz
C-Bus Toolkit project backup file to use as a source for labelling group addresses.
This is is equivalent to
cmqttd --project-file
.
Note
All file and directory names are case-sensitive, and must be lower case.
Docker usage examples¶
To use a PCI on /dev/ttyUSB0
, with an unauthenticated and unencrypted MQTT Broker at
192.0.2.1
, and the time zone set to Australia/Adelaide
:
# docker run --device /dev/ttyUSB0 -e "SERIAL_PORT=/dev/ttyUSB0" \
-e "MQTT_SERVER=192.0.2.1" -e "MQTT_USE_TLS=0" \
-e "TZ=Australia/Adelaide" cmqttd
To supply MQTT broker authentication details, create an /etc/cmqttd/auth
file to be
shared with the container as a Docker volume:
# mkdir -p /etc/cmqttd
# touch /etc/cmqttd/auth
# chmod 600 /etc/cmqttd/auth
# echo "my-username" >> /etc/cmqttd/auth
# echo "my-password" >> /etc/cmqttd/auth
Then to use these authentication details, with TLS enabled:
# docker run --device /dev/ttyUSB0 -e "SERIAL_PORT=/dev/ttyUSB0" \
-e "MQTT_SERVER=192.0.2.1" -e "TZ=Australia/Adelaide" \
-v /etc/cmqttd:/etc/cmqttd cmqttd
If you want to run the cmqttd
daemon in the background, on the same device
as a Home Assistant server with the MQTT broker add-on:
# docker run -dit --name cbus --restart=always \
--device /dev/ttyUSB0 --network hassio \
-e "TZ=Australia/Adelaide" -e "BROKER_USE_TLS=0" \
-e "SERIAL_PORT=/dev/ttyUSB0" \
-e "MQTT_SERVER=core-mosquitto" \
cmqttd
Note
You can verify the hostname of hassio’s MQTT broker with:
# docker inspect addon_core_mosquitto
If you want to run the daemon manually with other settings, you can run cmqttd
manually within
the container (ie: skipping the start-up script) with:
# docker run -e "TZ=Australia/Adelaide" cmqttd cmqttd --help
Note
When running without the start-up script:
- you must write
cmqttd
twice: first as the name of the image, and second as the program inside the image to run. - none of the environment variables (except
TZ
) are supported – you must use cmqttd command-line options instead. - files in
/etc/cmqttd
are not used unless equivalent cmqttd command-line options are manually specified.