1 """Sensor entities for the Motionblinds BLE integration."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
9 from typing
import Generic, TypeVar
11 from motionblindsble.const
import (
13 MotionCalibrationType,
16 from motionblindsble.device
import MotionDevice
21 SensorEntityDescription,
27 SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
42 from .entity
import MotionblindsBLEEntity
44 _LOGGER = logging.getLogger(__name__)
51 @dataclass(frozen=True, kw_only=True)
53 """Entity description of a sensor entity with initial_value attribute."""
55 initial_value: str |
None =
None
56 register_callback_func: Callable[
57 [MotionDevice], Callable[[Callable[[_T |
None],
None]],
None]
59 value_func: Callable[[_T |
None], StateType]
60 is_supported: Callable[[MotionDevice], bool] =
lambda device:
True
63 SENSORS: tuple[MotionblindsBLESensorEntityDescription, ...] = (
64 MotionblindsBLESensorEntityDescription[MotionConnectionType](
66 translation_key=ATTR_CONNECTION,
67 device_class=SensorDeviceClass.ENUM,
68 entity_category=EntityCategory.DIAGNOSTIC,
69 options=[
"connected",
"connecting",
"disconnected",
"disconnecting"],
70 initial_value=MotionConnectionType.DISCONNECTED.value,
71 register_callback_func=
lambda device: device.register_connection_callback,
72 value_func=
lambda value: value.value
if value
else None,
74 MotionblindsBLESensorEntityDescription[MotionCalibrationType](
76 translation_key=ATTR_CALIBRATION,
77 device_class=SensorDeviceClass.ENUM,
78 entity_category=EntityCategory.DIAGNOSTIC,
79 options=[
"calibrated",
"uncalibrated",
"calibrating"],
80 register_callback_func=
lambda device: device.register_calibration_callback,
81 value_func=
lambda value: value.value
if value
else None,
82 is_supported=
lambda device: device.blind_type
83 in {MotionBlindType.CURTAIN, MotionBlindType.VERTICAL},
85 MotionblindsBLESensorEntityDescription[int](
86 key=ATTR_SIGNAL_STRENGTH,
87 device_class=SensorDeviceClass.SIGNAL_STRENGTH,
88 entity_category=EntityCategory.DIAGNOSTIC,
89 native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
90 register_callback_func=
lambda device: device.register_signal_strength_callback,
91 value_func=
lambda value: value,
92 entity_registry_enabled_default=
False,
98 hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
100 """Set up sensor entities based on a config entry."""
102 device: MotionDevice = hass.data[DOMAIN][entry.entry_id]
104 entities: list[SensorEntity] = [
106 for description
in SENSORS
107 if description.is_supported(device)
114 """Representation of a sensor entity."""
116 entity_description: MotionblindsBLESensorEntityDescription[_T]
120 device: MotionDevice,
122 entity_description: MotionblindsBLESensorEntityDescription[_T],
124 """Initialize the sensor entity."""
126 device, entry, entity_description, unique_id_suffix=entity_description.key
131 """Log sensor entity information."""
133 "(%s) Setting up %s sensor entity",
134 self.
entryentry.data[CONF_MAC_CODE],
138 def async_callback(value: _T |
None) ->
None:
139 """Update the sensor value."""
147 """Representation of a battery sensor entity."""
151 device: MotionDevice,
154 """Initialize the sensor entity."""
157 native_unit_of_measurement=PERCENTAGE,
158 device_class=SensorDeviceClass.BATTERY,
159 state_class=SensorStateClass.MEASUREMENT,
160 entity_category=EntityCategory.DIAGNOSTIC,
162 super().
__init__(device, entry, entity_description)
165 """Register device callbacks."""
172 battery_percentage: int |
None,
173 is_charging: bool |
None,
174 is_wired: bool |
None,
176 """Update the battery sensor value and icon."""
178 if battery_percentage
is None:
183 self.
_attr_icon_attr_icon =
"mdi:power-plug-outline"
184 elif battery_percentage > 90
and not is_charging:
187 elif battery_percentage <= 5
and not is_charging:
189 self.
_attr_icon_attr_icon =
"mdi:battery-alert-variant-outline"
191 battery_icon_prefix = (
192 "mdi:battery-charging" if is_charging
else "mdi:battery"
194 battery_percentage_multiple_ten = ceil(battery_percentage / 10) * 10
195 self.
_attr_icon_attr_icon = f
"{battery_icon_prefix}-{battery_percentage_multiple_ten}"
None async_added_to_hass(self)
None async_update_battery(self, int|None battery_percentage, bool|None is_charging, bool|None is_wired)
None __init__(self, MotionDevice device, ConfigEntry entry)
None async_added_to_hass(self)
None __init__(self, MotionDevice device, ConfigEntry entry, MotionblindsBLESensorEntityDescription[_T] entity_description)
None async_write_ha_state(self)
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)