1 """Switch for Shelly."""
3 from __future__
import annotations
5 from dataclasses
import dataclass
6 from typing
import Any, cast
8 from aioshelly.block_device
import Block
9 from aioshelly.const
import MODEL_2, MODEL_25, MODEL_WALL_DISPLAY, RPC_GENERATIONS
12 DOMAIN
as SWITCH_PLATFORM,
14 SwitchEntityDescription,
22 from .const
import CONF_SLEEP_PERIOD, MOTION_MODELS
23 from .coordinator
import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator
25 BlockEntityDescription,
28 ShellyRpcAttributeEntity,
30 ShellySleepingBlockAttributeEntity,
31 async_setup_entry_attribute_entities,
32 async_setup_rpc_attribute_entities,
35 async_remove_orphaned_entities,
36 async_remove_shelly_entity,
39 get_virtual_component_ids,
40 is_block_channel_type_light,
41 is_rpc_channel_type_light,
42 is_rpc_thermostat_internal_actuator,
43 is_rpc_thermostat_mode,
47 @dataclass(frozen=True, kw_only=True)
49 """Class to describe a BLOCK switch."""
52 MOTION_SWITCH = BlockSwitchDescription(
53 key=
"sensor|motionActive",
54 name=
"Motion detection",
55 entity_category=EntityCategory.CONFIG,
59 @dataclass(frozen=True, kw_only=True)
61 """Class to describe a RPC virtual switch."""
64 RPC_VIRTUAL_SWITCH = RpcSwitchDescription(
72 entity_registry_enabled_default=
False,
73 entity_category=EntityCategory.CONFIG,
79 config_entry: ShellyConfigEntry,
80 async_add_entities: AddEntitiesCallback,
82 """Set up switches for device."""
92 config_entry: ShellyConfigEntry,
93 async_add_entities: AddEntitiesCallback,
95 """Set up entities for block device."""
96 coordinator = config_entry.runtime_data.block
100 if coordinator.model
in MOTION_MODELS:
105 {(
"sensor",
"motionActive"): MOTION_SWITCH},
106 BlockSleepingMotionSwitch,
110 if config_entry.data[CONF_SLEEP_PERIOD]:
115 coordinator.model
in [MODEL_2, MODEL_25]
116 and coordinator.device.settings[
"mode"] !=
"relay"
121 assert coordinator.device.blocks
122 for block
in coordinator.device.blocks:
124 block.type !=
"relay"
125 or block.channel
is not None
127 coordinator.device.settings,
int(block.channel)
132 relay_blocks.append(block)
133 unique_id = f
"{coordinator.mac}-{block.type}_{block.channel}"
145 config_entry: ShellyConfigEntry,
146 async_add_entities: AddEntitiesCallback,
148 """Set up entities for RPC device."""
149 coordinator = config_entry.runtime_data.rpc
154 for id_
in switch_key_ids:
158 if coordinator.model == MODEL_WALL_DISPLAY:
167 unique_id = f
"{coordinator.mac}-thermostat:{id_}"
174 switch_ids.append(id_)
175 unique_id = f
"{coordinator.mac}-switch:{id_}"
182 {
"boolean": RPC_VIRTUAL_SWITCH},
190 {
"script": RPC_SCRIPT_SWITCH},
197 coordinator.device.config, SWITCH_PLATFORM
201 config_entry.entry_id,
212 config_entry.entry_id,
215 coordinator.device.status,
226 ShellySleepingBlockAttributeEntity, RestoreEntity, SwitchEntity
228 """Entity that controls Motion Sensor on Block based Shelly devices."""
230 entity_description: BlockSwitchDescription
231 _attr_translation_key =
"motion_switch"
235 coordinator: ShellyBlockCoordinator,
238 description: BlockSwitchDescription,
239 entry: RegistryEntry |
None =
None,
241 """Initialize the sleeping sensor."""
242 super().
__init__(coordinator, block, attribute, description, entry)
243 self.
last_statelast_state: State |
None =
None
247 """If motion is active."""
254 return self.
last_statelast_state.state == STATE_ON
257 """Activate switch."""
258 await self.
coordinatorcoordinator.device.set_shelly_motion_detection(
True)
262 """Deactivate switch."""
263 await self.
coordinatorcoordinator.device.set_shelly_motion_detection(
False)
267 """Handle entity which will be added."""
274 """Entity that controls a relay on Block based Shelly devices."""
276 def __init__(self, coordinator: ShellyBlockCoordinator, block: Block) ->
None:
277 """Initialize relay switch."""
278 super().
__init__(coordinator, block)
283 """If switch is on."""
295 """Turn off relay."""
301 """When device updates, clear control result that overrides state."""
307 """Entity that controls a relay on RPC based Shelly devices."""
309 def __init__(self, coordinator: ShellyRpcCoordinator, id_: int) ->
None:
310 """Initialize relay switch."""
311 super().
__init__(coordinator, f
"switch:{id_}")
316 """If switch is on."""
321 await self.
call_rpccall_rpc(
"Switch.Set", {
"id": self.
_id_id,
"on":
True})
324 """Turn off relay."""
325 await self.
call_rpccall_rpc(
"Switch.Set", {
"id": self.
_id_id,
"on":
False})
329 """Entity that controls a virtual boolean component on RPC based Shelly devices."""
331 entity_description: RpcSwitchDescription
332 _attr_has_entity_name =
True
336 """If switch is on."""
341 await self.
call_rpccall_rpc(
"Boolean.Set", {
"id": self.
_id_id,
"value":
True})
344 """Turn off relay."""
345 await self.
call_rpccall_rpc(
"Boolean.Set", {
"id": self.
_id_id,
"value":
False})
349 """Entity that controls a script component on RPC based Shelly devices."""
351 entity_description: RpcSwitchDescription
352 _attr_has_entity_name =
True
356 """If switch is on."""
361 await self.
call_rpccall_rpc(
"Script.Start", {
"id": self.
_id_id})
364 """Turn off relay."""
365 await self.
call_rpccall_rpc(
"Script.Stop", {
"id": self.
_id_id})
Any set_state(self, **Any kwargs)
StateType attribute_value(self)
Any call_rpc(self, str method, Any params)
None __init__(self, ShellyBlockCoordinator coordinator, Block block)
None async_turn_on(self, **Any kwargs)
None async_turn_off(self, **Any kwargs)
None _update_callback(self)
None async_turn_on(self, **Any kwargs)
None __init__(self, ShellyBlockCoordinator coordinator, Block|None block, str attribute, BlockSwitchDescription description, RegistryEntry|None entry=None)
None async_turn_off(self, **Any kwargs)
None async_added_to_hass(self)
None __init__(self, ShellyRpcCoordinator coordinator, int id_)
None async_turn_off(self, **Any kwargs)
None async_turn_on(self, **Any kwargs)
None async_turn_off(self, **Any kwargs)
None async_turn_on(self, **Any kwargs)
None async_turn_on(self, **Any kwargs)
None async_turn_off(self, **Any kwargs)
None async_write_ha_state(self)
State|None async_get_last_state(self)
None async_setup_rpc_attribute_entities(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities, Mapping[str, RpcEntityDescription] 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)
None async_setup_rpc_entry(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities)
None async_setup_entry(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities)
None async_setup_block_entry(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities)
bool is_rpc_channel_type_light(dict[str, Any] config, int channel)
bool is_rpc_thermostat_internal_actuator(dict[str, Any] status)
list[str] get_virtual_component_ids(dict[str, Any] config, str platform)
bool is_rpc_thermostat_mode(int ident, dict[str, Any] status)
None async_remove_orphaned_entities(HomeAssistant hass, str config_entry_id, str mac, str platform, Iterable[str] keys, str|None key_suffix=None)
list[int] get_rpc_key_ids(dict[str, Any] keys_dict, str key)
int get_device_entry_gen(ConfigEntry entry)
bool is_block_channel_type_light(dict[str, Any] settings, int channel)
None async_remove_shelly_entity(HomeAssistant hass, str domain, str unique_id)