* fix: use quantization-aware comparison in skip_redundant_commands filter
_remove_redundant_attributes() compared target values against light state
with exact equality, but many targets can never round-trip exactly through
a device with coarser resolution:
- brightness: HA's 0-255 scale vs the 0-99 Z-Wave Multilevel Switch scale
leaves 156 of 255 targets that never converge (e.g. 230 -> 89 -> 229),
- color_temp_kelvin: the kelvin -> mired -> kelvin round trip leaves most
kelvin targets off by up to ~21 K at 6500 K (e.g. 5500 -> 182 -> 5495).
Such attributes survived the filter and were re-sent every interval
forever, which on larger Z-Wave meshes is enough to jam the controller.
Compare brightness with a tolerance of 2 (the exact worst case of the
0-99 scale) and color temperature in mired space, where devices actually
quantize and where the comparison is exact at every kelvin value. Both
are far below the manual-control detection thresholds
(BRIGHTNESS_CHANGE = 25, COLOR_TEMP_CHANGE = 100), so they cannot mask a
genuine user change.
Fixes#1512
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017P2wLQYGQH6npY5op5CKVD
* fix: tolerate one mired to cover both floor- and round-based conversions
The previous exact mired equality assumed round-based kelvin<->mired
conversion, but HA core's color_temperature_kelvin_to_mired() and
color_temperature_mired_to_kelvin() both use math.floor, under which a
target like 5500 K comes back as 5524 K in a different rounded mired
bucket and would never be filtered. Flooring in the comparison instead
would merely flip the failure onto integrations that round.
Comparing with a tolerance of one mired converges for both conversion
schemes (verified by brute force over 1000-10000 K: zero stuck targets
under either pipeline) and can hide at most ~2 mireds, far below the
~5.5 mired just-noticeable difference for color temperature.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017P2wLQYGQH6npY5op5CKVD
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
* refactor: introduce light control parameter enum
* refactor: replace manual control flag with parameter enum
* test: update deprecated color temp attribute
* build: set execution bits on task scripts
* feat: individual manual control of brightness and color
* test: add tests for individual manual control evaluation
* fix: sequential manual changes not always detected
If multiple attributes of a light were changed within an interval, only the last change was detected because the check in the interval only used the latest event. For example, if there was a brightness change and a following color change, only the color attribute was detected as manually controlled. To fix this, the manual control attribute flags are now set directly from the event handler so that all events are processed.
* fix: invalid service description
* docs: fix missing space in config description
* refactor: pluralize multivalued bitmask enum name
* Implement call intercept for multiple lights
* remove comment
* skip if no eids
* add comment
* fix type
* Fix skipped
* indentation
* Add logging and fix error
* Fix for HA ≤2023.04
* simplify
* remove unused ignores
* Debug mode
* Add test
* Make test failing
* rename switch
* rename lights
* Fix tests
* Rename lights in tests
* Remove unused dependencies
* Improve tests
* More tests
* Remove the DEBUG_MODE
* Add doc-string
* Extra test
* assert
* extra test
* Comments
* fix
* fix
* expand light groups
* more logging
* sort
* Revert is_proactively_adapting checks
This reverts commit 39fd8f2be0.
* simplify the mapping
* Revert "Revert is_proactively_adapting checks"
This reverts commit 18803e8e50.
* test
* no light groups
* do not expand
* Do not expand_light_groups in intercept
* more logging
* Fix
* add comment
* Add multi_light_intercept config option
* Update README.md, strings.json, and services.yaml
* add light group
* fix platform
* add simple test
* turn off again
* Test without take over control
* improve test and fix it in one way
* Fixes
* add cleanup fixture
* format
* Update test_switch.py
* add __str__
* remove unneeded call
* simplify service_data construction
* Generalize is_our_context
* Fix multi_light_intercept: false
* add comments
* add docs
* Update README.md, strings.json, and services.yaml
* Add feature line
* move function
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* Before scheduling turn_on do a last-minute check if lights are off
* Pass force
* add comment
* fix for proactive
* commetn
* No default for force
* rm newline
* no force
* Return bool
* Rename TurnOnOffListener to AdaptiveLightingManager
* Bump Python version
* Refactor and unify methods that are called once
* Simplify adaptation_utils.py
* Improve readability in adaptation_utils.py
* More renames
* Simplify
* More renames and simplifications
* fix test
* simplify _supported_features
* rename
* walrus
* drop old astral support
* Only support HA ≥2021.06
* Require 2016.06
* Try 2023.1
* even more old versions
* test
* more versions
* verify that only ≥2022.11 works
* named args
* setdefault
* no astral v1
* var
* simplify
* no need to pass adapt_brightness and adapt_color
* Add comment
* Fix multiple switches controlling one light
* WIP
* Keep length in AdaptationData
* Do not proceed if there is nothing to do
* Simplify
* Set tasks correctly
* log more
* WIP
* realize that intercept and double switch not possible
* Remove which from find_switch_for_lights
* Rephrase
* Check which one to cancel
* length -> max_length
* Implement test_two_switches_for_single_light
* Clean up
* Simplify is_color_brightness_or_both
* Improve test
* no wait
* logging
* just block
* make test such that it fails on main