mirror of
https://github.com/home-assistant/core.git
synced 2025-12-24 21:06:19 +00:00
Align Shelly event naming paradigm (#156774)
Signed-off-by: David Rapan <david@rapan.cz>
This commit is contained in:
@@ -32,11 +32,16 @@ from .utils import (
|
||||
async_remove_shelly_entity,
|
||||
get_block_channel,
|
||||
get_block_custom_name,
|
||||
get_block_number_of_channels,
|
||||
get_device_entry_gen,
|
||||
get_rpc_component_name,
|
||||
get_rpc_custom_name,
|
||||
get_rpc_entity_name,
|
||||
get_rpc_key,
|
||||
get_rpc_key_id,
|
||||
get_rpc_key_instances,
|
||||
get_rpc_number_of_channels,
|
||||
is_block_momentary_input,
|
||||
is_block_single_device,
|
||||
is_rpc_momentary_input,
|
||||
)
|
||||
|
||||
@@ -158,8 +163,7 @@ def _async_setup_rpc_entry(
|
||||
if script_name == BLE_SCRIPT_NAME:
|
||||
continue
|
||||
|
||||
script_id = int(script.split(":")[-1])
|
||||
if script_events and (event_types := script_events[script_id]):
|
||||
if script_events and (event_types := script_events[get_rpc_key_id(script)]):
|
||||
entities.append(ShellyRpcScriptEvent(coordinator, script, event_types))
|
||||
|
||||
# If a script is removed, from the device configuration, we need to remove orphaned entities
|
||||
@@ -197,13 +201,15 @@ class ShellyBlockEvent(ShellyBlockEntity, EventEntity):
|
||||
self._attr_event_types = list(BASIC_INPUTS_EVENTS_TYPES)
|
||||
self.entity_description = description
|
||||
|
||||
if (
|
||||
hasattr(self, "_attr_name")
|
||||
and self._attr_name
|
||||
and not get_block_custom_name(coordinator.device, block)
|
||||
if hasattr(self, "_attr_name") and not (
|
||||
(single := is_block_single_device(coordinator.device, block))
|
||||
and get_block_custom_name(coordinator.device, block)
|
||||
):
|
||||
self._attr_translation_placeholders = {
|
||||
"input_number": get_block_channel(block)
|
||||
if single
|
||||
and get_block_number_of_channels(coordinator.device, block) > 1
|
||||
else ""
|
||||
}
|
||||
|
||||
delattr(self, "_attr_name")
|
||||
@@ -237,22 +243,24 @@ class ShellyRpcEvent(CoordinatorEntity[ShellyRpcCoordinator], EventEntity):
|
||||
) -> None:
|
||||
"""Initialize Shelly entity."""
|
||||
super().__init__(coordinator)
|
||||
self.event_id = int(key.split(":")[-1])
|
||||
self._attr_device_info = get_entity_rpc_device_info(coordinator, key)
|
||||
self._attr_unique_id = f"{coordinator.mac}-{key}"
|
||||
self.entity_description = description
|
||||
|
||||
if description.key == "input":
|
||||
component = key.split(":")[0]
|
||||
component_id = key.split(":")[-1]
|
||||
if not get_rpc_component_name(coordinator.device, key) and (
|
||||
component.lower() == "input" and component_id.isnumeric()
|
||||
):
|
||||
self._attr_translation_placeholders = {"input_number": component_id}
|
||||
_, component, component_id = get_rpc_key(key)
|
||||
if not get_rpc_custom_name(coordinator.device, key):
|
||||
self._attr_translation_placeholders = {
|
||||
"input_number": component_id
|
||||
if get_rpc_number_of_channels(coordinator.device, component) > 1
|
||||
else ""
|
||||
}
|
||||
else:
|
||||
self._attr_name = get_rpc_entity_name(coordinator.device, key)
|
||||
self.event_id = int(component_id)
|
||||
elif description.key == "script":
|
||||
self._attr_name = get_rpc_entity_name(coordinator.device, key)
|
||||
self.event_id = get_rpc_key_id(key)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""When entity is added to hass."""
|
||||
|
||||
@@ -93,8 +93,8 @@ def async_remove_shelly_entity(
|
||||
entity_reg.async_remove(entity_id)
|
||||
|
||||
|
||||
def get_number_of_channels(device: BlockDevice, block: Block) -> int:
|
||||
"""Get number of channels for block type."""
|
||||
def get_block_number_of_channels(device: BlockDevice, block: Block) -> int:
|
||||
"""Get number of channels."""
|
||||
channels = None
|
||||
|
||||
if block.type == "input":
|
||||
@@ -154,7 +154,7 @@ def get_block_channel_name(device: BlockDevice, block: Block | None) -> str | No
|
||||
if (
|
||||
not block
|
||||
or block.type in ("device", "light", "relay", "emeter")
|
||||
or get_number_of_channels(device, block) == 1
|
||||
or get_block_number_of_channels(device, block) == 1
|
||||
):
|
||||
return None
|
||||
|
||||
@@ -253,7 +253,7 @@ def get_block_input_triggers(
|
||||
if not is_block_momentary_input(device.settings, block, True):
|
||||
return []
|
||||
|
||||
if block.type == "device" or get_number_of_channels(device, block) == 1:
|
||||
if block.type == "device" or get_block_number_of_channels(device, block) == 1:
|
||||
subtype = "button"
|
||||
else:
|
||||
assert block.channel
|
||||
@@ -397,8 +397,13 @@ def get_rpc_key(value: str) -> tuple[bool, str, str]:
|
||||
return len(parts) > 1, parts[0], parts[-1]
|
||||
|
||||
|
||||
def get_rpc_key_id(value: str) -> int:
|
||||
"""Get id from device key."""
|
||||
return int(get_rpc_key(value)[-1])
|
||||
|
||||
|
||||
def get_rpc_custom_name(device: RpcDevice, key: str) -> str | None:
|
||||
"""Get component name from device config."""
|
||||
"""Get custom name from device config."""
|
||||
if (
|
||||
key in device.config
|
||||
and key != "em:0" # workaround for Pro 3EM, we don't want to get name for em:0
|
||||
@@ -409,9 +414,9 @@ def get_rpc_custom_name(device: RpcDevice, key: str) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
def get_rpc_component_name(device: RpcDevice, key: str) -> str | None:
|
||||
"""Get component name from device config."""
|
||||
return get_rpc_custom_name(device, key)
|
||||
def get_rpc_number_of_channels(device: RpcDevice, component: str) -> int:
|
||||
"""Get number of channels."""
|
||||
return len(get_rpc_key_instances(device.status, component, all_lights=True))
|
||||
|
||||
|
||||
def get_rpc_channel_name(device: RpcDevice, key: str) -> str | None:
|
||||
@@ -419,9 +424,6 @@ def get_rpc_channel_name(device: RpcDevice, key: str) -> str | None:
|
||||
if BLU_TRV_IDENTIFIER in key:
|
||||
return None
|
||||
|
||||
instances = len(
|
||||
get_rpc_key_instances(device.status, key.split(":")[0], all_lights=True)
|
||||
)
|
||||
component = key.split(":")[0]
|
||||
component_id = key.split(":")[-1]
|
||||
|
||||
@@ -429,7 +431,9 @@ def get_rpc_channel_name(device: RpcDevice, key: str) -> str | None:
|
||||
if component in (*VIRTUAL_COMPONENTS, "input", "presencezone", "script"):
|
||||
return custom_name
|
||||
|
||||
return custom_name if instances == 1 else None
|
||||
channels = get_rpc_number_of_channels(device, component)
|
||||
|
||||
return custom_name if channels == 1 else None
|
||||
|
||||
if component in (*VIRTUAL_COMPONENTS, "input"):
|
||||
return f"{component.title()} {component_id}"
|
||||
@@ -890,7 +894,7 @@ def get_rpc_device_info(
|
||||
and get_irrigation_zone_id(device, key) is None
|
||||
)
|
||||
or idx is None
|
||||
or len(get_rpc_key_instances(device.status, component, all_lights=True)) < 2
|
||||
or get_rpc_number_of_channels(device, component) < 2
|
||||
):
|
||||
return DeviceInfo(connections={(CONNECTION_NETWORK_MAC, mac)})
|
||||
|
||||
@@ -923,6 +927,15 @@ def get_blu_trv_device_info(
|
||||
)
|
||||
|
||||
|
||||
def is_block_single_device(device: BlockDevice, block: Block | None = None) -> bool:
|
||||
"""Return true if block is single device."""
|
||||
return (
|
||||
block is None
|
||||
or block.type not in ("light", "relay", "emeter")
|
||||
or device.settings.get("mode") == "roller"
|
||||
)
|
||||
|
||||
|
||||
def get_block_device_info(
|
||||
device: BlockDevice,
|
||||
mac: str,
|
||||
@@ -933,14 +946,14 @@ def get_block_device_info(
|
||||
suggested_area: str | None = None,
|
||||
) -> DeviceInfo:
|
||||
"""Return device info for Block device."""
|
||||
if (
|
||||
block is None
|
||||
or block.type not in ("light", "relay", "emeter")
|
||||
or device.settings.get("mode") == "roller"
|
||||
or get_number_of_channels(device, block) < 2
|
||||
if is_block_single_device(device, block) or (
|
||||
block is not None and get_block_number_of_channels(device, block) < 2
|
||||
):
|
||||
return DeviceInfo(connections={(CONNECTION_NETWORK_MAC, mac)})
|
||||
|
||||
if TYPE_CHECKING:
|
||||
assert block
|
||||
|
||||
return DeviceInfo(
|
||||
identifiers={(DOMAIN, f"{mac}-{block.description}")},
|
||||
name=get_block_sub_device_name(device, block),
|
||||
|
||||
@@ -195,7 +195,7 @@ async def test_block_event(
|
||||
"""Test block device event."""
|
||||
await init_integration(hass, 1)
|
||||
# num_outputs is 2, device name and channel name is used
|
||||
entity_id = "event.test_name_channel_1"
|
||||
entity_id = "event.test_name_channel_1_input"
|
||||
|
||||
assert (state := hass.states.get(entity_id))
|
||||
assert state.state == STATE_UNKNOWN
|
||||
@@ -226,7 +226,38 @@ async def test_block_event_single_output(
|
||||
monkeypatch.setitem(mock_block_device.shelly, "num_outputs", 1)
|
||||
await init_integration(hass, 1)
|
||||
|
||||
assert hass.states.get("event.test_name")
|
||||
assert hass.states.get("event.test_name_input")
|
||||
|
||||
|
||||
async def test_block_event_custom_name(
|
||||
hass: HomeAssistant,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
mock_block_device: Mock,
|
||||
) -> None:
|
||||
"""Test block device event with custom name."""
|
||||
monkeypatch.setitem(
|
||||
mock_block_device.settings,
|
||||
"relays",
|
||||
[{"name": "test channel", "btn_type": "momentary"}, {"btn_type": "toggle"}],
|
||||
)
|
||||
await init_integration(hass, 1)
|
||||
# num_outputs is 2, device name and custom name is used
|
||||
assert hass.states.get("event.test_channel_input")
|
||||
|
||||
|
||||
async def test_block_event_custom_name_single_output(
|
||||
hass: HomeAssistant, mock_block_device: Mock, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Test block device event with custom name when num_outputs is 1."""
|
||||
monkeypatch.setitem(mock_block_device.shelly, "num_outputs", 1)
|
||||
monkeypatch.setitem(
|
||||
mock_block_device.settings,
|
||||
"relays",
|
||||
[{"name": "test channel", "btn_type": "momentary"}, {"btn_type": "toggle"}],
|
||||
)
|
||||
await init_integration(hass, 1)
|
||||
|
||||
assert hass.states.get("event.test_name_input")
|
||||
|
||||
|
||||
async def test_block_event_shix3_1(
|
||||
|
||||
@@ -27,9 +27,9 @@ from homeassistant.components.shelly.utils import (
|
||||
get_block_channel_name,
|
||||
get_block_device_sleep_period,
|
||||
get_block_input_triggers,
|
||||
get_block_number_of_channels,
|
||||
get_device_uptime,
|
||||
get_host,
|
||||
get_number_of_channels,
|
||||
get_release_url,
|
||||
get_rpc_channel_name,
|
||||
get_rpc_input_triggers,
|
||||
@@ -41,15 +41,15 @@ from homeassistant.util import dt as dt_util
|
||||
DEVICE_BLOCK_ID = 4
|
||||
|
||||
|
||||
async def test_block_get_number_of_channels(
|
||||
async def test_block_get_block_number_of_channels(
|
||||
mock_block_device: Mock, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Test block get number of channels."""
|
||||
"""Test block get block number of channels."""
|
||||
monkeypatch.setattr(mock_block_device.blocks[DEVICE_BLOCK_ID], "type", "emeter")
|
||||
monkeypatch.setitem(mock_block_device.shelly, "num_emeters", 3)
|
||||
|
||||
assert (
|
||||
get_number_of_channels(
|
||||
get_block_number_of_channels(
|
||||
mock_block_device,
|
||||
mock_block_device.blocks[DEVICE_BLOCK_ID],
|
||||
)
|
||||
@@ -59,7 +59,7 @@ async def test_block_get_number_of_channels(
|
||||
monkeypatch.setitem(mock_block_device.shelly, "num_inputs", 4)
|
||||
monkeypatch.setattr(mock_block_device.blocks[DEVICE_BLOCK_ID], "type", "input")
|
||||
assert (
|
||||
get_number_of_channels(
|
||||
get_block_number_of_channels(
|
||||
mock_block_device,
|
||||
mock_block_device.blocks[DEVICE_BLOCK_ID],
|
||||
)
|
||||
@@ -68,7 +68,7 @@ async def test_block_get_number_of_channels(
|
||||
|
||||
monkeypatch.setitem(mock_block_device.settings["device"], "type", MODEL_DIMMER_2)
|
||||
assert (
|
||||
get_number_of_channels(
|
||||
get_block_number_of_channels(
|
||||
mock_block_device,
|
||||
mock_block_device.blocks[DEVICE_BLOCK_ID],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user