From d4111617cad498b4c5d447088059761c5bdbb6e5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 14 Jul 2020 10:38:55 -1000 Subject: [PATCH] Ensure HomeKit does not throw when a linked motion sensor is removed (#37773) --- .../components/homekit/type_cameras.py | 22 +++++++++++++------ tests/components/homekit/test_type_cameras.py | 8 +++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/homekit/type_cameras.py b/homeassistant/components/homekit/type_cameras.py index f01840cf062..9cfacc9866d 100644 --- a/homeassistant/components/homekit/type_cameras.py +++ b/homeassistant/components/homekit/type_cameras.py @@ -16,7 +16,7 @@ from homeassistant.components.ffmpeg import DATA_FFMPEG from homeassistant.const import STATE_ON from homeassistant.core import callback from homeassistant.helpers.event import ( - async_track_state_change, + async_track_state_change_event, async_track_time_interval, ) from homeassistant.util import get_local_ip @@ -201,7 +201,7 @@ class Camera(HomeAccessory, PyhapCamera): self._char_motion_detected = serv_motion.configure_char( CHAR_MOTION_DETECTED, value=False ) - self._async_update_motion_state(None, None, state) + self._async_update_motion_state(state) async def run_handler(self): """Handle accessory driver started event. @@ -209,17 +209,25 @@ class Camera(HomeAccessory, PyhapCamera): Run inside the Home Assistant event loop. """ if self._char_motion_detected: - async_track_state_change( - self.hass, self.linked_motion_sensor, self._async_update_motion_state + async_track_state_change_event( + self.hass, + [self.linked_motion_sensor], + self._async_update_motion_state_event, ) await super().run_handler() @callback - def _async_update_motion_state( - self, entity_id=None, old_state=None, new_state=None - ): + def _async_update_motion_state_event(self, event): + """Handle state change event listener callback.""" + self._async_update_motion_state(event.data.get("new_state")) + + @callback + def _async_update_motion_state(self, new_state): """Handle link motion sensor state change to update HomeKit value.""" + if not new_state: + return + detected = new_state.state == STATE_ON if self._char_motion_detected.value == detected: return diff --git a/tests/components/homekit/test_type_cameras.py b/tests/components/homekit/test_type_cameras.py index 78e27231d19..dbc28cb1ea8 100644 --- a/tests/components/homekit/test_type_cameras.py +++ b/tests/components/homekit/test_type_cameras.py @@ -564,6 +564,14 @@ async def test_camera_with_linked_motion_sensor(hass, run_driver, events): await hass.async_block_till_done() assert char.value is True + # Ensure we do not throw when the linked + # motion sensor is removed + hass.states.async_remove(motion_entity_id) + await hass.async_block_till_done() + await acc.run_handler() + await hass.async_block_till_done() + assert char.value is True + async def test_camera_with_a_missing_linked_motion_sensor(hass, run_driver, events): """Test a camera with a configured linked motion sensor that is missing."""