Skip to content

3.3. MQTT client

Rutger Meekers edited this page Jan 9, 2022 · 18 revisions

Introduction

ebusd supports MQTT handling by using the mosquitto library connecting to an MQTT broker. In order to use it, a running mosquitto instance (see mosquitto.org) or any other MQTT 3.1 compliant broker is necessary.

To enable MQTT support, a corresponding build is necessary and the MQTT port needs to be enabled (see --mqttport). The MQTT topic published to (and also subscribed to) can be adjusted by using the --mqtttopic option and defaults to "ebusd/%circuit/%name" where "%circuit" is replaced by the circuit name and "%name" by the message name. You can use --mqttuser and --mqttpass for MQTT authentication.

When MQTT is activated and the broker connection was established successfully, ebusd publishes to the topic all messages that match the default access level or that of the user "mqtt" (see --aclfile). The format is either strings comparable to the read command output, or JSON when --mqttjson is enabled.

In addition to the message specific topics, ebusd also feeds the following general topics (where the "ebusd" prefix depends on how the topic is configured):

  • ebusd/global/version: the version string of ebusd (retained)
  • ebusd/global/running: true as long as ebusd is running (retained and set to false as last will)
  • ebusd/global/uptime: the up time in seconds
  • ebusd/global/signal: true or false depending on the signal state (retained and set to false when ebusd is stopped)
  • ebusd/global/scan: "OK", "running", or "finished" scan status (retained)
  • ebusd/global/updatecheck: the result of the update check (retained)

Due to the subscription to the topic, ebusd also allows actively sending messages on the eBUS. This is supported by using a specific suffix to the topic:

  • /get: initiates an active refresh of a read message from the eBUS.
    When the message was read, ebusd send the corresponding topic to MQTT.
  • /set: allows to send a write message to the eBUS (if the access level allows it, see above).
  • /list: publishes all messages known so far (according to access level, see above).

For /get and /set suffixes, the optional message payload can be used to transfer additional input data, e.g. the values to be set for a write message or the needed input for a read message, separated by semicolon.

In addition to that, appending a question mark and a poll priority digit allows adjusting the poll priority for read messages and enables automatic polling. For example, using mosquitto_pub -m '?3' -t 'ebusd/uih/YieldSum/get' would set the uih/YieldSum message to be polled with priority 3 and is equivalent to issuing ebusctl -c uih -p 3 YieldSum.

For the /list suffix, an non-empty message payload leads to publishing only those messages that were already sent or received before (by any instance). If message payload is null or has a length of zero, messages not yet seen before will be sent with a zero message payload.
Furthermore, the topic may also be incomplete, i.e. contain less parts for addressing all messages or all messages of a certain device only. Please note that the global topic prefix is not published again by the /list suffix.

Using local mosquitto server to exchange MQTT messages with remote MQTT broker

In order to use an existing MQTT broker to exchange MQTT messages between the two systems one can bridge the local mosquitto to an upstream MQTT broker. The example configuration snippet (to be placed in /etc/mosquitto/conf.d) below creates a bridge to a RabbitMQ broker. This approach might also be a solution if ebusd is not able to use the RabbitMQ broker directly.

# example configuration for bridging a RabbitMQ broker using a _non-encrypted_ connection
connection Rabbit

# If try_private is set to true, the bridge will attempt to indicate to the remote broker that it is a bridge not an ordinary client.
# If successful, this means that loop detection will be more effective and that retained messages will be propagated correctly. 
# Not all brokers support this feature so it may be necessary to set try_private to false if your bridge does not connect properly.
try_private false

# RabbitMQ server configuration, change IP address and add username/password if necessary
address RABBITMQ_SERVER_IP_OR_HOSTNAME
remote_clientid mosquitto_krypton
remote_username RABBITMQ_USERNAME
remote_password RABBITMQ_PASSWORD

# MQTT tweaks (works for me(tm))
bridge_attempt_unsubscribe false
bridge_protocol_version mqttv311
bridge_insecure true

# forward ebusd MQTT messages between mosquitto server and RabbitMQ server
# using prefix 'krypton' on RabbitMQ server instance
# Note: in this example 'krypton' is the hostname of a host running
#       ebusd service allowing us to easily distinguish between multiple sources
topic # both 2 ebusd/ krypton/ebusd/

Replace RABBITMQ_SERVER_IP_OR_HOSTNAME, RABBITMQ_USERNAME, RABBITMQ_PASSWORD and prefix krypton with values matching your environment. Save configuration snippet e.g. as /etc/mosquitto/conf.d/rabbit.conf and restart mosquitto server.

See also https://mosquitto.org/man/mosquitto-conf-5.html for details on used configuration settings above.