Z2M: adopt coordinator via explicit network params (final cutover fix) #371

Merged
k.renner merged 1 commits from claude-bot/zha-to-zigbee2mqtt into master 2026-07-23 11:53:14 +00:00
Member

The real adoption fix — verified byte order from herdsman source, verified key against your backup.

Why the backup approach didn't adopt

coordinator_backup.json does not make herdsman adopt an already-commissioned coordinator. herdsman's zstack manager compares the config network params against the adapter NV and refuses on mismatch (the backup only prevents accidental re-commissioning). Z2M sat on defaults (PAN 0x1a62/ch 11) vs your real network (PAN 0x8b2b/ch 25) and correctly refused — no re-pair, no damage. That error handed me the adapter's exact params.

The fix — explicit params, in config

advanced:
  channel: 25
  pan_id: 0x8B2B
  ext_pan_id: [0xfc,0x7a,0x73,0x5d,0x08,0xc1,0x54,0x76]   # natural order
  network_key: "!secret network_key"
  • Byte order pinned from zigbee-herdsman v10.6.1 source (determineStrategy): ext_pan_id is reversed only when writing NV, compared/logged non-reversed; network key never reversed → both natural order, matching the displayed adapter hex.
  • network_key stays secret: init container extracts it from the OpenBao backup (jq + sed → int array) into secret.yaml; non-secret params in the ConfigMap.
  • Cross-checked: the OpenBao backup's key/pan/ext/channel match the adapter exactly.

Safety

The coordinator_backup.json is still seeded, so if any param is still off, herdsman refuses and exits — never re-commissions. No path to a re-pair.

After merge (I do it)

Clear the stale PVC config once → Z2M starts, config matches adapter → adopts (resumes) the network. Then I disable ZHA so Z2M owns the coordinator, verify devices, and you re-interview any sleepy sensors.

🤖 Generated with Claude Code

The real adoption fix — verified byte order from herdsman source, verified key against your backup. ## Why the backup approach didn't adopt `coordinator_backup.json` does **not** make herdsman adopt an already-commissioned coordinator. herdsman's zstack manager compares the **config** network params against the adapter NV and refuses on mismatch (the backup only prevents accidental re-commissioning). Z2M sat on defaults (`PAN 0x1a62`/ch 11) vs your real network (`PAN 0x8b2b`/ch 25) and **correctly refused — no re-pair, no damage.** That error handed me the adapter's exact params. ## The fix — explicit params, in config ```yaml advanced: channel: 25 pan_id: 0x8B2B ext_pan_id: [0xfc,0x7a,0x73,0x5d,0x08,0xc1,0x54,0x76] # natural order network_key: "!secret network_key" ``` - **Byte order pinned from zigbee-herdsman v10.6.1 source** (`determineStrategy`): `ext_pan_id` is reversed only when *writing* NV, compared/logged non-reversed; network key never reversed → both natural order, matching the displayed adapter hex. - **network_key stays secret**: init container extracts it from the OpenBao backup (`jq` + `sed` → int array) into `secret.yaml`; non-secret params in the ConfigMap. - **Cross-checked**: the OpenBao backup's key/pan/ext/channel match the adapter exactly. ## Safety The `coordinator_backup.json` is still seeded, so if any param is still off, herdsman **refuses and exits** — never re-commissions. No path to a re-pair. ## After merge (I do it) Clear the stale PVC config once → Z2M starts, config matches adapter → **adopts (resumes) the network**. Then I disable ZHA so Z2M owns the coordinator, verify devices, and you re-interview any sleepy sensors. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-bot added 1 commit 2026-07-23 11:46:22 +00:00
The coordinator_backup.json approach did NOT make herdsman adopt the existing
network. herdsman's zstack manager compares the CONFIG network params against
the adapter's NV and refuses on mismatch; a backup only prevents accidental
re-commissioning, it does not supply the network to an already-commissioned
adapter. So Z2M sat on defaults (PAN 0x1a62 / channel 11) vs the real network
(PAN 0x8b2b / channel 25) and correctly refused — no re-pair, no damage.

Set the real network params explicitly (values are the adapter's own, read from
herdsman's own mismatch log, cross-checked against the OpenBao backup which
matches exactly: key fe0b..2d, pan 8b2b, ext fc7a735d08c15476, ch 25):

  advanced:
    channel: 25
    pan_id: 0x8B2B
    ext_pan_id: [0xfc,0x7a,0x73,0x5d,0x08,0xc1,0x54,0x76]   # natural order
    network_key: "!secret network_key"

Byte order pinned against zigbee-herdsman v10.6.1 source (determineStrategy):
ext_pan_id is reversed only when WRITING to NV, but compared/logged
non-reversed, and the network key is never reversed — so both go in natural
order matching the displayed adapter hex.

network_key stays secret: the init container extracts it from the OpenBao
coordinator backup (jq + sed -> natural-order int array) into
/app/data/secret.yaml, referenced by the config as a quoted "!secret" ref.
channel/pan_id/ext_pan_id are non-secret and live in the ConfigMap.

Verified: kustomize builds, deployment dry-run OK, extraction produces the
correct 16-byte array, config schema types valid. The final config<->adapter
match is confirmed at startup, where the coordinator_backup.json guarantees a
safe refusal (never a re-commission) if anything is still off.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
k.renner merged commit e2045eeb0b into master 2026-07-23 11:53:14 +00:00
Sign in to join this conversation.