diff --git a/homeassistant/components/skybell/binary_sensor.py b/homeassistant/components/skybell/binary_sensor.py index c6e8200c812..1e7eae145e3 100644 --- a/homeassistant/components/skybell/binary_sensor.py +++ b/homeassistant/components/skybell/binary_sensor.py @@ -2,7 +2,7 @@ from __future__ import annotations from datetime import timedelta -from typing import NamedTuple +from typing import Any import voluptuous as vol @@ -11,6 +11,7 @@ from homeassistant.components.binary_sensor import ( DEVICE_CLASS_OCCUPANCY, PLATFORM_SCHEMA, BinarySensorEntity, + BinarySensorEntityDescription, ) from homeassistant.const import CONF_ENTITY_NAMESPACE, CONF_MONITORED_CONDITIONS import homeassistant.helpers.config_validation as cv @@ -20,34 +21,27 @@ from . import DEFAULT_ENTITY_NAMESPACE, DOMAIN as SKYBELL_DOMAIN, SkybellDevice SCAN_INTERVAL = timedelta(seconds=10) -class SkybellBinarySensorMetadata(NamedTuple): - """Metadata for an individual Skybell binary_sensor.""" - - name: str - device_class: str - event: str - - -SENSOR_TYPES = { - "button": SkybellBinarySensorMetadata( - "Button", +BINARY_SENSOR_TYPES: dict[str, BinarySensorEntityDescription] = { + "button": BinarySensorEntityDescription( + key="device:sensor:button", + name="Button", device_class=DEVICE_CLASS_OCCUPANCY, - event="device:sensor:button", ), - "motion": SkybellBinarySensorMetadata( - "Motion", + "motion": BinarySensorEntityDescription( + key="device:sensor:motion", + name="Motion", device_class=DEVICE_CLASS_MOTION, - event="device:sensor:motion", ), } + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Optional( CONF_ENTITY_NAMESPACE, default=DEFAULT_ENTITY_NAMESPACE ): cv.string, vol.Required(CONF_MONITORED_CONDITIONS, default=[]): vol.All( - cv.ensure_list, [vol.In(SENSOR_TYPES)] + cv.ensure_list, [vol.In(BINARY_SENSOR_TYPES)] ), } ) @@ -57,36 +51,28 @@ def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the platform for a Skybell device.""" skybell = hass.data.get(SKYBELL_DOMAIN) - sensors = [] - for sensor_type in config.get(CONF_MONITORED_CONDITIONS): - for device in skybell.get_devices(): - sensors.append(SkybellBinarySensor(device, sensor_type)) + binary_sensors = [ + SkybellBinarySensor(device, BINARY_SENSOR_TYPES[sensor_type]) + for device in skybell.get_devices() + for sensor_type in config[CONF_MONITORED_CONDITIONS] + ] - add_entities(sensors, True) + add_entities(binary_sensors, True) class SkybellBinarySensor(SkybellDevice, BinarySensorEntity): """A binary sensor implementation for Skybell devices.""" - def __init__(self, device, sensor_type): + def __init__( + self, + device, + description: BinarySensorEntityDescription, + ): """Initialize a binary sensor for a Skybell device.""" super().__init__(device) - self._sensor_type = sensor_type - self._metadata = SENSOR_TYPES[self._sensor_type] - self._attr_name = f"{self._device.name} {self._metadata.name}" - self._device_class = self._metadata.device_class - self._event = {} - self._state = None - - @property - def is_on(self): - """Return True if the binary sensor is on.""" - return self._state - - @property - def device_class(self): - """Return the class of the binary sensor.""" - return self._device_class + self.entity_description = description + self._attr_name = f"{self._device.name} {description.name}" + self._event: dict[Any, Any] = {} @property def extra_state_attributes(self): @@ -101,8 +87,8 @@ class SkybellBinarySensor(SkybellDevice, BinarySensorEntity): """Get the latest data and updates the state.""" super().update() - event = self._device.latest(self._metadata.event) + event = self._device.latest(self.entity_description.key) - self._state = bool(event and event.get("id") != self._event.get("id")) + self._attr_is_on = bool(event and event.get("id") != self._event.get("id")) self._event = event or {} diff --git a/homeassistant/components/skybell/sensor.py b/homeassistant/components/skybell/sensor.py index de99a22f4c9..cee864911b4 100644 --- a/homeassistant/components/skybell/sensor.py +++ b/homeassistant/components/skybell/sensor.py @@ -1,9 +1,15 @@ """Sensor support for Skybell Doorbells.""" +from __future__ import annotations + from datetime import timedelta 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 CONF_ENTITY_NAMESPACE, CONF_MONITORED_CONDITIONS import homeassistant.helpers.config_validation as cv @@ -11,8 +17,15 @@ from . import DEFAULT_ENTITY_NAMESPACE, DOMAIN as SKYBELL_DOMAIN, SkybellDevice SCAN_INTERVAL = timedelta(seconds=30) -# Sensor types: Name, icon -SENSOR_TYPES = {"chime_level": ["Chime Level", "bell-ring"]} +SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( + SensorEntityDescription( + key="chime_level", + name="Chime Level", + icon="mdi:bell-ring", + ), +) +MONITORED_CONDITIONS: list[str] = [desc.key for desc in SENSOR_TYPES] + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { @@ -20,7 +33,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( CONF_ENTITY_NAMESPACE, default=DEFAULT_ENTITY_NAMESPACE ): cv.string, vol.Required(CONF_MONITORED_CONDITIONS, default=[]): vol.All( - cv.ensure_list, [vol.In(SENSOR_TYPES)] + cv.ensure_list, [vol.In(MONITORED_CONDITIONS)] ), } ) @@ -30,10 +43,12 @@ def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the platform for a Skybell device.""" skybell = hass.data.get(SKYBELL_DOMAIN) - sensors = [] - for sensor_type in config.get(CONF_MONITORED_CONDITIONS): - for device in skybell.get_devices(): - sensors.append(SkybellSensor(device, sensor_type)) + sensors = [ + SkybellSensor(device, description) + for device in skybell.get_devices() + for description in SENSOR_TYPES + if description.key in config[CONF_MONITORED_CONDITIONS] + ] add_entities(sensors, True) @@ -41,34 +56,19 @@ def setup_platform(hass, config, add_entities, discovery_info=None): class SkybellSensor(SkybellDevice, SensorEntity): """A sensor implementation for Skybell devices.""" - def __init__(self, device, sensor_type): + def __init__( + self, + device, + description: SensorEntityDescription, + ): """Initialize a sensor for a Skybell device.""" super().__init__(device) - self._sensor_type = sensor_type - self._icon = f"mdi:{SENSOR_TYPES[self._sensor_type][1]}" - self._name = "{} {}".format( - self._device.name, SENSOR_TYPES[self._sensor_type][0] - ) - self._state = None - - @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def state(self): - """Return the state of the sensor.""" - return self._state - - @property - def icon(self): - """Icon to use in the frontend, if any.""" - return self._icon + self.entity_description = description + self._attr_name = f"{self._device.name} {description.name}" def update(self): """Get the latest data and updates the state.""" super().update() - if self._sensor_type == "chime_level": - self._state = self._device.outdoor_chime_level + if self.entity_description.key == "chime_level": + self._attr_state = self._device.outdoor_chime_level diff --git a/homeassistant/components/skybell/switch.py b/homeassistant/components/skybell/switch.py index 5f9706de4d1..c842f0e91af 100644 --- a/homeassistant/components/skybell/switch.py +++ b/homeassistant/components/skybell/switch.py @@ -1,31 +1,30 @@ """Switch support for the Skybell HD Doorbell.""" from __future__ import annotations -from typing import NamedTuple - import voluptuous as vol -from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity +from homeassistant.components.switch import ( + PLATFORM_SCHEMA, + SwitchEntity, + SwitchEntityDescription, +) from homeassistant.const import CONF_ENTITY_NAMESPACE, CONF_MONITORED_CONDITIONS import homeassistant.helpers.config_validation as cv from . import DEFAULT_ENTITY_NAMESPACE, DOMAIN as SKYBELL_DOMAIN, SkybellDevice - -class SkybellSwitchMetadata(NamedTuple): - """Metadata for an individual Skybell switch.""" - - name: str - - -SWITCH_TYPES = { - "do_not_disturb": SkybellSwitchMetadata( - "Do Not Disturb", +SWITCH_TYPES: tuple[SwitchEntityDescription, ...] = ( + SwitchEntityDescription( + key="do_not_disturb", + name="Do Not Disturb", ), - "motion_sensor": SkybellSwitchMetadata( - "Motion Sensor", + SwitchEntityDescription( + key="motion_sensor", + name="Motion Sensor", ), -} +) +MONITORED_CONDITIONS: list[str] = [desc.key for desc in SWITCH_TYPES] + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { @@ -33,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( CONF_ENTITY_NAMESPACE, default=DEFAULT_ENTITY_NAMESPACE ): cv.string, vol.Required(CONF_MONITORED_CONDITIONS, default=[]): vol.All( - cv.ensure_list, [vol.In(SWITCH_TYPES)] + cv.ensure_list, [vol.In(MONITORED_CONDITIONS)] ), } ) @@ -43,33 +42,38 @@ def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the platform for a Skybell device.""" skybell = hass.data.get(SKYBELL_DOMAIN) - sensors = [] - for switch_type in config.get(CONF_MONITORED_CONDITIONS): - for device in skybell.get_devices(): - sensors.append(SkybellSwitch(device, switch_type)) + switches = [ + SkybellSwitch(device, description) + for device in skybell.get_devices() + for description in SWITCH_TYPES + if description.key in config[CONF_MONITORED_CONDITIONS] + ] - add_entities(sensors, True) + add_entities(switches, True) class SkybellSwitch(SkybellDevice, SwitchEntity): """A switch implementation for Skybell devices.""" - def __init__(self, device, switch_type): + def __init__( + self, + device, + description: SwitchEntityDescription, + ): """Initialize a light for a Skybell device.""" super().__init__(device) - self._switch_type = switch_type - metadata = SWITCH_TYPES[self._switch_type] - self._attr_name = f"{self._device.name} {metadata.name}" + self.entity_description = description + self._attr_name = f"{self._device.name} {description.name}" def turn_on(self, **kwargs): """Turn on the switch.""" - setattr(self._device, self._switch_type, True) + setattr(self._device, self.entity_description.key, True) def turn_off(self, **kwargs): """Turn off the switch.""" - setattr(self._device, self._switch_type, False) + setattr(self._device, self.entity_description.key, False) @property def is_on(self): """Return true if device is on.""" - return getattr(self._device, self._switch_type) + return getattr(self._device, self.entity_description.key)