From 2d5176d1f6c84f8551aff68c63c878c16b00b6d9 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Wed, 27 Dec 2023 13:39:01 +0100 Subject: [PATCH] Use entity descriptions in Netgear LTE (#106414) --- .../components/netgear_lte/__init__.py | 35 ++++- .../components/netgear_lte/binary_sensor.py | 42 ++++-- .../components/netgear_lte/sensor.py | 131 ++++++++++-------- .../components/netgear_lte/sensor_types.py | 42 ------ 4 files changed, 134 insertions(+), 116 deletions(-) delete mode 100644 homeassistant/components/netgear_lte/sensor_types.py diff --git a/homeassistant/components/netgear_lte/__init__.py b/homeassistant/components/netgear_lte/__init__.py index c7dd21405559..00a43282210d 100644 --- a/homeassistant/components/netgear_lte/__init__.py +++ b/homeassistant/components/netgear_lte/__init__.py @@ -25,7 +25,6 @@ from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.typing import ConfigType -from . import sensor_types from .const import ( ATTR_FROM, ATTR_HOST, @@ -45,6 +44,28 @@ SCAN_INTERVAL = timedelta(seconds=10) EVENT_SMS = "netgear_lte_sms" +ALL_SENSORS = [ + "sms", + "sms_total", + "usage", + "radio_quality", + "rx_level", + "tx_level", + "upstream", + "connection_text", + "connection_type", + "current_ps_service_type", + "register_network_display", + "current_band", + "cell_id", +] + +ALL_BINARY_SENSORS = [ + "roaming", + "wire_connected", + "mobile_connected", +] + NOTIFY_SCHEMA = vol.Schema( { @@ -55,17 +76,17 @@ NOTIFY_SCHEMA = vol.Schema( SENSOR_SCHEMA = vol.Schema( { - vol.Optional( - CONF_MONITORED_CONDITIONS, default=sensor_types.DEFAULT_SENSORS - ): vol.All(cv.ensure_list, [vol.In(sensor_types.ALL_SENSORS)]) + vol.Optional(CONF_MONITORED_CONDITIONS, default=["usage"]): vol.All( + cv.ensure_list, [vol.In(ALL_SENSORS)] + ) } ) BINARY_SENSOR_SCHEMA = vol.Schema( { - vol.Optional( - CONF_MONITORED_CONDITIONS, default=sensor_types.DEFAULT_BINARY_SENSORS - ): vol.All(cv.ensure_list, [vol.In(sensor_types.ALL_BINARY_SENSORS)]) + vol.Optional(CONF_MONITORED_CONDITIONS, default=["mobile_connected"]): vol.All( + cv.ensure_list, [vol.In(ALL_BINARY_SENSORS)] + ) } ) diff --git a/homeassistant/components/netgear_lte/binary_sensor.py b/homeassistant/components/netgear_lte/binary_sensor.py index b8441d8fb7cb..810e3733fbe9 100644 --- a/homeassistant/components/netgear_lte/binary_sensor.py +++ b/homeassistant/components/netgear_lte/binary_sensor.py @@ -1,14 +1,32 @@ """Support for Netgear LTE binary sensors.""" from __future__ import annotations -from homeassistant.components.binary_sensor import BinarySensorEntity +from homeassistant.components.binary_sensor import ( + BinarySensorDeviceClass, + BinarySensorEntity, + BinarySensorEntityDescription, +) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback +from . import ModemData from .const import DOMAIN from .entity import LTEEntity -from .sensor_types import ALL_BINARY_SENSORS, BINARY_SENSOR_CLASSES + +BINARY_SENSORS: tuple[BinarySensorEntityDescription, ...] = ( + BinarySensorEntityDescription( + key="roaming", + ), + BinarySensorEntityDescription( + key="wire_connected", + device_class=BinarySensorDeviceClass.CONNECTIVITY, + ), + BinarySensorEntityDescription( + key="mobile_connected", + device_class=BinarySensorDeviceClass.CONNECTIVITY, + ), +) async def async_setup_entry( @@ -18,19 +36,23 @@ async def async_setup_entry( modem_data = hass.data[DOMAIN].get_modem_data(entry.data) async_add_entities( - LTEBinarySensor(modem_data, sensor) for sensor in ALL_BINARY_SENSORS + NetgearLTEBinarySensor(modem_data, sensor) for sensor in BINARY_SENSORS ) -class LTEBinarySensor(LTEEntity, BinarySensorEntity): +class NetgearLTEBinarySensor(LTEEntity, BinarySensorEntity): """Netgear LTE binary sensor entity.""" + def __init__( + self, + modem_data: ModemData, + entity_description: BinarySensorEntityDescription, + ) -> None: + """Initialize a Netgear LTE binary sensor entity.""" + super().__init__(modem_data, entity_description.key) + self.entity_description = entity_description + @property def is_on(self): """Return true if the binary sensor is on.""" - return getattr(self.modem_data.data, self.sensor_type) - - @property - def device_class(self): - """Return the class of binary sensor.""" - return BINARY_SENSOR_CLASSES[self.sensor_type] + return getattr(self.modem_data.data, self.entity_description.key) diff --git a/homeassistant/components/netgear_lte/sensor.py b/homeassistant/components/netgear_lte/sensor.py index 5632999ae964..b91bb9b561a1 100644 --- a/homeassistant/components/netgear_lte/sensor.py +++ b/homeassistant/components/netgear_lte/sensor.py @@ -1,19 +1,72 @@ """Support for Netgear LTE sensors.""" from __future__ import annotations -from homeassistant.components.sensor import SensorDeviceClass, SensorEntity +from collections.abc import Callable +from dataclasses import dataclass + +from homeassistant.components.sensor import ( + SensorDeviceClass, + SensorEntity, + SensorEntityDescription, +) from homeassistant.config_entries import ConfigEntry +from homeassistant.const import ( + PERCENTAGE, + SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + UnitOfInformation, +) from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.typing import StateType +from . import ModemData from .const import DOMAIN from .entity import LTEEntity -from .sensor_types import ( - ALL_SENSORS, - SENSOR_SMS, - SENSOR_SMS_TOTAL, - SENSOR_UNITS, - SENSOR_USAGE, + + +@dataclass(frozen=True, kw_only=True) +class NetgearLTESensorEntityDescription(SensorEntityDescription): + """Class describing Netgear LTE entities.""" + + value_fn: Callable[[ModemData], StateType] | None = None + + +SENSORS: tuple[NetgearLTESensorEntityDescription, ...] = ( + NetgearLTESensorEntityDescription( + key="sms", + native_unit_of_measurement="unread", + value_fn=lambda modem_data: sum(1 for x in modem_data.data.sms if x.unread), + ), + NetgearLTESensorEntityDescription( + key="sms_total", + native_unit_of_measurement="messages", + value_fn=lambda modem_data: len(modem_data.data.sms), + ), + NetgearLTESensorEntityDescription( + key="usage", + device_class=SensorDeviceClass.DATA_SIZE, + native_unit_of_measurement=UnitOfInformation.MEBIBYTES, + value_fn=lambda modem_data: round(modem_data.data.usage / 1024**2, 1), + ), + NetgearLTESensorEntityDescription( + key="radio_quality", + native_unit_of_measurement=PERCENTAGE, + ), + NetgearLTESensorEntityDescription( + key="rx_level", + native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + ), + NetgearLTESensorEntityDescription( + key="tx_level", + native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + ), + NetgearLTESensorEntityDescription(key="upstream"), + NetgearLTESensorEntityDescription(key="connection_text"), + NetgearLTESensorEntityDescription(key="connection_type"), + NetgearLTESensorEntityDescription(key="current_ps_service_type"), + NetgearLTESensorEntityDescription(key="register_network_display"), + NetgearLTESensorEntityDescription(key="current_band"), + NetgearLTESensorEntityDescription(key="cell_id"), ) @@ -23,62 +76,26 @@ async def async_setup_entry( """Set up the Netgear LTE sensor.""" modem_data = hass.data[DOMAIN].get_modem_data(entry.data) - sensors: list[SensorEntity] = [] - for sensor in ALL_SENSORS: - if sensor == SENSOR_SMS: - sensors.append(SMSUnreadSensor(modem_data, sensor)) - elif sensor == SENSOR_SMS_TOTAL: - sensors.append(SMSTotalSensor(modem_data, sensor)) - elif sensor == SENSOR_USAGE: - sensors.append(UsageSensor(modem_data, sensor)) - else: - sensors.append(GenericSensor(modem_data, sensor)) - - async_add_entities(sensors) + async_add_entities(NetgearLTESensor(modem_data, sensor) for sensor in SENSORS) -class LTESensor(LTEEntity, SensorEntity): +class NetgearLTESensor(LTEEntity, SensorEntity): """Base LTE sensor entity.""" - @property - def native_unit_of_measurement(self): - """Return the unit of measurement.""" - return SENSOR_UNITS[self.sensor_type] + entity_description: NetgearLTESensorEntityDescription - -class SMSUnreadSensor(LTESensor): - """Unread SMS sensor entity.""" + def __init__( + self, + modem_data: ModemData, + entity_description: NetgearLTESensorEntityDescription, + ) -> None: + """Initialize a Netgear LTE sensor entity.""" + super().__init__(modem_data, entity_description.key) + self.entity_description = entity_description @property - def native_value(self): - """Return the state of the sensor.""" - return sum(1 for x in self.modem_data.data.sms if x.unread) - - -class SMSTotalSensor(LTESensor): - """Total SMS sensor entity.""" - - @property - def native_value(self): - """Return the state of the sensor.""" - return len(self.modem_data.data.sms) - - -class UsageSensor(LTESensor): - """Data usage sensor entity.""" - - _attr_device_class = SensorDeviceClass.DATA_SIZE - - @property - def native_value(self) -> float: - """Return the state of the sensor.""" - return round(self.modem_data.data.usage / 1024**2, 1) - - -class GenericSensor(LTESensor): - """Sensor entity with raw state.""" - - @property - def native_value(self): + def native_value(self) -> StateType: """Return the state of the sensor.""" + if self.entity_description.value_fn is not None: + return self.entity_description.value_fn(self.modem_data) return getattr(self.modem_data.data, self.sensor_type) diff --git a/homeassistant/components/netgear_lte/sensor_types.py b/homeassistant/components/netgear_lte/sensor_types.py deleted file mode 100644 index 01aa267e9536..000000000000 --- a/homeassistant/components/netgear_lte/sensor_types.py +++ /dev/null @@ -1,42 +0,0 @@ -"""Define possible sensor types.""" - -from homeassistant.components.binary_sensor import BinarySensorDeviceClass -from homeassistant.const import ( - PERCENTAGE, - SIGNAL_STRENGTH_DECIBELS_MILLIWATT, - UnitOfInformation, -) - -SENSOR_SMS = "sms" -SENSOR_SMS_TOTAL = "sms_total" -SENSOR_USAGE = "usage" - -SENSOR_UNITS = { - SENSOR_SMS: "unread", - SENSOR_SMS_TOTAL: "messages", - SENSOR_USAGE: UnitOfInformation.MEBIBYTES, - "radio_quality": PERCENTAGE, - "rx_level": SIGNAL_STRENGTH_DECIBELS_MILLIWATT, - "tx_level": SIGNAL_STRENGTH_DECIBELS_MILLIWATT, - "upstream": None, - "connection_text": None, - "connection_type": None, - "current_ps_service_type": None, - "register_network_display": None, - "current_band": None, - "cell_id": None, -} - -BINARY_SENSOR_MOBILE_CONNECTED = "mobile_connected" - -BINARY_SENSOR_CLASSES = { - "roaming": None, - "wire_connected": BinarySensorDeviceClass.CONNECTIVITY, - BINARY_SENSOR_MOBILE_CONNECTED: BinarySensorDeviceClass.CONNECTIVITY, -} - -ALL_SENSORS = list(SENSOR_UNITS) -DEFAULT_SENSORS = [SENSOR_USAGE] - -ALL_BINARY_SENSORS = list(BINARY_SENSOR_CLASSES) -DEFAULT_BINARY_SENSORS = [BINARY_SENSOR_MOBILE_CONNECTED]