Hue handle device update (#60612)
parent
de9e48174f
commit
19b4cc7119
|
@ -60,6 +60,19 @@ class HueSceneEntity(HueBaseEntity, SceneEntity):
|
|||
super().__init__(bridge, controller, resource)
|
||||
self.resource = resource
|
||||
self.controller = controller
|
||||
self.group = self.controller.get_group(self.resource.id)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Call when entity is added."""
|
||||
await super().async_added_to_hass()
|
||||
# Add value_changed callback for group to catch name changes.
|
||||
self.async_on_remove(
|
||||
self.bridge.api.groups.subscribe(
|
||||
self._handle_event,
|
||||
self.group.id,
|
||||
(EventType.RESOURCE_UPDATED),
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
|
@ -96,7 +109,6 @@ class HueSceneEntity(HueBaseEntity, SceneEntity):
|
|||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any] | None:
|
||||
"""Return the optional state attributes."""
|
||||
group = self.controller.get_group(self.resource.id)
|
||||
brightness = None
|
||||
if palette := self.resource.palette:
|
||||
if palette.dimming:
|
||||
|
@ -108,8 +120,8 @@ class HueSceneEntity(HueBaseEntity, SceneEntity):
|
|||
brightness = action.action.dimming.brightness
|
||||
break
|
||||
return {
|
||||
"group_name": group.metadata.name,
|
||||
"group_type": group.type.value,
|
||||
"group_name": self.group.metadata.name,
|
||||
"group_type": self.group.type.value,
|
||||
"name": self.resource.metadata.name,
|
||||
"speed": self.resource.speed,
|
||||
"brightness": brightness,
|
||||
|
|
|
@ -56,11 +56,11 @@ class HueBaseEntity(Entity):
|
|||
# creating a pretty name for device-less entities (e.g. groups/scenes)
|
||||
# should be handled in the platform instead
|
||||
return self.resource.type.value
|
||||
dev_name = self.device.metadata.name
|
||||
# if resource is a light, use the device name
|
||||
# if resource is a light, use the name from metadata
|
||||
if self.resource.type == ResourceTypes.LIGHT:
|
||||
return dev_name
|
||||
return self.resource.name
|
||||
# for sensors etc, use devicename + pretty name of type
|
||||
dev_name = self.device.metadata.name
|
||||
type_title = RESOURCE_TYPE_NAMES.get(
|
||||
self.resource.type, self.resource.type.value.replace("_", " ").title()
|
||||
)
|
||||
|
@ -76,6 +76,23 @@ class HueBaseEntity(Entity):
|
|||
(EventType.RESOURCE_UPDATED, EventType.RESOURCE_DELETED),
|
||||
)
|
||||
)
|
||||
# also subscribe to device update event to catch devicer changes (e.g. name)
|
||||
if self.device is None:
|
||||
return
|
||||
self.async_on_remove(
|
||||
self.bridge.api.devices.subscribe(
|
||||
self._handle_event,
|
||||
self.device.id,
|
||||
EventType.RESOURCE_UPDATED,
|
||||
)
|
||||
)
|
||||
# subscribe to zigbee_connectivity to catch availability changes
|
||||
if zigbee := self.bridge.api.devices.get_zigbee_connectivity(self.device.id):
|
||||
self.bridge.api.sensors.zigbee_connectivity.subscribe(
|
||||
self._handle_event,
|
||||
zigbee.id,
|
||||
EventType.RESOURCE_UPDATED,
|
||||
)
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
|
@ -98,7 +115,7 @@ class HueBaseEntity(Entity):
|
|||
|
||||
@callback
|
||||
def _handle_event(self, event_type: EventType, resource: CLIPResource) -> None:
|
||||
"""Handle status event for this resource."""
|
||||
"""Handle status event for this resource (or it's parent)."""
|
||||
if event_type == EventType.RESOURCE_DELETED and resource.id == self.resource.id:
|
||||
self.logger.debug("Received delete for %s", self.entity_id)
|
||||
# non-device bound entities like groups and scenes need to be removed here
|
||||
|
|
|
@ -32,7 +32,7 @@ FAKE_LIGHT = {
|
|||
},
|
||||
"id": "fake_light_id_1",
|
||||
"id_v1": "/lights/1",
|
||||
"metadata": {"archetype": "unknown", "name": "Hue fake light 1"},
|
||||
"metadata": {"archetype": "unknown", "name": "Hue fake light"},
|
||||
"mode": "normal",
|
||||
"on": {"on": False},
|
||||
"owner": {"rid": "fake_device_id_1", "rtype": "device"},
|
||||
|
|
|
@ -173,7 +173,7 @@ async def test_light_added(hass, mock_bridge_v2):
|
|||
|
||||
await setup_platform(hass, mock_bridge_v2, "light")
|
||||
|
||||
test_entity_id = "light.hue_mocked_device"
|
||||
test_entity_id = "light.hue_fake_light"
|
||||
|
||||
# verify entity does not exist before we start
|
||||
assert hass.states.get(test_entity_id) is None
|
||||
|
@ -186,7 +186,7 @@ async def test_light_added(hass, mock_bridge_v2):
|
|||
test_entity = hass.states.get(test_entity_id)
|
||||
assert test_entity is not None
|
||||
assert test_entity.state == "off"
|
||||
assert test_entity.attributes["friendly_name"] == FAKE_DEVICE["metadata"]["name"]
|
||||
assert test_entity.attributes["friendly_name"] == FAKE_LIGHT["metadata"]["name"]
|
||||
|
||||
|
||||
async def test_light_availability(hass, mock_bridge_v2, v2_resources_test_data):
|
||||
|
@ -212,13 +212,6 @@ async def test_light_availability(hass, mock_bridge_v2, v2_resources_test_data):
|
|||
"type": "zigbee_connectivity",
|
||||
},
|
||||
)
|
||||
mock_bridge_v2.api.emit_event(
|
||||
"update",
|
||||
{
|
||||
"id": "02cba059-9c2c-4d45-97e4-4f79b1bfbaa1",
|
||||
"type": "light",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# the entity should now be available only when zigbee is connected
|
||||
|
|
|
@ -118,6 +118,19 @@ async def test_scene_updates(hass, mock_bridge_v2, v2_resources_test_data):
|
|||
assert test_entity is not None
|
||||
assert test_entity.attributes["brightness"] == 35.0
|
||||
|
||||
# test entity name changes on group name change
|
||||
mock_bridge_v2.api.emit_event(
|
||||
"update",
|
||||
{
|
||||
"type": "room",
|
||||
"id": "6ddc9066-7e7d-4a03-a773-c73937968296",
|
||||
"metadata": {"name": "Test Room 2"},
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
test_entity = hass.states.get(test_entity_id)
|
||||
assert test_entity.name == "Test Room 2 - Mocked Scene"
|
||||
|
||||
# test delete
|
||||
mock_bridge_v2.api.emit_event("delete", updated_resource)
|
||||
await hass.async_block_till_done()
|
||||
|
|
Loading…
Reference in New Issue