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.
Polls ntfy.sh for ALERT_klubhaus_topic(_test) and publishes
{state: TOGGLE} to zigbee2mqtt/Sideboard Lamp/set on each new
message event. Dual-topic subscription so switching from test to
production requires no code change; sender still uses test topic.
- infra/doorbell-listener/: uv-based Docker service (arm64)
- compose: depends_on mosquitto, persists last_id per topic
- justfile: doorbell-publish, doorbell-logs, doorbell-rebuild,
restart-all now includes doorbell-listener
zigbee-monitor.yaml:
- Single click (action=single) toggles Squiggle, Sideboard Lamp,
Bamboo Lights
- Press-hold-release (action=release after hold) toggles DJ Booth
only
- Two filter functions: "Single click" and "Hold release", button-in
fan-out wires to both
- DJ Booth added to zigbee-state-in and ui-text widgets for visibility
- "plugs:" list replaced with "single_plugs:" and "hold_plugs:" for
declarative clarity (generator doesn't use them, but documents intent)
infra/zigbee2mqtt/configuration.yaml:
- Removed DJ Booth from "all_plugs" group (now Squiggle, Sideboard
Lamp, Bamboo Lights only)
- Pushed same change to live /root/zigbee2mqtt/configuration.yaml and
restarted zigbee2mqtt container
Diagnostics in justfile + scripts/:
justfile:
- Constants: RPI_HOST, MQTT_HOST, MQTT_PORT, RPI_DIR, NR_PORT
- rpi, mqtt-pub, mqtt-sub, mqtt-watch, mqtt-button
- nr-show, nr-diff, nr-logs, nr-editor, nr-dashboard
- z2m-devices, z2m-logs, z2m-state
- mqtt-logs, restart, restart-all
scripts/mqtt.py:
- MQTT publish/subscribe/watch helpers using paho-mqtt v2.x
- Run via uv run --with paho-mqtt (no global install needed)
scripts/diag.py:
- nr-show: live flow summary with mqtt-out topic list
- nr-diff: structural diff deployed vs repo, normalizes random uuids
- z2m-devices: paired devices + group membership
- mqtt-button: publish action and watch /set topics (E2E test)
Verified end-to-end via `just mqtt-button`:
single → 3 messages on .../set (Squiggle, Sideboard Lamp, Bamboo Lights)
release → 1 message on .../set (DJ Booth)
Closes#1.
Generator (scripts/flow2json.py):
- Emit all nodes at top level with z field (no wrapped tabs)
- Set icon: "" on ui-button to avoid Dashboard 2.0 prependIcon TypeError
- Set z field on ui-* widgets so they render in Dashboard 2.0 SPA
- Use ui-text label from spec, not name
Policy (policy/flow.rego) — 9 new deny rules:
- deny_wrapped_tab: tab with internal nodes[] (nodered 5.0 bug)
- deny_missing_wires: missing or non-array wires (Flow.js rewireNode crash)
- deny_no_autoconnect: mqtt-broker must reconnect
- deny_invalid_protocol: protocolVersion must be 3/4/5
- deny_unused_broker: broker declared but never referenced
- Plus deny_broker_port / deny_group_ref / deny_page_ref / deny_wire_ref refinements
Flow (zigbee-monitor.*):
- 22-node flat flow: button-in → btn-filter → 4 parallel plug-outs
- 4 ui-text widgets + ui-button for permit-join (60s)
- Renamed plug: "Laser & Fog" → "DJ Booth" (matches z2m friendly_name)
Repo hygiene:
- justfile: fix host IP 192.168.9.147 → 192.168.81.147, /ui → /dashboard
- README.md: document 8 generation invariants and rule table
Verified end-to-end: publishing {"action":"single"} on
zigbee2mqtt/Door Button triggers {"state":"TOGGLE"} on all four
.../set topics including the renamed DJ Booth.
462/462 conftest tests pass.