diff --git a/homeassistant/components/gios/const.py b/homeassistant/components/gios/const.py index 834735c6189..9b890442166 100644 --- a/homeassistant/components/gios/const.py +++ b/homeassistant/components/gios/const.py @@ -4,10 +4,10 @@ from __future__ import annotations from datetime import timedelta from typing import Final -from homeassistant.components.sensor import ATTR_STATE_CLASS, STATE_CLASS_MEASUREMENT +from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT from homeassistant.const import CONCENTRATION_MICROGRAMS_PER_CUBIC_METER -from .model import SensorDescription +from .model import GiosSensorEntityDescription ATTRIBUTION: Final = "Data provided by GIOĊš" @@ -22,9 +22,6 @@ API_TIMEOUT: Final = 30 ATTR_INDEX: Final = "index" ATTR_STATION: Final = "station" -ATTR_UNIT: Final = "unit" -ATTR_VALUE: Final = "value" -ATTR_STATION_NAME: Final = "station_name" ATTR_C6H6: Final = "c6h6" ATTR_CO: Final = "co" @@ -35,41 +32,52 @@ ATTR_PM25: Final = "pm25" ATTR_SO2: Final = "so2" ATTR_AQI: Final = "aqi" -SENSOR_TYPES: Final[dict[str, SensorDescription]] = { - ATTR_AQI: {}, - ATTR_C6H6: { - ATTR_UNIT: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, - ATTR_VALUE: round, - }, - ATTR_CO: { - ATTR_UNIT: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, - ATTR_VALUE: round, - }, - ATTR_NO2: { - ATTR_UNIT: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, - ATTR_VALUE: round, - }, - ATTR_O3: { - ATTR_UNIT: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, - ATTR_VALUE: round, - }, - ATTR_PM10: { - ATTR_UNIT: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, - ATTR_VALUE: round, - }, - ATTR_PM25: { - ATTR_UNIT: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, - ATTR_VALUE: round, - }, - ATTR_SO2: { - ATTR_UNIT: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, - ATTR_VALUE: round, - }, -} +SENSOR_TYPES: Final[tuple[GiosSensorEntityDescription, ...]] = ( + GiosSensorEntityDescription( + key=ATTR_AQI, + name="AQI", + value=None, + ), + GiosSensorEntityDescription( + key=ATTR_C6H6, + name="C6H6", + unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + state_class=STATE_CLASS_MEASUREMENT, + ), + GiosSensorEntityDescription( + key=ATTR_CO, + name="CO", + unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + state_class=STATE_CLASS_MEASUREMENT, + ), + GiosSensorEntityDescription( + key=ATTR_NO2, + name="NO2", + unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + state_class=STATE_CLASS_MEASUREMENT, + ), + GiosSensorEntityDescription( + key=ATTR_O3, + name="O3", + unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + state_class=STATE_CLASS_MEASUREMENT, + ), + GiosSensorEntityDescription( + key=ATTR_PM10, + name="PM10", + unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + state_class=STATE_CLASS_MEASUREMENT, + ), + GiosSensorEntityDescription( + key=ATTR_PM25, + name="PM2.5", + unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + state_class=STATE_CLASS_MEASUREMENT, + ), + GiosSensorEntityDescription( + key=ATTR_SO2, + name="SO2", + unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + state_class=STATE_CLASS_MEASUREMENT, + ), +) diff --git a/homeassistant/components/gios/model.py b/homeassistant/components/gios/model.py index 867c950e183..b6ae9a9f78f 100644 --- a/homeassistant/components/gios/model.py +++ b/homeassistant/components/gios/model.py @@ -1,12 +1,14 @@ """Type definitions for GIOS integration.""" from __future__ import annotations -from typing import Callable, TypedDict +from dataclasses import dataclass +from typing import Callable + +from homeassistant.components.sensor import SensorEntityDescription -class SensorDescription(TypedDict, total=False): - """Sensor description class.""" +@dataclass +class GiosSensorEntityDescription(SensorEntityDescription): + """Class describing GIOS sensor entities.""" - unit: str - state_class: str - value: Callable + value: Callable | None = round diff --git a/homeassistant/components/gios/sensor.py b/homeassistant/components/gios/sensor.py index 4ab7facec9f..b651112b9db 100644 --- a/homeassistant/components/gios/sensor.py +++ b/homeassistant/components/gios/sensor.py @@ -4,11 +4,7 @@ from __future__ import annotations import logging from typing import Any, cast -from homeassistant.components.sensor import ( - ATTR_STATE_CLASS, - DOMAIN as PLATFORM, - SensorEntity, -) +from homeassistant.components.sensor import DOMAIN as PLATFORM, SensorEntity from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_ATTRIBUTION, ATTR_NAME, CONF_NAME from homeassistant.core import HomeAssistant @@ -23,14 +19,13 @@ from .const import ( ATTR_INDEX, ATTR_PM25, ATTR_STATION, - ATTR_UNIT, - ATTR_VALUE, ATTRIBUTION, DEFAULT_NAME, DOMAIN, MANUFACTURER, SENSOR_TYPES, ) +from .model import GiosSensorEntityDescription _LOGGER = logging.getLogger(__name__) @@ -61,13 +56,13 @@ async def async_setup_entry( sensors: list[GiosSensor | GiosAqiSensor] = [] - for sensor in SENSOR_TYPES: - if getattr(coordinator.data, sensor) is None: + for description in SENSOR_TYPES: + if getattr(coordinator.data, description.key) is None: continue - if sensor == ATTR_AQI: - sensors.append(GiosAqiSensor(name, sensor, coordinator)) + if description.key == ATTR_AQI: + sensors.append(GiosAqiSensor(name, coordinator, description)) else: - sensors.append(GiosSensor(name, sensor, coordinator)) + sensors.append(GiosSensor(name, coordinator, description)) async_add_entities(sensors) @@ -75,13 +70,16 @@ class GiosSensor(CoordinatorEntity, SensorEntity): """Define an GIOS sensor.""" coordinator: GiosDataUpdateCoordinator + entity_description: GiosSensorEntityDescription def __init__( - self, name: str, sensor_type: str, coordinator: GiosDataUpdateCoordinator + self, + name: str, + coordinator: GiosDataUpdateCoordinator, + description: GiosSensorEntityDescription, ) -> None: """Initialize.""" super().__init__(coordinator) - self._description = SENSOR_TYPES[sensor_type] self._attr_device_info = { "identifiers": {(DOMAIN, str(coordinator.gios.station_id))}, "name": DEFAULT_NAME, @@ -89,33 +87,31 @@ class GiosSensor(CoordinatorEntity, SensorEntity): "entry_type": "service", } self._attr_icon = "mdi:blur" - if sensor_type == ATTR_PM25: - self._attr_name = f"{name} PM2.5" - else: - self._attr_name = f"{name} {sensor_type.upper()}" - self._attr_state_class = self._description.get(ATTR_STATE_CLASS) - self._attr_unique_id = f"{coordinator.gios.station_id}-{sensor_type}" - self._attr_unit_of_measurement = self._description.get(ATTR_UNIT) - self._sensor_type = sensor_type + self._attr_name = f"{name} {description.name}" + self._attr_unique_id = f"{coordinator.gios.station_id}-{description.key}" self._attrs: dict[str, Any] = { ATTR_ATTRIBUTION: ATTRIBUTION, ATTR_STATION: self.coordinator.gios.station_name, } + self.entity_description = description @property def extra_state_attributes(self) -> dict[str, Any]: """Return the state attributes.""" - self._attrs[ATTR_NAME] = getattr(self.coordinator.data, self._sensor_type).name + self._attrs[ATTR_NAME] = getattr( + self.coordinator.data, self.entity_description.key + ).name self._attrs[ATTR_INDEX] = getattr( - self.coordinator.data, self._sensor_type + self.coordinator.data, self.entity_description.key ).index return self._attrs @property def state(self) -> StateType: """Return the state.""" - state = getattr(self.coordinator.data, self._sensor_type).value - return cast(StateType, self._description[ATTR_VALUE](state)) + state = getattr(self.coordinator.data, self.entity_description.key).value + assert self.entity_description.value is not None + return cast(StateType, self.entity_description.value(state)) class GiosAqiSensor(GiosSensor): @@ -124,10 +120,14 @@ class GiosAqiSensor(GiosSensor): @property def state(self) -> StateType: """Return the state.""" - return cast(StateType, getattr(self.coordinator.data, self._sensor_type).value) + return cast( + StateType, getattr(self.coordinator.data, self.entity_description.key).value + ) @property def available(self) -> bool: """Return if entity is available.""" available = super().available - return available and bool(getattr(self.coordinator.data, self._sensor_type)) + return available and bool( + getattr(self.coordinator.data, self.entity_description.key) + )