mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Add support for device sub units in AVM Fritz!SmartHome (#142845)
This commit is contained in:
parent
a4f75ca249
commit
e418491f19
@ -77,12 +77,11 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
|
|||||||
self.configuration_url = self.fritz.get_prefixed_host()
|
self.configuration_url = self.fritz.get_prefixed_host()
|
||||||
|
|
||||||
await self.async_config_entry_first_refresh()
|
await self.async_config_entry_first_refresh()
|
||||||
self.cleanup_removed_devices(
|
self.cleanup_removed_devices(self.data)
|
||||||
list(self.data.devices) + list(self.data.templates)
|
|
||||||
)
|
|
||||||
|
|
||||||
def cleanup_removed_devices(self, available_ains: list[str]) -> None:
|
def cleanup_removed_devices(self, data: FritzboxCoordinatorData) -> None:
|
||||||
"""Cleanup entity and device registry from removed devices."""
|
"""Cleanup entity and device registry from removed devices."""
|
||||||
|
available_ains = list(data.devices) + list(data.templates)
|
||||||
entity_reg = er.async_get(self.hass)
|
entity_reg = er.async_get(self.hass)
|
||||||
for entity in er.async_entries_for_config_entry(
|
for entity in er.async_entries_for_config_entry(
|
||||||
entity_reg, self.config_entry.entry_id
|
entity_reg, self.config_entry.entry_id
|
||||||
@ -91,8 +90,13 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
|
|||||||
LOGGER.debug("Removing obsolete entity entry %s", entity.entity_id)
|
LOGGER.debug("Removing obsolete entity entry %s", entity.entity_id)
|
||||||
entity_reg.async_remove(entity.entity_id)
|
entity_reg.async_remove(entity.entity_id)
|
||||||
|
|
||||||
|
available_main_ains = [
|
||||||
|
ain
|
||||||
|
for ain, dev in data.devices.items()
|
||||||
|
if dev.device_and_unit_id[1] is None
|
||||||
|
]
|
||||||
device_reg = dr.async_get(self.hass)
|
device_reg = dr.async_get(self.hass)
|
||||||
identifiers = {(DOMAIN, ain) for ain in available_ains}
|
identifiers = {(DOMAIN, ain) for ain in available_main_ains}
|
||||||
for device in dr.async_entries_for_config_entry(
|
for device in dr.async_entries_for_config_entry(
|
||||||
device_reg, self.config_entry.entry_id
|
device_reg, self.config_entry.entry_id
|
||||||
):
|
):
|
||||||
@ -165,12 +169,26 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
|
|||||||
"""Fetch all device data."""
|
"""Fetch all device data."""
|
||||||
new_data = await self.hass.async_add_executor_job(self._update_fritz_devices)
|
new_data = await self.hass.async_add_executor_job(self._update_fritz_devices)
|
||||||
|
|
||||||
|
for device in new_data.devices.values():
|
||||||
|
# create device registry entry for new main devices
|
||||||
|
if (
|
||||||
|
device.ain not in self.data.devices
|
||||||
|
and device.device_and_unit_id[1] is None
|
||||||
|
):
|
||||||
|
dr.async_get(self.hass).async_get_or_create(
|
||||||
|
config_entry_id=self.config_entry.entry_id,
|
||||||
|
name=device.name,
|
||||||
|
identifiers={(DOMAIN, device.ain)},
|
||||||
|
manufacturer=device.manufacturer,
|
||||||
|
model=device.productname,
|
||||||
|
sw_version=device.fw_version,
|
||||||
|
configuration_url=self.configuration_url,
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.data.devices.keys() - new_data.devices.keys()
|
self.data.devices.keys() - new_data.devices.keys()
|
||||||
or self.data.templates.keys() - new_data.templates.keys()
|
or self.data.templates.keys() - new_data.templates.keys()
|
||||||
):
|
):
|
||||||
self.cleanup_removed_devices(
|
self.cleanup_removed_devices(new_data)
|
||||||
list(new_data.devices) + list(new_data.templates)
|
|
||||||
)
|
|
||||||
|
|
||||||
return new_data
|
return new_data
|
||||||
|
@ -58,11 +58,4 @@ class FritzBoxDeviceEntity(FritzBoxEntity):
|
|||||||
@property
|
@property
|
||||||
def device_info(self) -> DeviceInfo:
|
def device_info(self) -> DeviceInfo:
|
||||||
"""Return device specific attributes."""
|
"""Return device specific attributes."""
|
||||||
return DeviceInfo(
|
return DeviceInfo(identifiers={(DOMAIN, self.data.device_and_unit_id[0])})
|
||||||
name=self.data.name,
|
|
||||||
identifiers={(DOMAIN, self.ain)},
|
|
||||||
manufacturer=self.data.manufacturer,
|
|
||||||
model=self.data.productname,
|
|
||||||
sw_version=self.data.fw_version,
|
|
||||||
configuration_url=self.coordinator.configuration_url,
|
|
||||||
)
|
|
||||||
|
@ -60,6 +60,7 @@ class FritzEntityBaseMock(Mock):
|
|||||||
"""base mock of a AVM Fritz!Box binary sensor device."""
|
"""base mock of a AVM Fritz!Box binary sensor device."""
|
||||||
|
|
||||||
ain = CONF_FAKE_AIN
|
ain = CONF_FAKE_AIN
|
||||||
|
device_and_unit_id = (CONF_FAKE_AIN, None)
|
||||||
manufacturer = CONF_FAKE_MANUFACTURER
|
manufacturer = CONF_FAKE_MANUFACTURER
|
||||||
name = CONF_FAKE_NAME
|
name = CONF_FAKE_NAME
|
||||||
productname = CONF_FAKE_PRODUCTNAME
|
productname = CONF_FAKE_PRODUCTNAME
|
||||||
|
@ -110,6 +110,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
|
|
||||||
new_device = FritzDeviceBinarySensorMock()
|
new_device = FritzDeviceBinarySensorMock()
|
||||||
new_device.ain = "7890 1234"
|
new_device.ain = "7890 1234"
|
||||||
|
new_device.device_and_unit_id = ("7890 1234", None)
|
||||||
new_device.name = "new_device"
|
new_device.name = "new_device"
|
||||||
set_devices(fritz, devices=[device, new_device])
|
set_devices(fritz, devices=[device, new_device])
|
||||||
|
|
||||||
|
@ -85,8 +85,16 @@ async def test_coordinator_automatic_registry_cleanup(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test automatic registry cleanup."""
|
"""Test automatic registry cleanup."""
|
||||||
fritz().get_devices.return_value = [
|
fritz().get_devices.return_value = [
|
||||||
FritzDeviceSwitchMock(ain="fake ain switch", name="fake_switch"),
|
FritzDeviceSwitchMock(
|
||||||
FritzDeviceCoverMock(ain="fake ain cover", name="fake_cover"),
|
ain="fake ain switch",
|
||||||
|
device_and_unit_id=("fake ain switch", None),
|
||||||
|
name="fake_switch",
|
||||||
|
),
|
||||||
|
FritzDeviceCoverMock(
|
||||||
|
ain="fake ain cover",
|
||||||
|
device_and_unit_id=("fake ain cover", None),
|
||||||
|
name="fake_cover",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=FB_DOMAIN,
|
domain=FB_DOMAIN,
|
||||||
@ -101,7 +109,11 @@ async def test_coordinator_automatic_registry_cleanup(
|
|||||||
assert len(dr.async_entries_for_config_entry(device_registry, entry.entry_id)) == 2
|
assert len(dr.async_entries_for_config_entry(device_registry, entry.entry_id)) == 2
|
||||||
|
|
||||||
fritz().get_devices.return_value = [
|
fritz().get_devices.return_value = [
|
||||||
FritzDeviceSwitchMock(ain="fake ain switch", name="fake_switch")
|
FritzDeviceSwitchMock(
|
||||||
|
ain="fake ain switch",
|
||||||
|
device_and_unit_id=("fake ain switch", None),
|
||||||
|
name="fake_switch",
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=35))
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=35))
|
||||||
|
@ -108,6 +108,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
|
|
||||||
new_device = FritzDeviceSensorMock()
|
new_device = FritzDeviceSensorMock()
|
||||||
new_device.ain = "7890 1234"
|
new_device.ain = "7890 1234"
|
||||||
|
new_device.device_and_unit_id = ("7890 1234", None)
|
||||||
new_device.name = "new_device"
|
new_device.name = "new_device"
|
||||||
set_devices(fritz, devices=[device, new_device])
|
set_devices(fritz, devices=[device, new_device])
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user