From f1927026486f91207282cea82982a7188232f530 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Wed, 19 May 2021 13:20:11 +0200 Subject: [PATCH] Add Nettigo Air Monitor uptime sensor (#50834) --- homeassistant/components/nam/__init__.py | 2 +- homeassistant/components/nam/air_quality.py | 4 ++-- homeassistant/components/nam/const.py | 8 +++++++ homeassistant/components/nam/manifest.json | 2 +- homeassistant/components/nam/sensor.py | 25 ++++++++++++++++++--- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/nam/__init__.py | 1 + tests/components/nam/test_sensor.py | 21 +++++++++++++++++ 9 files changed, 58 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/nam/__init__.py b/homeassistant/components/nam/__init__.py index 04458967bed..7dc6701217d 100644 --- a/homeassistant/components/nam/__init__.py +++ b/homeassistant/components/nam/__init__.py @@ -31,7 +31,7 @@ PLATFORMS = ["air_quality", "sensor"] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Nettigo as config entry.""" - host = entry.data[CONF_HOST] + host: str = entry.data[CONF_HOST] websession = async_get_clientsession(hass) diff --git a/homeassistant/components/nam/air_quality.py b/homeassistant/components/nam/air_quality.py index 7823ffb110e..c39ad2bea73 100644 --- a/homeassistant/components/nam/air_quality.py +++ b/homeassistant/components/nam/air_quality.py @@ -19,9 +19,9 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Add a Nettigo Air Monitor entities from a config_entry.""" - coordinator = hass.data[DOMAIN][entry.entry_id] + coordinator: NAMDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] - entities = [] + entities: list[NAMAirQuality] = [] for sensor in AIR_QUALITY_SENSORS: if f"{sensor}{SUFFIX_P1}" in coordinator.data: entities.append(NAMAirQuality(coordinator, sensor)) diff --git a/homeassistant/components/nam/const.py b/homeassistant/components/nam/const.py index b14bcaa6fa1..3800057d5d7 100644 --- a/homeassistant/components/nam/const.py +++ b/homeassistant/components/nam/const.py @@ -10,6 +10,7 @@ from homeassistant.const import ( DEVICE_CLASS_PRESSURE, DEVICE_CLASS_SIGNAL_STRENGTH, DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_TIMESTAMP, PERCENTAGE, PRESSURE_HPA, SIGNAL_STRENGTH_DECIBELS_MILLIWATT, @@ -127,4 +128,11 @@ SENSORS: Final[dict[str, SensorDescription]] = { "icon": None, "enabled": True, }, + "uptime": { + "label": f"{DEFAULT_NAME} Uptime", + "unit": None, + "device_class": DEVICE_CLASS_TIMESTAMP, + "icon": None, + "enabled": False, + }, } diff --git a/homeassistant/components/nam/manifest.json b/homeassistant/components/nam/manifest.json index 80a31fe1596..3e03a0ad787 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==0.2.5"], + "requirements": ["nettigo-air-monitor==0.2.6"], "zeroconf": [{"type": "_http._tcp.local.", "name": "nam-*"}], "config_flow": true, "quality_scale": "platinum", diff --git a/homeassistant/components/nam/sensor.py b/homeassistant/components/nam/sensor.py index 39da7742bed..026e40483bd 100644 --- a/homeassistant/components/nam/sensor.py +++ b/homeassistant/components/nam/sensor.py @@ -1,6 +1,7 @@ """Support for the Nettigo Air Monitor service.""" from __future__ import annotations +from datetime import timedelta from typing import Any from homeassistant.components.sensor import SensorEntity @@ -9,6 +10,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity +from homeassistant.util.dt import utcnow from . import NAMDataUpdateCoordinator from .const import DOMAIN, SENSORS @@ -20,12 +22,15 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Add a Nettigo Air Monitor entities from a config_entry.""" - coordinator = hass.data[DOMAIN][entry.entry_id] + coordinator: NAMDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] - sensors = [] + sensors: list[NAMSensor | NAMSensorUptime] = [] for sensor in SENSORS: if sensor in coordinator.data: - sensors.append(NAMSensor(coordinator, sensor)) + if sensor == "uptime": + sensors.append(NAMSensorUptime(coordinator, sensor)) + else: + sensors.append(NAMSensor(coordinator, sensor)) async_add_entities(sensors, False) @@ -92,3 +97,17 @@ class NAMSensor(CoordinatorEntity, SensorEntity): return available and bool( getattr(self.coordinator.data, self.sensor_type, None) ) + + +class NAMSensorUptime(NAMSensor): + """Define an Nettigo Air Monitor uptime sensor.""" + + @property + def state(self) -> str: + """Return the state.""" + uptime_sec = getattr(self.coordinator.data, self.sensor_type) + return ( + (utcnow() - timedelta(seconds=uptime_sec)) + .replace(microsecond=0) + .isoformat() + ) diff --git a/requirements_all.txt b/requirements_all.txt index 971f637bc39..b802a152efb 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -997,7 +997,7 @@ netdata==0.2.0 netdisco==2.8.3 # homeassistant.components.nam -nettigo-air-monitor==0.2.5 +nettigo-air-monitor==0.2.6 # homeassistant.components.neurio_energy neurio==0.3.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index a3159aa20e9..8bf2a07c97a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -551,7 +551,7 @@ nessclient==0.9.15 netdisco==2.8.3 # homeassistant.components.nam -nettigo-air-monitor==0.2.5 +nettigo-air-monitor==0.2.6 # homeassistant.components.nexia nexia==0.9.7 diff --git a/tests/components/nam/__init__.py b/tests/components/nam/__init__.py index 1b6f89b76df..b4a6ebbf792 100644 --- a/tests/components/nam/__init__.py +++ b/tests/components/nam/__init__.py @@ -12,6 +12,7 @@ INCOMPLETE_NAM_DATA = { nam_data = { "software_version": "NAMF-2020-36", + "uptime": "456987", "sensordatavalues": [ {"value_type": "SDS_P1", "value": "18.65"}, {"value_type": "SDS_P2", "value": "11.03"}, diff --git a/tests/components/nam/test_sensor.py b/tests/components/nam/test_sensor.py index 148b048da90..2dfdc8987bc 100644 --- a/tests/components/nam/test_sensor.py +++ b/tests/components/nam/test_sensor.py @@ -14,6 +14,7 @@ from homeassistant.const import ( DEVICE_CLASS_PRESSURE, DEVICE_CLASS_SIGNAL_STRENGTH, DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_TIMESTAMP, PERCENTAGE, PRESSURE_HPA, SIGNAL_STRENGTH_DECIBELS_MILLIWATT, @@ -42,6 +43,14 @@ async def test_sensor(hass): disabled_by=None, ) + registry.async_get_or_create( + SENSOR_DOMAIN, + DOMAIN, + "aa:bb:cc:dd:ee:ff-uptime", + suggested_object_id="nettigo_air_monitor_uptime", + disabled_by=None, + ) + await init_integration(hass) state = hass.states.get("sensor.nettigo_air_monitor_bme280_humidity") @@ -167,6 +176,18 @@ async def test_sensor(hass): assert entry assert entry.unique_id == "aa:bb:cc:dd:ee:ff-signal" + state = hass.states.get("sensor.nettigo_air_monitor_uptime") + assert state + assert ( + state.state + == (utcnow() - timedelta(seconds=456987)).replace(microsecond=0).isoformat() + ) + assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TIMESTAMP + + entry = registry.async_get("sensor.nettigo_air_monitor_uptime") + assert entry + assert entry.unique_id == "aa:bb:cc:dd:ee:ff-uptime" + async def test_sensor_disabled(hass): """Test sensor disabled by default."""