mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Move Fritzbox power, energy and temperature switch attributes to sensors (#52562)
* deprecate switch entity properties * Add last_reset to FritzBoxEnergySensor * Remove obsolet temperature attribute
This commit is contained in:
parent
dee5d8903c
commit
42e8a7c842
@ -13,9 +13,6 @@ ATTR_STATE_WINDOW_OPEN: Final = "window_open"
|
||||
|
||||
ATTR_TEMPERATURE_UNIT: Final = "temperature_unit"
|
||||
|
||||
ATTR_TOTAL_CONSUMPTION: Final = "total_consumption"
|
||||
ATTR_TOTAL_CONSUMPTION_UNIT: Final = "total_consumption_unit"
|
||||
|
||||
CONF_CONNECTIONS: Final = "connections"
|
||||
CONF_COORDINATOR: Final = "coordinator"
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
"""Support for AVM FRITZ!SmartHome temperature sensor only devices."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
ATTR_STATE_CLASS,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
@ -13,12 +15,17 @@ from homeassistant.const import (
|
||||
ATTR_NAME,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
DEVICE_CLASS_BATTERY,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_POWER,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
PERCENTAGE,
|
||||
POWER_WATT,
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util.dt import utc_from_timestamp
|
||||
|
||||
from . import FritzBoxEntity
|
||||
from .const import (
|
||||
@ -68,11 +75,39 @@ async def async_setup_entry(
|
||||
)
|
||||
)
|
||||
|
||||
if device.has_powermeter:
|
||||
entities.append(
|
||||
FritzBoxPowerSensor(
|
||||
{
|
||||
ATTR_NAME: f"{device.name} Power Consumption",
|
||||
ATTR_ENTITY_ID: f"{device.ain}_power_consumption",
|
||||
ATTR_UNIT_OF_MEASUREMENT: POWER_WATT,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
coordinator,
|
||||
ain,
|
||||
)
|
||||
)
|
||||
entities.append(
|
||||
FritzBoxEnergySensor(
|
||||
{
|
||||
ATTR_NAME: f"{device.name} Total Energy",
|
||||
ATTR_ENTITY_ID: f"{device.ain}_total_energy",
|
||||
ATTR_UNIT_OF_MEASUREMENT: ENERGY_KILO_WATT_HOUR,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_ENERGY,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
coordinator,
|
||||
ain,
|
||||
)
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class FritzBoxBatterySensor(FritzBoxEntity, SensorEntity):
|
||||
"""The entity class for FRITZ!SmartHome sensors."""
|
||||
"""The entity class for FRITZ!SmartHome battery sensors."""
|
||||
|
||||
@property
|
||||
def state(self) -> int | None:
|
||||
@ -80,6 +115,30 @@ class FritzBoxBatterySensor(FritzBoxEntity, SensorEntity):
|
||||
return self.device.battery_level # type: ignore [no-any-return]
|
||||
|
||||
|
||||
class FritzBoxPowerSensor(FritzBoxEntity, SensorEntity):
|
||||
"""The entity class for FRITZ!SmartHome power consumption sensors."""
|
||||
|
||||
@property
|
||||
def state(self) -> float | None:
|
||||
"""Return the state of the sensor."""
|
||||
return self.device.power / 1000 # type: ignore [no-any-return]
|
||||
|
||||
|
||||
class FritzBoxEnergySensor(FritzBoxEntity, SensorEntity):
|
||||
"""The entity class for FRITZ!SmartHome total energy sensors."""
|
||||
|
||||
@property
|
||||
def state(self) -> float | None:
|
||||
"""Return the state of the sensor."""
|
||||
return (self.device.energy or 0.0) / 1000
|
||||
|
||||
@property
|
||||
def last_reset(self) -> datetime:
|
||||
"""Return the time when the sensor was last reset, if any."""
|
||||
# device does not provide timestamp of initialization
|
||||
return utc_from_timestamp(0)
|
||||
|
||||
|
||||
class FritzBoxTempSensor(FritzBoxEntity, SensorEntity):
|
||||
"""The entity class for FRITZ!SmartHome temperature sensors."""
|
||||
|
||||
|
@ -10,10 +10,7 @@ from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_NAME,
|
||||
ATTR_TEMPERATURE,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
@ -22,16 +19,11 @@ from . import FritzBoxEntity
|
||||
from .const import (
|
||||
ATTR_STATE_DEVICE_LOCKED,
|
||||
ATTR_STATE_LOCKED,
|
||||
ATTR_TEMPERATURE_UNIT,
|
||||
ATTR_TOTAL_CONSUMPTION,
|
||||
ATTR_TOTAL_CONSUMPTION_UNIT,
|
||||
CONF_COORDINATOR,
|
||||
DOMAIN as FRITZBOX_DOMAIN,
|
||||
)
|
||||
from .model import SwitchExtraAttributes
|
||||
|
||||
ATTR_TOTAL_CONSUMPTION_UNIT_VALUE = ENERGY_KILO_WATT_HOUR
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
@ -91,22 +83,4 @@ class FritzboxSwitch(FritzBoxEntity, SwitchEntity):
|
||||
ATTR_STATE_DEVICE_LOCKED: self.device.device_lock,
|
||||
ATTR_STATE_LOCKED: self.device.lock,
|
||||
}
|
||||
|
||||
if self.device.has_powermeter:
|
||||
attrs[
|
||||
ATTR_TOTAL_CONSUMPTION
|
||||
] = f"{((self.device.energy or 0.0) / 1000):.3f}"
|
||||
attrs[ATTR_TOTAL_CONSUMPTION_UNIT] = ATTR_TOTAL_CONSUMPTION_UNIT_VALUE
|
||||
if self.device.has_temperature_sensor:
|
||||
attrs[ATTR_TEMPERATURE] = str(
|
||||
self.hass.config.units.temperature(
|
||||
self.device.temperature, TEMP_CELSIUS
|
||||
)
|
||||
)
|
||||
attrs[ATTR_TEMPERATURE_UNIT] = self.hass.config.units.temperature_unit
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def current_power_w(self) -> float:
|
||||
"""Return the current power usage in W."""
|
||||
return self.device.power / 1000 # type: ignore [no-any-return]
|
||||
|
@ -55,6 +55,7 @@ class FritzDeviceBinarySensorMock(FritzDeviceBaseMock):
|
||||
battery_level = 23
|
||||
fw_version = "1.2.3"
|
||||
has_alarm = True
|
||||
has_powermeter = False
|
||||
has_switch = False
|
||||
has_temperature_sensor = False
|
||||
has_thermostat = False
|
||||
@ -73,6 +74,7 @@ class FritzDeviceClimateMock(FritzDeviceBaseMock):
|
||||
eco_temperature = 16.0
|
||||
fw_version = "1.2.3"
|
||||
has_alarm = False
|
||||
has_powermeter = False
|
||||
has_switch = False
|
||||
has_temperature_sensor = False
|
||||
has_thermostat = True
|
||||
@ -91,6 +93,7 @@ class FritzDeviceSensorMock(FritzDeviceBaseMock):
|
||||
device_lock = "fake_locked_device"
|
||||
fw_version = "1.2.3"
|
||||
has_alarm = False
|
||||
has_powermeter = False
|
||||
has_switch = False
|
||||
has_temperature_sensor = True
|
||||
has_thermostat = False
|
||||
@ -107,6 +110,7 @@ class FritzDeviceSwitchMock(FritzDeviceBaseMock):
|
||||
energy = 1234
|
||||
fw_version = "1.2.3"
|
||||
has_alarm = False
|
||||
has_powermeter = True
|
||||
has_switch = True
|
||||
has_temperature_sensor = True
|
||||
has_thermostat = False
|
||||
|
@ -7,24 +7,22 @@ from requests.exceptions import HTTPError
|
||||
from homeassistant.components.fritzbox.const import (
|
||||
ATTR_STATE_DEVICE_LOCKED,
|
||||
ATTR_STATE_LOCKED,
|
||||
ATTR_TEMPERATURE_UNIT,
|
||||
ATTR_TOTAL_CONSUMPTION,
|
||||
ATTR_TOTAL_CONSUMPTION_UNIT,
|
||||
DOMAIN as FB_DOMAIN,
|
||||
)
|
||||
from homeassistant.components.sensor import (
|
||||
ATTR_LAST_RESET,
|
||||
ATTR_STATE_CLASS,
|
||||
DOMAIN as SENSOR_DOMAIN,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
)
|
||||
from homeassistant.components.switch import ATTR_CURRENT_POWER_W, DOMAIN
|
||||
from homeassistant.components.switch import DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_FRIENDLY_NAME,
|
||||
ATTR_TEMPERATURE,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_DEVICES,
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
POWER_WATT,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
STATE_ON,
|
||||
@ -51,14 +49,9 @@ async def test_setup(hass: HomeAssistant, fritz: Mock):
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes[ATTR_CURRENT_POWER_W] == 5.678
|
||||
assert state.attributes[ATTR_FRIENDLY_NAME] == CONF_FAKE_NAME
|
||||
assert state.attributes[ATTR_STATE_DEVICE_LOCKED] == "fake_locked_device"
|
||||
assert state.attributes[ATTR_STATE_LOCKED] == "fake_locked"
|
||||
assert state.attributes[ATTR_TEMPERATURE] == "1.23"
|
||||
assert state.attributes[ATTR_TEMPERATURE_UNIT] == TEMP_CELSIUS
|
||||
assert state.attributes[ATTR_TOTAL_CONSUMPTION] == "1.234"
|
||||
assert state.attributes[ATTR_TOTAL_CONSUMPTION_UNIT] == ENERGY_KILO_WATT_HOUR
|
||||
assert ATTR_STATE_CLASS not in state.attributes
|
||||
|
||||
state = hass.states.get(f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_temperature")
|
||||
@ -70,6 +63,21 @@ async def test_setup(hass: HomeAssistant, fritz: Mock):
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == TEMP_CELSIUS
|
||||
assert state.attributes[ATTR_STATE_CLASS] == STATE_CLASS_MEASUREMENT
|
||||
|
||||
state = hass.states.get(f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_power_consumption")
|
||||
assert state
|
||||
assert state.state == "5.678"
|
||||
assert state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Power Consumption"
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == POWER_WATT
|
||||
assert state.attributes[ATTR_STATE_CLASS] == STATE_CLASS_MEASUREMENT
|
||||
|
||||
state = hass.states.get(f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_total_energy")
|
||||
assert state
|
||||
assert state.state == "1.234"
|
||||
assert state.attributes[ATTR_LAST_RESET] == "1970-01-01T00:00:00+00:00"
|
||||
assert state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Total Energy"
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == ENERGY_KILO_WATT_HOUR
|
||||
assert ATTR_STATE_CLASS not in state.attributes
|
||||
|
||||
|
||||
async def test_turn_on(hass: HomeAssistant, fritz: Mock):
|
||||
"""Test turn device on."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user