mirror of
https://github.com/home-assistant/core.git
synced 2026-09-24 07:25:52 -05:00
Address review feedback on Matter fan PercentSetting fix (#180554)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
2aa1b43811
commit
fde7f6c93e
@@ -39,6 +39,12 @@ FAN_MODE_MAP_REVERSE = {v: k for k, v in FAN_MODE_MAP.items()}
|
||||
PRESET_NATURAL_WIND = "natural_wind"
|
||||
PRESET_SLEEP_WIND = "sleep_wind"
|
||||
|
||||
# Some devices report 255 for PercentCurrent instead of their actual speed
|
||||
# while FanMode is Auto. This is not part of the Matter spec (which says the
|
||||
# device should keep reporting its real current speed, see spec 4.4.6.1.2 and
|
||||
# 4.4.6.4), but we need to work around it regardless.
|
||||
PERCENT_CURRENT_AUTO_QUIRK = 255
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
@@ -207,9 +213,9 @@ class MatterFan(MatterEntity, FanEntity):
|
||||
current_percent = self.get_matter_attribute_value(
|
||||
clusters.FanControl.Attributes.PercentCurrent
|
||||
)
|
||||
# NOTE that a device may give back 255 as a special value to indicate that
|
||||
# the speed is under automatic control and not set to a specific value.
|
||||
self._attr_percentage = None if current_percent == 255 else current_percent
|
||||
self._attr_percentage = (
|
||||
None if current_percent == PERCENT_CURRENT_AUTO_QUIRK else current_percent
|
||||
)
|
||||
|
||||
# get preset mode from fan mode (and wind feature if available)
|
||||
wind_setting = self.get_matter_attribute_value(
|
||||
@@ -242,7 +248,7 @@ class MatterFan(MatterEntity, FanEntity):
|
||||
# keep track of the last known mode for turn_on commands without preset
|
||||
if self._attr_preset_mode is not None:
|
||||
self._last_known_preset_mode = self._attr_preset_mode
|
||||
if current_percent and current_percent != 255:
|
||||
if current_percent and current_percent != PERCENT_CURRENT_AUTO_QUIRK:
|
||||
self._last_known_percentage = current_percent
|
||||
|
||||
@callback
|
||||
|
||||
@@ -134,10 +134,11 @@ async def test_fan_turn_on_with_percentage(
|
||||
attribute_path="1/514/2",
|
||||
value=50,
|
||||
)
|
||||
# test again where percentage is omitted in the service call
|
||||
# PercentCurrent is 255 (auto) on this fixture, which is not a valid
|
||||
# value to write back, so it should fall back to the last known preset
|
||||
# mode instead of blindly replaying the sentinel value.
|
||||
# test again where percentage is omitted in the service call.
|
||||
# This fixture's PercentCurrent is 255, a device-specific quirk value
|
||||
# (not part of the Matter spec) that is not valid to write back, so it
|
||||
# should fall back to the last known preset mode instead of blindly
|
||||
# replaying that sentinel value.
|
||||
matter_client.write_attribute.reset_mock()
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
@@ -153,6 +154,33 @@ async def test_fan_turn_on_with_percentage(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||
@pytest.mark.parametrize("node_fixture", ["mock_air_purifier"])
|
||||
async def test_fan_turn_on_replays_last_known_percentage(
|
||||
hass: HomeAssistant,
|
||||
matter_client: MagicMock,
|
||||
matter_node: MatterNode,
|
||||
) -> None:
|
||||
"""Test that a bare turn_on replays a real last known percentage."""
|
||||
entity_id = "fan.mock_air_purifier"
|
||||
# simulate the device confirming a real (non-quirk) speed
|
||||
set_node_attribute(matter_node, 1, 514, 3, 70)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert matter_client.write_attribute.call_count == 1
|
||||
assert matter_client.write_attribute.call_args == call(
|
||||
node_id=matter_node.node_id,
|
||||
attribute_path="1/514/2",
|
||||
value=70,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||
@pytest.mark.parametrize("node_fixture", ["mock_fan"])
|
||||
async def test_fan_turn_on_with_preset_mode(
|
||||
|
||||
Reference in New Issue
Block a user