Pop search terms in here.

Feed the Birds

Hubitat to MQTT

I've been developing drivers for various Zigbee devices for the Hubitat platform, but some devices can be a right pain in the bum. Foolishly, I decided to control my lights with Xiaomi's Aqara range of wireless remote switches. This was after literal years of pain with their wired switches, so you would have thought I'd have learned. Seems not.

If you followed that third link, you'll have seen it takes you to the Zigbee2MQTT supported devices page, which should give you a clue as to how well my efforts went. The switches would work absolutely perfectly, right up until the point that they would quietly and randomly drop from the Zigbee mesh, causing everyone in the house to shout at me.

I finally decided that I'd had enough, so familiarised myself with MQTT and created what I called a "routing driver" which creates and updates native Hubitat devices from the output of Zigbee2MQTT, neatly side-stepping all those Zigbee issues by making them Somebody Else's Problem.

The lightswitch of despair.

In the process I decided that I really liked MQTT, and started using it as a means of triggering actions on devices, such as turning on a camera display in the kitchen when a doorbell is pressed. It's a great, lightweight way to get messages around a network. And the internet, should you wish!

Hubitat Doesn't Do MQTT. Sort of.

Trick is, I'd spent all that time nicely integrating a bunch of devices with Hubitat, which is my preferred automation platform due to all the legacy AlertMe kit around the place. Just as there was no established means of integrating MQTT in to Hubitat, there's no built-in way to get the device information out via MQTT either.

(This isn't really true, as MQTT subscription and publishing is provided by the Hubitat platform itself, it's just not wrapped up in a way any typical non-developer would be willing to engage with.)

However, Hubitat does have a Maker API app built-in. The expected means of "push" exporting device activity is via HTTP(S) using POST. If only something could listen to that.

The Hubitat Maker API

Receive With Nginx

Another favourite bit of software, nginx will absolutely listen to these POST messages. The simplest means for me to get the desired outcome was to use an Nginx server, which was already running some services in the house, and its libnginx-mod-http-lua module to run a few lines of Lua which passes the body of Hubitat's POST message to a Bash shell script.

server {

  listen 5000;

  location / {

    content_by_lua_block {
      ngx.req.read_body()
      local body = ngx.req.get_body_data()
      os.execute("/opt/hubitat2mqtt/hubitat2mqtt.sh " .. body)
    }

  }

  access_log off;

}

The shell script deals with rearranging the content into JSON which is then sent to the MQTT broker using Mosquitto.

#!/usr/bin/env bash

## hubitat2mqtt.sh v1.01 (23rd June 2025)
##  Converts the HTTP POST output of Hubitat's Maker API into valid JSON,
##  then publishes that data with the same topic format as Zigbee2MQTT.

broker="192.168.1.1"
mqttuser="hubitat2mqtt"
mqttpass="hubitat2mqtt"

# Lose the wrapping.
data=$(echo "$1" | sed 's/{//g; s/}//g' )
data=${data#content:}

# Split the pairs into an array.
IFS=',' read -r -a pairs <<< "$data"
declare -A arr
for pair in "${pairs[@]}"; do
  IFS=':' read -r key value <<< "$pair"
  arr[$key]=$value
done

# Muddle the array into valid notation.
json="{"
for key in "${!arr[@]}"; do
  value=${arr[$key]}
  if [[ $value =~ ^-?[0-9]+(\.[0-9]+)?$ ]] || [[ $value == "null" ]]; then
    json+="\"$key\":$value,"
  else
    value=$(echo "$value" | sed 's/"/\\"/g')
    json+="\"$key\":\"$value\","
  fi
done
json="${json%,}"
json+="}"

# Grab the device name.
name=$(echo $json | jq -r '.displayName')

# Publish!
mosquitto_pub -h "$broker" -u "$mqttuser" -P "$mqttpass" -t "hubitat2mqtt/$name" -m "$json"

exit 0

The latest version of this should be hubitat2mqtt.sh on GitHub.

Opened Data

This little tangle of computer spaghetti lets me open up selected devices connected to Hubitat for the whole network to receive via the Mosquitto broker. They can be controlled through the Maker API's usual endpoints, while their status can be viewed using MQTT.

A better way to have done this would have been to create a Hubitat app instead. Having written drivers (but never an app) I suppose that may not have been too complicated, but I needed something Good Enough, and Good Enough this is.

It's really very responsive, and hasn't missed a beat since I set it up last year.

← Recent Articles
June 23, 2025