You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
End Device Initiator flag remains set when forwarding remote group commands #65
One caveat at the beginning: this whole investigation was done using an AI agent, I am not that knowledgeable in the zigbee stack.
Ziggurat currently forwards group commands (e.g. from a remote) with the NWK End Device Initiator flag still set. A bound light does not respond, although Ziggurat receives and retransmits the commands successfully.
Zigbee specification 05-3474-23, §3.3.1.1.8, requires the parent to clear this flag when relaying a message from an end-device child. Under §3.6.2.2, other routers must reject an initiator-marked message if the source is not an end device in their neighbor table.
The remote’s On/Off and Level Control bindings point to group 3; the bulb’s queried membership includes group 3.
The raw capture shows the remote sending a MAC unicast to the coordinator with NWK destination 0xFFFD. Ziggurat broadcasts three copies, all with successful radio TX results. The NWK frame control remains 0x2248, retaining End Device Initiator. The source and sequence are preserved, and the radius decreases from 12 to 11.
In crates/ziggurat-driver/src/zigbee_stack/nwk.rs, maybe_relay_broadcast() clones the frame without clearing end_device_initiator. The unicast relay path also retains it.
I applied a local fix that clears the flag before forwarding, including broadcast retries and indirect copies. After deployment, toggle and brightness controls worked.
Thanks for the detailed analysis, it checks out. The Zigbee R23.2 spec (§3.3.1.1.8) requires a router parent to clear the End Device Initiator bit when relaying a frame from one of its end device children, and ziggurat never did, so routers that don't have the remote as their own child drop the relayed group command (§3.6.2.2).
Fix: #66. It clears the bit for frames whose NWK source is one of our end device children, in both the broadcast relay (the relayed copy, its retransmits, and the copies queued for sleepy children) and the unicast relay (sender retries and the indirect queue). That matches the paths your local fix covered.
Details
Spec §3.3.1.1.8: "After validating the source (see section 3.6.2.2), a router parent device SHALL clear this field when relaying a message sent by one of its end device children."
Spec §3.6.2.2: a receiver searches its neighbor table for an end device with the frame's source address and drops the frame if there is none; an end device receiver drops any frame with the bit set.
In crates/ziggurat-driver/src/zigbee_stack/nwk.rs, maybe_relay_broadcast, the sleepy-child fan-out and relay_unicast_nwk_frame all forwarded the frame with the bit unchanged.
Activity
TheJulianJES commentedon Oct 14, 2026
@zigpy-review-bot Investigate. Possibly also open PR(s). Do up to 6 review rounds for both code and PR description.
zigpy-review-bot commentedon Oct 14, 2026
Thanks for the detailed analysis, it checks out. The Zigbee R23.2 spec (§3.3.1.1.8) requires a router parent to clear the End Device Initiator bit when relaying a frame from one of its end device children, and ziggurat never did, so routers that don't have the remote as their own child drop the relayed group command (§3.6.2.2).
Fix: #66. It clears the bit for frames whose NWK source is one of our end device children, in both the broadcast relay (the relayed copy, its retransmits, and the copies queued for sleepy children) and the unicast relay (sender retries and the indirect queue). That matches the paths your local fix covered.
Details
crates/ziggurat-driver/src/zigbee_stack/nwk.rs,maybe_relay_broadcast, the sleepy-child fan-out andrelay_unicast_nwk_frameall forwarded the frame with the bit unchanged.