mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
Fix next change (scheduler) sensors in AVM FRITZ!SmartHome (#126363)
This commit is contained in:
parent
fba24b8ead
commit
4eb1fca68e
@ -83,20 +83,38 @@ def entity_category_temperature(device: FritzhomeDevice) -> EntityCategory | Non
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def value_nextchange_preset(device: FritzhomeDevice) -> str:
|
def value_nextchange_preset(device: FritzhomeDevice) -> str | None:
|
||||||
"""Return native value for next scheduled preset sensor."""
|
"""Return native value for next scheduled preset sensor."""
|
||||||
|
if not device.nextchange_endperiod:
|
||||||
|
return None
|
||||||
if device.nextchange_temperature == device.eco_temperature:
|
if device.nextchange_temperature == device.eco_temperature:
|
||||||
return PRESET_ECO
|
return PRESET_ECO
|
||||||
return PRESET_COMFORT
|
return PRESET_COMFORT
|
||||||
|
|
||||||
|
|
||||||
def value_scheduled_preset(device: FritzhomeDevice) -> str:
|
def value_scheduled_preset(device: FritzhomeDevice) -> str | None:
|
||||||
"""Return native value for current scheduled preset sensor."""
|
"""Return native value for current scheduled preset sensor."""
|
||||||
|
if not device.nextchange_endperiod:
|
||||||
|
return None
|
||||||
if device.nextchange_temperature == device.eco_temperature:
|
if device.nextchange_temperature == device.eco_temperature:
|
||||||
return PRESET_COMFORT
|
return PRESET_COMFORT
|
||||||
return PRESET_ECO
|
return PRESET_ECO
|
||||||
|
|
||||||
|
|
||||||
|
def value_nextchange_temperature(device: FritzhomeDevice) -> float | None:
|
||||||
|
"""Return native value for next scheduled temperature time sensor."""
|
||||||
|
if device.nextchange_endperiod and isinstance(device.nextchange_temperature, float):
|
||||||
|
return device.nextchange_temperature
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def value_nextchange_time(device: FritzhomeDevice) -> datetime | None:
|
||||||
|
"""Return native value for next scheduled changed time sensor."""
|
||||||
|
if device.nextchange_endperiod:
|
||||||
|
return utc_from_timestamp(device.nextchange_endperiod)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||||
FritzSensorEntityDescription(
|
FritzSensorEntityDescription(
|
||||||
key="temperature",
|
key="temperature",
|
||||||
@ -181,7 +199,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
|||||||
device_class=SensorDeviceClass.TEMPERATURE,
|
device_class=SensorDeviceClass.TEMPERATURE,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
suitable=suitable_nextchange_temperature,
|
suitable=suitable_nextchange_temperature,
|
||||||
native_value=lambda device: device.nextchange_temperature,
|
native_value=value_nextchange_temperature,
|
||||||
),
|
),
|
||||||
FritzSensorEntityDescription(
|
FritzSensorEntityDescription(
|
||||||
key="nextchange_time",
|
key="nextchange_time",
|
||||||
@ -189,7 +207,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
|||||||
device_class=SensorDeviceClass.TIMESTAMP,
|
device_class=SensorDeviceClass.TIMESTAMP,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
suitable=suitable_nextchange_time,
|
suitable=suitable_nextchange_time,
|
||||||
native_value=lambda device: utc_from_timestamp(device.nextchange_endperiod),
|
native_value=value_nextchange_time,
|
||||||
),
|
),
|
||||||
FritzSensorEntityDescription(
|
FritzSensorEntityDescription(
|
||||||
key="nextchange_preset",
|
key="nextchange_preset",
|
||||||
|
@ -5,7 +5,6 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from homeassistant.components.climate import PRESET_COMFORT, PRESET_ECO
|
|
||||||
from homeassistant.components.fritzbox.const import DOMAIN
|
from homeassistant.components.fritzbox.const import DOMAIN
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
@ -110,9 +109,7 @@ class FritzDeviceClimateMock(FritzEntityBaseMock):
|
|||||||
target_temperature = 19.5
|
target_temperature = 19.5
|
||||||
window_open = "fake_window"
|
window_open = "fake_window"
|
||||||
nextchange_temperature = 22.0
|
nextchange_temperature = 22.0
|
||||||
nextchange_endperiod = 0
|
nextchange_endperiod = 1726855200
|
||||||
nextchange_preset = PRESET_COMFORT
|
|
||||||
scheduled_preset = PRESET_ECO
|
|
||||||
|
|
||||||
|
|
||||||
class FritzDeviceClimateWithoutTempSensorMock(FritzDeviceClimateMock):
|
class FritzDeviceClimateWithoutTempSensorMock(FritzDeviceClimateMock):
|
||||||
|
@ -123,7 +123,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_next_scheduled_change_time"
|
f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_next_scheduled_change_time"
|
||||||
)
|
)
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "1970-01-01T00:00:00+00:00"
|
assert state.state == "2024-09-20T18:00:00+00:00"
|
||||||
assert (
|
assert (
|
||||||
state.attributes[ATTR_FRIENDLY_NAME]
|
state.attributes[ATTR_FRIENDLY_NAME]
|
||||||
== f"{CONF_FAKE_NAME} Next scheduled change time"
|
== f"{CONF_FAKE_NAME} Next scheduled change time"
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
from requests.exceptions import HTTPError
|
from requests.exceptions import HTTPError
|
||||||
|
|
||||||
|
from homeassistant.components.climate import PRESET_COMFORT, PRESET_ECO
|
||||||
from homeassistant.components.fritzbox.const import DOMAIN as FB_DOMAIN
|
from homeassistant.components.fritzbox.const import DOMAIN as FB_DOMAIN
|
||||||
from homeassistant.components.sensor import ATTR_STATE_CLASS, DOMAIN, SensorStateClass
|
from homeassistant.components.sensor import ATTR_STATE_CLASS, DOMAIN, SensorStateClass
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -12,6 +14,7 @@ from homeassistant.const import (
|
|||||||
ATTR_UNIT_OF_MEASUREMENT,
|
ATTR_UNIT_OF_MEASUREMENT,
|
||||||
CONF_DEVICES,
|
CONF_DEVICES,
|
||||||
PERCENTAGE,
|
PERCENTAGE,
|
||||||
|
STATE_UNKNOWN,
|
||||||
EntityCategory,
|
EntityCategory,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
@ -19,7 +22,12 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from . import FritzDeviceSensorMock, set_devices, setup_config_entry
|
from . import (
|
||||||
|
FritzDeviceClimateMock,
|
||||||
|
FritzDeviceSensorMock,
|
||||||
|
set_devices,
|
||||||
|
setup_config_entry,
|
||||||
|
)
|
||||||
from .const import CONF_FAKE_NAME, MOCK_CONFIG
|
from .const import CONF_FAKE_NAME, MOCK_CONFIG
|
||||||
|
|
||||||
from tests.common import async_fire_time_changed
|
from tests.common import async_fire_time_changed
|
||||||
@ -132,3 +140,55 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
|
|
||||||
state = hass.states.get(f"{DOMAIN}.new_device_temperature")
|
state = hass.states.get(f"{DOMAIN}.new_device_temperature")
|
||||||
assert state
|
assert state
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("next_changes", "expected_states"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
[0, 16],
|
||||||
|
[STATE_UNKNOWN, STATE_UNKNOWN, STATE_UNKNOWN, STATE_UNKNOWN],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
[0, 22],
|
||||||
|
[STATE_UNKNOWN, STATE_UNKNOWN, STATE_UNKNOWN, STATE_UNKNOWN],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
[1726855200, 16.0],
|
||||||
|
["2024-09-20T18:00:00+00:00", "16.0", PRESET_ECO, PRESET_COMFORT],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
[1726855200, 22.0],
|
||||||
|
["2024-09-20T18:00:00+00:00", "22.0", PRESET_COMFORT, PRESET_ECO],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_next_change_sensors(
|
||||||
|
hass: HomeAssistant, fritz: Mock, next_changes: list, expected_states: list
|
||||||
|
) -> None:
|
||||||
|
"""Test next change sensors."""
|
||||||
|
device = FritzDeviceClimateMock()
|
||||||
|
device.nextchange_endperiod = next_changes[0]
|
||||||
|
device.nextchange_temperature = next_changes[1]
|
||||||
|
|
||||||
|
assert await setup_config_entry(
|
||||||
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
||||||
|
)
|
||||||
|
|
||||||
|
base_name = f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}"
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_name}_next_scheduled_change_time")
|
||||||
|
assert state
|
||||||
|
assert state.state == expected_states[0]
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_name}_next_scheduled_temperature")
|
||||||
|
assert state
|
||||||
|
assert state.state == expected_states[1]
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_name}_next_scheduled_preset")
|
||||||
|
assert state
|
||||||
|
assert state.state == expected_states[2]
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_name}_current_scheduled_preset")
|
||||||
|
assert state
|
||||||
|
assert state.state == expected_states[3]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user