Setting Up Zigbee2MQTT With HomeAssistant
<img class="introimage" itemprop="image" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/usb_coordinator.jpg" style="display: none"/><div>
<p>I've run a network of Zigbee devices for quite some time now. Although we've got a few wi-fi smart sockets, I <em>prefer</em> Zigbee because it's entirely local and doesn't leave our stuff <a href="https://www.bentasker.co.uk/posts/blog/house-stuff/heating-with-electric-instead-of-gas.html#access-to-the-manufacturers-platform">reliant on someone else's cloud service</a>.</p>
<p>Our setup has been <em>fairly</em> reliable but we periodically have issues with messages getting lost. </p>
<p>This only seems to affect devices which intermittently send (or receive) rather than regularly sending updates. This means that messages for devices like door contacts and <a href="https://www.bentasker.co.uk/posts/blog/house-stuff/adding-remote-start-to-our-ancient-dishwasher.html">fingerbots</a> don't always make it through.</p>
<p>Having used the same co-ordinator for about 5 years, I decided to try and address this issue by switching to a newer and more powerful one.</p>
<p>This post talks about setting <a href="https://www.zigbee2mqtt.io">Zigbee2MQTT</a> up to talk to a Hamgeek HMG-01 Plus and <a href="https://www.home-assistant.io/">Home Assistant</a> (via a <a href="https://en.wikipedia.org/wiki/MQTT">MQTT</a> broker).</p>
<p>Note: I <a href="https://www.bentasker.co.uk/posts/blog/general/migrating-from-homeassistant-os-to-homeassistant-in-docker.html">no longer run HAOS or a Supervised setup</a>, so this post describes setting the relevant components up separately. If you <strong>are</strong> running HAOS/Supervised, there's <a href="https://github.com/zigbee2mqtt/hassio-zigbee2mqtt">an official addon</a> which can be installed instead.</p>
<!-- TEASER_END -->
<hr/>
<h3 id="contents">Contents</h3>
<div class="toc">
<ul>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#contents">Contents</a></li>
<li>
<a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#the-hardware">The Hardware</a><ul>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#the-original-coordinator">The Original Coordinator</a></li>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#the-new-zigbee-bridge">The New Zigbee Bridge</a></li>
</ul>
</li>
<li>
<a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#setup">Setup</a><ul>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#the-plan">The Plan</a></li>
<li>
<a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#connecting-to-mqtt">Connecting to MQTT</a><ul>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#zigbee2mqtt-setup">Zigbee2MQTT Setup</a></li>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#connection-ping-error">Connection Ping Error</a></li>
</ul>
</li>
<li>
<a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#connecting-homeassistant">Connecting HomeAssistant</a><ul>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#auto-discovery-breakage">Auto-Discovery Breakage</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#moving-devices-between-networks">Moving Devices Between Networks</a><ul>
<li>
<a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#updating-home-assistant-config">Updating Home Assistant Config</a><ul>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#button-push-automations">Button Push Automations</a></li>
</ul>
</li>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#unsupported-devices">Unsupported Devices</a></li>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#making-better-use-of-the-mesh">Making Better Use Of The Mesh</a></li>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#disabling-zha">Disabling ZHA</a></li>
</ul>
</li>
<li><a href="https://www.bentasker.co.uk/posts/blog/house-stuff/moving-my-zigbee-network-from-zha-to-zigbee2mqtt.html#conclusion">Conclusion</a></li>
</ul>
</div>
<hr/>
<h3 id="the-hardware">The Hardware</h3>
<h4 id="the-original-coordinator">The Original Coordinator</h4>
<p>We've used the same zigbee coordinator since first getting started - it's a (bare) USB with a CC2531 chip on it:</p>
<p><img alt="Photo of the original coordinator, it's a bare USB stick cable tied onto the front of a metal rack" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/usb_coordinator.jpg"/></p>
<p>I bought the stick about 5 years ago for £15, so we've <em>definitely</em> got our moneys worth out of it.</p>
<p>Use of this stick brings a drawback on top of the message loss: It has to be physically connected to my HomeAssistant instance, restricting my ability to move HomeAssistant between hardware.</p>
<p>So, I wanted the replacement to be network rather than direct attached.</p>
<hr/>
<h4 id="the-new-zigbee-bridge">The New Zigbee Bridge</h4>
<p>The bridge that I ordered is a Hamgeek HMG-01 Plus:</p>
<p><img alt="A photo of the HMG-01 Zigbee to ethernet bridge. It's a small black box with a big black antenna on the back" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/hamgeek_HMG-01.jpg"/></p>
<p>At £75, it was decidedly more expensive than the USB stick that it was replacing but, I hoped, would help with the network's reliability.</p>
<p>The box acts as an ethernet to Zigbee bridge: software wishing to interact with the Zigbee network can connect to a raw TCP port and send messages over that.</p>
<p>It's running <a href="https://github.com/xyzroe/xzg">XZG</a>, which has the ability to connect to a Wireguard VPN and/or to publish directly into a MQTT broker:</p>
<p><img alt="Screenshot of the web interface. There are options for VPN and MQTT on the side" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/xzg_interface.png"/></p>
<p>I <em>had</em> hoped that the MQTT support would mean that I didn't need to run a separate Zigbee2MQTT instance. However, that didn't really pan out (more on that later).</p>
<hr/>
<h3 id="setup">Setup</h3>
<h4 id="the-plan">The Plan</h4>
<p>The initial plan was quite simple:</p>
<ol>
<li>Connect the box to the network</li>
<li>Have it publish into my <a href="https://mosquitto.org/">mosquitto broker</a> (I described setting that up <a href="https://www.bentasker.co.uk/posts/blog/house-stuff/connecting-my-smart-meter-to-influxdb-using-telegraf-and-a-glow-display.html#running-mosquitto">here</a>)</li>
<li>Use <a href="https://www.home-assistant.io/integrations/mqtt#mqtt-discovery">MQTT Discovery</a> to have devices appear in Home Assistant</li>
<li>Move Zigbee devices over</li>
</ol>
<p>The plan involved running the two networks side by side for a little while and manually moving things around.</p>
<p>Manual moves were necessary because switching out a Zigbee coordinator <em>isn't</em> as straightforward as replacing a wifi router - you can't generally just configure it to advertise the original network and have it work.</p>
<p>I was also going to move from using <a href="https://www.home-assistant.io/integrations/zha/">ZHA</a> to using <a href="https://www.zigbee2mqtt.io/">Zigbee2MQTT</a>. This wasn't the result of any particular issues with ZHA (I've been quite happy with it), but simply a reflection of Home Assistant not allowing you to configure more than one ZHA connection at a time: I couldn't run side-by-side <strong>and</strong> use ZHA for both.</p>
<hr/>
<h4 id="connecting-to-mqtt">Connecting to MQTT</h4>
<p>Physically connecting the box to the network was, of course, straight forward. It has DHCP enabled by default, so I just needed to log into <a href="https://www.bentasker.co.uk/posts/blog/general/opnsense-pfsense-fttp-and-1gbps-pppoe.html">my OpnSense Router</a> and look at which IP had been allocated (and make the assignment permanent).</p>
<p>The HMG-01 exposes a simple web-interface which I logged into before configuring it to connect to my Mosquitto instance:</p>
<p><img alt="Screenshot of the MQTT settings page" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/mqtt_settings.png"/></p>
<p>Unfortunately, it failed to do so.</p>
<p>There was no obvious reason for this failure - mosquitto wasn't logging anything untoward, and the HMG's web interface doesn't <em>really</em> do logs (there <em>is</em> a debug console, but it dumps data in hex - not the most convenient thing to use).</p>
<p>The web interface <strong>was</strong> notifying me that there was a firmware update available, so I decided to install that in the hope that it'd fix things.</p>
<p>Unfortunately, installation of <em>that</em> failed too: the progress bar got to about 98% and then just hung, with the HMG-01 going unreachable on the network.</p>
<p>I waited a while and then power cycled it hoping that I hadn't bricked the thing. Thankfully, it came straight back up, albeit still running the old firmware. I tried a firmware update again - this time it didn't hang, but it still didn't manage to install the update.</p>
<hr/>
<h5 id="zigbee2mqtt-setup">Zigbee2MQTT Setup</h5>
<p>Rather than repeatedly banging my head against the same wall, I decided to set up a separate Zigbee2MQTT instance instead. The web interface on the HMG-01 can even generate the necessary configuration for you:</p>
<pre><code class="language-yaml"># Serial settings
serial:
# Location of XZG
port: tcp://192.168.5.174:6638
baudrate: 115200
# Disable Zigbee led?
disable_led: false
# Set output power to max 20
advanced:
transmit_power: 20
</code></pre>
<p>I started by creating somewhere for the config to live:</p>
<pre><code class="language-sh">mkdir -p docker_files/zigbee2mqtt/data
nano docker_files/zigbee2mqtt/data/configuration.yaml
</code></pre>
<p>The <a href="https://www.zigbee2mqtt.io/guide/getting-started/">docs</a> include some extra stuff, so I merged it with what the HMG-01 had given me:</p>
<pre><code class="language-yaml">version: 4
mqtt:
base_topic: zigbee2mqtt
server: mqtt://192.168.5.5:1883
user: zigbee
password: NotMyRealPassword
serial:
port: tcp://192.168.5.174:6638
baudrate: 115200
advanced:
transmit_power: 20
frontend:
enabled: true
homeassistant:
enabled: true
</code></pre>
<p>I then just needed to spin up a container:</p>
<pre><code class="language-sh"># Zigbee2MQTT exposes a web interface on port 8080
docker run \
-d \
--name=zigbee2mqtt \
-v $PWD/docker_files/zigbee2mqtt/data:/app/data \
-p 8080:8080 \
--restart=always \
koenkk/zigbee2mqtt
</code></pre>
<p>The container started up and then <strong>immediately</strong> failed, logging the following:</p>
<pre><code class="language-text">error: z2m: Exiting...
error: z2m: Error: Cannot discover TCP adapters at this time. Specify valid 'adapter' and 'port' in your configuration.
</code></pre>
<p>The cause was <em>reasonably</em> obvious: the <code>zigbee2mqtt</code> docs include an <code>adapter</code> attribute, whilst the config generated by the HMG-01 doesn't.</p>
<p>What <em>wasn't</em> immediately clear, though, is which adapter type I needed to specify: Zigbee2MQTT supports <a href="https://www.zigbee2mqtt.io/guide/adapters/">a variety of types</a>.</p>
<p>The status page on the HMG-01 helped to clear that up:</p>
<p><img alt="Status page says the HMG-01 is rocking a CC26252P7" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/hardware_type.png"/></p>
<p>Cross-referencing that with the Zigbee2MQTT docs shows that it's a <a href="https://www.zigbee2mqtt.io/guide/adapters/zstack.html">zstack</a> adapter, so I updated the <code>serial</code> section of the config file and restarted the docker container:</p>
<pre><code class="language-yaml">serial:
port: tcp://192.168.5.174:6638
baudrate: 115200
adapter: zstack
</code></pre>
<p>Good news! It connected!</p>
<hr/>
<h5 id="connection-ping-error">Connection Ping Error</h5>
<p>Bad news... it only connected for about a minute, and then exited with a new error message</p>
<pre><code class="language-text">Error: SRSP - SYS - ping after 6000ms
</code></pre>
<p><a href="https://www.zigbee2mqtt.io/guide/installation/20_zigbee2mqtt-fails-to-start_crashes-runtime.html#error-srsp-sys-ping-after-6000ms-for-zstack-or-host-fatal-error-for-emberznet">The docs</a> note that this could be a firmware issue:</p>
<blockquote>
<p>If you are using a CC2530 or CC2531; it is a common issue for this adapter to crash (due to its outdated hardware). Reflashing the firmware should fix the problem</p>
</blockquote>
<p>So, I was straight back to having to get the HMG-01 to update its firmware.</p>
<p>In order to try and start from a clean slate, I power cycled the HMG-01, logged in and selected to update the Zigbee firmware:</p>
<p><img alt="Screenshot of the Zigbee update screen in the web interface, the most recent update is 10th July 2024" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/zigbee_ota_update.png"/></p>
<p>This time, it installed and the box rebooted, reporting the new version when it came up.</p>
<p>Next, I installed OS updates, hoping that they wouldn't get stuck this time around:</p>
<p><img alt="Screenshot of the ESP32 updates page, latest update is 14th Sept 2024" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/esp32_update.png"/></p>
<p>It went straight through and, one reboot later, the box was reporting the correct version.</p>
<p>The interface also indicated that Zigbee2MQTT had now successfully connected to it.</p>
<hr/>
<h4 id="connecting-homeassistant">Connecting HomeAssistant</h4>
<p>The next step was to get HomeAssistant looking at MQTT.</p>
<p>This was already <em>mostly</em> set up from when I <a href="https://www.bentasker.co.uk/posts/blog/house-stuff/connecting-my-smart-meter-to-influxdb-using-telegraf-and-a-glow-display.html#linking-to-homeassistant">hooked my Glow IHD up</a>, but to recap:</p>
<ul>
<li>
<code>Settings</code> </li>
<li>
<code>Device and Integrations</code> </li>
<li>
<code>Add Integration</code> </li>
<li><code>MQTT</code></li>
<li><code>MQTT</code></li>
<li>Enter broker details</li>
<li>Hit Submit and then Finish</li>
</ul>
<p>HomeAssistant has MQTT autodiscovery enabled by default, so everything should be in place.</p>
<p>The way that auto-discovery works is simple, but clever: When Zigbee2MQTT adds a new <em>thing</em> it publishes a message into a topic beginning with <code>homeassistant</code>: </p>
<pre><code class="language-text">info: z2m:mqtt: MQTT publish: topic 'homeassistant/light/0x00158d000507f0c1/light/config', payload '{"availability":[{"topic":"zigbee2mqtt/bridge/state","value_template":"{{ value_json.state }}"}],"brightness":true,"brightness_scale":254,"command_topic":"zigbee2mqtt/bedroom_light/set","device":{"hw_version":1,"identifiers":["zigbee2mqtt_0x00158d000507f0c1"],"manufacturer":"Innr","model":"B22 bulb dimmable","model_id":"BY 165","name":"bedroom_light","sw_version":"2.0","via_device":"zigbee2mqtt_bridge_0x00124b002e1249ab"},"effect":true,"effect_list":["blink","breathe","okay","channel_change","finish_effect","stop_effect"],"name":null,"object_id":"bedroom_light","origin":{"name":"Zigbee2MQTT","sw":"2.0.0","url":"https://www.zigbee2mqtt.io"},"schema":"json","state_topic":"zigbee2mqtt/bedroom_light","unique_id":"0x00158d000507f0c1_light_zigbee2mqtt"}'
</code></pre>
<p>HomeAssistant subscribes and creates devices, entities and actions when these messages appear.</p>
<hr/>
<h5 id="auto-discovery-breakage">Auto-Discovery Breakage</h5>
<p>I was ready to add my first zigbee device to the new network - I'd specifically bought a new sensor so that I could test without the complexity of adding something which had previously been on a different network.</p>
<p>After putting the device into pairing mode, I connected to the Zigbee2MQTT web interface and clicked <code>Permit Join</code>. Within seconds, the new device appeared and notifications popped up to say that it had completed interview.</p>
<p>But... the device <strong>didn't</strong> appear in Home Assistant.</p>
<p>Nothing in Home Assistant's UI suggested an issue, the device just wasn't appearing.</p>
<p>I double checked the MQTT integration's configuration (you need to click <code>Reconfigure MQTT</code> to get at the settings) and Auto Discovery was <em>definitely</em> enabled:</p>
<p><img alt="MQTT auto discovery is definitely enabled in HomeAssistant" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/discovery_enabled.png"/></p>
<p>I hadn't changed any of the other settings, so it <em>should</em> have been working.</p>
<p>Home Assistant's log pointed me towards the issue:</p>
<pre><code class="language-text">ERROR (MainThread) [homeassistant.components.mqtt.mixins] Error 'extra keys not allowed @ data['device']['model_id']' when processing MQTT discovery message topic: 'homeassistant/update/0x282c02bfffeac0e6/update/config', message: '{'availability': [{'topic': 'zigbee2mqtt/bridge/state', 'value_template': '{{ value_json.state }}'}], 'command_topic': 'zigbee2mqtt/bridge/request/device/ota_update/update', 'device': {'hw_version': 0, 'identifiers': ['zigbee2mqtt_0x282c02bfffeac0e6'], 'manufacturer': 'Third Reality', 'model': 'Wireless motion sensor', 'model_id': '3RMS16BZ', 'name': 'hallmotionsensor', 'sw_version': 'v1.00.79', 'via_device': 'zigbee2mqtt_bridge_0x00124b002e1249ab'}, 'device_class': 'firmware', 'entity_category': 'config', 'entity_picture': 'https://github.com/Koenkk/zigbee2mqtt/raw/master/images/logo.png', 'json_attributes_template': '{"in_progress": {{ iif(value_json[\'update\'][\'state\'] == \'updating\', \'true\', \'false\') }} }', 'json_attributes_topic': 'zigbee2mqtt/hallmotionsensor', 'latest_version_template': "{{ value_json['update']['latest_version'] }}", 'latest_version_topic': 'zigbee2mqtt/hallmotionsensor', 'name': None, 'object_id': 'hallmotionsensor', 'origin': {'name': 'Zigbee2MQTT', 'sw_version': '2.0.0', 'support_url': 'https://www.zigbee2mqtt.io'}, 'payload_install': '{"id": "0x282c02bfffeac0e6"}', 'state_topic': 'zigbee2mqtt/hallmotionsensor', 'unique_id': '0x282c02bfffeac0e6_update_zigbee2mqtt', 'value_template': "{{ value_json['update']['installed_version'] }}", 'platform': 'mqtt'}'
</code></pre>
<p>It was complaining that the payload contained an unexpected attribute (<code>model_id</code>).</p>
<p>I checked and found that I was running quite an old Home Assistant image (from March last year). Presuming that support for this attribute might have been added in a more recent release, I updated the container to run the latest (<code>2025.1.3</code>).</p>
<p>By the time that Home Assistant came back up, the new device was present and working.</p>
<p><img alt="Screenshot of the MQTT integration page, showing the motion sensor that I added" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/motion_sensor.png"/></p>
<p>This issue also highlighted that I'd <em>probably</em> dodged a bullet by not spending too much time trying to get the HMG's built-in MQTT support working: If some future backwards incompatible-change is made to Home Assistant's auto-discovery, I'll only need to update <code>zigbee2mqtt</code> rather than having to wait (and hope) for a firmware update.</p>
<hr/>
<h3 id="moving-devices-between-networks">Moving Devices Between Networks</h3>
<p>Now that I had a working network, it was time to start moving devices over.</p>
<p>If you're here looking for an easy way to do this, I've got some bad news: there isn't one and you're likely going to need to go round holding buttons to factory reset your Zigbee devices.</p>
<p>Admittedly, this isn't true of all devices - I did have <em>some</em> luck in clicking <code>Remove Device</code> in Home Assistant's ZHA config:</p>
<p><img alt="Screenshot of the location of the Remove button in ZHA config" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/remove_button.png"/></p>
<p>However, most devices wouldn't join a new network when kicked out of the original and needed a physical intervention to reset them.</p>
<p>The way to factory reset devices basically fall into two groups</p>
<ul>
<li>Anything with a button: hold for 10 seconds (normally resulting in an LED flashing)</li>
<li>Light bulbs: flick the power on and off quickly 6 times (resulting in the bulb flashing)</li>
</ul>
<p>The most annoying variation on these is devices with a recessed reset button, requiring a pokey device to press and hold them.</p>
<p>Just before resetting a device, I opened the Zigbee2MQTT web interface on my phone and clicked <code>Permit Join</code></p>
<p><img alt="Screenshot of the Zigbee2MQTT web interface's navigation bar" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/permit_join.png"/></p>
<p>After being reset, each device appeared in the device list.</p>
<p>When they first appear, their "friendly name" is set to their IEEE address - something like <code>0x282c01bfffaac0f6</code> - which obviously isn't all that human friendly.</p>
<p>I edited the name, telling Zigbee2MQTT to also update the entity ID in Home Assistant (which works by sending messages into the auto discovery topic):</p>
<p><img alt="Screenshot of the Zigbee2MQTT rename device screen. There's an option to have it also update the entity ID in home asssistant" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/rename_device.png"/></p>
<p>I started by resetting anything which I knew could act as a Router - the idea being that it would extend the mesh (and therefore coverage), making it easier to get simple sensors to pair.</p>
<hr/>
<h4 id="updating-home-assistant-config">Updating Home Assistant Config</h4>
<p>Still working from my phone, as I paired each new device, I went into the ZHA configuration and removed it. This didn't serve any immediate purpose other than to allow the list to act as a "still todo" list.</p>
<p>I also looked for automations and scripts which referenced the original entities so that I could update them to use the newly discovered devices, only moving onto pairing the next device once I was happy I'd got everything.</p>
<p>One tip that I discovered a little too late: If you restart Home Assistant, it'll log an error for any automation which references an invalid device:</p>
<pre><code class="language-text">ERROR (MainThread) [homeassistant.components.automation] Automation with alias 'Summer House Notify Too Hot' failed to setup triggers and has been disabled: Unknown device 'a90c8ee913f427fc150d1c21f6cbe822'
</code></pre>
<p>This is obviously <em>quite</em> useful for verifying whether you've missed anything once you've finished removing devices.</p>
<hr/>
<h5 id="button-push-automations">Button Push Automations</h5>
<p>I remembered that it had originally been <a href="https://www.bentasker.co.uk/posts/blog/general/712-musings-on-home-automation.html#zigbeeevents">a bit of a pain</a> getting automations to fire in response to button pushes, so once I came to the first button I slowed down.</p>
<p>With ZHA, I'd had to create an event based automation which triggered on a (fairly generic) event and then filtered based on the payload:</p>
<pre><code class="language-yaml">- id: '1608742755182'
alias: Shower Room Button Press
description: ''
trigger:
- platform: event
event_type: zha_event
condition:
- condition: template
value_template: '{{ trigger.event.data.device_ieee == "5c:02:72:ff:fe:49:f2:ef"}}'
action:
- choose:
- conditions:
- condition: template
value_template: '{{ trigger.event.data.command == "on" }}'
sequence:
- service: script.towel_rail_power_on
data: {}
default:
- service: script.towel_rail_power_off
data: {}
mode: single
</code></pre>
<p>Button press automations are <strong>far</strong> simpler with Zigbee2MQTT - the first time that it sees something happen, it pushes a message to have auto-discovery attach an action type to the device.</p>
<p>So, after pairing the button, the first thing that I needed to do was to <em>push it</em>.</p>
<p><img alt="Gif: push the button " src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/push_the_button.gif"/></p>
<p>Home Assistant's automation builder then exposed <code>"single" action</code> as a trigger-able event:</p>
<p><img alt='The trigger block in an automation. Device hall_pushbutton as action "single"' src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/automation_trigger.png"/></p>
<p>Double-pressing the button similarly led to a <code>double</code> action also becoming available.</p>
<hr/>
<h4 id="unsupported-devices">Unsupported Devices</h4>
<p>When I came to pair the smart-socket in our garage, I ran into something new: Zigbee2MQTT reported that the device wasn't supported.</p>
<p><img alt="Screenshot from the interface showing that it's not supported" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/unsupported_device.png"/></p>
<p>Clicking the <a href="https://www.zigbee2mqtt.io/advanced/support-new-devices/01_support_new_devices.html">how_to_add_support</a> link showed that this <em>sounds</em> more concerning than it actually is. The socket works just fine as a Zigbee device (and still appears in Home Assistant), it's just that Zigbee2MQTT lacks a definition of how the device should be presented.</p>
<p>The docs link describes how to extract information and raise a PR - something that I'll do once I've found a suitable product image for it.</p>
<hr/>
<h4 id="making-better-use-of-the-mesh">Making Better Use Of The Mesh</h4>
<p>One thing that I noticed quite early on was that most of my sensors were connecting directly to the coordinator:</p>
<p><img alt="Map of the mesh network - sensors tend to connect direct to the coordinator" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/mesh.png"/></p>
<p>The numbers on the lines show link quality, some of the sensors could <em>quite clearly</em> benefit from connecting via a router.</p>
<p>They'll probably move around over time, but it's also possible to force a sensor to pair with a specific repeater: by kicking it back out of the network and then choosing the desired repeater in the <code>Permit Join</code> dropdown:</p>
<p><img alt="Screen shot of the permit join button, I've selected bedroom_tv" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/permit_join_custom.png"/></p>
<p>When it rejoins, it'll connect via the specified router</p>
<p><img alt="Routing has been updated and various devices now mesh via their local router" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/final_mesh.png"/></p>
<hr/>
<h4 id="disabling-zha">Disabling ZHA</h4>
<p>With all of my devices moved across, it was time to remove ZHA from Home Assistant.</p>
<p>To do this, I went into the ZHA integration and clicked the three dots by the coordinator</p>
<p><img alt="Screenshot of the Integration entries. There's a three dot menu on the right hand side" src="https://www.bentasker.co.uk/images/BlogItems/zigbee2mqtt_setup/integration_entries.png"/></p>
<p>Clicking <code>Delete</code> removed the entry and when I went back to the Integrations view ZHA was no longer listed.</p>
<p>Finally, I needed to recreate the docker container <em>without</em> passing the adaptor through. The original docker invocation included:</p>
<pre><code class="language-sh">--device /dev/serial/by-id/usb-Texas_Instruments_TI_CC2531_USB_CDC___0X00124B011949A347-if00:/dev/serial/by-id/usb-Texas_Instruments_TI_CC2531_USB_CDC___0X00124B011949A347-if00
</code></pre>
<p>So, I re-ran it without:</p>
<pre><code class="language-sh">docker run \
-d \
--name=homeassistant \
-v ${PWD}/docker_files/homeassistant/config:/config \
-p 8123:8123 \
--restart=unless-stopped \
ghcr.io/home-assistant/home-assistant:2025.1.3
</code></pre>
<p>Once Home Assistant was up, I unplugged the adaptor.</p>
<p>Now that it has no ties to the hardware, I can look at moving Home Assistant into my k8s cluster.</p>
<hr/>
<h3 id="conclusion">Conclusion</h3>
<p>It's something that I've grumbled about (<a href="https://www.bentasker.co.uk/posts/blog/general/712-musings-on-home-automation.html">at length</a>) before, but nothing in home automation <em>ever</em> seems to be straightforward. For all the potential of automation, implementations often lack the polish that we've come to expect in consumer devices.</p>
<p>Measured against that (somewhat low) bar, though, moving my network over to the new coordinator and stack wasn't too bad. It's true that there were some hiccups at the start, but some of those were the result of me not having updated Home Assistant in a while.</p>
<p>Moving Zigbee devices between coordinators <em>was</em> a bit of a pain, because it meant having to walk around the house holding reset buttons. However, it also presented an opportunity to replace batteries, so I <em>probably</em> shouldn't mind too much.</p>
<p>So far, things look good: there's been no sign of message loss, with one-shot devices working exactly as they should.</p>
<p>Zigbee2MQTT also exposes a bunch of functionality which ZHA does not. In particular, the ability to bind devices to one another so that (for example) a button can turn lights on even if the co-ordinator and/or Home Assistant are down. At some point I'll get around to playing with that properly.</p>
<p>Finally, I've alluded to it a couple of times in this post, but it seems worth saying explicitly: The Zigbee2MQTT documentation really is <strong>absolutely fantastic</strong>.</p>
</div>