Ensure homekit state changed listeners are unsubscribed on reload (#37200)
* Ensure homekit state changed listeners are unsubscribed on reload * fix mocking
This commit is contained in:
parent
7ef33a7219
commit
0f72008090
4 changed files with 44 additions and 10 deletions
|
@ -576,6 +576,8 @@ class HomeKit:
|
|||
self.status = STATUS_STOPPED
|
||||
_LOGGER.debug("Driver stop for %s", self._name)
|
||||
self.hass.add_job(self.driver.stop)
|
||||
for acc in self.bridge.accessories.values():
|
||||
acc.async_stop()
|
||||
|
||||
@callback
|
||||
def _async_configure_linked_sensors(self, ent_reg_ent, device_lookup, state):
|
||||
|
|
|
@ -270,6 +270,7 @@ class HomeAccessory(Accessory):
|
|||
self.entity_id = entity_id
|
||||
self.hass = hass
|
||||
self.debounce = {}
|
||||
self._subscriptions = []
|
||||
self._char_battery = None
|
||||
self._char_charging = None
|
||||
self._char_low_battery = None
|
||||
|
@ -343,9 +344,11 @@ class HomeAccessory(Accessory):
|
|||
"""
|
||||
state = self.hass.states.get(self.entity_id)
|
||||
self.async_update_state_callback(None, None, state)
|
||||
self._subscriptions.append(
|
||||
async_track_state_change(
|
||||
self.hass, self.entity_id, self.async_update_state_callback
|
||||
)
|
||||
)
|
||||
|
||||
battery_charging_state = None
|
||||
battery_state = None
|
||||
|
@ -357,11 +360,13 @@ class HomeAccessory(Accessory):
|
|||
battery_charging_state = linked_battery_sensor_state.attributes.get(
|
||||
ATTR_BATTERY_CHARGING
|
||||
)
|
||||
self._subscriptions.append(
|
||||
async_track_state_change(
|
||||
self.hass,
|
||||
self.linked_battery_sensor,
|
||||
self.async_update_linked_battery_callback,
|
||||
)
|
||||
)
|
||||
else:
|
||||
battery_state = state.attributes.get(ATTR_BATTERY_LEVEL)
|
||||
if self.linked_battery_charging_sensor:
|
||||
|
@ -369,11 +374,13 @@ class HomeAccessory(Accessory):
|
|||
self.hass.states.get(self.linked_battery_charging_sensor).state
|
||||
== STATE_ON
|
||||
)
|
||||
self._subscriptions.append(
|
||||
async_track_state_change(
|
||||
self.hass,
|
||||
self.linked_battery_charging_sensor,
|
||||
self.async_update_linked_battery_charging_callback,
|
||||
)
|
||||
)
|
||||
elif battery_charging_state is None:
|
||||
battery_charging_state = state.attributes.get(ATTR_BATTERY_CHARGING)
|
||||
|
||||
|
@ -481,6 +488,12 @@ class HomeAccessory(Accessory):
|
|||
self.hass.bus.async_fire(EVENT_HOMEKIT_CHANGED, event_data)
|
||||
await self.hass.services.async_call(domain, service, service_data)
|
||||
|
||||
@ha_callback
|
||||
def async_stop(self):
|
||||
"""Cancel any subscriptions when the bridge is stopped."""
|
||||
while self._subscriptions:
|
||||
self._subscriptions.pop(0)()
|
||||
|
||||
|
||||
class HomeBridge(Bridge):
|
||||
"""Adapter class for Bridge."""
|
||||
|
|
|
@ -45,6 +45,7 @@ from homeassistant.const import (
|
|||
STATE_UNAVAILABLE,
|
||||
__version__,
|
||||
)
|
||||
from homeassistant.helpers.event import TRACK_STATE_CHANGE_CALLBACKS
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.async_mock import Mock, patch
|
||||
|
@ -83,6 +84,22 @@ async def test_debounce(hass):
|
|||
assert counter == 2
|
||||
|
||||
|
||||
async def test_accessory_cancels_track_state_change_on_stop(hass, hk_driver):
|
||||
"""Ensure homekit state changed listeners are unsubscribed on reload."""
|
||||
entity_id = "sensor.accessory"
|
||||
hass.states.async_set(entity_id, None)
|
||||
acc = HomeAccessory(
|
||||
hass, hk_driver, "Home Accessory", entity_id, 2, {"platform": "isy994"}
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
):
|
||||
await acc.run_handler()
|
||||
assert len(hass.data[TRACK_STATE_CHANGE_CALLBACKS][entity_id]) == 1
|
||||
acc.async_stop()
|
||||
assert entity_id not in hass.data[TRACK_STATE_CHANGE_CALLBACKS]
|
||||
|
||||
|
||||
async def test_home_accessory(hass, hk_driver):
|
||||
"""Test HomeAccessory class."""
|
||||
entity_id = "sensor.accessory"
|
||||
|
|
|
@ -605,6 +605,8 @@ async def test_homekit_stop(hass):
|
|||
entry_id=entry.entry_id,
|
||||
)
|
||||
homekit.driver = Mock()
|
||||
homekit.bridge = Mock()
|
||||
homekit.bridge.accessories = {}
|
||||
|
||||
await async_init_integration(hass)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue