Fix error when describing deCONZ events of removed devices (#84194)

* Fix error when describing deCONZ events of removed devices

* Apply suggestions from code review

Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>

Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
This commit is contained in:
Jelte Zeilstra 2022-12-20 10:06:01 +01:00 committed by GitHub
parent 3884e16b46
commit 3fc667f55d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 11 deletions

View File

@ -4,7 +4,7 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
from homeassistant.components.logbook import LOGBOOK_ENTRY_MESSAGE, LOGBOOK_ENTRY_NAME from homeassistant.components.logbook import LOGBOOK_ENTRY_MESSAGE, LOGBOOK_ENTRY_NAME
from homeassistant.const import ATTR_DEVICE_ID, CONF_EVENT from homeassistant.const import ATTR_DEVICE_ID, CONF_EVENT, CONF_ID
from homeassistant.core import Event, HomeAssistant, callback from homeassistant.core import Event, HomeAssistant, callback
import homeassistant.helpers.device_registry as dr import homeassistant.helpers.device_registry as dr
@ -130,27 +130,34 @@ def async_describe_events(
@callback @callback
def async_describe_deconz_alarm_event(event: Event) -> dict[str, str]: def async_describe_deconz_alarm_event(event: Event) -> dict[str, str]:
"""Describe deCONZ logbook alarm event.""" """Describe deCONZ logbook alarm event."""
device = device_registry.devices[event.data[ATTR_DEVICE_ID]] if device := device_registry.devices.get(event.data[ATTR_DEVICE_ID]):
deconz_alarm_event = _get_deconz_event_from_device(hass, device) deconz_alarm_event = _get_deconz_event_from_device(hass, device)
name = deconz_alarm_event.device.name
else:
name = event.data[CONF_ID]
data = event.data[CONF_EVENT] data = event.data[CONF_EVENT]
return { return {
LOGBOOK_ENTRY_NAME: f"{deconz_alarm_event.device.name}", LOGBOOK_ENTRY_NAME: name,
LOGBOOK_ENTRY_MESSAGE: f"fired event '{data}'", LOGBOOK_ENTRY_MESSAGE: f"fired event '{data}'",
} }
@callback @callback
def async_describe_deconz_event(event: Event) -> dict[str, str]: def async_describe_deconz_event(event: Event) -> dict[str, str]:
"""Describe deCONZ logbook event.""" """Describe deCONZ logbook event."""
device = device_registry.devices[event.data[ATTR_DEVICE_ID]] if device := device_registry.devices.get(event.data[ATTR_DEVICE_ID]):
deconz_event = _get_deconz_event_from_device(hass, device) deconz_event = _get_deconz_event_from_device(hass, device)
name = deconz_event.device.name
else:
deconz_event = None
name = event.data[CONF_ID]
action = None action = None
interface = None interface = None
data = event.data.get(CONF_EVENT) or event.data.get(CONF_GESTURE, "") data = event.data.get(CONF_EVENT) or event.data.get(CONF_GESTURE, "")
if data and deconz_event.device.model_id in REMOTES: if data and deconz_event and deconz_event.device.model_id in REMOTES:
action, interface = _get_device_event_description( action, interface = _get_device_event_description(
deconz_event.device.model_id, data deconz_event.device.model_id, data
) )
@ -158,26 +165,26 @@ def async_describe_events(
# Unknown event # Unknown event
if not data: if not data:
return { return {
LOGBOOK_ENTRY_NAME: f"{deconz_event.device.name}", LOGBOOK_ENTRY_NAME: name,
LOGBOOK_ENTRY_MESSAGE: "fired an unknown event", LOGBOOK_ENTRY_MESSAGE: "fired an unknown event",
} }
# No device event match # No device event match
if not action: if not action:
return { return {
LOGBOOK_ENTRY_NAME: f"{deconz_event.device.name}", LOGBOOK_ENTRY_NAME: name,
LOGBOOK_ENTRY_MESSAGE: f"fired event '{data}'", LOGBOOK_ENTRY_MESSAGE: f"fired event '{data}'",
} }
# Gesture event # Gesture event
if not interface: if not interface:
return { return {
LOGBOOK_ENTRY_NAME: f"{deconz_event.device.name}", LOGBOOK_ENTRY_NAME: name,
LOGBOOK_ENTRY_MESSAGE: f"fired event '{ACTIONS[action]}'", LOGBOOK_ENTRY_MESSAGE: f"fired event '{ACTIONS[action]}'",
} }
return { return {
LOGBOOK_ENTRY_NAME: f"{deconz_event.device.name}", LOGBOOK_ENTRY_NAME: name,
LOGBOOK_ENTRY_MESSAGE: f"'{ACTIONS[action]}' event for '{INTERFACES[interface]}' was fired", LOGBOOK_ENTRY_MESSAGE: f"'{ACTIONS[action]}' event for '{INTERFACES[interface]}' was fired",
} }

View File

@ -66,6 +66,9 @@ async def test_humanifying_deconz_alarm_event(hass, aioclient_mock):
identifiers={(DECONZ_DOMAIN, keypad_serial)} identifiers={(DECONZ_DOMAIN, keypad_serial)}
) )
removed_device_event_id = "removed_device"
removed_device_serial = "00:00:00:00:00:00:00:05"
hass.config.components.add("recorder") hass.config.components.add("recorder")
assert await async_setup_component(hass, "logbook", {}) assert await async_setup_component(hass, "logbook", {})
@ -82,6 +85,17 @@ async def test_humanifying_deconz_alarm_event(hass, aioclient_mock):
CONF_UNIQUE_ID: keypad_serial, CONF_UNIQUE_ID: keypad_serial,
}, },
), ),
# Event of a removed device
MockRow(
CONF_DECONZ_ALARM_EVENT,
{
CONF_CODE: 1234,
CONF_DEVICE_ID: "ff99ff99ff99ff99ff99ff99ff99ff99",
CONF_EVENT: STATE_ALARM_ARMED_AWAY,
CONF_ID: removed_device_event_id,
CONF_UNIQUE_ID: removed_device_serial,
},
),
], ],
) )
@ -89,6 +103,10 @@ async def test_humanifying_deconz_alarm_event(hass, aioclient_mock):
assert events[0]["domain"] == "deconz" assert events[0]["domain"] == "deconz"
assert events[0]["message"] == "fired event 'armed_away'" assert events[0]["message"] == "fired event 'armed_away'"
assert events[1]["name"] == "removed_device"
assert events[1]["domain"] == "deconz"
assert events[1]["message"] == "fired event 'armed_away'"
async def test_humanifying_deconz_event(hass, aioclient_mock): async def test_humanifying_deconz_event(hass, aioclient_mock):
"""Test humanifying deCONZ event.""" """Test humanifying deCONZ event."""
@ -155,6 +173,9 @@ async def test_humanifying_deconz_event(hass, aioclient_mock):
identifiers={(DECONZ_DOMAIN, faulty_serial)} identifiers={(DECONZ_DOMAIN, faulty_serial)}
) )
removed_device_event_id = "removed_device"
removed_device_serial = "00:00:00:00:00:00:00:05"
hass.config.components.add("recorder") hass.config.components.add("recorder")
assert await async_setup_component(hass, "logbook", {}) assert await async_setup_component(hass, "logbook", {})
@ -211,6 +232,16 @@ async def test_humanifying_deconz_event(hass, aioclient_mock):
CONF_UNIQUE_ID: faulty_serial, CONF_UNIQUE_ID: faulty_serial,
}, },
), ),
# Event of a removed device
MockRow(
CONF_DECONZ_EVENT,
{
CONF_DEVICE_ID: "ff99ff99ff99ff99ff99ff99ff99ff99",
CONF_EVENT: 2000,
CONF_ID: removed_device_event_id,
CONF_UNIQUE_ID: removed_device_serial,
},
),
], ],
) )
@ -233,3 +264,7 @@ async def test_humanifying_deconz_event(hass, aioclient_mock):
assert events[4]["name"] == "Faulty event" assert events[4]["name"] == "Faulty event"
assert events[4]["domain"] == "deconz" assert events[4]["domain"] == "deconz"
assert events[4]["message"] == "fired an unknown event" assert events[4]["message"] == "fired an unknown event"
assert events[5]["name"] == "removed_device"
assert events[5]["domain"] == "deconz"
assert events[5]["message"] == "fired event '2000'"