Why I use MQTT

I want devices and services from different vendors to work together. MQTT is an open standard, and Eclipse Mosquitto is an open-source broker. A device publishes a reading to a topic such as haus/test/temperatur. openHAB can subscribe to that topic, and other applications can receive the same reading independently. An application such as openHAB stores the readings separately if you want a history.

  1. DevicePublishes a reading to a topic
  2. MosquittoRoutes the message
  3. openHABSubscribes to the topic and updates the Item
The device sends the reading to the broker. openHAB receives it through its subscription.

Check an existing broker

My Pi 4 with openHABian runs Eclipse Mosquitto 2.0.21. Before changing an existing setup, check the service, listeners and connected clients. A listener on 0.0.0.0 or [::] listens on all addresses for that IP version. Reachability also depends on your network and firewall.

On my home network, two Shelly H&T Gen3 sensors, a Shelly Plus Plug S and HeishaMon for my heat pump connect to the broker. openHAB runs on the same Pi and connects as another client. The battery-powered H&T sensors are easier to spot in the connection log than in a list of current connections.

systemctl is-active mosquitto
dpkg-query -W mosquitto
sudo ss -lntp "( sport = :1883 or sport = :8883 )"
sudo ss -Hnt state established "( sport = :1883 or sport = :8883 )"

If allow_anonymous is true, the broker accepts connections without a user account. Include devices that are only occasionally online when listing clients. Then create MQTT accounts, enter their credentials on the clients and test the connections before turning off anonymous access.

Install Mosquitto on a new system

I already run an MQTT broker on my Pi 4 with openHABian. On an existing system, check the service, listeners and clients first. The following commands are for a fresh setup using the Debian packages.

sudo apt update
sudo apt install mosquitto mosquitto-clients

Create a dedicated MQTT account. The command prompts for its password. The -c option creates a password file and overwrites an existing one. The check in front prevents that. To add accounts to the same file later, use mosquitto_passwd without -c.

sudo test ! -e /etc/mosquitto/praxis.passwd &&
  sudo mosquitto_passwd -c /etc/mosquitto/praxis.passwd mqtt-praxis &&
  sudo chown root:mosquitto /etc/mosquitto/praxis.passwd &&
  sudo chmod 0640 /etc/mosquitto/praxis.passwd

Save these lines in /etc/mosquitto/conf.d/praxis.conf. The first line binds the broker to 127.0.0.1. This works for tests on the Pi and for openHAB running on the same machine.

sudoedit /etc/mosquitto/conf.d/praxis.conf
listener 1883 127.0.0.1
allow_anonymous false
password_file /etc/mosquitto/praxis.passwd
sudo systemctl restart mosquitto && systemctl is-active mosquitto
sudo journalctl -u mosquitto -n 15 --no-pager

For devices on your home network, add a listener in the same file. Replace the example IP with your Pi’s fixed LAN address, restart Mosquitto and enter that address, port 1883 and the MQTT account on the device. Use your trusted home network. Port 1883 carries messages and credentials in clear text without TLS. Leave the port closed on your router and use TLS or an encrypted private connection across untrusted networks.

listener 1883 192.168.1.50

Publish and receive a message

Run the block in a Bash terminal on your Pi and enter the MQTT password you just created. The example reserves the topic haus/test/praxis/temperatur. The broker briefly retains the test value so the subscriber can read it after publishing. The expected output is haus/test/praxis/temperatur 21.5. The block then clears the retained value and removes the temporary credentials.

(
  set -e
  umask 077
  config=$(mktemp -d)
  trap 'rm -f -- "$config/mosquitto_pub" "$config/mosquitto_sub"; rmdir -- "$config"' EXIT
  IFS= read -rs -p "MQTT password: " password
  printf '\n'
  printf '%s\n' '-h 127.0.0.1' '-p 1883' '-u mqtt-praxis' "-P $password" > "$config/mosquitto_pub"
  unset password
  cp -- "$config/mosquitto_pub" "$config/mosquitto_sub"
  export XDG_CONFIG_HOME="$config"
  topic=haus/test/praxis/temperatur
  mosquitto_pub -t "$topic" -q 1 -r -m 21.5
  status=0
  mosquitto_sub -t "$topic" -C 1 -W 5 -v || status=$?
  mosquitto_pub -t "$topic" -q 1 -r -n
  exit "$status"
)

Connect openHAB to the broker

  1. Install the MQTT binding in openHAB. Under Settings → Things, add an MQTT Broker Thing.
  2. Enter 127.0.0.1 if both services are on the same Pi, along with port 1883 and the MQTT account. The Broker Thing should show ONLINE.
  3. Add a Generic MQTT Thing for a device and select the Broker Thing. Set the channel to the device’s state topic, then link an Item to the channel. A state topic is sufficient for a reading. Add a command topic for a device that openHAB needs to control.
  4. For the test, add a Number channel, enter haus/test/praxis/temperatur as the state topic and link a Number Item. Repeat the publish and subscribe test. You should see the value update to 21.5 in openHAB.

The broker is online but no value appears

Check the topic name first. MQTT topic names are case-sensitive. For a device that publishes occasionally, wait for its next message. If a message arrives and the Number channel receives a whole JSON object, the Item may stay empty or keep its previous value.

Extract a number with JSONPath

  1. MQTT message{"temperature": 21.5}
  2. Channel transformationJSONPATH($.temperature)
  3. Number Item21.5
The example JSON message becomes the number 21.5.

Install the JSONPath Transformation add-on if needed. Open the MQTT channel, enable advanced settings and enter JSONPATH($.temperature) under Incoming Value Transformations. $.temperature selects the temperature field directly inside the JSON object. Adapt the path to the message your device actually sends.

Sources