diff --git a/homeassistant/components/arlo/sensor.py b/homeassistant/components/arlo/sensor.py index c794bf1ef5e..883fd011c52 100644 --- a/homeassistant/components/arlo/sensor.py +++ b/homeassistant/components/arlo/sensor.py @@ -1,13 +1,19 @@ """Sensor support for Netgear Arlo IP cameras.""" +from dataclasses import replace import logging import voluptuous as vol -from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity +from homeassistant.components.sensor import ( + PLATFORM_SCHEMA, + SensorEntity, + SensorEntityDescription, +) from homeassistant.const import ( ATTR_ATTRIBUTION, CONCENTRATION_PARTS_PER_MILLION, CONF_MONITORED_CONDITIONS, + DEVICE_CLASS_BATTERY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, PERCENTAGE, @@ -22,17 +28,43 @@ from . import ATTRIBUTION, DATA_ARLO, DEFAULT_BRAND, SIGNAL_UPDATE_ARLO _LOGGER = logging.getLogger(__name__) -# sensor_type [ description, unit, icon ] -SENSOR_TYPES = { - "last_capture": ["Last", None, "run-fast"], - "total_cameras": ["Arlo Cameras", None, "video"], - "captured_today": ["Captured Today", None, "file-video"], - "battery_level": ["Battery Level", PERCENTAGE, "battery-50"], - "signal_strength": ["Signal Strength", None, "signal"], - "temperature": ["Temperature", TEMP_CELSIUS, "thermometer"], - "humidity": ["Humidity", PERCENTAGE, "water-percent"], - "air_quality": ["Air Quality", CONCENTRATION_PARTS_PER_MILLION, "biohazard"], -} +SENSOR_TYPES = ( + SensorEntityDescription(key="last_capture", name="Last", icon="mdi:run-fast"), + SensorEntityDescription(key="total_cameras", name="Arlo Cameras", icon="mdi:video"), + SensorEntityDescription( + key="captured_today", name="Captured Today", icon="mdi:file-video" + ), + SensorEntityDescription( + key="battery_level", + name="Battery Level", + unit_of_measurement=PERCENTAGE, + icon="mdi:battery-50", + device_class=DEVICE_CLASS_BATTERY, + ), + SensorEntityDescription( + key="signal_strength", name="Signal Strength", icon="mdi:signal" + ), + SensorEntityDescription( + key="temperature", + name="Temperature", + unit_of_measurement=TEMP_CELSIUS, + icon="mdi:thermometer", + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key="humidity", + name="Humidity", + unit_of_measurement=PERCENTAGE, + icon="mdi:water-percent", + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key="air_quality", + name="Air Quality", + unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, + icon="mdi:biohazard", + ), +) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { @@ -50,24 +82,27 @@ def setup_platform(hass, config, add_entities, discovery_info=None): return sensors = [] - for sensor_type in config[CONF_MONITORED_CONDITIONS]: - if sensor_type == "total_cameras": - sensors.append(ArloSensor(SENSOR_TYPES[sensor_type][0], arlo, sensor_type)) + for sensor_original in SENSOR_TYPES: + if sensor_original.key not in config[CONF_MONITORED_CONDITIONS]: + continue + sensor_entry = replace(sensor_original) + if sensor_entry.key == "total_cameras": + sensors.append(ArloSensor(arlo, sensor_entry)) else: for camera in arlo.cameras: - if sensor_type in ("temperature", "humidity", "air_quality"): + if sensor_entry.key in ("temperature", "humidity", "air_quality"): continue - name = f"{SENSOR_TYPES[sensor_type][0]} {camera.name}" - sensors.append(ArloSensor(name, camera, sensor_type)) + sensor_entry.name = f"{sensor_entry.name} {camera.name}" + sensors.append(ArloSensor(camera, sensor_entry)) for base_station in arlo.base_stations: if ( - sensor_type in ("temperature", "humidity", "air_quality") + sensor_entry.key in ("temperature", "humidity", "air_quality") and base_station.model_id == "ABC1000" ): - name = f"{SENSOR_TYPES[sensor_type][0]} {base_station.name}" - sensors.append(ArloSensor(name, base_station, sensor_type)) + sensor_entry.name = f"{sensor_entry.name} {base_station.name}" + sensors.append(ArloSensor(base_station, sensor_entry)) add_entities(sensors, True) @@ -75,19 +110,11 @@ def setup_platform(hass, config, add_entities, discovery_info=None): class ArloSensor(SensorEntity): """An implementation of a Netgear Arlo IP sensor.""" - def __init__(self, name, device, sensor_type): + def __init__(self, device, sensor_entry): """Initialize an Arlo sensor.""" - _LOGGER.debug("ArloSensor created for %s", name) - self._name = name + self.entity_description = sensor_entry self._data = device - self._sensor_type = sensor_type self._state = None - self._icon = f"mdi:{SENSOR_TYPES.get(self._sensor_type)[2]}" - - @property - def name(self): - """Return the name of this camera.""" - return self._name async def async_added_to_hass(self): """Register callbacks.""" @@ -110,36 +137,22 @@ class ArloSensor(SensorEntity): @property def icon(self): """Icon to use in the frontend, if any.""" - if self._sensor_type == "battery_level" and self._state is not None: + if self.entity_description.key == "battery_level" and self._state is not None: return icon_for_battery_level( battery_level=int(self._state), charging=False ) - return self._icon - - @property - def unit_of_measurement(self): - """Return the units of measurement.""" - return SENSOR_TYPES.get(self._sensor_type)[1] - - @property - def device_class(self): - """Return the device class of the sensor.""" - if self._sensor_type == "temperature": - return DEVICE_CLASS_TEMPERATURE - if self._sensor_type == "humidity": - return DEVICE_CLASS_HUMIDITY - return None + return self.entity_description.icon def update(self): """Get the latest data and updates the state.""" _LOGGER.debug("Updating Arlo sensor %s", self.name) - if self._sensor_type == "total_cameras": + if self.entity_description.key == "total_cameras": self._state = len(self._data.cameras) - elif self._sensor_type == "captured_today": + elif self.entity_description.key == "captured_today": self._state = len(self._data.captured_today) - elif self._sensor_type == "last_capture": + elif self.entity_description.key == "last_capture": try: video = self._data.last_video self._state = video.created_at_pretty("%m-%d-%Y %H:%M:%S") @@ -151,31 +164,31 @@ class ArloSensor(SensorEntity): _LOGGER.debug(error_msg) self._state = None - elif self._sensor_type == "battery_level": + elif self.entity_description.key == "battery_level": try: self._state = self._data.battery_level except TypeError: self._state = None - elif self._sensor_type == "signal_strength": + elif self.entity_description.key == "signal_strength": try: self._state = self._data.signal_strength except TypeError: self._state = None - elif self._sensor_type == "temperature": + elif self.entity_description.key == "temperature": try: self._state = self._data.ambient_temperature except TypeError: self._state = None - elif self._sensor_type == "humidity": + elif self.entity_description.key == "humidity": try: self._state = self._data.ambient_humidity except TypeError: self._state = None - elif self._sensor_type == "air_quality": + elif self.entity_description.key == "air_quality": try: self._state = self._data.ambient_air_quality except TypeError: @@ -189,7 +202,7 @@ class ArloSensor(SensorEntity): attrs[ATTR_ATTRIBUTION] = ATTRIBUTION attrs["brand"] = DEFAULT_BRAND - if self._sensor_type != "total_cameras": + if self.entity_description.key != "total_cameras": attrs["model"] = self._data.model_id return attrs diff --git a/tests/components/arlo/test_sensor.py b/tests/components/arlo/test_sensor.py index b8389d1903f..34d5088397d 100644 --- a/tests/components/arlo/test_sensor.py +++ b/tests/components/arlo/test_sensor.py @@ -5,6 +5,7 @@ from unittest.mock import patch import pytest from homeassistant.components.arlo import DATA_ARLO, sensor as arlo +from homeassistant.components.arlo.sensor import SENSOR_TYPES from homeassistant.const import ( ATTR_ATTRIBUTION, DEVICE_CLASS_HUMIDITY, @@ -20,7 +21,11 @@ def _get_named_tuple(input_dict): def _get_sensor(name="Last", sensor_type="last_capture", data=None): if data is None: data = {} - return arlo.ArloSensor(name, data, sensor_type) + sensor_entry = next( + sensor_entry for sensor_entry in SENSOR_TYPES if sensor_entry.key == sensor_type + ) + sensor_entry.name = name + return arlo.ArloSensor(data, sensor_entry) @pytest.fixture()