Use SensorEntityDescription in GIOS integration (#53581)

This commit is contained in:
Maciej Bieniek 2021-07-28 08:21:00 +02:00 committed by GitHub
parent b7f1f2330a
commit 9b67605b8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 77 deletions

View file

@ -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,
),
)

View file

@ -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

View file

@ -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)
)