Simplify AirVisual Pro sensor implementation (#84898)

* Simplify AirVisual Pro sensor implementation

* Code review
This commit is contained in:
Aaron Bach 2023-01-01 06:19:29 -07:00 committed by GitHub
parent 34b5928707
commit e62ee331c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 80 deletions

View file

@ -1,6 +1,8 @@
"""Support for AirVisual Pro sensors."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from homeassistant.components.sensor import (
@ -23,78 +25,93 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AirVisualProData, AirVisualProEntity
from .const import DOMAIN
SENSOR_KIND_AQI = "air_quality_index"
SENSOR_KIND_BATTERY_LEVEL = "battery_level"
SENSOR_KIND_CO2 = "carbon_dioxide"
SENSOR_KIND_HUMIDITY = "humidity"
SENSOR_KIND_PM_0_1 = "particulate_matter_0_1"
SENSOR_KIND_PM_1_0 = "particulate_matter_1_0"
SENSOR_KIND_PM_2_5 = "particulate_matter_2_5"
SENSOR_KIND_SENSOR_LIFE = "sensor_life"
SENSOR_KIND_TEMPERATURE = "temperature"
SENSOR_KIND_VOC = "voc"
@dataclass
class AirVisualProMeasurementKeyMixin:
"""Define an entity description mixin to include a measurement key."""
value_fn: Callable[[dict[str, Any], dict[str, Any], dict[str, Any]], float | int]
@dataclass
class AirVisualProMeasurementDescription(
SensorEntityDescription, AirVisualProMeasurementKeyMixin
):
"""Describe an AirVisual Pro sensor."""
SENSOR_DESCRIPTIONS = (
SensorEntityDescription(
key=SENSOR_KIND_AQI,
AirVisualProMeasurementDescription(
key="air_quality_index",
name="Air quality index",
device_class=SensorDeviceClass.AQI,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements[
async_get_aqi_locale(settings)
],
),
SensorEntityDescription(
key=SENSOR_KIND_BATTERY_LEVEL,
AirVisualProMeasurementDescription(
key="battery_level",
name="Battery",
device_class=SensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda settings, status, measurements: status["battery"],
),
SensorEntityDescription(
key=SENSOR_KIND_CO2,
AirVisualProMeasurementDescription(
key="carbon_dioxide",
name="C02",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["co2"],
),
SensorEntityDescription(
key=SENSOR_KIND_HUMIDITY,
AirVisualProMeasurementDescription(
key="humidity",
name="Humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda settings, status, measurements: measurements["humidity"],
),
SensorEntityDescription(
key=SENSOR_KIND_PM_0_1,
AirVisualProMeasurementDescription(
key="particulate_matter_0_1",
name="PM 0.1",
device_class=SensorDeviceClass.PM1,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["pm0_1"],
),
SensorEntityDescription(
key=SENSOR_KIND_PM_1_0,
AirVisualProMeasurementDescription(
key="particulate_matter_1_0",
name="PM 1.0",
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["pm1_0"],
),
SensorEntityDescription(
key=SENSOR_KIND_PM_2_5,
AirVisualProMeasurementDescription(
key="particulate_matter_2_5",
name="PM 2.5",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["pm2_5"],
),
SensorEntityDescription(
key=SENSOR_KIND_TEMPERATURE,
AirVisualProMeasurementDescription(
key="temperature",
name="Temperature",
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["temperature_C"],
),
SensorEntityDescription(
key=SENSOR_KIND_VOC,
AirVisualProMeasurementDescription(
key="voc",
name="VOC",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["voc"],
),
)
@ -124,40 +141,13 @@ class AirVisualProSensor(AirVisualProEntity, SensorEntity):
_attr_has_entity_name = True
MEASUREMENTS_KEY_TO_VALUE = {
SENSOR_KIND_CO2: "co2",
SENSOR_KIND_HUMIDITY: "humidity",
SENSOR_KIND_PM_0_1: "pm0_1",
SENSOR_KIND_PM_1_0: "pm1_0",
SENSOR_KIND_PM_2_5: "pm2_5",
SENSOR_KIND_TEMPERATURE: "temperature_C",
SENSOR_KIND_VOC: "voc",
}
entity_description: AirVisualProMeasurementDescription
@property
def measurements(self) -> dict[str, Any]:
"""Define measurements data."""
return self.coordinator.data["measurements"]
@property
def settings(self) -> dict[str, Any]:
"""Define settings data."""
return self.coordinator.data["settings"]
@property
def status(self) -> dict[str, Any]:
"""Define status data."""
return self.coordinator.data["status"]
@callback
def _async_update_from_latest_data(self) -> None:
"""Update the entity from the latest data."""
if self.entity_description.key == SENSOR_KIND_AQI:
locale = async_get_aqi_locale(self.settings)
self._attr_native_value = self.measurements[locale]
elif self.entity_description.key == SENSOR_KIND_BATTERY_LEVEL:
self._attr_native_value = self.status["battery"]
else:
self._attr_native_value = self.measurements[
self.MEASUREMENTS_KEY_TO_VALUE[self.entity_description.key]
]
def native_value(self) -> float | int:
"""Return the sensor value."""
return self.entity_description.value_fn(
self.coordinator.data["settings"],
self.coordinator.data["status"],
self.coordinator.data["measurements"],
)