Skip to content

Commit 9f0db98

Browse files
puddlyfrenck
authored andcommitted
Strip _CLIENT suffix from ZHA event unique_id (home-assistant#145006)
1 parent 0ba55c3 commit 9f0db98

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

homeassistant/components/zha/helpers.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,13 +419,26 @@ def zha_device_info(self) -> dict[str, Any]:
419419
@callback
420420
def handle_zha_event(self, zha_event: ZHAEvent) -> None:
421421
"""Handle a ZHA event."""
422+
if ATTR_UNIQUE_ID in zha_event.data:
423+
unique_id = zha_event.data[ATTR_UNIQUE_ID]
424+
425+
# Client cluster handler unique IDs in the ZHA lib were disambiguated by
426+
# adding a suffix of `_CLIENT`. Unfortunately, this breaks existing
427+
# automations that match the `unique_id` key. This can be removed in a
428+
# future release with proper notice of a breaking change.
429+
unique_id = unique_id.removesuffix("_CLIENT")
430+
else:
431+
unique_id = zha_event.unique_id
432+
422433
self.gateway_proxy.hass.bus.async_fire(
423434
ZHA_EVENT,
424435
{
425436
ATTR_DEVICE_IEEE: str(zha_event.device_ieee),
426-
ATTR_UNIQUE_ID: zha_event.unique_id,
427437
ATTR_DEVICE_ID: self.device_id,
428438
**zha_event.data,
439+
# The order of these keys is intentional, `zha_event.data` can contain
440+
# a `unique_id` key, which we explicitly replace
441+
ATTR_UNIQUE_ID: unique_id,
429442
},
430443
)
431444

tests/components/zha/test_device_action.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,67 @@ async def test_invalid_zha_event_type(
258258
# `zha_send_event` accepts only zigpy responses, lists, and dicts
259259
with pytest.raises(TypeError):
260260
cluster_handler.zha_send_event(COMMAND_SINGLE, 123)
261+
262+
263+
async def test_client_unique_id_suffix_stripped(
264+
hass: HomeAssistant, setup_zha, zigpy_device_mock
265+
) -> None:
266+
"""Test that the `_CLIENT_` unique ID suffix is stripped."""
267+
assert await async_setup_component(
268+
hass,
269+
automation.DOMAIN,
270+
{
271+
automation.DOMAIN: {
272+
"trigger": {
273+
"platform": "event",
274+
"event_type": "zha_event",
275+
"event_data": {
276+
"unique_id": "38:5b:44:ff:fe:a7:cc:69:1:0x0006", # no `_CLIENT` suffix
277+
"endpoint_id": 1,
278+
"cluster_id": 6,
279+
"command": "on",
280+
"args": [],
281+
"params": {},
282+
},
283+
},
284+
"action": {"service": "zha.test"},
285+
}
286+
},
287+
)
288+
289+
service_calls = async_mock_service(hass, DOMAIN, "test")
290+
291+
await setup_zha()
292+
gateway = get_zha_gateway(hass)
293+
294+
zigpy_device = zigpy_device_mock(
295+
{
296+
1: {
297+
SIG_EP_INPUT: [
298+
general.Basic.cluster_id,
299+
security.IasZone.cluster_id,
300+
security.IasWd.cluster_id,
301+
],
302+
SIG_EP_OUTPUT: [general.OnOff.cluster_id],
303+
SIG_EP_TYPE: zha.DeviceType.ON_OFF_SWITCH,
304+
SIG_EP_PROFILE: zha.PROFILE_ID,
305+
}
306+
}
307+
)
308+
309+
zha_device = gateway.get_or_create_device(zigpy_device)
310+
await gateway.async_device_initialized(zha_device.device)
311+
312+
zha_device.emit_zha_event(
313+
{
314+
"unique_id": "38:5b:44:ff:fe:a7:cc:69:1:0x0006_CLIENT",
315+
"endpoint_id": 1,
316+
"cluster_id": 6,
317+
"command": "on",
318+
"args": [],
319+
"params": {},
320+
}
321+
)
322+
323+
await hass.async_block_till_done(wait_background_tasks=True)
324+
assert len(service_calls) == 1

0 commit comments

Comments
 (0)