Fix Multilevel Switch values being exposed when Window Covering CC is supported
Some devices support both Window Covering CC and Multilevel Switch CC for backward compatibility, but still report their status using Multilevel Switch CC instead of Window Covering CC. According to Z-Wave specifications, Multilevel Switch CC must be hidden in favor of Window Covering CC when both are supported, but unsolicited Multilevel Switch CC reports were causing values to get exposed to applications, resulting in errors when used.
Root Cause
The issue occurred because MultilevelSwitchCCReport automatically persisted values via @ccValueProperty decorators, regardless of whether Window Covering CC was supported. This meant that even when the Multilevel Switch CC was properly hidden during interview (via modifySupportedCCBeforeInterview), incoming reports would still create Multilevel Switch values in the value database.
Solution
Override the persistValues() method in MultilevelSwitchCCReport to:
- Check if the endpoint supports Window Covering CC
- If supported, dynamically determine the appropriate Window Covering parameter to map to:
- Look up supported Window Covering parameters from the value database
- Select the first odd parameter (which has position support)
- Fall back to the first supported parameter if no odd parameters exist
- If not supported, use the default persistence behavior for backward compatibility
This approach leverages the existing CC persistence infrastructure and provides a clean, centralized solution without requiring changes to the command handling pipeline.
Example
// Before: Multilevel Switch values would always be persisted
node.getValue(MultilevelSwitchCCValues.currentValue) // Returns value even when Window Covering is supported
// After: Values are mapped to the appropriate Window Covering parameter when both CCs are supported
// If supported parameters are [0, 3, 5], parameter 3 ("Outbound Right") is selected (first odd parameter)
node.getValue(WindowCoveringCCValues.currentValue(3)) // Returns the mapped value
node.getValue(MultilevelSwitchCCValues.currentValue) // Returns undefined when Window Covering is supported
Fixes #6318.
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.
💡 The pull request title does not match our guidelines 💡
We follow conventional commits, check out the description and examples. This means that the PR title must...
- start with the type of change, e.g.
feat:, orfix: - optionally specify a scope, for example we use
configfor changes to config files:feat(config): - contain a description that explains what is being changed, e.g. add a parameter, correct a typo, ...
- and ideally explains what the change affects, e.g. the device (manufacturer, device label, firmware, ...)
The description should use uppercase and lowercase normally, except for the first character which must be lowercase.
How about this title instead?
fix(multilevelSwitch): prevent exposure of Multilevel Switch values when Window Covering CC is supported
💡 The pull request title does not match our guidelines 💡
We follow conventional commits, check out the description and examples. This means that the PR title must...
- start with the type of change, e.g.
feat:, orfix: - optionally specify a scope, for example we use
configfor changes to config files:feat(config): - contain a description that explains what is being changed, e.g. add a parameter, correct a typo, ...
- and ideally explains what the change affects, e.g. the device (manufacturer, device label, firmware, ...)
The description should use uppercase and lowercase normally, except for the first character which must be lowercase.
How about this title instead?
fix(multilevel switch): prevent exposure of values when Window Covering CC is supported
💡 The pull request title does not match our guidelines 💡
We follow conventional commits, check out the description and examples. This means that the PR title must...
- start with the type of change, e.g.
feat:, orfix: - optionally specify a scope, for example we use
configfor changes to config files:feat(config): - contain a description that explains what is being changed, e.g. add a parameter, correct a typo, ...
- and ideally explains what the change affects, e.g. the device (manufacturer, device label, firmware, ...)
The description should use uppercase and lowercase normally, except for the first character which must be lowercase.
How about this title instead?
fix(multilevelSwitch): resolve exposure of values when Window Covering CC is supported
💡 The pull request title does not match our guidelines 💡
We follow conventional commits, check out the description and examples. This means that the PR title must...
- start with the type of change, e.g.
feat:, orfix: - optionally specify a scope, for example we use
configfor changes to config files:feat(config): - contain a description that explains what is being changed, e.g. add a parameter, correct a typo, ...
- and ideally explains what the change affects, e.g. the device (manufacturer, device label, firmware, ...)
The description should use uppercase and lowercase normally, except for the first character which must be lowercase.
How about this title instead?
fix(multilevelSwitch): prevent exposure of values when Window Covering CC is supported
@copilot remove
packages/zwave-js/src/lib/test/cc/MultilevelSwitchWindowCoveringMapping.test.ts...
Done in commit f459ad3. The implementation now:
- Removes the unit test file as requested
- Dynamically looks up supported Window Covering parameters from the value database
- Selects the first odd parameter (with position support), falling back to the first supported parameter if none exist
- Uses the
WindowCoveringParameterenum throughout instead of magic values - Includes comprehensive integration tests covering:
- Single parameter (parameter 1)
- Multiple parameters with odd ones available (selects parameter 3)
- Only even parameters available (falls back to parameter 4)
[!WARNING]
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
plugins.dprint.dev
- Triggering command:
/home/REDACTED/work/zwave-js/zwave-js/node_modules/.store/dprint-npm-0.50.1-1d083965cb/package/dprint fmt(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)
💡 The pull request title does not match our guidelines 💡
We follow conventional commits, check out the description and examples. This means that the PR title must...
- start with the type of change, e.g.
feat:, orfix: - optionally specify a scope, for example we use
configfor changes to config files:feat(config): - contain a description that explains what is being changed, e.g. add a parameter, correct a typo, ...
- and ideally explains what the change affects, e.g. the device (manufacturer, device label, firmware, ...)
The description should use uppercase and lowercase normally, except for the first character which must be lowercase.
How about this title instead?
fix(multilevelSwitch): prevent exposure of Multilevel Switch values when Window Covering CC is supported