IoT Automation

Homebridge MQTT: Bringing MQTT Devices into Apple Home

Expose MQTT sensors, switches and lights as HomeKit accessories with Homebridge and the mqttthing plugin, including JSON payloads, TLS credentials and a sensible topic layout.

Homebridge MQTT bridge turning cloud broker topics into Apple Home accessories on an iPhone
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

Homebridge MQTT integration lets you control DIY sensors, relays and lights from the Apple Home app and Siri, even though HomeKit itself knows nothing about MQTT. In this tutorial you will install the mqttthing plugin, map topics to HomeKit characteristics for a temperature sensor, a switch, a dimmable light and a contact sensor, handle JSON payloads, and move the setup onto a private TLS broker.

How Homebridge Talks to MQTT

Homebridge is a Node.js server that emulates HomeKit accessories. Plugins provide the actual device logic. The most widely used MQTT plugin, homebridge-mqttthing, lets you declare an accessory in JSON and map each HomeKit characteristic to an MQTT topic: a get topic that Homebridge subscribes to for the current value, and a set topic it publishes to when you tap a tile or ask Siri.

 Apple Home / Siri
        |
   (HomeKit, LAN)
        |
    Homebridge  --  homebridge-mqttthing
        |
   (MQTT over TLS)
        |
   MQTT broker  <-->  ESP32, Tasmota, Zigbee2MQTT, scripts

Because the devices only ever talk to the broker, they can live on another network or another site. Homebridge only needs outbound access to the broker. If you want the background on this pattern first, the article on what an MQTT broker does explains publish and subscribe in plain terms.

Installing the mqttthing Plugin

If you use the Homebridge UI (the default in official images), open Plugins, search for mqttthing and install Homebridge Mqttthing. From the command line on a Homebridge host:

sudo npm install -g homebridge-mqttthing
sudo hb-service restart

Accessories are defined in the accessories array of config.json. The UI includes a form-based editor for the plugin, but the raw JSON is clearer for learning, so the examples below use it. You can paste them into Config > JSON Config.

A First Homebridge MQTT Accessory: Temperature Sensor

Start with the public test broker so you can watch everything happen. Pick a random string (here h3m8x2) to keep your topics separate in the shared public area.

{
  "accessory": "mqttthing",
  "type": "temperatureSensor",
  "name": "Greenhouse Temperature",
  "url": "mqtt://broker.connectmq.com:1883",
  "mqttOptions": { "clientId": "hb-gh-temp-h3m8x2" },
  "topics": {
    "getCurrentTemperature": "connectmq/demo/h3m8x2/greenhouse/temperature"
  },
  "logMqtt": true
}

Save, restart Homebridge, then publish a reading:

mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-h3m8x2 \
  -t 'connectmq/demo/h3m8x2/greenhouse/temperature' -m '23.5' -r

The tile in Apple Home updates within a second. The -r flag makes the message retained, so after a Homebridge restart the last value is delivered immediately instead of the tile showing "No Response" until the next reading.

Switches and Lights with Commands

Controllable accessories need both a get and a set topic. Using separate topics for commands and confirmed state is good practice: Homebridge publishes the request, the device acts, and the device publishes its real state back.

{
  "accessory": "mqttthing",
  "type": "switch",
  "name": "Vent Fan",
  "url": "mqtt://broker.connectmq.com:1883",
  "mqttOptions": { "clientId": "hb-fan-h3m8x2" },
  "topics": {
    "getOn": "connectmq/demo/h3m8x2/greenhouse/fan/state",
    "setOn": "connectmq/demo/h3m8x2/greenhouse/fan/set"
  },
  "onValue": "ON",
  "offValue": "OFF"
}

A dimmable light adds a brightness characteristic:

{
  "accessory": "mqttthing",
  "type": "lightbulb",
  "name": "Grow Light",
  "url": "mqtt://broker.connectmq.com:1883",
  "mqttOptions": { "clientId": "hb-light-h3m8x2" },
  "topics": {
    "getOn": "connectmq/demo/h3m8x2/greenhouse/light/state",
    "setOn": "connectmq/demo/h3m8x2/greenhouse/light/set",
    "getBrightness": "connectmq/demo/h3m8x2/greenhouse/light/brightness",
    "setBrightness": "connectmq/demo/h3m8x2/greenhouse/light/brightness/set"
  },
  "onValue": "ON",
  "offValue": "OFF"
}

Watch what Homebridge sends while you tap the tiles:

mosquitto_sub -h broker.connectmq.com -p 1883 -i mon-h3m8x2 \
  -t 'connectmq/demo/h3m8x2/greenhouse/#' -v

Handling JSON Payloads

Many devices publish one JSON document with several values rather than one topic per value. mqttthing accepts a topic object with an apply function, a short JavaScript body that receives message and returns the value to use.

{
  "accessory": "mqttthing",
  "type": "contactSensor",
  "name": "Greenhouse Door",
  "url": "mqtt://broker.connectmq.com:1883",
  "mqttOptions": { "clientId": "hb-door-h3m8x2" },
  "topics": {
    "getContactSensorState": {
      "topic": "connectmq/demo/h3m8x2/greenhouse/telemetry",
      "apply": "return JSON.parse(message).door === 'open' ? 1 : 0;"
    }
  }
}

HomeKit's contact sensor uses 0 for detected (closed) and 1 for not detected (open), which is why the function maps open to 1. The same technique works on set topics to wrap a command in JSON, for example "apply": "return JSON.stringify({state: message});".

Mapping Common Device Types

HomeKit type (type) Key topics Typical payload
temperatureSensor getCurrentTemperature 23.5
humiditySensor getCurrentRelativeHumidity 64
switch / outlet getOn, setOn ON / OFF with onValue and offValue
lightbulb getOn, setOn, getBrightness, setBrightness ON, 0-100
contactSensor getContactSensorState 0 closed, 1 open
motionSensor getMotionDetected true / false
leakSensor getLeakDetected 0 / 1

The plugin supports many more types, including garage doors, thermostats, fans and window coverings. Each has its own characteristic names; the plugin's README lists them all.

Connection Count and Client IDs

Every mqttthing accessory opens its own MQTT connection. Ten accessories therefore mean ten clients on the broker, each needing a unique client ID. Two consequences follow:

  1. Give every accessory its own clientId in mqttOptions. Duplicate IDs make the broker disconnect the earlier session, and accessories flicker between responding and not responding.
  2. Count connections against your plan. The ConnectMQ free Serverless plan allows up to 25 concurrent connections, which covers Homebridge plus a modest number of devices. Larger setups fit the paid Serverless plan with up to 1,000.

If you need many accessories on a single connection, consider letting Home Assistant or Node-RED own the broker connection and expose HomeKit through their own HomeKit bridges.

Production: TLS and Credentials

Anything in the public test area can be read by anyone who guesses the topic, and someone could also publish to your set topics. Before controlling real equipment, create a private broker and switch every accessory to TLS:

{
  "accessory": "mqttthing",
  "type": "switch",
  "name": "Vent Fan",
  "url": "mqtts://broker.connectmq.com:8883",
  "username": "YOUR_USERNAME",
  "password": "YOUR_PASSWORD",
  "mqttOptions": { "clientId": "YOUR_CLIENT_ID" },
  "topics": {
    "getOn": "site1/greenhouse/fan/state",
    "setOn": "site1/greenhouse/fan/set"
  },
  "onValue": "ON",
  "offValue": "OFF"
}

Node.js trusts the Let's Encrypt chain used by ConnectMQ out of the box, so no CA file is required. On ConnectMQ, client IDs are bound to the credentials issued in the portal, so when you need several connections, issue a credential set per accessory group and keep track of which ID belongs where.

Running mqttthing as a Child Bridge

Homebridge can run a plugin as a child bridge: a separate process with its own HomeKit pairing. Enabling it for mqttthing (in the plugin settings, Bridge Settings) has two practical benefits. A crash or misbehaving accessory definition no longer takes down every other plugin, and restarting the child bridge after editing topics is faster than restarting all of Homebridge. You pair the child bridge once in the Home app, and accessories added to it later appear automatically.

It is also worth publishing a retained availability topic from each device with a last will of offline. mqttthing can use it through the getOnline topic together with onlineValue and offlineValue, so Apple Home shows a device as not responding when it really is offline instead of displaying a stale value.

Troubleshooting Homebridge MQTT

  • Accessory shows No Response. No value has arrived on the get topic since Homebridge started. Publish retained state from devices, or check the topic for typos with logMqtt: true.
  • Tile toggles back by itself. The device is not publishing its new state on the get topic, or publishes a value that does not match onValue.
  • Constant reconnect messages in the log. Duplicate client IDs or wrong credentials. Look for Connection refused and the reason in the Homebridge log.
  • Siri says the device is not responding but the app works. Usually a HomeKit hub (Apple TV or HomePod) issue rather than MQTT; check that the hub can reach Homebridge on the LAN.

Where to Go Next

Homebridge gives you the Apple side; the devices still need to publish sensible topics. The ESPHome MQTT guide shows how to build sensors that publish state and accept commands, and the smart home MQTT topic structure article helps you design topics that stay manageable. If Home Assistant runs alongside Homebridge, see Home Assistant with an external MQTT broker. For the broader context of combining devices and logic, read the IoT automation guide, and to understand why a hosted MQTT broker beats a broker on the Homebridge Pi for remote access, compare the options there.

Connect Homebridge to ConnectMQ

ConnectMQ gives Homebridge a private, TLS-secured broker reachable from any network, with a live topic explorer to debug your accessories as you configure them. Create a free Serverless broker at app.connectmq.com, no credit card needed, and paste the generated credentials into your mqttthing accessories.

Frequently Asked Questions

Does HomeKit support MQTT natively?

No. HomeKit uses its own accessory protocol, so you need a bridge such as Homebridge with an MQTT plugin to translate between the two.

Can I control Homebridge MQTT devices when I am away from home?

Yes, through a HomeKit home hub as usual. Because the devices talk to a cloud broker, they can even be at a different site from Homebridge.

Why do my sensors show No Response after a restart?

Homebridge has not yet received a value. Publish state messages with the retain flag so the broker delivers the last value as soon as Homebridge subscribes.

Is mqttthing the only Homebridge MQTT plugin?

No, but it is the most general one. Other plugins target specific ecosystems such as Zigbee2MQTT or Tasmota and can be simpler if you use only those devices.

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.