Currently Home Assistant only polls for Hue motion sensor data every 5 seconds which makes motion events slow and unusable for automatic lights and other automations. There was an open pull-request to make this interval configurable but it was declined and closed by HA's founder balloob:

I sort of get it. Hue should release methods for real-time data but I doubt that is going to happen anytime soon if at all. In the mean time I keep taking out the garbage and having my driveway lights not turn on until I am almost all the way down my driveway (oh god, first world problems).

We will be using a Node-RED flow utilizing the node-red-contrib-huemagic library to capture the events and turn them into MQTT messages that Home Assistant will be listening for.

This can be a flawless transition if you rename the existing motion sensor (by giving it a suffix like _original) and doing the swap of the entity ID with the new MQTT sensor. This way you don't have to update the entity ID in all of your flows/automations or groups.

Requirements

  • Home Assistant
  • Node-RED
  • MQTT broker installed (I have guide for installing Mosquitto MQTT in Unraid here)
  • node-red-contrib-huemagic library installed in Node-RED
  • Hue indoor or outdoor motion sensor.

Setup

Node-RED


Here is the flow I use to turn these motion events into MQTT messages:

[{"id":"e284427b.261a5","type":"hue-motion","z":"ff717302.0c688","name":"Hue motion sensor 1","bridge":"d2b1d65b.cbe438","sensorid":"9","x":260,"y":1820,"wires":[["fbb3fa7c.cc67e8"]]},{"id":"713b2e63.684c7","type":"hue-motion","z":"ff717302.0c688","name":"Hue outdoor motion sensor 1","bridge":"d2b1d65b.cbe438","sensorid":"12","x":240,"y":1860,"wires":[["fbb3fa7c.cc67e8"]]},{"id":"fbb3fa7c.cc67e8","type":"function","z":"ff717302.0c688","name":"","func":"var sensorMqttChannelMappings = { // sensor_id: mqtt_channel\n    9: 'sensors/driveway/motion',\n    12: 'sensors/frontdooroutside/motion'\n};\n\nif(msg.info && msg.info.id && typeof msg.payload.motion !== 'undefined') {\n    for(var sensor_id in sensorMqttChannelMappings) {\n        if(sensor_id != msg.info.id) continue;\n        var newMsg = {};\n        newMsg.topic = sensorMqttChannelMappings[sensor_id];\n        newMsg.payload = msg.payload.motion; // reset sensor back to 0\n        node.status({\n            fill: newMsg.payload ? \"green\" : \"red\",\n            shape: \"dot\",\n            text: newMsg.topic\n        });\n        return [newMsg];\n    }\n}","outputs":1,"noerr":0,"x":450,"y":1840,"wires":[["57f6ee2e.54e4f","44867d57.a0cc34"]]},{"id":"57f6ee2e.54e4f","type":"debug","z":"ff717302.0c688","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":630,"y":1860,"wires":[]},{"id":"44867d57.a0cc34","type":"mqtt out","z":"ff717302.0c688","name":"","topic":"","qos":"","retain":"true","broker":"5a59e251.9e1d4c","x":630,"y":1820,"wires":[]},{"id":"c625eba6.8dc8d8","type":"comment","z":"ff717302.0c688","name":"Hue Motion Sensor to MQTT","info":"","x":480,"y":1780,"wires":[]},{"id":"d2b1d65b.cbe438","type":"hue-bridge","z":"","name":"Home Hue Bridge","bridge":"192.168.1.142","key":"-P3euEiGIF6D4pb6TD1WE2ECJzrkR7RNpyUn5Pic","interval":"2000"},{"id":"5a59e251.9e1d4c","type":"mqtt-broker","z":"","name":"","broker":"192.168.1.10","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","willTopic":"","willQos":"0","willPayload":""}]

If you haven't setup your bridge in one of the MagicHue node's you will need to double click the node and set it up and choose which sensor you want to use (I have two in mine but you can have as little or many as you want).

There is a debug node in this flow just to help you see if things are working. Once you see messages coming through on MQTT you can delete this node or disable it. You can verify messages are being sent by connecting to your MQTT server with the HiveMQ Websocket Client and subscribing to the target topic(s).

You will then need to update the sensorMqttChannelMappings variable with the mappings of your sensors to MQTT channels. You can get the sensor ID number by editing the Hue Motion node after you save it and it will show the ID instead of the name. Here is what my setup looks like (and what you will see when you open it up):

var sensorMqttChannelMappings = { // sensor_id: mqtt_channel
    9: 'sensors/driveway/motion',
    12: 'sensors/frontdooroutside/motion'
};

Home Assistant

Now we are ready to set it up in Home Assistant. Here is an example from my configuration.yaml file for two motion sensors (this will need to be changed to match your setup):

binary_sensor:
  - platform: mqtt
    state_topic: 'sensors/driveway/motion'
    name: 'Driveway Motion'
    qos: 0
    payload_on: "1"
    payload_off: "0"
    value_template: '{{ value }}'
    device_class: 'motion'
  - platform: mqtt
    state_topic: 'sensors/frontdooroutside/motion'
    name: 'Front Door Motion'
    qos: 0
    payload_on: "1"
    payload_off: "0"
    value_template: '{{ value }}'
    device_class: 'motion'

Conclusion

And that is it! You should now have motion events that occur in near real-time in Home Assistant. I wish there was a native fix for this but at least this works really well for now. The performance is night-and-day difference. The only issue is if you have a lot of Hue motion sensors you could overload your bridge with too many checks. You would either have to turn the interval up (to 2 or 3 seconds) if this started happening or buy another Hue bridge to split the load.

Instead of using the bridge to trigger lights on/off I currently have Home Assistant doing it via Node-RED. This is so I can have switches in Home Assistant to enable/disable this functionality (without disabling the whole motion sensor).

I have written quite a few other articles about Node-RED and Home Assistant. If you liked this one I recommend you check them out. Please feel free to leave a comment if this helped you at all or if you have any questions.