Migrate binary sensor device classes to StrEnum (#60651)

This commit is contained in:
Franck Nijhof 2021-12-01 08:12:09 +01:00 committed by GitHub
parent 12ff5dee74
commit 2b8f245e27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 135 additions and 102 deletions

View File

@ -18,6 +18,7 @@ from homeassistant.helpers.config_validation import ( # noqa: F401
from homeassistant.helpers.entity import Entity, EntityDescription from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType, StateType from homeassistant.helpers.typing import ConfigType, StateType
from homeassistant.util.enum import StrEnum
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -26,118 +27,124 @@ SCAN_INTERVAL = timedelta(seconds=30)
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + ".{}"
# On means low, Off means normal
DEVICE_CLASS_BATTERY = "battery"
# On means charging, Off means not charging class BinarySensorDeviceClass(StrEnum):
DEVICE_CLASS_BATTERY_CHARGING = "battery_charging" """Device class for binary sensors."""
# On means cold, Off means normal # On means low, Off means normal
DEVICE_CLASS_COLD = "cold" BATTERY = "battery"
# On means connected, Off means disconnected # On means charging, Off means not charging
DEVICE_CLASS_CONNECTIVITY = "connectivity" BATTERY_CHARGING = "battery_charging"
# On means open, Off means closed # On means cold, Off means normal
DEVICE_CLASS_DOOR = "door" COLD = "cold"
# On means open, Off means closed # On means connected, Off means disconnected
DEVICE_CLASS_GARAGE_DOOR = "garage_door" CONNECTIVITY = "connectivity"
# On means gas detected, Off means no gas (clear) # On means open, Off means closed
DEVICE_CLASS_GAS = "gas" DOOR = "door"
# On means hot, Off means normal # On means open, Off means closed
DEVICE_CLASS_HEAT = "heat" GARAGE_DOOR = "garage_door"
# On means light detected, Off means no light # On means gas detected, Off means no gas (clear)
DEVICE_CLASS_LIGHT = "light" GAS = "gas"
# On means open (unlocked), Off means closed (locked) # On means hot, Off means normal
DEVICE_CLASS_LOCK = "lock" HEAT = "heat"
# On means wet, Off means dry # On means light detected, Off means no light
DEVICE_CLASS_MOISTURE = "moisture" LIGHT = "light"
# On means motion detected, Off means no motion (clear) # On means open (unlocked), Off means closed (locked)
DEVICE_CLASS_MOTION = "motion" LOCK = "lock"
# On means moving, Off means not moving (stopped) # On means wet, Off means dry
DEVICE_CLASS_MOVING = "moving" MOISTURE = "moisture"
# On means occupied, Off means not occupied (clear) # On means motion detected, Off means no motion (clear)
DEVICE_CLASS_OCCUPANCY = "occupancy" MOTION = "motion"
# On means open, Off means closed # On means moving, Off means not moving (stopped)
DEVICE_CLASS_OPENING = "opening" MOVING = "moving"
# On means plugged in, Off means unplugged # On means occupied, Off means not occupied (clear)
DEVICE_CLASS_PLUG = "plug" OCCUPANCY = "occupancy"
# On means power detected, Off means no power # On means open, Off means closed
DEVICE_CLASS_POWER = "power" OPENING = "opening"
# On means home, Off means away # On means plugged in, Off means unplugged
DEVICE_CLASS_PRESENCE = "presence" PLUG = "plug"
# On means problem detected, Off means no problem (OK) # On means power detected, Off means no power
DEVICE_CLASS_PROBLEM = "problem" POWER = "power"
# On means running, Off means not running # On means home, Off means away
DEVICE_CLASS_RUNNING = "running" PRESENCE = "presence"
# On means unsafe, Off means safe # On means problem detected, Off means no problem (OK)
DEVICE_CLASS_SAFETY = "safety" PROBLEM = "problem"
# On means smoke detected, Off means no smoke (clear) # On means running, Off means not running
DEVICE_CLASS_SMOKE = "smoke" RUNNING = "running"
# On means sound detected, Off means no sound (clear) # On means unsafe, Off means safe
DEVICE_CLASS_SOUND = "sound" SAFETY = "safety"
# On means tampering detected, Off means no tampering (clear) # On means smoke detected, Off means no smoke (clear)
DEVICE_CLASS_TAMPER = "tamper" SMOKE = "smoke"
# On means update available, Off means up-to-date # On means sound detected, Off means no sound (clear)
DEVICE_CLASS_UPDATE = "update" SOUND = "sound"
# On means vibration detected, Off means no vibration # On means tampering detected, Off means no tampering (clear)
DEVICE_CLASS_VIBRATION = "vibration" TAMPER = "tamper"
# On means open, Off means closed # On means update available, Off means up-to-date
DEVICE_CLASS_WINDOW = "window" UPDATE = "update"
DEVICE_CLASSES = [ # On means vibration detected, Off means no vibration
DEVICE_CLASS_BATTERY, VIBRATION = "vibration"
DEVICE_CLASS_BATTERY_CHARGING,
DEVICE_CLASS_COLD,
DEVICE_CLASS_CONNECTIVITY,
DEVICE_CLASS_DOOR,
DEVICE_CLASS_GARAGE_DOOR,
DEVICE_CLASS_GAS,
DEVICE_CLASS_HEAT,
DEVICE_CLASS_LIGHT,
DEVICE_CLASS_LOCK,
DEVICE_CLASS_MOISTURE,
DEVICE_CLASS_MOTION,
DEVICE_CLASS_MOVING,
DEVICE_CLASS_OCCUPANCY,
DEVICE_CLASS_OPENING,
DEVICE_CLASS_PLUG,
DEVICE_CLASS_POWER,
DEVICE_CLASS_PRESENCE,
DEVICE_CLASS_PROBLEM,
DEVICE_CLASS_RUNNING,
DEVICE_CLASS_SAFETY,
DEVICE_CLASS_SMOKE,
DEVICE_CLASS_SOUND,
DEVICE_CLASS_TAMPER,
DEVICE_CLASS_UPDATE,
DEVICE_CLASS_VIBRATION,
DEVICE_CLASS_WINDOW,
]
DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(DEVICE_CLASSES)) # On means open, Off means closed
WINDOW = "window"
DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.Coerce(BinarySensorDeviceClass))
# DEVICE_CLASS* below are deprecated as of 2021.12
# use the BinarySensorDeviceClass enum instead.
DEVICE_CLASSES = [cls.value for cls in BinarySensorDeviceClass]
DEVICE_CLASS_BATTERY = BinarySensorDeviceClass.BATTERY.value
DEVICE_CLASS_BATTERY_CHARGING = BinarySensorDeviceClass.BATTERY_CHARGING.value
DEVICE_CLASS_COLD = BinarySensorDeviceClass.COLD.value
DEVICE_CLASS_CONNECTIVITY = BinarySensorDeviceClass.CONNECTIVITY.value
DEVICE_CLASS_DOOR = BinarySensorDeviceClass.DOOR.value
DEVICE_CLASS_GARAGE_DOOR = BinarySensorDeviceClass.GARAGE_DOOR.value
DEVICE_CLASS_GAS = BinarySensorDeviceClass.GAS.value
DEVICE_CLASS_HEAT = BinarySensorDeviceClass.HEAT.value
DEVICE_CLASS_LIGHT = BinarySensorDeviceClass.LIGHT.value
DEVICE_CLASS_LOCK = BinarySensorDeviceClass.LOCK.value
DEVICE_CLASS_MOISTURE = BinarySensorDeviceClass.MOISTURE.value
DEVICE_CLASS_MOTION = BinarySensorDeviceClass.MOTION.value
DEVICE_CLASS_MOVING = BinarySensorDeviceClass.MOVING.value
DEVICE_CLASS_OCCUPANCY = BinarySensorDeviceClass.OCCUPANCY.value
DEVICE_CLASS_OPENING = BinarySensorDeviceClass.OPENING.value
DEVICE_CLASS_PLUG = BinarySensorDeviceClass.PLUG.value
DEVICE_CLASS_POWER = BinarySensorDeviceClass.POWER.value
DEVICE_CLASS_PRESENCE = BinarySensorDeviceClass.PRESENCE.value
DEVICE_CLASS_PROBLEM = BinarySensorDeviceClass.PROBLEM.value
DEVICE_CLASS_RUNNING = BinarySensorDeviceClass.RUNNING.value
DEVICE_CLASS_SAFETY = BinarySensorDeviceClass.SAFETY.value
DEVICE_CLASS_SMOKE = BinarySensorDeviceClass.SMOKE.value
DEVICE_CLASS_SOUND = BinarySensorDeviceClass.SOUND.value
DEVICE_CLASS_TAMPER = BinarySensorDeviceClass.TAMPER.value
DEVICE_CLASS_UPDATE = BinarySensorDeviceClass.UPDATE.value
DEVICE_CLASS_VIBRATION = BinarySensorDeviceClass.VIBRATION.value
DEVICE_CLASS_WINDOW = BinarySensorDeviceClass.WINDOW.value
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
@ -166,14 +173,26 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
class BinarySensorEntityDescription(EntityDescription): class BinarySensorEntityDescription(EntityDescription):
"""A class that describes binary sensor entities.""" """A class that describes binary sensor entities."""
device_class: BinarySensorDeviceClass | str | None = None
class BinarySensorEntity(Entity): class BinarySensorEntity(Entity):
"""Represent a binary sensor.""" """Represent a binary sensor."""
entity_description: BinarySensorEntityDescription entity_description: BinarySensorEntityDescription
_attr_device_class: BinarySensorDeviceClass | str | None
_attr_is_on: bool | None = None _attr_is_on: bool | None = None
_attr_state: None = None _attr_state: None = None
@property
def device_class(self) -> BinarySensorDeviceClass | str | None:
"""Return the class of this entity."""
if hasattr(self, "_attr_device_class"):
return self._attr_device_class
if hasattr(self, "entity_description"):
return self.entity_description.device_class
return None
@property @property
def is_on(self) -> bool | None: def is_on(self) -> bool | None:
"""Return true if the binary sensor is on.""" """Return true if the binary sensor is on."""

View File

@ -1,7 +1,6 @@
"""Demo platform that has two fake binary sensors.""" """Demo platform that has two fake binary sensors."""
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
DEVICE_CLASS_MOISTURE, BinarySensorDeviceClass,
DEVICE_CLASS_MOTION,
BinarySensorEntity, BinarySensorEntity,
) )
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
@ -14,10 +13,13 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async_add_entities( async_add_entities(
[ [
DemoBinarySensor( DemoBinarySensor(
"binary_1", "Basement Floor Wet", False, DEVICE_CLASS_MOISTURE "binary_1",
"Basement Floor Wet",
False,
BinarySensorDeviceClass.MOISTURE,
), ),
DemoBinarySensor( DemoBinarySensor(
"binary_2", "Movement Backyard", True, DEVICE_CLASS_MOTION "binary_2", "Movement Backyard", True, BinarySensorDeviceClass.MOTION
), ),
] ]
) )
@ -31,7 +33,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class DemoBinarySensor(BinarySensorEntity): class DemoBinarySensor(BinarySensorEntity):
"""representation of a Demo binary sensor.""" """representation of a Demo binary sensor."""
def __init__(self, unique_id, name, state, device_class): def __init__(
self,
unique_id: str,
name: str,
state: bool,
device_class: BinarySensorDeviceClass,
) -> None:
"""Initialize the demo sensor.""" """Initialize the demo sensor."""
self._unique_id = unique_id self._unique_id = unique_id
self._name = name self._name = name
@ -55,7 +63,7 @@ class DemoBinarySensor(BinarySensorEntity):
return self._unique_id return self._unique_id
@property @property
def device_class(self): def device_class(self) -> BinarySensorDeviceClass:
"""Return the class of this sensor.""" """Return the class of this sensor."""
return self._sensor_type return self._sensor_type

View File

@ -8,9 +8,7 @@ from typing import Any
from pysiaalarm import SIAEvent from pysiaalarm import SIAEvent
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
DEVICE_CLASS_MOISTURE, BinarySensorDeviceClass,
DEVICE_CLASS_POWER,
DEVICE_CLASS_SMOKE,
BinarySensorEntity, BinarySensorEntity,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -81,11 +79,11 @@ class SIABinarySensorBase(SIABaseEntity, BinarySensorEntity):
entry: ConfigEntry, entry: ConfigEntry,
account_data: dict[str, Any], account_data: dict[str, Any],
zone: int, zone: int,
device_class: str, device_class: BinarySensorDeviceClass,
) -> None: ) -> None:
"""Initialize a base binary sensor.""" """Initialize a base binary sensor."""
super().__init__(entry, account_data, zone, device_class) super().__init__(entry, account_data, zone)
self._attr_device_class = device_class
self._attr_unique_id = SIA_UNIQUE_ID_FORMAT_BINARY.format( self._attr_unique_id = SIA_UNIQUE_ID_FORMAT_BINARY.format(
self._entry.entry_id, self._account, self._zone, self._attr_device_class self._entry.entry_id, self._account, self._zone, self._attr_device_class
) )
@ -111,7 +109,7 @@ class SIABinarySensorMoisture(SIABinarySensorBase):
zone: int, zone: int,
) -> None: ) -> None:
"""Initialize a Moisture binary sensor.""" """Initialize a Moisture binary sensor."""
super().__init__(entry, account_data, zone, DEVICE_CLASS_MOISTURE) super().__init__(entry, account_data, zone, BinarySensorDeviceClass.MOISTURE)
self._attr_entity_registry_enabled_default = False self._attr_entity_registry_enabled_default = False
def update_state(self, sia_event: SIAEvent) -> None: def update_state(self, sia_event: SIAEvent) -> None:
@ -132,7 +130,7 @@ class SIABinarySensorSmoke(SIABinarySensorBase):
zone: int, zone: int,
) -> None: ) -> None:
"""Initialize a Smoke binary sensor.""" """Initialize a Smoke binary sensor."""
super().__init__(entry, account_data, zone, DEVICE_CLASS_SMOKE) super().__init__(entry, account_data, zone, BinarySensorDeviceClass.SMOKE)
self._attr_entity_registry_enabled_default = False self._attr_entity_registry_enabled_default = False
def update_state(self, sia_event: SIAEvent) -> None: def update_state(self, sia_event: SIAEvent) -> None:
@ -152,7 +150,9 @@ class SIABinarySensorPower(SIABinarySensorBase):
account_data: dict[str, Any], account_data: dict[str, Any],
) -> None: ) -> None:
"""Initialize a Power binary sensor.""" """Initialize a Power binary sensor."""
super().__init__(entry, account_data, SIA_HUB_ZONE, DEVICE_CLASS_POWER) super().__init__(
entry, account_data, SIA_HUB_ZONE, BinarySensorDeviceClass.POWER
)
self._attr_entity_registry_enabled_default = True self._attr_entity_registry_enabled_default = True
def update_state(self, sia_event: SIAEvent) -> None: def update_state(self, sia_event: SIAEvent) -> None:

View File

@ -29,13 +29,13 @@ class SIABaseEntity(RestoreEntity):
entry: ConfigEntry, entry: ConfigEntry,
account_data: dict[str, Any], account_data: dict[str, Any],
zone: int, zone: int,
device_class: str, device_class: str | None = None,
) -> None: ) -> None:
"""Create SIABaseEntity object.""" """Create SIABaseEntity object."""
self._entry: ConfigEntry = entry self._entry: ConfigEntry = entry
self._account_data: dict[str, Any] = account_data self._account_data: dict[str, Any] = account_data
self._zone: int = zone self._zone: int = zone
self._attr_device_class: str = device_class self._attr_device_class = device_class
self._port: int = self._entry.data[CONF_PORT] self._port: int = self._entry.data[CONF_PORT]
self._account: str = self._account_data[CONF_ACCOUNT] self._account: str = self._account_data[CONF_ACCOUNT]

View File

@ -2,7 +2,11 @@
import voluptuous as vol import voluptuous as vol
from homeassistant.components.binary_sensor import PLATFORM_SCHEMA, BinarySensorEntity from homeassistant.components.binary_sensor import (
PLATFORM_SCHEMA,
BinarySensorDeviceClass,
BinarySensorEntity,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_USERNAME from homeassistant.const import CONF_USERNAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
@ -29,3 +33,5 @@ async def async_setup_entry(
class UpCloudBinarySensor(UpCloudServerEntity, BinarySensorEntity): class UpCloudBinarySensor(UpCloudServerEntity, BinarySensorEntity):
"""Representation of an UpCloud server sensor.""" """Representation of an UpCloud server sensor."""
_attr_device_class = BinarySensorDeviceClass.POWER