Skip to content

feat(colorControl): Add the OptionsMask / OptionsOverride command fields - #233

Open
TedTolboom wants to merge 1 commit into
athombv:masterfrom
TedTolboom:feature/color-control-options
Open

TedTolboom wants to merge 1 commit into
athombv:masterfrom
TedTolboom:feature/color-control-options

Conversation

@TedTolboom

Copy link
Copy Markdown
Contributor

Summary

The Color Control commands Move to Hue, Move to Saturation, Move to Hue and Saturation, Move to Color and Move to Color
Temperature end with the OptionsMask and OptionsOverride fields (map8, ZCL r8 Figures 5-2 – 5-12). Together they
temporarily override the Options attribute for that one command, e.g. executeIfOff (ZCL r8 5.2.2.3.3).

zigbee-clusters already defines the options attribute (map8('executeIfOff')), but not these command fields. So a
driver cannot send them without building a raw ZCL frame.

This PR adds both fields to the five commands as optional fields (encodeMissingFieldsBehavior: 'skip', as described
in AGENTS.md).

Compatibility

Existing calls without the options encode exactly as before; the new fields are only sent when provided:

Call Payload (Move to Color Temperature, 286 Mired, 1.5 s)
{ colorTemperature, transitionTime } (unchanged) 1e 01 0f 00
+ optionsMask: ['executeIfOff'], optionsOverride: ['executeIfOff'] 1e 01 0f 00 01 01

Note: ZCL r8 says the two fields "SHALL both be present. Default values are provided to interpret missing fields from
legacy devices"
(CCB 2814). Making them optional keeps the current behaviour for all existing drivers. Encoding
00 00 by default would follow r8 more strictly, but it changes the payload for every device, so I left that decision
to you.

Why

Aqara hubs send the color temperature command with these fields (… 01 01, execute if off). The Aqara Ceiling Light T1M
(lumi.light.acn032) depends on them. Homey runs its white scenes (e.g. a "breathing" sequence) as level + color
temperature steps, and without the fields the light follows the level steps but not the color temperature steps. With
the fields, as the Aqara hub sends them, the light follows both. This was validated with a sniffer capture of the Aqara
hub and of Homey. Until now we work around it in the app with a subclass that adds a second command with id 0x0A.

Changes

  • lib/clusters/colorControl.js:
    • OPTIONS_BITMAP (map8('executeIfOff')), shared by the options attribute and the new fields;
    • OPTIONS_ARGS (optionsMask, optionsOverride) added to the five commands, with encodeMissingFieldsBehavior: 'skip'.
  • index.d.ts: regenerated with npm run generate-types.
  • test/colorControl.js: encoding tests against the spec bytes, without options (unchanged payload) and with options
    (Figures 5-9 and 5-12), plus a loopback test that receives the options.

Test plan

  • npm test: 96 passing, including the 4 new tests
  • npm run lint
  • npm run build
  • Aqara Ceiling Light T1M on Homey Pro: color temperature steps are followed with the options, also when the
    sequence starts from off

Not included (possible follow-ups)

  • The enhanced hue commands, move / step commands and colorLoopSet, which also have these fields in r8.
  • Level Control: r8 defines the same fields for its commands.

🤖 Generated with Claude Code

The Move to Hue, Move to Saturation, Move to Hue and Saturation, Move to
Color and Move to Color Temperature commands end with the OptionsMask and
OptionsOverride fields (ZCL r8 5.2.2.3.3), which temporarily override the
Options attribute, e.g. executeIfOff. They were not defined, so a driver
could not send them without building a raw frame.

The fields are optional (encodeMissingFieldsBehavior 'skip'): existing calls
without them encode exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant