1
0
mirror of https://github.com/home-assistant/core.git synced 2026-08-06 21:35:13 +01:00
Files
core/homeassistant/components/imou/sensor.py
T
2026-07-21 13:53:27 +02:00

180 lines
6.0 KiB
Python

"""Support for Imou sensor entities."""
from dataclasses import dataclass
from typing import override
from pyimouapi.const import PARAM_STATE_VARIANT, STATE_VARIANT_NUMERIC
from pyimouapi.ha_device import ImouHaDevice
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
PERCENTAGE,
EntityCategory,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfEnergy,
UnitOfPower,
UnitOfTemperature,
UnitOfTime,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from .const import PARAM_STATE, PARAM_STATUS, imou_device_identifier
from .coordinator import ImouConfigEntry, ImouDataUpdateCoordinator
from .entity import ImouEntity
PARALLEL_UPDATES = 0
STATUS_OPTIONS = ["online", "offline", "sleep", "upgrading"]
@dataclass(frozen=True, kw_only=True)
class ImouSensorEntityDescription(SensorEntityDescription):
"""Describes an Imou sensor entity."""
SENSOR_DESCRIPTIONS: dict[str, ImouSensorEntityDescription] = {
PARAM_STATUS: ImouSensorEntityDescription(
key=PARAM_STATUS,
translation_key=PARAM_STATUS,
device_class=SensorDeviceClass.ENUM,
entity_category=EntityCategory.DIAGNOSTIC,
options=STATUS_OPTIONS,
),
"battery": ImouSensorEntityDescription(
key="battery",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
suggested_display_precision=0,
),
"storage_used": ImouSensorEntityDescription(
key="storage_used",
translation_key="storage_used",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
suggested_display_precision=0,
),
"temperature_current": ImouSensorEntityDescription(
key="temperature_current",
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=1,
),
"humidity_current": ImouSensorEntityDescription(
key="humidity_current",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=1,
),
"power": ImouSensorEntityDescription(
key="power",
device_class=SensorDeviceClass.POWER,
native_unit_of_measurement=UnitOfPower.WATT,
state_class=SensorStateClass.MEASUREMENT,
),
"voltage": ImouSensorEntityDescription(
key="voltage",
device_class=SensorDeviceClass.VOLTAGE,
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
state_class=SensorStateClass.MEASUREMENT,
),
"current": ImouSensorEntityDescription(
key="current",
device_class=SensorDeviceClass.CURRENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
state_class=SensorStateClass.MEASUREMENT,
),
"switch_cnt": ImouSensorEntityDescription(
key="switch_cnt",
translation_key="switch_cnt",
state_class=SensorStateClass.TOTAL,
),
"use_electricity": ImouSensorEntityDescription(
key="use_electricity",
translation_key="use_electricity",
device_class=SensorDeviceClass.ENERGY,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
state_class=SensorStateClass.TOTAL_INCREASING,
),
"use_time": ImouSensorEntityDescription(
key="use_time",
translation_key="use_time",
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.MINUTES,
state_class=SensorStateClass.TOTAL_INCREASING,
),
}
def _iter_sensors(
coordinator: ImouDataUpdateCoordinator,
) -> list[tuple[ImouSensorEntityDescription, ImouHaDevice]]:
"""Return (description, device) pairs for supported sensors."""
return [
(SENSOR_DESCRIPTIONS[sensor_type], device)
for device in coordinator.devices
for sensor_type in device.sensors
if sensor_type in SENSOR_DESCRIPTIONS
]
async def async_setup_entry(
hass: HomeAssistant,
entry: ImouConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Imou sensor entities."""
coordinator = entry.runtime_data
def _add_sensors(new_devices: list[ImouHaDevice]) -> None:
device_keys = {imou_device_identifier(device) for device in new_devices}
async_add_entities(
ImouSensor(coordinator, description, device)
for description, device in _iter_sensors(coordinator)
if imou_device_identifier(device) in device_keys
)
entry.async_on_unload(coordinator.register_new_device_callback(_add_sensors))
_add_sensors(coordinator.devices)
class ImouSensor(ImouEntity, SensorEntity):
"""Imou sensor entity."""
entity_description: ImouSensorEntityDescription
@property
def _is_numeric_variant(self) -> bool:
"""Return True when the sensor value is numeric."""
return (
self.device.sensors[self._entity_type].get(PARAM_STATE_VARIANT)
== STATE_VARIANT_NUMERIC
)
@property
@override
def native_value(self) -> StateType:
"""Return the sensor value.
Numeric sensors only expose numeric values; error codes such as
storage_used e1/e2 become None (unknown) instead of mixing enum states.
"""
value = self.device.sensors[self._entity_type][PARAM_STATE]
if self.entity_description.device_class == SensorDeviceClass.ENUM:
return value
if not self._is_numeric_variant:
return None
return value