MQTT Home Assistant - IoT
The bridge normalises KNX telegrams into structured messages that can be consumed by IoT transports (MQTT, REST, Modbus) and accepts flow inputs to write back to the KNX bus. It mirrors the runtime logic of the Node-RED editor help and shows how to hook the node to third-party connectors.
Operating mode
The node has a Mode selector:
- IoT bridge (default) — the behaviour described below: a list of mappings that turn KNX telegrams into MQTT/REST/Modbus output messages and back.
- MQTT / Home Assistant (native) — the node connects directly to an MQTT broker and bridges KNX ↔ MQTT both ways, publishing Home Assistant MQTT Discovery so KNX appears automatically in Home Assistant. No
mqtt in/mqtt outwiring is needed.
MQTT / Home Assistant mode
Requirements: an MQTT broker reachable by both Node-RED and Home Assistant, with the MQTT integration enabled in HA. All entities are grouped under a single HA device named after the node.
| Field | Purpose |
|---|---|
| KNX bus connection | Stand-alone (default): the node talks to the KNX gateway directly and shows no input/output pins. Flow messages: the node exposes an input pin and an output pin — wire the output of a KNXUltimate node in Universal mode to the input (KNX bus → MQTT) and the output pin to the input of another KNXUltimate node in Universal mode (MQTT → KNX bus). |
| Broker URL / Username / Password | MQTT broker connection. |
| Base topic | Root of the state/command topics (default knx-ultimate). |
| Publish HA discovery / Discovery prefix | Enable Home Assistant MQTT Discovery and set its prefix (default homeassistant). |
| Entity name format | How the HA entity names are built from the ETS import, whose names start with the group-address path, e.g. (Lights->Ground floor) Living room. Options: As imported from ETS (default), Name first (Living room (Lights->Ground floor)), Name only (Living room), Name + group address (Living room (0/1/2)). |
| Group addresses to expose | Checkbox list of every address imported in the gateway (ETS). Ticked addresses become HA entities, typed automatically from the DPT (switch, sensor, binary_sensor, number, text). Filter + Select all / none; all selected by default. Each row also has a Read only toggle: a read-only address is still published to Home Assistant (state visible) but never accepts commands back to the KNX bus (switches become binary_sensors, numbers become sensors). The Set read only / Clear read only buttons apply it to all currently shown addresses. |
| Covers & Thermostats | Composite entities that aggregate several addresses (see below). |
Covers & Thermostats
Covers and thermostats combine several group addresses into one HA entity, so they can’t be derived from a single DPT - add them in the list:
- Cover: Up/Down GA (1.008), optional Stop GA (1.007), optional Set/Status position GA (5.001). Invert position maps KNX (0% = open) to Home Assistant (100% = open).
- Thermostat: current temperature GA (9.001), setpoint set/status GA (9.001), optional On/Off GA (1.001 → off/heat), plus min/max temperature and step.
Datapoint types are read from the ETS import when available, otherwise from KNX defaults. For reliable status, the addresses used by covers/thermostats should be present in the ETS import.
Native KNX integration vs MQTT bridge. If Home Assistant already talks to KNX through its built-in KNX integration, covers/climate are configured there with group addresses and this MQTT bridge is not needed. Use this mode when Node-RED owns the KNX bus and Home Assistant sees everything over MQTT.
Mapping recap
| Field | Purpose | Notes |
|---|---|---|
| Label | Friendly name | Used in the status text and msg.bridge.label. |
| GA / DPT | KNX group address and datapoint | Set via ETS CSV autocomplete or manually. |
| Direction | KNX→IoT, IoT→KNX, Bidirectional | Determines which pins are active. |
| Channel type | MQTT / REST / Modbus | Changes the meaning of Target. |
| Target | Topic, base URL or register address | Leave empty to fall back to the node outputtopic. |
| Template | String payload formatter | Use placeholders {{value}}, {{ga}}, {{type}}, {{target}}, {{label}}, {{isoTimestamp}}. |
| Scale / Offset | Numeric conversion | Applied KNX→IoT; inverse is used IoT→KNX. |
| Timeout / Retry | Pass-through hints | Convey the desired retry/window to downstream nodes. |
Typical transports
MQTT broker
- Publishing: wire output 1 to the core
mqtt outnode. The bridge setsmsg.topicandmsg.payloadso you can publish directly. - Subscribing: connect a core
mqtt innode to the bridge input. Payloads are converted according to the mapping and written to KNX. The ack on output 2 confirms the write.REST API
- Bridge output 1 into the core
http requestnode (or contrib nodes such asnode-red-contrib-http-request). - The bridge copies
bridge.methodtomsg.methodand the formatted template tomsg.payloadso you can push JSON payloads or form data to webhooks.Modbus registers
- Pair the bridge with
node-red-contrib-modbusmodbus-flex-writeormodbus-writenodes. - Use the mapping
Targetas the Modbus address/identifier. Output 1 exposes the processed value undermsg.payloadand the metadata inmsg.bridge.Example flows
KNX → MQTT status topic
```json
[ { “id”: “bridge1”, “type”: “knxUltimateIoTBridge”, “z”: “flow1”, “server”: “gateway1”, “name”: “Light bridge”, “emitOnChangeOnly”: true, “readOnDeploy”: true, “acceptFlowInput”: true, “mappings”: [ { “id”: “map-light”, “enabled”: true, “label”: “Living light”, “ga”: “1/1/10”, “dpt”: “1.001”, “direction”: “bidirectional”, “iotType”: “mqtt”, “target”: “knx/light/living”, “method”: “POST”, “modbusFunction”: “writeHoldingRegister”, “scale”: 1, “offset”: 0, “template”: “{{value}}”, “property”: “”, “timeout”: 0, “retry”: 0 } ], “wires”: [[“mqttOut”],[“debugAck”]] }, { “id”: “mqttOut”, “type”: “mqtt out”, “name”: “MQTT status”, “topic”: “”, “qos”: “0”, “retain”: “false”, “broker”: “mqttBroker”, “x”: 520, “y”: 120, “wires”: [] }, { “id”: “debugAck”, “type”: “debug”, “name”: “KNX ack”, “active”: true, “tosidebar”: true, “complete”: “true”, “x”: 520, “y”: 180, “wires”: [] } ]
### MQTT command → KNX feedback
```json
[
{
"id": "mqttIn",
"type": "mqtt in",
"name": "MQTT command",
"topic": "knx/light/living/set",
"qos": "1",
"datatype": "auto",
"broker": "mqttBroker",
"x": 140,
"y": 200,
"wires": [["bridge1"]]
}
]
Combine both snippets in the same flow to round-trip KNX ↔ MQTT with acknowledgements.
REST snapshot payload
{
"id": "bridge-rest",
"type": "knxUltimateIoTBridge",
"name": "Power meter bridge",
"mappings": [
{
"label": "Total active power",
"ga": "2/1/20",
"dpt": "9.024",
"direction": "knx-to-iot",
"iotType": "rest",
"target": "https://example/api/knx/power",
"method": "POST",
"template": "{\"value\":{{value}},\"ga\":\"{{ga}}\",\"ts\":\"{{isoTimestamp}}\"}"
}
]
}
Pipe output 1 into an http request node pointing at the same URL. Use the response to log success or retry via the bridge metadata (bridge.retry).
Modbus register write
- Mapping:
Target = 40010,Channel type = Modbus,Direction = Bidirectional. - Place a
modbus-flex-writenode fromnode-red-contrib-modbusafter output 1 and forwardmsg.payloadinto itsvalueproperty. - Use the ack output to confirm KNX writes when an automation updates the Modbus register first.
Tips & troubleshooting
- Leaves
Targetempty to inherit the nodeoutputtopicif you plan to drive multiple mappings into the same MQTT/REST entry point. emitOnChangeOnlyis useful for High frequency sensors; disable it when you need every telegram (e.g., counters).- Output 2 always mirrors the original
msg.payloadreceived from the IoT side underbridgemetadata—log it to diagnose scaling issues. - For Modbus floats, pair the bridge with a
functionnode to convert to the register format required by your specific device (e.g., 16-bit vs 32-bit). Happy bridging!
- Leaves