Use EntityDescription - skybell (#53564)

* Use EntityDescription - skybell

* Fix typing
This commit is contained in:
Marc Mueller 2021-07-27 19:51:07 +02:00 committed by GitHub
parent a133eae88e
commit 736577abef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 102 deletions

View File

@ -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 {}

View File

@ -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

View File

@ -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)