Group Overkiz sub-devices by placeOID

This commit is contained in:
Paul Bottein
2026-02-05 12:23:09 +01:00
parent fa58fe5f4e
commit c014d32cac

View File

@@ -58,12 +58,62 @@ class OverkizEntity(CoordinatorEntity[OverkizDataUpdateCoordinator]):
"""Return Overkiz device linked to this entity."""
return self.coordinator.data[self.device_url]
def _has_siblings_with_different_place_oid(self) -> bool:
"""Check if sibling devices (same base_url) have different placeOIDs.
Returns True if there are devices sharing the same base_device_url
but with different place_oid values. This indicates the devices
should be grouped by placeOID rather than by base URL.
"""
if not self.device.place_oid:
return False
for device in self.coordinator.data.values():
# Check for sibling devices (same base URL, different device URL)
if (
device.device_url != self.device_url
and device.device_url.startswith(f"{self.base_device_url}#")
and device.place_oid
and device.place_oid != self.device.place_oid
):
return True
return False
def _is_main_device_for_place_oid(self) -> bool:
"""Check if this device is the main device for its placeOID group.
When multiple devices share the same placeOID, the one with the lowest
device URL index is considered the main device and provides full device info.
Other devices just reference the identifier.
"""
if not self.device.place_oid:
return True
my_index = int(self.device_url.split("#")[-1])
# Find all devices with the same base URL and placeOID
for device in self.coordinator.data.values():
if (
device.device_url != self.device_url
and device.device_url.startswith(f"{self.base_device_url}#")
and device.place_oid == self.device.place_oid
):
# Compare device URL indices - lower index is the main device
other_index = int(device.device_url.split("#")[-1])
if other_index < my_index:
return False
return True
def generate_device_info(self) -> DeviceInfo:
"""Return device registry information for this entity."""
# Some devices, such as the Smart Thermostat have several devices
# in one physical device, with same device url, terminated by '#' and a number.
# In this case, we use the base device url as the device identifier.
if self.is_sub_device:
# Check if siblings have different placeOIDs - if so, use placeOID grouping
use_place_oid_grouping = self._has_siblings_with_different_place_oid()
if self.is_sub_device and not use_place_oid_grouping:
# Only return the url of the base device, to inherit device name
# and model from parent device.
return DeviceInfo(
@@ -91,8 +141,35 @@ class OverkizEntity(CoordinatorEntity[OverkizDataUpdateCoordinator]):
else None
)
# Use placeOID-based identifier when siblings have different placeOIDs
if use_place_oid_grouping:
identifier = f"{self.base_device_url}#{self.device.place_oid}"
# Only the main device for this placeOID provides full device info.
# Other devices just reference the identifier.
if not self._is_main_device_for_place_oid():
return DeviceInfo(
identifiers={(DOMAIN, identifier)},
)
# Link sub-devices to the main actuator (#1 device).
main_device = self.coordinator.data.get(f"{self.base_device_url}#1")
if main_device and main_device.place_oid:
main_device_identifier = (
f"{self.base_device_url}#{main_device.place_oid}"
)
if self.device_url.endswith("#1"):
via_device = (DOMAIN, self.executor.get_gateway_id())
else:
via_device = (DOMAIN, main_device_identifier)
else:
via_device = (DOMAIN, self.executor.get_gateway_id())
else:
identifier = self.executor.base_device_url
via_device = (DOMAIN, self.executor.get_gateway_id())
return DeviceInfo(
identifiers={(DOMAIN, self.executor.base_device_url)},
identifiers={(DOMAIN, identifier)},
name=self.device.label,
manufacturer=str(manufacturer),
model=str(model),
@@ -102,7 +179,7 @@ class OverkizEntity(CoordinatorEntity[OverkizDataUpdateCoordinator]):
),
hw_version=self.device.controllable_name,
suggested_area=suggested_area,
via_device=(DOMAIN, self.executor.get_gateway_id()),
via_device=via_device,
configuration_url=self.coordinator.client.server.configuration_url,
)