mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 23:27:37 +00:00
Refactor Fronius sensor device class and long term statistics (#54185)
This commit is contained in:
parent
2720ba2753
commit
539ed56000
@ -12,7 +12,6 @@ from homeassistant.components.sensor import (
|
|||||||
PLATFORM_SCHEMA,
|
PLATFORM_SCHEMA,
|
||||||
STATE_CLASS_MEASUREMENT,
|
STATE_CLASS_MEASUREMENT,
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
SensorEntityDescription,
|
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_DEVICE,
|
CONF_DEVICE,
|
||||||
@ -20,8 +19,14 @@ from homeassistant.const import (
|
|||||||
CONF_RESOURCE,
|
CONF_RESOURCE,
|
||||||
CONF_SCAN_INTERVAL,
|
CONF_SCAN_INTERVAL,
|
||||||
CONF_SENSOR_TYPE,
|
CONF_SENSOR_TYPE,
|
||||||
|
DEVICE_CLASS_BATTERY,
|
||||||
|
DEVICE_CLASS_CURRENT,
|
||||||
DEVICE_CLASS_ENERGY,
|
DEVICE_CLASS_ENERGY,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_POWER,
|
||||||
|
DEVICE_CLASS_POWER_FACTOR,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
DEVICE_CLASS_TIMESTAMP,
|
||||||
|
DEVICE_CLASS_VOLTAGE,
|
||||||
)
|
)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
@ -48,6 +53,17 @@ DEFAULT_SCAN_INTERVAL = timedelta(seconds=60)
|
|||||||
SENSOR_TYPES = [TYPE_INVERTER, TYPE_STORAGE, TYPE_METER, TYPE_POWER_FLOW]
|
SENSOR_TYPES = [TYPE_INVERTER, TYPE_STORAGE, TYPE_METER, TYPE_POWER_FLOW]
|
||||||
SCOPE_TYPES = [SCOPE_DEVICE, SCOPE_SYSTEM]
|
SCOPE_TYPES = [SCOPE_DEVICE, SCOPE_SYSTEM]
|
||||||
|
|
||||||
|
PREFIX_DEVICE_CLASS_MAPPING = [
|
||||||
|
("state_of_charge", DEVICE_CLASS_BATTERY),
|
||||||
|
("temperature", DEVICE_CLASS_TEMPERATURE),
|
||||||
|
("power_factor", DEVICE_CLASS_POWER_FACTOR),
|
||||||
|
("power", DEVICE_CLASS_POWER),
|
||||||
|
("energy", DEVICE_CLASS_ENERGY),
|
||||||
|
("current", DEVICE_CLASS_CURRENT),
|
||||||
|
("timestamp", DEVICE_CLASS_TIMESTAMP),
|
||||||
|
("voltage", DEVICE_CLASS_VOLTAGE),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def _device_id_validator(config):
|
def _device_id_validator(config):
|
||||||
"""Ensure that inverters have default id 1 and other devices 0."""
|
"""Ensure that inverters have default id 1 and other devices 0."""
|
||||||
@ -161,12 +177,6 @@ class FroniusAdapter:
|
|||||||
"""Whether the fronius device is active."""
|
"""Whether the fronius device is active."""
|
||||||
return self._available
|
return self._available
|
||||||
|
|
||||||
def entity_description( # pylint: disable=no-self-use
|
|
||||||
self, key
|
|
||||||
) -> SensorEntityDescription | None:
|
|
||||||
"""Create entity description for a key."""
|
|
||||||
return None
|
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Retrieve and update latest state."""
|
"""Retrieve and update latest state."""
|
||||||
try:
|
try:
|
||||||
@ -223,18 +233,6 @@ class FroniusAdapter:
|
|||||||
class FroniusInverterSystem(FroniusAdapter):
|
class FroniusInverterSystem(FroniusAdapter):
|
||||||
"""Adapter for the fronius inverter with system scope."""
|
"""Adapter for the fronius inverter with system scope."""
|
||||||
|
|
||||||
def entity_description(self, key):
|
|
||||||
"""Return the entity descriptor."""
|
|
||||||
if key != "energy_total":
|
|
||||||
return None
|
|
||||||
|
|
||||||
return SensorEntityDescription(
|
|
||||||
key=key,
|
|
||||||
device_class=DEVICE_CLASS_ENERGY,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
last_reset=dt.utc_from_timestamp(0),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _update(self):
|
async def _update(self):
|
||||||
"""Get the values for the current state."""
|
"""Get the values for the current state."""
|
||||||
return await self.bridge.current_system_inverter_data()
|
return await self.bridge.current_system_inverter_data()
|
||||||
@ -243,18 +241,6 @@ class FroniusInverterSystem(FroniusAdapter):
|
|||||||
class FroniusInverterDevice(FroniusAdapter):
|
class FroniusInverterDevice(FroniusAdapter):
|
||||||
"""Adapter for the fronius inverter with device scope."""
|
"""Adapter for the fronius inverter with device scope."""
|
||||||
|
|
||||||
def entity_description(self, key):
|
|
||||||
"""Return the entity descriptor."""
|
|
||||||
if key != "energy_total":
|
|
||||||
return None
|
|
||||||
|
|
||||||
return SensorEntityDescription(
|
|
||||||
key=key,
|
|
||||||
device_class=DEVICE_CLASS_ENERGY,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
last_reset=dt.utc_from_timestamp(0),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _update(self):
|
async def _update(self):
|
||||||
"""Get the values for the current state."""
|
"""Get the values for the current state."""
|
||||||
return await self.bridge.current_inverter_data(self._device)
|
return await self.bridge.current_inverter_data(self._device)
|
||||||
@ -271,18 +257,6 @@ class FroniusStorage(FroniusAdapter):
|
|||||||
class FroniusMeterSystem(FroniusAdapter):
|
class FroniusMeterSystem(FroniusAdapter):
|
||||||
"""Adapter for the fronius meter with system scope."""
|
"""Adapter for the fronius meter with system scope."""
|
||||||
|
|
||||||
def entity_description(self, key):
|
|
||||||
"""Return the entity descriptor."""
|
|
||||||
if not key.startswith("energy_real_"):
|
|
||||||
return None
|
|
||||||
|
|
||||||
return SensorEntityDescription(
|
|
||||||
key=key,
|
|
||||||
device_class=DEVICE_CLASS_ENERGY,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
last_reset=dt.utc_from_timestamp(0),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _update(self):
|
async def _update(self):
|
||||||
"""Get the values for the current state."""
|
"""Get the values for the current state."""
|
||||||
return await self.bridge.current_system_meter_data()
|
return await self.bridge.current_system_meter_data()
|
||||||
@ -291,18 +265,6 @@ class FroniusMeterSystem(FroniusAdapter):
|
|||||||
class FroniusMeterDevice(FroniusAdapter):
|
class FroniusMeterDevice(FroniusAdapter):
|
||||||
"""Adapter for the fronius meter with device scope."""
|
"""Adapter for the fronius meter with device scope."""
|
||||||
|
|
||||||
def entity_description(self, key):
|
|
||||||
"""Return the entity descriptor."""
|
|
||||||
if not key.startswith("energy_real_"):
|
|
||||||
return None
|
|
||||||
|
|
||||||
return SensorEntityDescription(
|
|
||||||
key=key,
|
|
||||||
device_class=DEVICE_CLASS_ENERGY,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
last_reset=dt.utc_from_timestamp(0),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _update(self):
|
async def _update(self):
|
||||||
"""Get the values for the current state."""
|
"""Get the values for the current state."""
|
||||||
return await self.bridge.current_meter_data(self._device)
|
return await self.bridge.current_meter_data(self._device)
|
||||||
@ -311,14 +273,6 @@ class FroniusMeterDevice(FroniusAdapter):
|
|||||||
class FroniusPowerFlow(FroniusAdapter):
|
class FroniusPowerFlow(FroniusAdapter):
|
||||||
"""Adapter for the fronius power flow."""
|
"""Adapter for the fronius power flow."""
|
||||||
|
|
||||||
def entity_description(self, key):
|
|
||||||
"""Return the entity descriptor."""
|
|
||||||
return SensorEntityDescription(
|
|
||||||
key=key,
|
|
||||||
device_class=DEVICE_CLASS_POWER,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _update(self):
|
async def _update(self):
|
||||||
"""Get the values for the current state."""
|
"""Get the values for the current state."""
|
||||||
return await self.bridge.current_power_flow()
|
return await self.bridge.current_power_flow()
|
||||||
@ -327,13 +281,17 @@ class FroniusPowerFlow(FroniusAdapter):
|
|||||||
class FroniusTemplateSensor(SensorEntity):
|
class FroniusTemplateSensor(SensorEntity):
|
||||||
"""Sensor for the single values (e.g. pv power, ac power)."""
|
"""Sensor for the single values (e.g. pv power, ac power)."""
|
||||||
|
|
||||||
def __init__(self, parent: FroniusAdapter, key):
|
_attr_state_class = STATE_CLASS_MEASUREMENT
|
||||||
|
|
||||||
|
def __init__(self, parent: FroniusAdapter, key: str) -> None:
|
||||||
"""Initialize a singular value sensor."""
|
"""Initialize a singular value sensor."""
|
||||||
self._key = key
|
self._key = key
|
||||||
self._attr_name = f"{key.replace('_', ' ').capitalize()} {parent.name}"
|
self._attr_name = f"{key.replace('_', ' ').capitalize()} {parent.name}"
|
||||||
self._parent = parent
|
self._parent = parent
|
||||||
if entity_description := parent.entity_description(key):
|
for prefix, device_class in PREFIX_DEVICE_CLASS_MAPPING:
|
||||||
self.entity_description = entity_description
|
if self._key.startswith(prefix):
|
||||||
|
self._attr_device_class = device_class
|
||||||
|
break
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
@ -353,6 +311,17 @@ class FroniusTemplateSensor(SensorEntity):
|
|||||||
self._attr_state = round(self._attr_state, 2)
|
self._attr_state = round(self._attr_state, 2)
|
||||||
self._attr_unit_of_measurement = state.get("unit")
|
self._attr_unit_of_measurement = state.get("unit")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def last_reset(self) -> dt.dt.datetime | None:
|
||||||
|
"""Return the time when the sensor was last reset, if it is a meter."""
|
||||||
|
if self._key.endswith("day"):
|
||||||
|
return dt.start_of_local_day()
|
||||||
|
if self._key.endswith("year"):
|
||||||
|
return dt.start_of_local_day(dt.dt.date(dt.now().year, 1, 1))
|
||||||
|
if self._key.endswith("total") or self._key.startswith("energy_real"):
|
||||||
|
return dt.utc_from_timestamp(0)
|
||||||
|
return None
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Register at parent component for updates."""
|
"""Register at parent component for updates."""
|
||||||
self.async_on_remove(self._parent.register(self))
|
self.async_on_remove(self._parent.register(self))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user