mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 22:27:07 +00:00
Remove boost and off temperature workaround from AVM Fritz!SmartHome (#142863)
* remove workaround * remove hvacmode from mapping dict
This commit is contained in:
parent
1bfd585f3c
commit
253cc377b4
@ -53,8 +53,11 @@ MAX_TEMPERATURE = 28
|
|||||||
# special temperatures for on/off in Fritz!Box API (modified by pyfritzhome)
|
# special temperatures for on/off in Fritz!Box API (modified by pyfritzhome)
|
||||||
ON_API_TEMPERATURE = 127.0
|
ON_API_TEMPERATURE = 127.0
|
||||||
OFF_API_TEMPERATURE = 126.5
|
OFF_API_TEMPERATURE = 126.5
|
||||||
ON_REPORT_SET_TEMPERATURE = 30.0
|
PRESET_API_HKR_STATE_MAPPING = {
|
||||||
OFF_REPORT_SET_TEMPERATURE = 0.0
|
PRESET_COMFORT: "comfort",
|
||||||
|
PRESET_BOOST: "on",
|
||||||
|
PRESET_ECO: "eco",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
@ -128,29 +131,28 @@ class FritzboxThermostat(FritzBoxDeviceEntity, ClimateEntity):
|
|||||||
return self.data.actual_temperature # type: ignore [no-any-return]
|
return self.data.actual_temperature # type: ignore [no-any-return]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_temperature(self) -> float:
|
def target_temperature(self) -> float | None:
|
||||||
"""Return the temperature we try to reach."""
|
"""Return the temperature we try to reach."""
|
||||||
if self.data.target_temperature == ON_API_TEMPERATURE:
|
if self.data.target_temperature in [ON_API_TEMPERATURE, OFF_API_TEMPERATURE]:
|
||||||
return ON_REPORT_SET_TEMPERATURE
|
return None
|
||||||
if self.data.target_temperature == OFF_API_TEMPERATURE:
|
|
||||||
return OFF_REPORT_SET_TEMPERATURE
|
|
||||||
return self.data.target_temperature # type: ignore [no-any-return]
|
return self.data.target_temperature # type: ignore [no-any-return]
|
||||||
|
|
||||||
|
async def async_set_hkr_state(self, hkr_state: str) -> None:
|
||||||
|
"""Set the state of the climate."""
|
||||||
|
await self.hass.async_add_executor_job(self.data.set_hkr_state, hkr_state, True)
|
||||||
|
await self.coordinator.async_refresh()
|
||||||
|
|
||||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||||
"""Set new target temperature."""
|
"""Set new target temperature."""
|
||||||
if (hvac_mode := kwargs.get(ATTR_HVAC_MODE)) is HVACMode.OFF:
|
if kwargs.get(ATTR_HVAC_MODE) is HVACMode.OFF:
|
||||||
await self.async_set_hvac_mode(hvac_mode)
|
await self.async_set_hkr_state("off")
|
||||||
elif (target_temp := kwargs.get(ATTR_TEMPERATURE)) is not None:
|
elif (target_temp := kwargs.get(ATTR_TEMPERATURE)) is not None:
|
||||||
if target_temp == OFF_API_TEMPERATURE:
|
|
||||||
target_temp = OFF_REPORT_SET_TEMPERATURE
|
|
||||||
elif target_temp == ON_API_TEMPERATURE:
|
|
||||||
target_temp = ON_REPORT_SET_TEMPERATURE
|
|
||||||
await self.hass.async_add_executor_job(
|
await self.hass.async_add_executor_job(
|
||||||
self.data.set_target_temperature, target_temp, True
|
self.data.set_target_temperature, target_temp, True
|
||||||
)
|
)
|
||||||
|
await self.coordinator.async_refresh()
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
await self.coordinator.async_refresh()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_mode(self) -> HVACMode:
|
def hvac_mode(self) -> HVACMode:
|
||||||
@ -159,10 +161,7 @@ class FritzboxThermostat(FritzBoxDeviceEntity, ClimateEntity):
|
|||||||
return HVACMode.HEAT
|
return HVACMode.HEAT
|
||||||
if self.data.summer_active:
|
if self.data.summer_active:
|
||||||
return HVACMode.OFF
|
return HVACMode.OFF
|
||||||
if self.data.target_temperature in (
|
if self.data.target_temperature == OFF_API_TEMPERATURE:
|
||||||
OFF_REPORT_SET_TEMPERATURE,
|
|
||||||
OFF_API_TEMPERATURE,
|
|
||||||
):
|
|
||||||
return HVACMode.OFF
|
return HVACMode.OFF
|
||||||
|
|
||||||
return HVACMode.HEAT
|
return HVACMode.HEAT
|
||||||
@ -180,7 +179,7 @@ class FritzboxThermostat(FritzBoxDeviceEntity, ClimateEntity):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
if hvac_mode is HVACMode.OFF:
|
if hvac_mode is HVACMode.OFF:
|
||||||
await self.async_set_temperature(temperature=OFF_REPORT_SET_TEMPERATURE)
|
await self.async_set_hkr_state("off")
|
||||||
else:
|
else:
|
||||||
if value_scheduled_preset(self.data) == PRESET_ECO:
|
if value_scheduled_preset(self.data) == PRESET_ECO:
|
||||||
target_temp = self.data.eco_temperature
|
target_temp = self.data.eco_temperature
|
||||||
@ -210,12 +209,7 @@ class FritzboxThermostat(FritzBoxDeviceEntity, ClimateEntity):
|
|||||||
translation_domain=DOMAIN,
|
translation_domain=DOMAIN,
|
||||||
translation_key="change_preset_while_active_mode",
|
translation_key="change_preset_while_active_mode",
|
||||||
)
|
)
|
||||||
if preset_mode == PRESET_COMFORT:
|
await self.async_set_hkr_state(PRESET_API_HKR_STATE_MAPPING[preset_mode])
|
||||||
await self.async_set_temperature(temperature=self.data.comfort_temperature)
|
|
||||||
elif preset_mode == PRESET_ECO:
|
|
||||||
await self.async_set_temperature(temperature=self.data.eco_temperature)
|
|
||||||
elif preset_mode == PRESET_BOOST:
|
|
||||||
await self.async_set_temperature(temperature=ON_REPORT_SET_TEMPERATURE)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> ClimateExtraAttributes:
|
def extra_state_attributes(self) -> ClimateExtraAttributes:
|
||||||
|
@ -94,7 +94,7 @@ async def test_target_temperature_on(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
|
|
||||||
state = hass.states.get(ENTITY_ID)
|
state = hass.states.get(ENTITY_ID)
|
||||||
assert state
|
assert state
|
||||||
assert state.attributes[ATTR_TEMPERATURE] == 30
|
assert state.attributes[ATTR_TEMPERATURE] is None
|
||||||
|
|
||||||
|
|
||||||
async def test_target_temperature_off(hass: HomeAssistant, fritz: Mock) -> None:
|
async def test_target_temperature_off(hass: HomeAssistant, fritz: Mock) -> None:
|
||||||
@ -107,7 +107,7 @@ async def test_target_temperature_off(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
|
|
||||||
state = hass.states.get(ENTITY_ID)
|
state = hass.states.get(ENTITY_ID)
|
||||||
assert state
|
assert state
|
||||||
assert state.attributes[ATTR_TEMPERATURE] == 0
|
assert state.attributes[ATTR_TEMPERATURE] is None
|
||||||
|
|
||||||
|
|
||||||
async def test_update(hass: HomeAssistant, fritz: Mock) -> None:
|
async def test_update(hass: HomeAssistant, fritz: Mock) -> None:
|
||||||
@ -177,15 +177,20 @@ async def test_update_error(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("service_data", "expected_call_args"),
|
(
|
||||||
|
"service_data",
|
||||||
|
"expected_set_target_temperature_call_args",
|
||||||
|
"expected_set_hkr_state_call_args",
|
||||||
|
),
|
||||||
[
|
[
|
||||||
({ATTR_TEMPERATURE: 23}, [call(23, True)]),
|
({ATTR_TEMPERATURE: 23}, [call(23, True)], []),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
ATTR_HVAC_MODE: HVACMode.OFF,
|
ATTR_HVAC_MODE: HVACMode.OFF,
|
||||||
ATTR_TEMPERATURE: 23,
|
ATTR_TEMPERATURE: 23,
|
||||||
},
|
},
|
||||||
[call(0, True)],
|
[],
|
||||||
|
[call("off", True)],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -193,6 +198,7 @@ async def test_update_error(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
ATTR_TEMPERATURE: 23,
|
ATTR_TEMPERATURE: 23,
|
||||||
},
|
},
|
||||||
[call(23, True)],
|
[call(23, True)],
|
||||||
|
[],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -200,7 +206,8 @@ async def test_set_temperature(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
fritz: Mock,
|
fritz: Mock,
|
||||||
service_data: dict,
|
service_data: dict,
|
||||||
expected_call_args: list[_Call],
|
expected_set_target_temperature_call_args: list[_Call],
|
||||||
|
expected_set_hkr_state_call_args: list[_Call],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test setting temperature."""
|
"""Test setting temperature."""
|
||||||
device = FritzDeviceClimateMock()
|
device = FritzDeviceClimateMock()
|
||||||
@ -214,29 +221,60 @@ async def test_set_temperature(
|
|||||||
{ATTR_ENTITY_ID: ENTITY_ID, **service_data},
|
{ATTR_ENTITY_ID: ENTITY_ID, **service_data},
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
assert device.set_target_temperature.call_count == len(expected_call_args)
|
assert device.set_target_temperature.call_count == len(
|
||||||
assert device.set_target_temperature.call_args_list == expected_call_args
|
expected_set_target_temperature_call_args
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
device.set_target_temperature.call_args_list
|
||||||
|
== expected_set_target_temperature_call_args
|
||||||
|
)
|
||||||
|
assert device.set_hkr_state.call_count == len(expected_set_hkr_state_call_args)
|
||||||
|
assert device.set_hkr_state.call_args_list == expected_set_hkr_state_call_args
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("service_data", "target_temperature", "current_preset", "expected_call_args"),
|
(
|
||||||
|
"service_data",
|
||||||
|
"target_temperature",
|
||||||
|
"current_preset",
|
||||||
|
"expected_set_target_temperature_call_args",
|
||||||
|
"expected_set_hkr_state_call_args",
|
||||||
|
),
|
||||||
[
|
[
|
||||||
# mode off always sets target temperature to 0
|
# mode off always sets hkr state off
|
||||||
({ATTR_HVAC_MODE: HVACMode.OFF}, 22, PRESET_COMFORT, [call(0, True)]),
|
({ATTR_HVAC_MODE: HVACMode.OFF}, 22, PRESET_COMFORT, [], [call("off", True)]),
|
||||||
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, PRESET_ECO, [call(0, True)]),
|
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, PRESET_ECO, [], [call("off", True)]),
|
||||||
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, None, [call(0, True)]),
|
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, None, [], [call("off", True)]),
|
||||||
# mode heat sets target temperature based on current scheduled preset,
|
# mode heat sets target temperature based on current scheduled preset,
|
||||||
# when not already in mode heat
|
# when not already in mode heat
|
||||||
({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},
|
||||||
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, None, [call(22, True)]),
|
OFF_API_TEMPERATURE,
|
||||||
|
PRESET_COMFORT,
|
||||||
|
[call(22, True)],
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{ATTR_HVAC_MODE: HVACMode.HEAT},
|
||||||
|
OFF_API_TEMPERATURE,
|
||||||
|
PRESET_ECO,
|
||||||
|
[call(16, True)],
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{ATTR_HVAC_MODE: HVACMode.HEAT},
|
||||||
|
OFF_API_TEMPERATURE,
|
||||||
|
None,
|
||||||
|
[call(22, True)],
|
||||||
|
[],
|
||||||
|
),
|
||||||
# mode heat does not set target temperature, when already in mode heat
|
# 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_COMFORT, [], []),
|
||||||
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, PRESET_ECO, []),
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, PRESET_ECO, [], []),
|
||||||
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, None, []),
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, None, [], []),
|
||||||
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, PRESET_COMFORT, []),
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, PRESET_COMFORT, [], []),
|
||||||
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, PRESET_ECO, []),
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, PRESET_ECO, [], []),
|
||||||
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, None, []),
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, None, [], []),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_set_hvac_mode(
|
async def test_set_hvac_mode(
|
||||||
@ -245,7 +283,8 @@ async def test_set_hvac_mode(
|
|||||||
service_data: dict,
|
service_data: dict,
|
||||||
target_temperature: float,
|
target_temperature: float,
|
||||||
current_preset: str,
|
current_preset: str,
|
||||||
expected_call_args: list[_Call],
|
expected_set_target_temperature_call_args: list[_Call],
|
||||||
|
expected_set_hkr_state_call_args: list[_Call],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test setting hvac mode."""
|
"""Test setting hvac mode."""
|
||||||
device = FritzDeviceClimateMock()
|
device = FritzDeviceClimateMock()
|
||||||
@ -269,16 +308,23 @@ async def test_set_hvac_mode(
|
|||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert device.set_target_temperature.call_count == len(expected_call_args)
|
assert device.set_target_temperature.call_count == len(
|
||||||
assert device.set_target_temperature.call_args_list == expected_call_args
|
expected_set_target_temperature_call_args
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
device.set_target_temperature.call_args_list
|
||||||
|
== expected_set_target_temperature_call_args
|
||||||
|
)
|
||||||
|
assert device.set_hkr_state.call_count == len(expected_set_hkr_state_call_args)
|
||||||
|
assert device.set_hkr_state.call_args_list == expected_set_hkr_state_call_args
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("comfort_temperature", "expected_call_args"),
|
("comfort_temperature", "expected_call_args"),
|
||||||
[
|
[
|
||||||
(20, [call(20, True)]),
|
(20, [call("comfort", True)]),
|
||||||
(28, [call(28, True)]),
|
(28, [call("comfort", True)]),
|
||||||
(ON_API_TEMPERATURE, [call(30, True)]),
|
(ON_API_TEMPERATURE, [call("comfort", True)]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_set_preset_mode_comfort(
|
async def test_set_preset_mode_comfort(
|
||||||
@ -300,16 +346,16 @@ async def test_set_preset_mode_comfort(
|
|||||||
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_COMFORT},
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_COMFORT},
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
assert device.set_target_temperature.call_count == len(expected_call_args)
|
assert device.set_hkr_state.call_count == len(expected_call_args)
|
||||||
assert device.set_target_temperature.call_args_list == expected_call_args
|
assert device.set_hkr_state.call_args_list == expected_call_args
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("eco_temperature", "expected_call_args"),
|
("eco_temperature", "expected_call_args"),
|
||||||
[
|
[
|
||||||
(20, [call(20, True)]),
|
(20, [call("eco", True)]),
|
||||||
(16, [call(16, True)]),
|
(16, [call("eco", True)]),
|
||||||
(OFF_API_TEMPERATURE, [call(0, True)]),
|
(OFF_API_TEMPERATURE, [call("eco", True)]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_set_preset_mode_eco(
|
async def test_set_preset_mode_eco(
|
||||||
@ -331,8 +377,8 @@ async def test_set_preset_mode_eco(
|
|||||||
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_ECO},
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_ECO},
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
assert device.set_target_temperature.call_count == len(expected_call_args)
|
assert device.set_hkr_state.call_count == len(expected_call_args)
|
||||||
assert device.set_target_temperature.call_args_list == expected_call_args
|
assert device.set_hkr_state.call_args_list == expected_call_args
|
||||||
|
|
||||||
|
|
||||||
async def test_set_preset_mode_boost(
|
async def test_set_preset_mode_boost(
|
||||||
@ -351,8 +397,8 @@ async def test_set_preset_mode_boost(
|
|||||||
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_BOOST},
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_BOOST},
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
assert device.set_target_temperature.call_count == 1
|
assert device.set_hkr_state.call_count == 1
|
||||||
assert device.set_target_temperature.call_args_list == [call(30, True)]
|
assert device.set_hkr_state.call_args_list == [call("on", True)]
|
||||||
|
|
||||||
|
|
||||||
async def test_preset_mode_update(hass: HomeAssistant, fritz: Mock) -> None:
|
async def test_preset_mode_update(hass: HomeAssistant, fritz: Mock) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user