From 6a3619d9fae29747f97389ce7ceeb8e35ea1a32f Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Tue, 7 Feb 2023 09:14:20 +0100 Subject: [PATCH] Refactor NAM sensor platform (#87048) * Bump backend library * Remove AQI_LEVEL_STATE_MAPPING * Add native_precission * Update diagnostics fixture * Use _attr_native_value * Fix type * Improve lambda * Revert native_value property * native_precision -> suggested_display_precision --- homeassistant/components/nam/manifest.json | 2 +- homeassistant/components/nam/sensor.py | 119 +++++++++++------- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- .../nam/fixtures/diagnostics_data.json | 32 ++--- tests/components/nam/test_init.py | 2 +- tests/components/nam/test_sensor.py | 28 ++--- 7 files changed, 107 insertions(+), 80 deletions(-) diff --git a/homeassistant/components/nam/manifest.json b/homeassistant/components/nam/manifest.json index 936c389339d..cc568fbc3a4 100644 --- a/homeassistant/components/nam/manifest.json +++ b/homeassistant/components/nam/manifest.json @@ -3,7 +3,7 @@ "name": "Nettigo Air Monitor", "documentation": "https://www.home-assistant.io/integrations/nam", "codeowners": ["@bieniu"], - "requirements": ["nettigo-air-monitor==1.6.0"], + "requirements": ["nettigo-air-monitor==2.0.0"], "zeroconf": [ { "type": "_http._tcp.local.", diff --git a/homeassistant/components/nam/sensor.py b/homeassistant/components/nam/sensor.py index 5dab563d409..7222b7dee3c 100644 --- a/homeassistant/components/nam/sensor.py +++ b/homeassistant/components/nam/sensor.py @@ -1,10 +1,12 @@ """Support for the Nettigo Air Monitor service.""" from __future__ import annotations +from collections.abc import Callable from dataclasses import dataclass from datetime import datetime, timedelta import logging -from typing import cast + +from nettigo_air_monitor import NAMSensors from homeassistant.components.sensor import ( DOMAIN as PLATFORM, @@ -71,231 +73,282 @@ PARALLEL_UPDATES = 1 _LOGGER = logging.getLogger(__name__) -AQI_LEVEL_STATE_MAPPING = { - "very low": "very_low", - "low": "low", - "medium": "medium", - "high": "high", - "very high": "very_high", -} + +@dataclass +class NAMSensorRequiredKeysMixin: + """Class for NAM entity required keys.""" + + value: Callable[[NAMSensors], StateType | datetime] @dataclass -class NAMSensorEntityDescription(SensorEntityDescription): - """Describes NAM sensor entity.""" - - mapping: dict[str, str] | None = None +class NAMSensorEntityDescription(SensorEntityDescription, NAMSensorRequiredKeysMixin): + """NAM sensor entity description.""" SENSORS: tuple[NAMSensorEntityDescription, ...] = ( NAMSensorEntityDescription( key=ATTR_BME280_HUMIDITY, name="BME280 humidity", + suggested_display_precision=1, native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.HUMIDITY, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.bme280_humidity, ), NAMSensorEntityDescription( key=ATTR_BME280_PRESSURE, name="BME280 pressure", + suggested_display_precision=0, native_unit_of_measurement=UnitOfPressure.HPA, device_class=SensorDeviceClass.PRESSURE, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.bme280_pressure, ), NAMSensorEntityDescription( key=ATTR_BME280_TEMPERATURE, name="BME280 temperature", + suggested_display_precision=1, native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.bme280_temperature, ), NAMSensorEntityDescription( key=ATTR_BMP180_PRESSURE, name="BMP180 pressure", + suggested_display_precision=0, native_unit_of_measurement=UnitOfPressure.HPA, device_class=SensorDeviceClass.PRESSURE, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.bmp180_pressure, ), NAMSensorEntityDescription( key=ATTR_BMP180_TEMPERATURE, name="BMP180 temperature", + suggested_display_precision=1, native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.bmp180_temperature, ), NAMSensorEntityDescription( key=ATTR_BMP280_PRESSURE, name="BMP280 pressure", + suggested_display_precision=0, native_unit_of_measurement=UnitOfPressure.HPA, device_class=SensorDeviceClass.PRESSURE, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.bmp280_pressure, ), NAMSensorEntityDescription( key=ATTR_BMP280_TEMPERATURE, name="BMP280 temperature", + suggested_display_precision=1, native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.bmp280_temperature, ), NAMSensorEntityDescription( key=ATTR_HECA_HUMIDITY, name="HECA humidity", + suggested_display_precision=1, native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.HUMIDITY, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.heca_humidity, ), NAMSensorEntityDescription( key=ATTR_HECA_TEMPERATURE, name="HECA temperature", + suggested_display_precision=1, native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.heca_temperature, ), NAMSensorEntityDescription( key=ATTR_MHZ14A_CARBON_DIOXIDE, name="MH-Z14A carbon dioxide", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, device_class=SensorDeviceClass.CO2, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.mhz14a_carbon_dioxide, ), NAMSensorEntityDescription( key=ATTR_PMSX003_CAQI, name="PMSx003 CAQI", icon="mdi:air-filter", + value=lambda sensors: sensors.pms_caqi, ), NAMSensorEntityDescription( key=ATTR_PMSX003_CAQI_LEVEL, name="PMSx003 CAQI level", icon="mdi:air-filter", device_class=SensorDeviceClass.ENUM, - mapping=AQI_LEVEL_STATE_MAPPING, + options=["very_low", "low", "medium", "high", "very_high"], translation_key="caqi_level", + value=lambda sensors: sensors.pms_caqi_level, ), NAMSensorEntityDescription( key=ATTR_PMSX003_P0, name="PMSx003 particulate matter 1.0", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM1, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.pms_p0, ), NAMSensorEntityDescription( key=ATTR_PMSX003_P1, name="PMSx003 particulate matter 10", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM10, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.pms_p1, ), NAMSensorEntityDescription( key=ATTR_PMSX003_P2, name="PMSx003 particulate matter 2.5", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM25, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.pms_p2, ), NAMSensorEntityDescription( key=ATTR_SDS011_CAQI, name="SDS011 CAQI", icon="mdi:air-filter", + value=lambda sensors: sensors.sds011_caqi, ), NAMSensorEntityDescription( key=ATTR_SDS011_CAQI_LEVEL, name="SDS011 CAQI level", icon="mdi:air-filter", device_class=SensorDeviceClass.ENUM, - mapping=AQI_LEVEL_STATE_MAPPING, + options=["very_low", "low", "medium", "high", "very_high"], translation_key="caqi_level", + value=lambda sensors: sensors.sds011_caqi_level, ), NAMSensorEntityDescription( key=ATTR_SDS011_P1, name="SDS011 particulate matter 10", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM10, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.sds011_p1, ), NAMSensorEntityDescription( key=ATTR_SDS011_P2, name="SDS011 particulate matter 2.5", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM25, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.sds011_p2, ), NAMSensorEntityDescription( key=ATTR_SHT3X_HUMIDITY, name="SHT3X humidity", + suggested_display_precision=1, native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.HUMIDITY, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.sht3x_humidity, ), NAMSensorEntityDescription( key=ATTR_SHT3X_TEMPERATURE, name="SHT3X temperature", + suggested_display_precision=1, native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.sht3x_temperature, ), NAMSensorEntityDescription( key=ATTR_SPS30_CAQI, name="SPS30 CAQI", icon="mdi:air-filter", + value=lambda sensors: sensors.sps30_caqi, ), NAMSensorEntityDescription( key=ATTR_SPS30_CAQI_LEVEL, name="SPS30 CAQI level", icon="mdi:air-filter", device_class=SensorDeviceClass.ENUM, - mapping=AQI_LEVEL_STATE_MAPPING, + options=["very_low", "low", "medium", "high", "very_high"], translation_key="caqi_level", + value=lambda sensors: sensors.sps30_caqi_level, ), NAMSensorEntityDescription( key=ATTR_SPS30_P0, name="SPS30 particulate matter 1.0", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM1, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.sps30_p0, ), NAMSensorEntityDescription( key=ATTR_SPS30_P1, name="SPS30 particulate matter 10", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM10, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.sps30_p1, ), NAMSensorEntityDescription( key=ATTR_SPS30_P2, name="SPS30 particulate matter 2.5", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM25, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.sps30_p2, ), NAMSensorEntityDescription( key=ATTR_SPS30_P4, name="SPS30 particulate matter 4.0", + suggested_display_precision=0, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, icon="mdi:molecule", state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.sps30_p4, ), NAMSensorEntityDescription( key=ATTR_DHT22_HUMIDITY, name="DHT22 humidity", + suggested_display_precision=1, native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.HUMIDITY, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.dht22_humidity, ), NAMSensorEntityDescription( key=ATTR_DHT22_TEMPERATURE, name="DHT22 temperature", + suggested_display_precision=1, native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + value=lambda sensors: sensors.dht22_temperature, ), NAMSensorEntityDescription( key=ATTR_SIGNAL_STRENGTH, name="Signal strength", + suggested_display_precision=0, native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT, device_class=SensorDeviceClass.SIGNAL_STRENGTH, entity_registry_enabled_default=False, state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, + value=lambda sensors: sensors.signal, ), NAMSensorEntityDescription( key=ATTR_UPTIME, @@ -303,6 +356,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = ( device_class=SensorDeviceClass.TIMESTAMP, entity_registry_enabled_default=False, entity_category=EntityCategory.DIAGNOSTIC, + value=lambda sensors: utcnow() - timedelta(seconds=sensors.uptime or 0), ), ) @@ -328,13 +382,10 @@ async def async_setup_entry( ) ent_reg.async_update_entity(entity_id, new_unique_id=new_unique_id) - sensors: list[NAMSensor | NAMSensorUptime] = [] + sensors: list[NAMSensor] = [] for description in SENSORS: if getattr(coordinator.data, description.key) is not None: - if description.key == ATTR_UPTIME: - sensors.append(NAMSensorUptime(coordinator, description)) - else: - sensors.append(NAMSensor(coordinator, description)) + sensors.append(NAMSensor(coordinator, description)) async_add_entities(sensors, False) @@ -356,18 +407,6 @@ class NAMSensor(CoordinatorEntity[NAMDataUpdateCoordinator], SensorEntity): self._attr_unique_id = f"{coordinator.unique_id}-{description.key}" self.entity_description = description - @property - def native_value(self) -> StateType | datetime: - """Return the state.""" - if self.entity_description.mapping is not None: - return self.entity_description.mapping[ - cast(str, getattr(self.coordinator.data, self.entity_description.key)) - ] - - return cast( - StateType, getattr(self.coordinator.data, self.entity_description.key) - ) - @property def available(self) -> bool: """Return if entity is available.""" @@ -382,18 +421,6 @@ class NAMSensor(CoordinatorEntity[NAMDataUpdateCoordinator], SensorEntity): ) @property - def options(self) -> list[str] | None: - """If the entity description provides a mapping, use that.""" - if self.entity_description.mapping: - return list(self.entity_description.mapping.values()) - return super().options - - -class NAMSensorUptime(NAMSensor): - """Define an Nettigo Air Monitor uptime sensor.""" - - @property - def native_value(self) -> datetime: + def native_value(self) -> StateType | datetime: """Return the state.""" - uptime_sec = getattr(self.coordinator.data, self.entity_description.key) - return utcnow() - timedelta(seconds=uptime_sec) + return self.entity_description.value(self.coordinator.data) diff --git a/requirements_all.txt b/requirements_all.txt index ecafd4606e7..7b8d9edf786 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1186,7 +1186,7 @@ netdisco==3.0.0 netmap==0.7.0.2 # homeassistant.components.nam -nettigo-air-monitor==1.6.0 +nettigo-air-monitor==2.0.0 # homeassistant.components.neurio_energy neurio==0.3.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 428f909b5ef..eb019566e90 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -882,7 +882,7 @@ netdisco==3.0.0 netmap==0.7.0.2 # homeassistant.components.nam -nettigo-air-monitor==1.6.0 +nettigo-air-monitor==2.0.0 # homeassistant.components.nexia nexia==2.0.6 diff --git a/tests/components/nam/fixtures/diagnostics_data.json b/tests/components/nam/fixtures/diagnostics_data.json index 67ba64576fd..a384e8cd386 100644 --- a/tests/components/nam/fixtures/diagnostics_data.json +++ b/tests/components/nam/fixtures/diagnostics_data.json @@ -1,33 +1,33 @@ { "bme280_humidity": 45.7, - "bme280_pressure": 1011, + "bme280_pressure": 1011.012, "bme280_temperature": 7.6, - "bmp180_pressure": 1032, + "bmp180_pressure": 1032.012, "bmp180_temperature": 7.6, - "bmp280_pressure": 1022, + "bmp280_pressure": 1022.012, "bmp280_temperature": 5.6, "dht22_humidity": 46.2, "dht22_temperature": 6.3, "heca_humidity": 50.0, "heca_temperature": 8.0, - "mhz14a_carbon_dioxide": 865, + "mhz14a_carbon_dioxide": 865.0, "pms_caqi": 19, - "pms_caqi_level": "very low", - "pms_p0": 6, - "pms_p1": 10, - "pms_p2": 11, + "pms_caqi_level": "very_low", + "pms_p0": 6.0, + "pms_p1": 10.0, + "pms_p2": 11.0, "sds011_caqi": 19, - "sds011_caqi_level": "very low", - "sds011_p1": 19, - "sds011_p2": 11, + "sds011_caqi_level": "very_low", + "sds011_p1": 18.6, + "sds011_p2": 11.0, "sht3x_humidity": 34.7, "sht3x_temperature": 6.3, - "signal": -72, + "signal": -72.0, "sps30_caqi": 54, "sps30_caqi_level": "medium", - "sps30_p0": 31, - "sps30_p1": 21, - "sps30_p2": 34, - "sps30_p4": 25, + "sps30_p0": 31.2, + "sps30_p1": 21.2, + "sps30_p2": 34.3, + "sps30_p4": 24.7, "uptime": 456987 } diff --git a/tests/components/nam/test_init.py b/tests/components/nam/test_init.py index a6d11305599..49b07a85b89 100644 --- a/tests/components/nam/test_init.py +++ b/tests/components/nam/test_init.py @@ -21,7 +21,7 @@ async def test_async_setup_entry(hass): state = hass.states.get("sensor.nettigo_air_monitor_sds011_particulate_matter_2_5") assert state is not None assert state.state != STATE_UNAVAILABLE - assert state.state == "11" + assert state.state == "11.0" async def test_config_not_ready(hass): diff --git a/tests/components/nam/test_sensor.py b/tests/components/nam/test_sensor.py index 81f114c5a8f..05ddbbfc837 100644 --- a/tests/components/nam/test_sensor.py +++ b/tests/components/nam/test_sensor.py @@ -83,7 +83,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_bme280_pressure") assert state - assert state.state == "1011" + assert state.state == "1011.012" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PRESSURE assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfPressure.HPA @@ -105,7 +105,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_bmp180_pressure") assert state - assert state.state == "1032" + assert state.state == "1032.012" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PRESSURE assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfPressure.HPA @@ -127,7 +127,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_bmp280_pressure") assert state - assert state.state == "1022" + assert state.state == "1022.012" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PRESSURE assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfPressure.HPA @@ -204,7 +204,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_signal_strength") assert state - assert state.state == "-72" + assert state.state == "-72.0" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.SIGNAL_STRENGTH assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( @@ -258,7 +258,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_pmsx003_particulate_matter_10") assert state - assert state.state == "10" + assert state.state == "10.0" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM10 assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( @@ -274,7 +274,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_pmsx003_particulate_matter_2_5") assert state - assert state.state == "11" + assert state.state == "11.0" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM25 assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( @@ -290,7 +290,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_pmsx003_particulate_matter_1_0") assert state - assert state.state == "6" + assert state.state == "6.0" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM1 assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( @@ -306,7 +306,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_sds011_particulate_matter_10") assert state - assert state.state == "19" + assert state.state == "18.6" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM10 assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( @@ -349,7 +349,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_sds011_particulate_matter_2_5") assert state - assert state.state == "11" + assert state.state == "11.0" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM25 assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( @@ -392,7 +392,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_sps30_particulate_matter_1_0") assert state - assert state.state == "31" + assert state.state == "31.2" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM1 assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( @@ -408,7 +408,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_sps30_particulate_matter_10") assert state - assert state.state == "21" + assert state.state == "21.2" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM10 assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( @@ -422,7 +422,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_sps30_particulate_matter_2_5") assert state - assert state.state == "34" + assert state.state == "34.3" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM25 assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( @@ -438,7 +438,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_sps30_particulate_matter_4_0") assert state - assert state.state == "25" + assert state.state == "24.7" assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert ( state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) @@ -454,7 +454,7 @@ async def test_sensor(hass): state = hass.states.get("sensor.nettigo_air_monitor_mh_z14a_carbon_dioxide") assert state - assert state.state == "865" + assert state.state == "865.0" assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.CO2 assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.MEASUREMENT assert (