IoT Automation

openHAB MQTT Binding Tutorial: Broker Bridge, Generic Things and Rules

Connect openHAB to an external MQTT broker, model sensors and switches as generic MQTT things, parse JSON payloads and publish from rules, with a TLS setup ready for production.

openHAB MQTT binding connecting a broker bridge thing to sensors and switches through a cloud MQTT broker
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

The openHAB MQTT binding turns any MQTT topic into channels you can link to items, show on dashboards and use in rules. In this tutorial you will connect openHAB to an external broker, define generic MQTT things for a sensor and a switch, parse JSON payloads, publish commands from rules, and harden the setup with TLS and credentials.

How the openHAB MQTT Binding Is Organised

openHAB models MQTT in two layers. The broker bridge (mqtt:broker) is the connection: host, port, TLS, client ID and credentials. Underneath it sit things, each of which describes one device by its topics. The most flexible thing type is the generic MQTT thing (mqtt:topic), where you declare each channel and the state and command topics it uses. Items then link to those channels exactly as they would to any other binding.

Layer Thing type Holds
Connection mqtt:broker (bridge) Host, port, TLS, client ID, username, password, last will
Device mqtt:topic (generic thing) Channels with state and command topics
Device (auto) Home Assistant or Homie things Created from discovery messages
Model Items Linked to channels, used in UI and rules

A single broker bridge can serve hundreds of things, and it uses only one MQTT connection. That matters on plans with connection quotas: openHAB counts as one client however many devices it models.

Install the binding from Settings > Add-on Store > Bindings > MQTT Binding. If your devices send JSON, also install the JSONPath Transformation from the transformations section.

Connecting openHAB to an MQTT Broker

You can create the bridge in the UI (Things > + > MQTT Binding > MQTT Broker) or in a .things file. Text configuration is easier to share and back up, so this tutorial uses it. Create conf/things/mqtt.things:

Bridge mqtt:broker:connectmq "ConnectMQ Broker" [
    host="broker.connectmq.com",
    port=1883,
    secure=false,
    clientID="openhab-r4t8w1",
    lwtTopic="connectmq/demo/r4t8w1/openhab/status",
    lwtMessage="offline",
    lwtRetain=true,
    birthTopic="connectmq/demo/r4t8w1/openhab/status",
    birthMessage="online",
    birthRetain=true
] {
    Thing topic greenhouse "Greenhouse Sensor" {
    Channels:
        Type number : temperature "Temperature" [
            stateTopic="connectmq/demo/r4t8w1/greenhouse/telemetry",
            transformationPattern="JSONPATH:$.temp",
            unit="°C"
        ]
        Type number : humidity "Humidity" [
            stateTopic="connectmq/demo/r4t8w1/greenhouse/telemetry",
            transformationPattern="JSONPATH:$.hum",
            unit="%"
        ]
        Type switch : fan "Vent Fan" [
            stateTopic="connectmq/demo/r4t8w1/greenhouse/fan/state",
            commandTopic="connectmq/demo/r4t8w1/greenhouse/fan/set",
            on="ON",
            off="OFF"
        ]
        Type contact : door "Door" [
            stateTopic="connectmq/demo/r4t8w1/greenhouse/door",
            on="OPEN",
            off="CLOSED"
        ]
    }
}

This connects to the public test broker anonymously. Replace r4t8w1 with your own random string, because the public area is shared and readable by everyone. The client ID must be non-empty and unique; reusing one that another client holds will make both connections drop repeatedly.

Check Settings > Things: the bridge should be ONLINE within a few seconds, followed by the greenhouse thing.

Linking items

Create conf/items/greenhouse.items:

Number:Temperature GH_Temperature "Temperature [%.1f °C]" <temperature> { channel="mqtt:topic:connectmq:greenhouse:temperature" }
Number:Dimensionless GH_Humidity "Humidity [%.0f %%]" <humidity> { channel="mqtt:topic:connectmq:greenhouse:humidity" }
Switch GH_Fan "Vent Fan" <fan> { channel="mqtt:topic:connectmq:greenhouse:fan" }
Contact GH_Door "Door [%s]" <door> { channel="mqtt:topic:connectmq:greenhouse:door" }

Note the channel UID pattern: mqtt:topic:<bridge id>:<thing id>:<channel id>. A typo there is the most common reason an item stays NULL.

Testing the openHAB MQTT Channels

Simulate the device from a terminal:

# sensor reading (JSON parsed by JSONPath)
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-r4t8w1 \
  -t 'connectmq/demo/r4t8w1/greenhouse/telemetry' -m '{"temp":24.6,"hum":71}'

# door contact
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-r4t8w1 \
  -t 'connectmq/demo/r4t8w1/greenhouse/door' -m 'OPEN'

# watch the commands openHAB sends
mosquitto_sub -h broker.connectmq.com -p 1883 -i mon-r4t8w1 \
  -t 'connectmq/demo/r4t8w1/greenhouse/fan/set' -v

Toggle the fan in the openHAB UI and the ON or OFF command appears in the subscriber window. A real device would act on it and publish its new state to fan/state, which openHAB uses to update the item. Keeping command and state topics separate means the UI shows the confirmed state, not just the last click.

Parsing JSON and Formatting Commands

Most modern devices publish JSON. Besides transformationPattern for incoming values, the generic thing supports formatBeforePublish for outgoing ones. For example, a dimmer that expects {"brightness": 40}:

Type dimmer : lamp "Grow Lamp" [
    stateTopic="connectmq/demo/r4t8w1/greenhouse/lamp/state",
    commandTopic="connectmq/demo/r4t8w1/greenhouse/lamp/set",
    transformationPattern="JSONPATH:$.brightness",
    formatBeforePublish="{\"brightness\": %s}",
    min=0,
    max=100
]

Transformations can be chained with the ∩ character in the pattern if you need several steps, for example JSONPath followed by a MAP lookup. Keep chains short; when the logic grows, a rule is easier to debug.

Publishing MQTT Messages from openHAB Rules

Commands linked to channels cover most needs, but sometimes you want to publish to an arbitrary topic, for example to send a schedule to a controller. The broker bridge exposes a publishMQTT action for that. In a DSL rule file conf/rules/greenhouse.rules:

rule "Greenhouse overheat"
when
    Item GH_Temperature changed
then
    val temp = (GH_Temperature.state as QuantityType<Number>).toUnit("°C").doubleValue
    if (temp > 30.0 && GH_Fan.state != ON) {
        GH_Fan.sendCommand(ON)
        val mqtt = getActions("mqtt", "mqtt:broker:connectmq")
        mqtt.publishMQTT("connectmq/demo/r4t8w1/greenhouse/event",
            "{\"event\":\"overheat\",\"temp\":" + temp + "}", false)
    }
end

The same action is available from JavaScript rules through actions.get("mqtt", "mqtt:broker:connectmq"). Avoid publishing to the same topic a channel subscribes to unless you intend to create a loop.

Triggering rules from raw topics

If you only want to react to a message without modelling an item, add a trigger channel to the bridge:

Bridge mqtt:broker:connectmq "ConnectMQ Broker" [ ... ] {
    Channels:
        Type publishTrigger : alarms "Alarms" [
            stateTopic="connectmq/demo/r4t8w1/+/alarm",
            separator="#"
        ]
}

A rule triggered by Channel "mqtt:broker:connectmq:alarms" triggered receives the topic and payload joined by the separator, so one rule can handle alarms from every device.

Production Setup with TLS and Credentials

Before connecting real devices, move off the public test area. Create a private broker, then update the bridge:

Bridge mqtt:broker:connectmq "ConnectMQ Broker" [
    host="broker.connectmq.com",
    port=8883,
    secure=true,
    certificatepin=false,
    publickeypin=false,
    clientID="YOUR_CLIENT_ID",
    username="YOUR_USERNAME",
    password="YOUR_PASSWORD",
    lwtTopic="site1/openhab/status",
    lwtMessage="offline",
    lwtRetain=true
]

ConnectMQ's certificate is issued by Let's Encrypt, which Java trusts by default, so no extra certificate import is needed. Certificate pinning is switched off explicitly because Let's Encrypt certificates are renewed every few months; a pinned certificate would make the bridge reject the broker after the next renewal. Use the client ID exactly as issued, since it is bound to the credentials. For more on locking down the whole system, read the MQTT security best practices.

If you prefer to run your broker locally inside openHAB's network, you can still bridge it to the cloud later, but a fully managed MQTT service removes the need to maintain a separate broker host and lets remote sites and phones reach the same topics.

Showing Device Availability

A generic thing stays ONLINE as long as the bridge is connected, even if the device behind it lost power hours ago. To make that visible, have each device publish a retained online message when it connects and set a retained offline last will. Then add availability settings to the thing:

Thing topic greenhouse "Greenhouse Sensor" [
    availabilityTopic="connectmq/demo/r4t8w1/greenhouse/status",
    payloadAvailable="online",
    payloadNotAvailable="offline"
] {
    // channels as before
}

When the device drops off, the broker publishes its will, openHAB marks the thing OFFLINE and linked items become UNDEF. Rules and dashboards can then distinguish "the sensor reads 0" from "the sensor is gone", which matters a great deal for anything that drives heating, irrigation or alarms.

Troubleshooting Checklist

  1. Bridge stays OFFLINE. Check host and port, and that secure=true is set only with port 8883. Look in openhab.log for the reason code.
  2. Bridge flaps between ONLINE and OFFLINE. Duplicate client ID; another openHAB instance or test tool uses the same one.
  3. Thing ONLINE but item NULL. Wrong channel UID in the item, a topic typo, or the JSONPath add-on is missing. Use log:set DEBUG org.openhab.binding.mqtt in the console to see every received message.
  4. Switch shows UNDEF. The payload does not match on or off exactly; values are case-sensitive.
  5. Commands do nothing. Make sure the device listens on the command topic, and that you are not publishing to its state topic.

Where openHAB Fits in a Wider System

openHAB is one consumer on the broker, not the owner of the data. ESPHome nodes, Tasmota plugs and Zigbee2MQTT can all publish to the same broker, and other tools can read the same topics. The ESPHome MQTT tutorial shows how to publish from YAML-configured devices, and Tasmota MQTT covers flashed smart plugs. For the bigger architectural picture, see the IoT automation guide. And if you are still comparing brokers, the overview of a cloud MQTT broker explains the trade-offs.

Run openHAB on a ConnectMQ Broker

ConnectMQ provides a private MQTT 3.1.1 and 5.0 broker with TLS, generated credentials and a live topic explorer that makes debugging openHAB channels straightforward. Create a free Serverless broker at app.connectmq.com with no credit card, paste the credentials into your bridge, and your openHAB things are online.

Frequently Asked Questions

Does openHAB include its own MQTT broker?

No. Current openHAB versions only provide the client binding, so you need an external broker such as a local Mosquitto instance or a cloud broker like ConnectMQ.

Can openHAB use MQTT 5?

The broker bridge has an mqttVersion parameter that can be set to V5. Version 3.1.1 remains the default and works for nearly all devices.

How many MQTT connections does openHAB use?

One per broker bridge, regardless of how many generic things sit under it. That makes it efficient on connection-limited plans.

Why do my items update but commands are not sent?

The channel probably has no commandTopic, or the item is linked read-only. Add a command topic and confirm with a subscriber that the message is published.

Related articles

Zigbee2MQTT Setup Guide: From Coordinator to Dashboard

Install Zigbee2MQTT with Docker, configure the coordinator and MQTT connection, pair and rename devices, control them over MQTT and view their states on a dashboard, testing first on a free public broker.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.