From 38a210292f40dab36dfcf8be950f0231d50dde08 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 17 Aug 2021 00:14:00 +0200 Subject: [PATCH] Use EntityDescription - logi_circle (#54429) --- .../components/logi_circle/__init__.py | 8 +- homeassistant/components/logi_circle/const.py | 46 +++++++-- .../components/logi_circle/sensor.py | 95 ++++++++----------- 3 files changed, 81 insertions(+), 68 deletions(-) diff --git a/homeassistant/components/logi_circle/__init__.py b/homeassistant/components/logi_circle/__init__.py index 9e1a4803e11..d9060b10080 100644 --- a/homeassistant/components/logi_circle/__init__.py +++ b/homeassistant/components/logi_circle/__init__.py @@ -29,8 +29,8 @@ from .const import ( DEFAULT_CACHEDB, DOMAIN, LED_MODE_KEY, - LOGI_SENSORS, RECORDING_MODE_KEY, + SENSOR_TYPES, SIGNAL_LOGI_CIRCLE_RECONFIGURE, SIGNAL_LOGI_CIRCLE_RECORD, SIGNAL_LOGI_CIRCLE_SNAPSHOT, @@ -50,10 +50,12 @@ ATTR_DURATION = "duration" PLATFORMS = ["camera", "sensor"] +SENSOR_KEYS = [desc.key for desc in SENSOR_TYPES] + SENSOR_SCHEMA = vol.Schema( { - vol.Optional(CONF_MONITORED_CONDITIONS, default=list(LOGI_SENSORS)): vol.All( - cv.ensure_list, [vol.In(LOGI_SENSORS)] + vol.Optional(CONF_MONITORED_CONDITIONS, default=SENSOR_KEYS): vol.All( + cv.ensure_list, [vol.In(SENSOR_KEYS)] ) } ) diff --git a/homeassistant/components/logi_circle/const.py b/homeassistant/components/logi_circle/const.py index 92967d2eb84..02e51993198 100644 --- a/homeassistant/components/logi_circle/const.py +++ b/homeassistant/components/logi_circle/const.py @@ -1,4 +1,7 @@ """Constants in Logi Circle component.""" +from __future__ import annotations + +from homeassistant.components.sensor import SensorEntityDescription from homeassistant.const import PERCENTAGE DOMAIN = "logi_circle" @@ -12,15 +15,40 @@ DEFAULT_CACHEDB = ".logi_cache.pickle" LED_MODE_KEY = "LED" RECORDING_MODE_KEY = "RECORDING_MODE" -# Sensor types: Name, unit of measure, icon per sensor key. -LOGI_SENSORS = { - "battery_level": ["Battery", PERCENTAGE, "battery-50"], - "last_activity_time": ["Last Activity", None, "history"], - "recording": ["Recording Mode", None, "eye"], - "signal_strength_category": ["WiFi Signal Category", None, "wifi"], - "signal_strength_percentage": ["WiFi Signal Strength", PERCENTAGE, "wifi"], - "streaming": ["Streaming Mode", None, "camera"], -} +SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( + SensorEntityDescription( + key="battery_level", + name="Battery", + native_unit_of_measurement=PERCENTAGE, + icon="mdi:battery-50", + ), + SensorEntityDescription( + key="last_activity_time", + name="Last Activity", + icon="mdi:history", + ), + SensorEntityDescription( + key="recording", + name="Recording Mode", + icon="mdi:eye", + ), + SensorEntityDescription( + key="signal_strength_category", + name="WiFi Signal Category", + icon="mdi:wifi", + ), + SensorEntityDescription( + key="signal_strength_percentage", + name="WiFi Signal Strength", + native_unit_of_measurement=PERCENTAGE, + icon="mdi:wifi", + ), + SensorEntityDescription( + key="streaming", + name="Streaming Mode", + icon="mdi:camera", + ), +) SIGNAL_LOGI_CIRCLE_RECONFIGURE = "logi_circle_reconfigure" SIGNAL_LOGI_CIRCLE_SNAPSHOT = "logi_circle_snapshot" diff --git a/homeassistant/components/logi_circle/sensor.py b/homeassistant/components/logi_circle/sensor.py index a4158762b37..50671152587 100644 --- a/homeassistant/components/logi_circle/sensor.py +++ b/homeassistant/components/logi_circle/sensor.py @@ -1,7 +1,10 @@ """Support for Logi Circle sensors.""" -import logging +from __future__ import annotations -from homeassistant.components.sensor import SensorEntity +import logging +from typing import Any + +from homeassistant.components.sensor import SensorEntity, SensorEntityDescription from homeassistant.const import ( ATTR_ATTRIBUTION, ATTR_BATTERY_CHARGING, @@ -13,12 +16,7 @@ from homeassistant.const import ( from homeassistant.helpers.icon import icon_for_battery_level from homeassistant.util.dt import as_local -from .const import ( - ATTRIBUTION, - DEVICE_BRAND, - DOMAIN as LOGI_CIRCLE_DOMAIN, - LOGI_SENSORS as SENSOR_TYPES, -) +from .const import ATTRIBUTION, DEVICE_BRAND, DOMAIN as LOGI_CIRCLE_DOMAIN, SENSOR_TYPES _LOGGER = logging.getLogger(__name__) @@ -33,44 +31,30 @@ async def async_setup_entry(hass, entry, async_add_entities): devices = await hass.data[LOGI_CIRCLE_DOMAIN].cameras time_zone = str(hass.config.time_zone) - sensors = [] - for sensor_type in entry.data.get(CONF_SENSORS).get(CONF_MONITORED_CONDITIONS): - for device in devices: - if device.supports_feature(sensor_type): - sensors.append(LogiSensor(device, time_zone, sensor_type)) + monitored_conditions = entry.data.get(CONF_SENSORS).get(CONF_MONITORED_CONDITIONS) + entities = [ + LogiSensor(device, time_zone, description) + for description in SENSOR_TYPES + if description.key in monitored_conditions + for device in devices + if device.supports_feature(description.key) + ] - async_add_entities(sensors, True) + async_add_entities(entities, True) class LogiSensor(SensorEntity): """A sensor implementation for a Logi Circle camera.""" - def __init__(self, camera, time_zone, sensor_type): + def __init__(self, camera, time_zone, description: SensorEntityDescription): """Initialize a sensor for Logi Circle camera.""" - self._sensor_type = sensor_type + self.entity_description = description self._camera = camera - self._id = f"{self._camera.mac_address}-{self._sensor_type}" - self._icon = f"mdi:{SENSOR_TYPES.get(self._sensor_type)[2]}" - self._name = f"{self._camera.name} {SENSOR_TYPES.get(self._sensor_type)[0]}" - self._activity = {} - self._state = None + self._attr_unique_id = f"{camera.mac_address}-{description.key}" + self._attr_name = f"{camera.name} {description.name}" + self._activity: dict[Any, Any] = {} self._tz = time_zone - @property - def unique_id(self): - """Return a unique ID.""" - return self._id - - @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def native_value(self): - """Return the state of the sensor.""" - return self._state - @property def device_info(self): """Return information about the device.""" @@ -93,7 +77,7 @@ class LogiSensor(SensorEntity): "microphone_gain": self._camera.microphone_gain, } - if self._sensor_type == "battery_level": + if self.entity_description.key == "battery_level": state[ATTR_BATTERY_CHARGING] = self._camera.charging return state @@ -101,37 +85,36 @@ class LogiSensor(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: + sensor_type = self.entity_description.key + if sensor_type == "battery_level" and self._attr_native_value is not None: return icon_for_battery_level( - battery_level=int(self._state), charging=False + battery_level=int(self._attr_native_value), charging=False ) - if self._sensor_type == "recording_mode" and self._state is not None: - return "mdi:eye" if self._state == STATE_ON else "mdi:eye-off" - if self._sensor_type == "streaming_mode" and self._state is not None: - return "mdi:camera" if self._state == STATE_ON else "mdi:camera-off" - return self._icon - - @property - def native_unit_of_measurement(self): - """Return the units of measurement.""" - return SENSOR_TYPES.get(self._sensor_type)[1] + if sensor_type == "recording_mode" and self._attr_native_value is not None: + return "mdi:eye" if self._attr_native_value == STATE_ON else "mdi:eye-off" + if sensor_type == "streaming_mode" and self._attr_native_value is not None: + return ( + "mdi:camera" + if self._attr_native_value == STATE_ON + else "mdi:camera-off" + ) + return self.entity_description.icon async def async_update(self): """Get the latest data and updates the state.""" - _LOGGER.debug("Pulling data from %s sensor", self._name) + _LOGGER.debug("Pulling data from %s sensor", self.name) await self._camera.update() - if self._sensor_type == "last_activity_time": + if self.entity_description.key == "last_activity_time": last_activity = await self._camera.get_last_activity(force_refresh=True) if last_activity is not None: last_activity_time = as_local(last_activity.end_time_utc) - self._state = ( + self._attr_native_value = ( f"{last_activity_time.hour:0>2}:{last_activity_time.minute:0>2}" ) else: - state = getattr(self._camera, self._sensor_type, None) + state = getattr(self._camera, self.entity_description.key, None) if isinstance(state, bool): - self._state = STATE_ON if state is True else STATE_OFF + self._attr_native_value = STATE_ON if state is True else STATE_OFF else: - self._state = state - self._state = state + self._attr_native_value = state