mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 01:38:02 +00:00
Convert Shelly block switches to EntityDescription (#106985)
This commit is contained in:
parent
c0e5a549b6
commit
61e0b938ae
@ -7,7 +7,7 @@ from dataclasses import dataclass
|
|||||||
from typing import Any, cast
|
from typing import Any, cast
|
||||||
|
|
||||||
from aioshelly.block_device import Block
|
from aioshelly.block_device import Block
|
||||||
from aioshelly.const import MODEL_2, MODEL_25, RPC_GENERATIONS
|
from aioshelly.const import RPC_GENERATIONS
|
||||||
|
|
||||||
from homeassistant.components.climate import DOMAIN as CLIMATE_PLATFORM
|
from homeassistant.components.climate import DOMAIN as CLIMATE_PLATFORM
|
||||||
from homeassistant.components.switch import (
|
from homeassistant.components.switch import (
|
||||||
@ -21,12 +21,11 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
|||||||
from homeassistant.helpers.entity_registry import RegistryEntry
|
from homeassistant.helpers.entity_registry import RegistryEntry
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
from .const import CONF_SLEEP_PERIOD, MOTION_MODELS
|
|
||||||
from .coordinator import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator
|
from .coordinator import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator
|
||||||
from .entity import (
|
from .entity import (
|
||||||
BlockEntityDescription,
|
BlockEntityDescription,
|
||||||
RpcEntityDescription,
|
RpcEntityDescription,
|
||||||
ShellyBlockEntity,
|
ShellyBlockAttributeEntity,
|
||||||
ShellyRpcAttributeEntity,
|
ShellyRpcAttributeEntity,
|
||||||
ShellySleepingBlockAttributeEntity,
|
ShellySleepingBlockAttributeEntity,
|
||||||
async_setup_entry_attribute_entities,
|
async_setup_entry_attribute_entities,
|
||||||
@ -34,10 +33,9 @@ from .entity import (
|
|||||||
)
|
)
|
||||||
from .utils import (
|
from .utils import (
|
||||||
async_remove_orphaned_entities,
|
async_remove_orphaned_entities,
|
||||||
async_remove_shelly_entity,
|
|
||||||
get_device_entry_gen,
|
get_device_entry_gen,
|
||||||
get_virtual_component_ids,
|
get_virtual_component_ids,
|
||||||
is_block_channel_type_light,
|
is_block_exclude_from_relay,
|
||||||
is_rpc_exclude_from_relay,
|
is_rpc_exclude_from_relay,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,11 +45,20 @@ class BlockSwitchDescription(BlockEntityDescription, SwitchEntityDescription):
|
|||||||
"""Class to describe a BLOCK switch."""
|
"""Class to describe a BLOCK switch."""
|
||||||
|
|
||||||
|
|
||||||
MOTION_SWITCH = BlockSwitchDescription(
|
BLOCK_RELAY_SWITCHES = {
|
||||||
key="sensor|motionActive",
|
("relay", "output"): BlockSwitchDescription(
|
||||||
name="Motion detection",
|
key="relay|output",
|
||||||
entity_category=EntityCategory.CONFIG,
|
removal_condition=is_block_exclude_from_relay,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
BLOCK_SLEEPING_MOTION_SWITCH = {
|
||||||
|
("sensor", "motionActive"): BlockSwitchDescription(
|
||||||
|
key="sensor|motionActive",
|
||||||
|
name="Motion detection",
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, kw_only=True)
|
@dataclass(frozen=True, kw_only=True)
|
||||||
@ -120,46 +127,17 @@ def async_setup_block_entry(
|
|||||||
coordinator = config_entry.runtime_data.block
|
coordinator = config_entry.runtime_data.block
|
||||||
assert coordinator
|
assert coordinator
|
||||||
|
|
||||||
# Add Shelly Motion as a switch
|
async_setup_entry_attribute_entities(
|
||||||
if coordinator.model in MOTION_MODELS:
|
hass, config_entry, async_add_entities, BLOCK_RELAY_SWITCHES, BlockRelaySwitch
|
||||||
async_setup_entry_attribute_entities(
|
)
|
||||||
hass,
|
|
||||||
config_entry,
|
|
||||||
async_add_entities,
|
|
||||||
{("sensor", "motionActive"): MOTION_SWITCH},
|
|
||||||
BlockSleepingMotionSwitch,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
if config_entry.data[CONF_SLEEP_PERIOD]:
|
async_setup_entry_attribute_entities(
|
||||||
return
|
hass,
|
||||||
|
config_entry,
|
||||||
# In roller mode the relay blocks exist but do not contain required info
|
async_add_entities,
|
||||||
if (
|
BLOCK_SLEEPING_MOTION_SWITCH,
|
||||||
coordinator.model in [MODEL_2, MODEL_25]
|
BlockSleepingMotionSwitch,
|
||||||
and coordinator.device.settings["mode"] != "relay"
|
)
|
||||||
):
|
|
||||||
return
|
|
||||||
|
|
||||||
relay_blocks = []
|
|
||||||
assert coordinator.device.blocks
|
|
||||||
for block in coordinator.device.blocks:
|
|
||||||
if block.type != "relay" or (
|
|
||||||
block.channel is not None
|
|
||||||
and is_block_channel_type_light(
|
|
||||||
coordinator.device.settings, int(block.channel)
|
|
||||||
)
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
|
|
||||||
relay_blocks.append(block)
|
|
||||||
unique_id = f"{coordinator.mac}-{block.type}_{block.channel}"
|
|
||||||
async_remove_shelly_entity(hass, "light", unique_id)
|
|
||||||
|
|
||||||
if not relay_blocks:
|
|
||||||
return
|
|
||||||
|
|
||||||
async_add_entities(BlockRelaySwitch(coordinator, block) for block in relay_blocks)
|
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -265,13 +243,22 @@ class BlockSleepingMotionSwitch(
|
|||||||
self.last_state = last_state
|
self.last_state = last_state
|
||||||
|
|
||||||
|
|
||||||
class BlockRelaySwitch(ShellyBlockEntity, SwitchEntity):
|
class BlockRelaySwitch(ShellyBlockAttributeEntity, SwitchEntity):
|
||||||
"""Entity that controls a relay on Block based Shelly devices."""
|
"""Entity that controls a relay on Block based Shelly devices."""
|
||||||
|
|
||||||
def __init__(self, coordinator: ShellyBlockCoordinator, block: Block) -> None:
|
entity_description: BlockSwitchDescription
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
coordinator: ShellyBlockCoordinator,
|
||||||
|
block: Block,
|
||||||
|
attribute: str,
|
||||||
|
description: BlockSwitchDescription,
|
||||||
|
) -> None:
|
||||||
"""Initialize relay switch."""
|
"""Initialize relay switch."""
|
||||||
super().__init__(coordinator, block)
|
super().__init__(coordinator, block, attribute, description)
|
||||||
self.control_result: dict[str, Any] | None = None
|
self.control_result: dict[str, Any] | None = None
|
||||||
|
self._attr_unique_id: str = f"{coordinator.mac}-{block.description}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
|
@ -6,7 +6,7 @@ from collections.abc import Iterable
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from ipaddress import IPv4Address, IPv6Address, ip_address
|
from ipaddress import IPv4Address, IPv6Address, ip_address
|
||||||
from types import MappingProxyType
|
from types import MappingProxyType
|
||||||
from typing import Any, cast
|
from typing import TYPE_CHECKING, Any, cast
|
||||||
|
|
||||||
from aiohttp.web import Request, WebSocketResponse
|
from aiohttp.web import Request, WebSocketResponse
|
||||||
from aioshelly.block_device import COAP, Block, BlockDevice
|
from aioshelly.block_device import COAP, Block, BlockDevice
|
||||||
@ -175,6 +175,18 @@ def is_block_momentary_input(
|
|||||||
return button_type in momentary_types
|
return button_type in momentary_types
|
||||||
|
|
||||||
|
|
||||||
|
def is_block_exclude_from_relay(settings: dict[str, Any], block: Block) -> bool:
|
||||||
|
"""Return true if block should be excluded from switch platform."""
|
||||||
|
|
||||||
|
if settings.get("mode") == "roller":
|
||||||
|
return True
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
assert block.channel is not None
|
||||||
|
|
||||||
|
return is_block_channel_type_light(settings, int(block.channel))
|
||||||
|
|
||||||
|
|
||||||
def get_device_uptime(uptime: float, last_uptime: datetime | None) -> datetime:
|
def get_device_uptime(uptime: float, last_uptime: datetime | None) -> datetime:
|
||||||
"""Return device uptime string, tolerate up to 5 seconds deviation."""
|
"""Return device uptime string, tolerate up to 5 seconds deviation."""
|
||||||
delta_uptime = utcnow() - timedelta(seconds=uptime)
|
delta_uptime = utcnow() - timedelta(seconds=uptime)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user