Register custom clusters on first pairing, not only after restart#2943
Open
krobipd wants to merge 1 commit into
Open
Register custom clusters on first pairing, not only after restart#2943krobipd wants to merge 1 commit into
krobipd wants to merge 1 commit into
Conversation
ioBroker#2915) A freshly paired device only receives 'deviceJoined'/'deviceInterview' events, never 'start'. modernExtend onEvent handlers that key on 'start' -- notably deviceAddCustomCluster -- therefore never register their custom clusters until the next adapter restart. An incoming frame on such an unregistered custom cluster then fails to parse with UNSUPPORTED_CLUSTER, which is exactly why a restart or re-pair fixes it: onZigbeeStarted fires 'start' for every known device and registers the clusters up front. Mirror zigbee2mqtt's onEvent extension (lib/extension/onEvent.ts): track which devices already got a 'start', and the first time a device is seen with any other (non-stop) event, synthesise 'start' first so its custom clusters are registered before the real event is dispatched. If the model is not resolvable yet during a join this is a no-op and retried on the next event. Verified without hardware in lib/zbDeviceEvent.test.js (Node's built-in test runner): the real DeviceEvent extension + a real herdsman definition using deviceAddCustomCluster (Develco AQSZB-110) + a mocked device. The test fails against the current code (custom clusters stay empty on first pairing) and passes with the fix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
deviceAddCustomCluster(herdsmanmodernExtend) registers a device's custom clusters via two paths: itsconfigurechain, and anonEventhandler keyed onevent.type === 'start'. In this adapter'start'is only ever fired fromonZigbeeStarted— i.e. for devices that already exist at adapter start (zbDeviceEvent.js). A freshly paired device only seesdeviceJoined/deviceInterview, never'start', so that handler never runs for it and its custom clusters aren't registered until the next restart. An incoming frame on an unregistered custom cluster then fails to parse in herdsman'sgetCluster()withUNSUPPORTED_CLUSTER.This matches the report, including why a restart or re-pair fixes it: on restart
onZigbeeStartedfires'start'for every device and registers the clusters up front.Verified without hardware (deterministic): running the real
DeviceEventextension against a real herdsman definition usingdeviceAddCustomCluster(Develco AQSZB-110) with a mocked device —device.customClustersstays empty after adeviceInterviewon the current code, and is populated after'start'. The regression test below fails on the current code and passes with the fix.Not verified (timing — your hardware): whether, in practice, a frame actually lands on the custom cluster before the cluster is registered.
configurealso registers it, just later/queued, so the window is real but timing-dependent. That last link between this asymmetry and the exact error you observe is the one thing I'm asking you to confirm.The fix
Mirror zigbee2mqtt's onEvent extension (
lib/extension/onEvent.ts): track which devices already received a'start', and the first time a device is seen with any non-start/stopevent, synthesise'start'first so its custom clusters are registered before the real event is dispatched. No-op + retried on the next event if the model isn't resolvable yet during a join.Test
lib/zbDeviceEvent.test.js— Node's built-in runner, no framework, no hardware:Covers: custom clusters registered on a fresh pairing; no second synthetic start once started; no-op + retry while the model is unresolved; re-arm after stop. (I used
node:testbecausenpm run test:jscurrently errors on the deprecated mocha--opts— I did not touch the test setup.)Notes
npm run test:package(56) andnpm run test:unitpass; ESLint clean.Addresses #2915
🤖 Generated with Claude Code