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

@ -21,7 +21,7 @@ from homeassistant.const import (
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
Platform, Platform,
) )
from homeassistant.core import Event, HomeAssistant, callback from homeassistant.core import Event, HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.entity import DeviceInfo, EntityDescription from homeassistant.helpers.entity import DeviceInfo, EntityDescription
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import (
@ -136,19 +136,3 @@ class AirVisualProEntity(CoordinatorEntity):
hw_version=self.coordinator.data["status"]["system_version"], hw_version=self.coordinator.data["status"]["system_version"],
sw_version=self.coordinator.data["status"]["app_version"], sw_version=self.coordinator.data["status"]["app_version"],
) )
@callback
def _async_update_from_latest_data(self) -> None:
"""Update the entity's underlying data."""
raise NotImplementedError
@callback
def _handle_coordinator_update(self) -> None:
"""Respond to a DataUpdateCoordinator update."""
self._async_update_from_latest_data()
self.async_write_ha_state()
async def async_added_to_hass(self) -> None:
"""Handle entity which will be added."""
await super().async_added_to_hass()
self._async_update_from_latest_data()

View File

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