1 """Binary sensor for Shelly."""
3 from __future__
import annotations
5 from dataclasses
import dataclass
6 from typing
import Final, cast
8 from aioshelly.const
import RPC_GENERATIONS
11 DOMAIN
as BINARY_SENSOR_PLATFORM,
12 BinarySensorDeviceClass,
14 BinarySensorEntityDescription,
21 from .const
import CONF_SLEEP_PERIOD
22 from .coordinator
import ShellyConfigEntry
24 BlockEntityDescription,
25 RestEntityDescription,
27 ShellyBlockAttributeEntity,
28 ShellyRestAttributeEntity,
29 ShellyRpcAttributeEntity,
30 ShellySleepingBlockAttributeEntity,
31 ShellySleepingRpcAttributeEntity,
32 async_setup_entry_attribute_entities,
33 async_setup_entry_rest,
34 async_setup_entry_rpc,
37 async_remove_orphaned_entities,
39 get_virtual_component_ids,
40 is_block_momentary_input,
41 is_rpc_momentary_input,
45 @dataclass(frozen=True, kw_only=True)
47 BlockEntityDescription, BinarySensorEntityDescription
49 """Class to describe a BLOCK binary sensor."""
52 @dataclass(frozen=True, kw_only=True)
54 """Class to describe a RPC binary sensor."""
57 @dataclass(frozen=
True, kw_only=
True)
59 """Class to describe a REST binary sensor."""
62 SENSORS: dict[tuple[str, str], BlockBinarySensorDescription] = {
63 (
"device",
"overtemp"): BlockBinarySensorDescription(
64 key=
"device|overtemp",
66 device_class=BinarySensorDeviceClass.PROBLEM,
67 entity_category=EntityCategory.DIAGNOSTIC,
70 key=
"device|overpower",
72 device_class=BinarySensorDeviceClass.PROBLEM,
73 entity_category=EntityCategory.DIAGNOSTIC,
76 key=
"light|overpower",
78 device_class=BinarySensorDeviceClass.PROBLEM,
79 entity_category=EntityCategory.DIAGNOSTIC,
82 key=
"relay|overpower",
84 device_class=BinarySensorDeviceClass.PROBLEM,
85 entity_category=EntityCategory.DIAGNOSTIC,
88 key=
"sensor|dwIsOpened",
90 device_class=BinarySensorDeviceClass.OPENING,
91 available=
lambda block: cast(int, block.dwIsOpened) != -1,
94 key=
"sensor|flood", name=
"Flood", device_class=BinarySensorDeviceClass.MOISTURE
99 device_class=BinarySensorDeviceClass.GAS,
100 translation_key=
"gas",
101 value=
lambda value: value
in [
"mild",
"heavy"],
102 extra_state_attributes=
lambda block: {
"detected": block.gas},
105 key=
"sensor|smoke", name=
"Smoke", device_class=BinarySensorDeviceClass.SMOKE
108 key=
"sensor|vibration",
110 device_class=BinarySensorDeviceClass.VIBRATION,
115 device_class=BinarySensorDeviceClass.POWER,
116 entity_registry_enabled_default=
False,
117 removal_condition=is_block_momentary_input,
122 device_class=BinarySensorDeviceClass.POWER,
123 entity_registry_enabled_default=
False,
124 removal_condition=is_block_momentary_input,
129 device_class=BinarySensorDeviceClass.POWER,
130 entity_registry_enabled_default=
False,
131 removal_condition=is_block_momentary_input,
134 key=
"sensor|extInput",
135 name=
"External input",
136 device_class=BinarySensorDeviceClass.POWER,
137 entity_registry_enabled_default=
False,
140 key=
"sensor|motion", name=
"Motion", device_class=BinarySensorDeviceClass.MOTION
144 REST_SENSORS: Final = {
148 value=
lambda status, _: status[
"cloud"][
"connected"],
149 device_class=BinarySensorDeviceClass.CONNECTIVITY,
150 entity_registry_enabled_default=
False,
151 entity_category=EntityCategory.DIAGNOSTIC,
155 RPC_SENSORS: Final = {
160 device_class=BinarySensorDeviceClass.POWER,
161 entity_registry_enabled_default=
False,
162 removal_condition=is_rpc_momentary_input,
168 device_class=BinarySensorDeviceClass.CONNECTIVITY,
169 entity_registry_enabled_default=
False,
170 entity_category=EntityCategory.DIAGNOSTIC,
175 name=
"External power",
176 value=
lambda status, _: status[
"present"],
177 device_class=BinarySensorDeviceClass.POWER,
178 entity_category=EntityCategory.DIAGNOSTIC,
184 device_class=BinarySensorDeviceClass.PROBLEM,
185 value=
lambda status, _:
False if status
is None else "overtemp" in status,
186 entity_category=EntityCategory.DIAGNOSTIC,
187 supported=
lambda status: status.get(
"apower")
is not None,
193 device_class=BinarySensorDeviceClass.PROBLEM,
194 value=
lambda status, _:
False if status
is None else "overpower" in status,
195 entity_category=EntityCategory.DIAGNOSTIC,
196 supported=
lambda status: status.get(
"apower")
is not None,
202 device_class=BinarySensorDeviceClass.PROBLEM,
203 value=
lambda status, _:
False if status
is None else "overvoltage" in status,
204 entity_category=EntityCategory.DIAGNOSTIC,
205 supported=
lambda status: status.get(
"apower")
is not None,
211 device_class=BinarySensorDeviceClass.PROBLEM,
212 value=
lambda status, _:
False if status
is None else "overcurrent" in status,
213 entity_category=EntityCategory.DIAGNOSTIC,
214 supported=
lambda status: status.get(
"apower")
is not None,
220 device_class=BinarySensorDeviceClass.SMOKE,
224 sub_key=
"restart_required",
225 name=
"Restart required",
226 device_class=BinarySensorDeviceClass.PROBLEM,
227 entity_registry_enabled_default=
False,
228 entity_category=EntityCategory.DIAGNOSTIC,
233 has_entity_name=
True,
240 config_entry: ShellyConfigEntry,
241 async_add_entities: AddEntitiesCallback,
243 """Set up sensors for device."""
245 if config_entry.data[CONF_SLEEP_PERIOD]:
251 RpcSleepingBinarySensor,
254 coordinator = config_entry.runtime_data.rpc
258 hass, config_entry, async_add_entities, RPC_SENSORS, RpcBinarySensor
264 coordinator.device.config, BINARY_SENSOR_PLATFORM
268 config_entry.entry_id,
270 BINARY_SENSOR_PLATFORM,
271 virtual_binary_sensor_ids,
276 if config_entry.data[CONF_SLEEP_PERIOD]:
282 BlockSleepingBinarySensor,
302 """Represent a block binary sensor entity."""
304 entity_description: BlockBinarySensorDescription
308 """Return true if sensor state is on."""
313 """Represent a REST binary sensor entity."""
315 entity_description: RestBinarySensorDescription
319 """Return true if REST sensor state is on."""
324 """Represent a RPC binary sensor entity."""
326 entity_description: RpcBinarySensorDescription
330 """Return true if RPC sensor state is on."""
335 ShellySleepingBlockAttributeEntity, BinarySensorEntity, RestoreEntity
337 """Represent a block sleeping binary sensor."""
339 entity_description: BlockBinarySensorDescription
342 """Handle entity which will be added."""
348 """Return true if sensor state is on."""
355 return self.
last_statelast_state.state == STATE_ON
359 ShellySleepingRpcAttributeEntity, BinarySensorEntity, RestoreEntity
361 """Represent a RPC sleeping binary sensor entity."""
363 entity_description: RpcBinarySensorDescription
366 """Handle entity which will be added."""
372 """Return true if RPC sensor state is on."""
379 return self.
last_statelast_state.state == STATE_ON
None async_added_to_hass(self)
None async_added_to_hass(self)
StateType attribute_value(self)
StateType attribute_value(self)
StateType attribute_value(self)
State|None async_get_last_state(self)
None async_setup_entry(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities)
None async_setup_entry_rpc(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities, Mapping[str, RpcEntityDescription] sensors, Callable sensor_class)
None async_setup_entry_rest(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities, Mapping[str, RestEntityDescription] sensors, Callable sensor_class)
None async_setup_entry_attribute_entities(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities, Mapping[tuple[str, str], BlockEntityDescription] sensors, Callable sensor_class)
list[str] get_virtual_component_ids(dict[str, Any] config, str platform)
None async_remove_orphaned_entities(HomeAssistant hass, str config_entry_id, str mac, str platform, Iterable[str] keys, str|None key_suffix=None)
int get_device_entry_gen(ConfigEntry entry)