Add support for battery to Yale Access Bluetooth (#83691)

* Add support for battery level to Yale Access Bluetooth

* fix

* bump

* bump

* bump

* bump

* fix

* bump

* battery level is always an estimate from voltage, but than again it always is for every device

* bump

* review

* bump again to fix slow start

* other one
This commit is contained in:
J. Nick Koston 2022-12-10 08:55:22 -10:00 committed by GitHub
parent 119f2a90b7
commit 5c79dae4c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 18 deletions

View file

@ -1,11 +1,23 @@
"""Support for yalexs ble sensors."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from yalexs_ble import ConnectionInfo, LockInfo, LockState
from homeassistant import config_entries
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
from homeassistant.const import SIGNAL_STRENGTH_DECIBELS_MILLIWATT
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
ELECTRIC_POTENTIAL_VOLT,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -15,6 +27,60 @@ from .entity import YALEXSBLEEntity
from .models import YaleXSBLEData
@dataclass
class YaleXSBLERequiredKeysMixin:
"""Mixin for required keys."""
value_fn: Callable[[LockState, LockInfo, ConnectionInfo], int | float | None]
@dataclass
class YaleXSBLESensorEntityDescription(
SensorEntityDescription, YaleXSBLERequiredKeysMixin
):
"""Describes Yale Access Bluetooth sensor entity."""
SENSORS: tuple[YaleXSBLESensorEntityDescription, ...] = (
YaleXSBLESensorEntityDescription(
key="", # No key for the original RSSI sensor unique id
name="Signal strength",
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
has_entity_name=True,
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
entity_registry_enabled_default=False,
value_fn=lambda state, info, connection: connection.rssi,
),
YaleXSBLESensorEntityDescription(
key="battery_level",
name="Battery level",
device_class=SensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
has_entity_name=True,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda state, info, connection: state.battery.percentage
if state.battery
else None,
),
YaleXSBLESensorEntityDescription(
key="battery_voltage",
name="Battery Voltage",
device_class=SensorDeviceClass.VOLTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
has_entity_name=True,
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
entity_registry_enabled_default=False,
value_fn=lambda state, info, connection: state.battery.voltage
if state.battery
else None,
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: config_entries.ConfigEntry,
@ -22,23 +88,30 @@ async def async_setup_entry(
) -> None:
"""Set up YALE XS Bluetooth sensors."""
data: YaleXSBLEData = hass.data[DOMAIN][entry.entry_id]
async_add_entities([YaleXSBLERSSISensor(data)])
async_add_entities(YaleXSBLESensor(description, data) for description in SENSORS)
class YaleXSBLERSSISensor(YALEXSBLEEntity, SensorEntity):
"""Yale XS Bluetooth RSSI sensor."""
class YaleXSBLESensor(YALEXSBLEEntity, SensorEntity):
"""Yale XS Bluetooth sensor."""
_attr_device_class = SensorDeviceClass.SIGNAL_STRENGTH
_attr_entity_category = EntityCategory.DIAGNOSTIC
_attr_entity_registry_enabled_default = False
_attr_has_entity_name = True
_attr_name = "Signal strength"
_attr_native_unit_of_measurement = SIGNAL_STRENGTH_DECIBELS_MILLIWATT
entity_description: YaleXSBLESensorEntityDescription
def __init__(
self,
description: YaleXSBLESensorEntityDescription,
data: YaleXSBLEData,
) -> None:
"""Initialize the sensor."""
self.entity_description = description
super().__init__(data)
self._attr_unique_id = f"{data.lock.address}{description.key}"
@callback
def _async_update_state(
self, new_state: LockState, lock_info: LockInfo, connection_info: ConnectionInfo
) -> None:
"""Update the state."""
self._attr_native_value = connection_info.rssi
self._attr_native_value = self.entity_description.value_fn(
new_state, lock_info, connection_info
)
super()._async_update_state(new_state, lock_info, connection_info)