Adapt sia to set via_device_id in DeviceInfo (#177760)

This commit is contained in:
Erik Montnemery
2026-08-03 16:53:42 +02:00
committed by GitHub
parent 96f3fe3122
commit 6c27469b3a
4 changed files with 92 additions and 9 deletions
@@ -72,7 +72,7 @@ async def async_setup_entry(
"""Set up SIA alarm_control_panel(s) from a config entry."""
async_add_entities(
SIAAlarmControlPanel(
entry, account_data[CONF_ACCOUNT], zone, ENTITY_DESCRIPTION_ALARM
hass, entry, account_data[CONF_ACCOUNT], zone, ENTITY_DESCRIPTION_ALARM
)
for account_data in entry.data[CONF_ACCOUNTS]
for zone in range(
@@ -89,6 +89,7 @@ class SIAAlarmControlPanel(SIABaseEntity, AlarmControlPanelEntity):
def __init__(
self,
hass: HomeAssistant,
entry: ConfigEntry,
account: str,
zone: int,
@@ -96,6 +97,7 @@ class SIAAlarmControlPanel(SIABaseEntity, AlarmControlPanelEntity):
) -> None:
"""Create SIAAlarmControlPanel object."""
super().__init__(
hass,
entry,
account,
zone,
+12 -6
View File
@@ -82,7 +82,9 @@ ENTITY_DESCRIPTION_CONNECTIVITY = SIABinarySensorEntityDescription(
)
def generate_binary_sensors(entry: ConfigEntry) -> Iterable[SIABinarySensor]:
def generate_binary_sensors(
hass: HomeAssistant, entry: ConfigEntry
) -> Iterable[SIABinarySensor]:
"""Generate binary sensors.
For each Account there is one power sensor with zone == 0.
@@ -93,12 +95,16 @@ def generate_binary_sensors(entry: ConfigEntry) -> Iterable[SIABinarySensor]:
zones = entry.options[CONF_ACCOUNTS][account][CONF_ZONES]
yield SIABinarySensorConnectivity(
entry, account, SIA_HUB_ZONE, ENTITY_DESCRIPTION_CONNECTIVITY
hass, entry, account, SIA_HUB_ZONE, ENTITY_DESCRIPTION_CONNECTIVITY
)
yield SIABinarySensor(
hass, entry, account, SIA_HUB_ZONE, ENTITY_DESCRIPTION_POWER
)
yield SIABinarySensor(entry, account, SIA_HUB_ZONE, ENTITY_DESCRIPTION_POWER)
for zone in range(1, zones + 1):
yield SIABinarySensor(entry, account, zone, ENTITY_DESCRIPTION_SMOKE)
yield SIABinarySensor(entry, account, zone, ENTITY_DESCRIPTION_MOISTURE)
yield SIABinarySensor(hass, entry, account, zone, ENTITY_DESCRIPTION_SMOKE)
yield SIABinarySensor(
hass, entry, account, zone, ENTITY_DESCRIPTION_MOISTURE
)
async def async_setup_entry(
@@ -107,7 +113,7 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up SIA binary sensors from a config entry."""
async_add_entities(generate_binary_sensors(entry))
async_add_entities(generate_binary_sensors(hass, entry))
class SIABinarySensor(SIABaseEntity, BinarySensorEntity):
+8 -2
View File
@@ -10,7 +10,8 @@ from pysiaalarm import SIAEvent
from homeassistant.components.alarm_control_panel import AlarmControlPanelState
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PORT
from homeassistant.core import CALLBACK_TYPE, State, callback
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, State, callback
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import EntityDescription
@@ -55,6 +56,7 @@ class SIABaseEntity(RestoreEntity):
def __init__(
self,
hass: HomeAssistant,
entry: ConfigEntry,
account: str,
zone: int,
@@ -77,7 +79,11 @@ class SIABaseEntity(RestoreEntity):
self._attr_device_info = DeviceInfo(
name=self._attr_name,
identifiers={(DOMAIN, self._attr_unique_id)},
via_device=(DOMAIN, f"{entry.data[CONF_PORT]}_{account}"),
via_device_id=dr.async_get_device_id_by_identifier(
hass,
(DOMAIN, f"{self.port}_{self.account}"),
config_entry_id=entry.entry_id,
),
)
self._post_interval_update_cb_canceller: CALLBACK_TYPE | None = None
+69
View File
@@ -0,0 +1,69 @@
"""Test the sia setup process."""
from collections.abc import Generator
from unittest.mock import patch
import pytest
from homeassistant.components.sia.const import (
CONF_ACCOUNT,
CONF_ACCOUNTS,
CONF_ENCRYPTION_KEY,
CONF_IGNORE_TIMESTAMPS,
CONF_PING_INTERVAL,
CONF_ZONES,
DOMAIN,
)
from homeassistant.const import CONF_PORT, CONF_PROTOCOL
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from tests.common import MockConfigEntry
CONFIG_ENTRY_DATA = {
CONF_PORT: 7777,
CONF_PROTOCOL: "TCP",
CONF_ACCOUNTS: [
{
CONF_ACCOUNT: "ABCDEF",
CONF_ENCRYPTION_KEY: "AAAAAAAAAAAAAAAA",
CONF_PING_INTERVAL: 10,
},
],
}
CONFIG_ENTRY_OPTIONS = {
CONF_ACCOUNTS: {"ABCDEF": {CONF_IGNORE_TIMESTAMPS: False, CONF_ZONES: 1}}
}
@pytest.fixture(autouse=True)
def mock_sia_client() -> Generator[None]:
"""Mock SIAClient so no real socket is opened."""
with patch("homeassistant.components.sia.hub.SIAClient", autospec=True):
yield
async def test_entity_device_linked_to_hub_device(
hass: HomeAssistant, device_registry: dr.DeviceRegistry
) -> None:
"""Test an entity's device is linked to its hub device via via_device_id."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data=CONFIG_ENTRY_DATA,
options=CONFIG_ENTRY_OPTIONS,
title="SIA Alarm on port 7777",
)
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
hub_device = device_registry.async_get_device_by_identifier(
(DOMAIN, "7777_ABCDEF"), config_entry.entry_id
)
assert hub_device is not None
alarm_device = device_registry.async_get_device_by_identifier(
(DOMAIN, f"{config_entry.entry_id}_ABCDEF_1"), config_entry.entry_id
)
assert alarm_device is not None
assert alarm_device.via_device_id == hub_device.id