zigbee2mqtt: patch Bridge TypeError on BLZ coordinator

The Pine64 BLZ fork's zigbee2mqtt image crashes on start because
Bridge.start() calls firstCoordinatorEndpoint().deviceIeeeAddress
before the onMQTTMessage listener is registered. The BLZ coordinator
does not register its endpoint (the coordinator is the dongle itself,
no ZDO loopback), so firstCoordinatorEndpoint() returns undefined.

The crash happens in publishInfo() BEFORE onMQTTMessage is wired up,
which means every bridge MQTT request (permit_join, device rename,
group ops, etc.) silently no-ops — even though the message is
received.

Add infra/zigbee2mqtt/scripts/blz-bridge-patch.js that applies two
surgical fixes (idempotent):

  1. Optional chain on the .deviceIeeeAddress access so the missing
     endpoint doesn't throw.
  2. Move onMQTTMessage registration BEFORE publishInfo/devices/
     groups/definitions, and wrap each publish in try/catch so
     Bridge.start() completes even if a single publish fails.

Add 'just z2m-patch-bridge' to apply the patch on the live container
after fresh image pulls.
This commit is contained in:
2026-07-01 01:22:56 -07:00
parent 758edc0a9a
commit c2de5ba85b
2 changed files with 109 additions and 1 deletions
+18 -1
View File
@@ -155,9 +155,26 @@ doorbell-publish TITLE BODY="Someone is at the door":
doorbell-rebuild:
ssh {{RPI_HOST}} 'cd {{RPI_DIR}}/nr-flow-validator && docker compose build doorbell-listener && docker compose up -d doorbell-listener'
# Patch zigbee2mqtt's bridge.js for BLZ adapter compatibility.
# The Pine64 latest-dev image crashes on start because Bridge.start() calls
# firstCoordinatorEndpoint().deviceIeeeAddress BEFORE registering the
# onMQTTMessage listener, so permit_join (and every other bridge MQTT
# request) silently no-ops.
#
# Run this after every fresh image pull OR after the zigbee2mqtt container
# is recreated (the patch is lost on image rebuild).
z2m-patch-bridge:
@echo "Copying patch script into zigbee2mqtt container..."
ssh {{RPI_HOST}} 'docker cp {{justfile_directory()}}/infra/zigbee2mqtt/scripts/blz-bridge-patch.js zigbee2mqtt:/tmp/blz-bridge-patch.js'
@echo "Applying patch (idempotent)..."
ssh {{RPI_HOST}} 'docker exec zigbee2mqtt node /tmp/blz-bridge-patch.js'
@echo "Restarting zigbee2mqtt..."
ssh {{RPI_HOST}} 'docker restart zigbee2mqtt'
@echo "Done. Verify with: just z2m-logs"
# Show paired zigbee devices and their friendly names
z2m-devices:
ssh {{RPI_HOST}} 'cat {{RPI_DIR}}/zigbee2mqtt/configuration.yaml' > /tmp/z2m.yaml
ssh {{RPI_HOST}} 'cat {{RPI_DIR}}/nr-flow-validator/infra/zigbee2mqtt/configuration.yaml' > /tmp/z2m.yaml
python3 scripts/diag.py z2m-devices /tmp/z2m.yaml
# Show per-device persisted state from z2m