Fix command latency in AVM Fritz!SmartHome (#136739)

This commit is contained in:
Michael 2025-01-29 12:55:59 +01:00 committed by GitHub
parent bc2976904e
commit c974251faa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 34 additions and 31 deletions

View File

@ -141,7 +141,7 @@ class FritzboxThermostat(FritzBoxDeviceEntity, ClimateEntity):
await self.async_set_hvac_mode(hvac_mode)
elif target_temp is not None:
await self.hass.async_add_executor_job(
self.data.set_target_temperature, target_temp
self.data.set_target_temperature, target_temp, True
)
else:
return

View File

@ -71,21 +71,21 @@ class FritzboxCover(FritzBoxDeviceEntity, CoverEntity):
async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the cover."""
await self.hass.async_add_executor_job(self.data.set_blind_open)
await self.hass.async_add_executor_job(self.data.set_blind_open, True)
await self.coordinator.async_refresh()
async def async_close_cover(self, **kwargs: Any) -> None:
"""Close the cover."""
await self.hass.async_add_executor_job(self.data.set_blind_close)
await self.hass.async_add_executor_job(self.data.set_blind_close, True)
await self.coordinator.async_refresh()
async def async_set_cover_position(self, **kwargs: Any) -> None:
"""Move the cover to a specific position."""
await self.hass.async_add_executor_job(
self.data.set_level_percentage, 100 - kwargs[ATTR_POSITION]
self.data.set_level_percentage, 100 - kwargs[ATTR_POSITION], True
)
async def async_stop_cover(self, **kwargs: Any) -> None:
"""Stop the cover."""
await self.hass.async_add_executor_job(self.data.set_blind_stop)
await self.hass.async_add_executor_job(self.data.set_blind_stop, True)
await self.coordinator.async_refresh()

View File

@ -122,7 +122,7 @@ class FritzboxLight(FritzBoxDeviceEntity, LightEntity):
"""Turn the light on."""
if kwargs.get(ATTR_BRIGHTNESS) is not None:
level = kwargs[ATTR_BRIGHTNESS]
await self.hass.async_add_executor_job(self.data.set_level, level)
await self.hass.async_add_executor_job(self.data.set_level, level, True)
if kwargs.get(ATTR_HS_COLOR) is not None:
# Try setunmappedcolor first. This allows free color selection,
# but we don't know if its supported by all devices.
@ -133,7 +133,10 @@ class FritzboxLight(FritzBoxDeviceEntity, LightEntity):
cast(float, kwargs[ATTR_HS_COLOR][1]) * 255.0 / 100.0
)
await self.hass.async_add_executor_job(
self.data.set_unmapped_color, (unmapped_hue, unmapped_saturation)
self.data.set_unmapped_color,
(unmapped_hue, unmapped_saturation),
0,
True,
)
# This will raise 400 BAD REQUEST if the setunmappedcolor is not available
except HTTPError as err:
@ -152,18 +155,18 @@ class FritzboxLight(FritzBoxDeviceEntity, LightEntity):
key=lambda x: abs(x - unmapped_saturation),
)
await self.hass.async_add_executor_job(
self.data.set_color, (hue, saturation)
self.data.set_color, (hue, saturation), 0, True
)
if kwargs.get(ATTR_COLOR_TEMP_KELVIN) is not None:
await self.hass.async_add_executor_job(
self.data.set_color_temp, kwargs[ATTR_COLOR_TEMP_KELVIN]
self.data.set_color_temp, kwargs[ATTR_COLOR_TEMP_KELVIN], 0, True
)
await self.hass.async_add_executor_job(self.data.set_state_on)
await self.hass.async_add_executor_job(self.data.set_state_on, True)
await self.coordinator.async_refresh()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
await self.hass.async_add_executor_job(self.data.set_state_off)
await self.hass.async_add_executor_job(self.data.set_state_off, True)
await self.coordinator.async_refresh()

View File

@ -51,13 +51,13 @@ class FritzboxSwitch(FritzBoxDeviceEntity, SwitchEntity):
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on."""
self.check_lock_state()
await self.hass.async_add_executor_job(self.data.set_switch_state_on)
await self.hass.async_add_executor_job(self.data.set_switch_state_on, True)
await self.coordinator.async_refresh()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the switch off."""
self.check_lock_state()
await self.hass.async_add_executor_job(self.data.set_switch_state_off)
await self.hass.async_add_executor_job(self.data.set_switch_state_off, True)
await self.coordinator.async_refresh()
def check_lock_state(self) -> None:

View File

@ -273,20 +273,20 @@ async def test_update_error(hass: HomeAssistant, fritz: Mock) -> None:
@pytest.mark.parametrize(
("service_data", "expected_call_args"),
[
({ATTR_TEMPERATURE: 23}, [call(23)]),
({ATTR_TEMPERATURE: 23}, [call(23, True)]),
(
{
ATTR_HVAC_MODE: HVACMode.OFF,
ATTR_TEMPERATURE: 23,
},
[call(0)],
[call(0, True)],
),
(
{
ATTR_HVAC_MODE: HVACMode.HEAT,
ATTR_TEMPERATURE: 23,
},
[call(23)],
[call(23, True)],
),
],
)
@ -316,14 +316,14 @@ async def test_set_temperature(
("service_data", "target_temperature", "current_preset", "expected_call_args"),
[
# mode off always sets target temperature to 0
({ATTR_HVAC_MODE: HVACMode.OFF}, 22, PRESET_COMFORT, [call(0)]),
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, PRESET_ECO, [call(0)]),
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, None, [call(0)]),
({ATTR_HVAC_MODE: HVACMode.OFF}, 22, PRESET_COMFORT, [call(0, True)]),
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, PRESET_ECO, [call(0, True)]),
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, None, [call(0, True)]),
# mode heat sets target temperature based on current scheduled preset,
# when not already in mode heat
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, PRESET_COMFORT, [call(22)]),
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, PRESET_ECO, [call(16)]),
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, None, [call(22)]),
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, PRESET_COMFORT, [call(22, True)]),
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, PRESET_ECO, [call(16, True)]),
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, None, [call(22, True)]),
# mode heat does not set target temperature, when already in mode heat
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, PRESET_COMFORT, []),
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, PRESET_ECO, []),
@ -380,7 +380,7 @@ async def test_set_preset_mode_comfort(hass: HomeAssistant, fritz: Mock) -> None
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_COMFORT},
True,
)
assert device.set_target_temperature.call_args_list == [call(22)]
assert device.set_target_temperature.call_args_list == [call(22, True)]
async def test_set_preset_mode_eco(hass: HomeAssistant, fritz: Mock) -> None:
@ -396,7 +396,7 @@ async def test_set_preset_mode_eco(hass: HomeAssistant, fritz: Mock) -> None:
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_ECO},
True,
)
assert device.set_target_temperature.call_args_list == [call(16)]
assert device.set_target_temperature.call_args_list == [call(16, True)]
async def test_preset_mode_update(hass: HomeAssistant, fritz: Mock) -> None:

View File

@ -99,7 +99,7 @@ async def test_set_position_cover(hass: HomeAssistant, fritz: Mock) -> None:
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_POSITION: 50},
True,
)
assert device.set_level_percentage.call_args_list == [call(50)]
assert device.set_level_percentage.call_args_list == [call(50, True)]
async def test_stop_cover(hass: HomeAssistant, fritz: Mock) -> None:

View File

@ -155,8 +155,8 @@ async def test_turn_on(hass: HomeAssistant, fritz: Mock) -> None:
assert device.set_state_on.call_count == 1
assert device.set_level.call_count == 1
assert device.set_color_temp.call_count == 1
assert device.set_color_temp.call_args_list == [call(3000)]
assert device.set_level.call_args_list == [call(100)]
assert device.set_color_temp.call_args_list == [call(3000, 0, True)]
assert device.set_level.call_args_list == [call(100, True)]
async def test_turn_on_color(hass: HomeAssistant, fritz: Mock) -> None:
@ -178,9 +178,9 @@ async def test_turn_on_color(hass: HomeAssistant, fritz: Mock) -> None:
assert device.set_state_on.call_count == 1
assert device.set_level.call_count == 1
assert device.set_unmapped_color.call_count == 1
assert device.set_level.call_args_list == [call(100)]
assert device.set_level.call_args_list == [call(100, True)]
assert device.set_unmapped_color.call_args_list == [
call((100, round(70 * 255.0 / 100.0)))
call((100, round(70 * 255.0 / 100.0)), 0, True)
]
@ -212,8 +212,8 @@ async def test_turn_on_color_unsupported_api_method(
assert device.set_state_on.call_count == 1
assert device.set_level.call_count == 1
assert device.set_color.call_count == 1
assert device.set_level.call_args_list == [call(100)]
assert device.set_color.call_args_list == [call((100, 70))]
assert device.set_level.call_args_list == [call(100, True)]
assert device.set_color.call_args_list == [call((100, 70), 0, True)]
# test for unknown error
error.response.status_code = 500