mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Switch homekit to use async_track_state_change_event (#37253)
* Switch homekit to use async_track_state_change_event Calling async_track_state_change_event directly is faster than async_track_state_change and has slightly lower latency triggering state updates in homekit * check for deleted entities * Update additional tests for linked sensor removals * Ensure removing entities does not result in an exception
This commit is contained in:
parent
9b77e16ffc
commit
711b8e10a3
@ -33,7 +33,7 @@ from homeassistant.const import (
|
|||||||
)
|
)
|
||||||
from homeassistant.core import callback as ha_callback, split_entity_id
|
from homeassistant.core import callback as ha_callback, split_entity_id
|
||||||
from homeassistant.helpers.event import (
|
from homeassistant.helpers.event import (
|
||||||
async_track_state_change,
|
async_track_state_change_event,
|
||||||
track_point_in_utc_time,
|
track_point_in_utc_time,
|
||||||
)
|
)
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
@ -346,10 +346,10 @@ class HomeAccessory(Accessory):
|
|||||||
Run inside the Home Assistant event loop.
|
Run inside the Home Assistant event loop.
|
||||||
"""
|
"""
|
||||||
state = self.hass.states.get(self.entity_id)
|
state = self.hass.states.get(self.entity_id)
|
||||||
self.async_update_state_callback(None, None, state)
|
self.async_update_state_callback(state)
|
||||||
self._subscriptions.append(
|
self._subscriptions.append(
|
||||||
async_track_state_change(
|
async_track_state_change_event(
|
||||||
self.hass, self.entity_id, self.async_update_state_callback
|
self.hass, [self.entity_id], self.async_update_event_state_callback
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -364,36 +364,37 @@ class HomeAccessory(Accessory):
|
|||||||
ATTR_BATTERY_CHARGING
|
ATTR_BATTERY_CHARGING
|
||||||
)
|
)
|
||||||
self._subscriptions.append(
|
self._subscriptions.append(
|
||||||
async_track_state_change(
|
async_track_state_change_event(
|
||||||
self.hass,
|
self.hass,
|
||||||
self.linked_battery_sensor,
|
[self.linked_battery_sensor],
|
||||||
self.async_update_linked_battery_callback,
|
self.async_update_linked_battery_callback,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
elif state is not None:
|
||||||
battery_state = state.attributes.get(ATTR_BATTERY_LEVEL)
|
battery_state = state.attributes.get(ATTR_BATTERY_LEVEL)
|
||||||
if self.linked_battery_charging_sensor:
|
if self.linked_battery_charging_sensor:
|
||||||
battery_charging_state = (
|
state = self.hass.states.get(self.linked_battery_charging_sensor)
|
||||||
self.hass.states.get(self.linked_battery_charging_sensor).state
|
battery_charging_state = state and state.state == STATE_ON
|
||||||
== STATE_ON
|
|
||||||
)
|
|
||||||
self._subscriptions.append(
|
self._subscriptions.append(
|
||||||
async_track_state_change(
|
async_track_state_change_event(
|
||||||
self.hass,
|
self.hass,
|
||||||
self.linked_battery_charging_sensor,
|
[self.linked_battery_charging_sensor],
|
||||||
self.async_update_linked_battery_charging_callback,
|
self.async_update_linked_battery_charging_callback,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif battery_charging_state is None:
|
elif battery_charging_state is None and state is not None:
|
||||||
battery_charging_state = state.attributes.get(ATTR_BATTERY_CHARGING)
|
battery_charging_state = state.attributes.get(ATTR_BATTERY_CHARGING)
|
||||||
|
|
||||||
if battery_state is not None or battery_charging_state is not None:
|
if battery_state is not None or battery_charging_state is not None:
|
||||||
self.async_update_battery(battery_state, battery_charging_state)
|
self.async_update_battery(battery_state, battery_charging_state)
|
||||||
|
|
||||||
@ha_callback
|
@ha_callback
|
||||||
def async_update_state_callback(
|
def async_update_event_state_callback(self, event):
|
||||||
self, entity_id=None, old_state=None, new_state=None
|
"""Handle state change event listener callback."""
|
||||||
):
|
self.async_update_state_callback(event.data.get("new_state"))
|
||||||
|
|
||||||
|
@ha_callback
|
||||||
|
def async_update_state_callback(self, new_state):
|
||||||
"""Handle state change listener callback."""
|
"""Handle state change listener callback."""
|
||||||
_LOGGER.debug("New_state: %s", new_state)
|
_LOGGER.debug("New_state: %s", new_state)
|
||||||
if new_state is None:
|
if new_state is None:
|
||||||
@ -415,10 +416,11 @@ class HomeAccessory(Accessory):
|
|||||||
self.async_update_state(new_state)
|
self.async_update_state(new_state)
|
||||||
|
|
||||||
@ha_callback
|
@ha_callback
|
||||||
def async_update_linked_battery_callback(
|
def async_update_linked_battery_callback(self, event):
|
||||||
self, entity_id=None, old_state=None, new_state=None
|
|
||||||
):
|
|
||||||
"""Handle linked battery sensor state change listener callback."""
|
"""Handle linked battery sensor state change listener callback."""
|
||||||
|
new_state = event.data.get("new_state")
|
||||||
|
if new_state is None:
|
||||||
|
return
|
||||||
if self.linked_battery_charging_sensor:
|
if self.linked_battery_charging_sensor:
|
||||||
battery_charging_state = None
|
battery_charging_state = None
|
||||||
else:
|
else:
|
||||||
@ -426,10 +428,11 @@ class HomeAccessory(Accessory):
|
|||||||
self.async_update_battery(new_state.state, battery_charging_state)
|
self.async_update_battery(new_state.state, battery_charging_state)
|
||||||
|
|
||||||
@ha_callback
|
@ha_callback
|
||||||
def async_update_linked_battery_charging_callback(
|
def async_update_linked_battery_charging_callback(self, event):
|
||||||
self, entity_id=None, old_state=None, new_state=None
|
|
||||||
):
|
|
||||||
"""Handle linked battery charging sensor state change listener callback."""
|
"""Handle linked battery charging sensor state change listener callback."""
|
||||||
|
new_state = event.data.get("new_state")
|
||||||
|
if new_state is None:
|
||||||
|
return
|
||||||
self.async_update_battery(None, new_state.state == STATE_ON)
|
self.async_update_battery(None, new_state.state == STATE_ON)
|
||||||
|
|
||||||
@ha_callback
|
@ha_callback
|
||||||
|
@ -207,6 +207,7 @@ async def test_battery_service(hass, hk_driver, caplog):
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
mock_async_update_state.assert_called_with(state)
|
mock_async_update_state.assert_called_with(state)
|
||||||
|
|
||||||
assert acc._char_battery.value == 15
|
assert acc._char_battery.value == 15
|
||||||
assert acc._char_low_battery.value == 1
|
assert acc._char_low_battery.value == 1
|
||||||
assert acc._char_charging.value == 2
|
assert acc._char_charging.value == 2
|
||||||
@ -218,6 +219,7 @@ async def test_battery_service(hass, hk_driver, caplog):
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
mock_async_update_state.assert_called_with(state)
|
mock_async_update_state.assert_called_with(state)
|
||||||
|
|
||||||
assert acc._char_battery.value == 15
|
assert acc._char_battery.value == 15
|
||||||
assert acc._char_low_battery.value == 1
|
assert acc._char_low_battery.value == 1
|
||||||
assert acc._char_charging.value == 2
|
assert acc._char_charging.value == 2
|
||||||
@ -341,7 +343,12 @@ async def test_linked_battery_sensor(hass, hk_driver, caplog):
|
|||||||
|
|
||||||
hass.states.async_set(linked_battery, 100, {ATTR_BATTERY_CHARGING: False})
|
hass.states.async_set(linked_battery, 100, {ATTR_BATTERY_CHARGING: False})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get(entity_id)
|
assert acc._char_battery.value == 100
|
||||||
|
assert acc._char_low_battery.value == 0
|
||||||
|
assert acc._char_charging.value == 0
|
||||||
|
|
||||||
|
hass.states.async_remove(linked_battery)
|
||||||
|
await hass.async_block_till_done()
|
||||||
assert acc._char_battery.value == 100
|
assert acc._char_battery.value == 100
|
||||||
assert acc._char_low_battery.value == 0
|
assert acc._char_low_battery.value == 0
|
||||||
assert acc._char_charging.value == 0
|
assert acc._char_charging.value == 0
|
||||||
@ -396,6 +403,14 @@ async def test_linked_battery_charging_sensor(hass, hk_driver, caplog):
|
|||||||
mock_async_update_state.assert_called_with(state)
|
mock_async_update_state.assert_called_with(state)
|
||||||
assert acc._char_charging.value == 1
|
assert acc._char_charging.value == 1
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||||
|
) as mock_async_update_state:
|
||||||
|
hass.states.async_remove(linked_battery_charging_sensor)
|
||||||
|
await acc.run_handler()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert acc._char_charging.value == 1
|
||||||
|
|
||||||
|
|
||||||
async def test_linked_battery_sensor_and_linked_battery_charging_sensor(
|
async def test_linked_battery_sensor_and_linked_battery_charging_sensor(
|
||||||
hass, hk_driver, caplog
|
hass, hk_driver, caplog
|
||||||
@ -439,6 +454,12 @@ async def test_linked_battery_sensor_and_linked_battery_charging_sensor(
|
|||||||
assert acc._char_low_battery.value == 0
|
assert acc._char_low_battery.value == 0
|
||||||
assert acc._char_charging.value == 0
|
assert acc._char_charging.value == 0
|
||||||
|
|
||||||
|
hass.states.async_remove(linked_battery_charging_sensor)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert acc._char_battery.value == 50
|
||||||
|
assert acc._char_low_battery.value == 0
|
||||||
|
assert acc._char_charging.value == 0
|
||||||
|
|
||||||
|
|
||||||
async def test_missing_linked_battery_charging_sensor(hass, hk_driver, caplog):
|
async def test_missing_linked_battery_charging_sensor(hass, hk_driver, caplog):
|
||||||
"""Test battery service with linked_battery_charging_sensor that is mapping to a missing entity."""
|
"""Test battery service with linked_battery_charging_sensor that is mapping to a missing entity."""
|
||||||
@ -457,6 +478,24 @@ async def test_missing_linked_battery_charging_sensor(hass, hk_driver, caplog):
|
|||||||
)
|
)
|
||||||
assert acc.linked_battery_charging_sensor is None
|
assert acc.linked_battery_charging_sensor is None
|
||||||
|
|
||||||
|
# Make sure we don't throw if the linked_battery_charging_sensor
|
||||||
|
# is removed
|
||||||
|
hass.states.async_remove(linked_battery_charging_sensor)
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||||
|
):
|
||||||
|
await acc.run_handler()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Make sure we don't throw if the entity_id
|
||||||
|
# is removed
|
||||||
|
hass.states.async_remove(entity_id)
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||||
|
):
|
||||||
|
await acc.run_handler()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
async def test_missing_linked_battery_sensor(hass, hk_driver, caplog):
|
async def test_missing_linked_battery_sensor(hass, hk_driver, caplog):
|
||||||
"""Test battery service with missing linked_battery_sensor."""
|
"""Test battery service with missing linked_battery_sensor."""
|
||||||
@ -488,6 +527,18 @@ async def test_missing_linked_battery_sensor(hass, hk_driver, caplog):
|
|||||||
assert acc._char_low_battery is None
|
assert acc._char_low_battery is None
|
||||||
assert acc._char_charging is None
|
assert acc._char_charging is None
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||||
|
) as mock_async_update_state:
|
||||||
|
hass.states.async_remove(entity_id)
|
||||||
|
await acc.run_handler()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert not acc.linked_battery_sensor
|
||||||
|
assert acc._char_battery is None
|
||||||
|
assert acc._char_low_battery is None
|
||||||
|
assert acc._char_charging is None
|
||||||
|
|
||||||
|
|
||||||
async def test_battery_appears_after_startup(hass, hk_driver, caplog):
|
async def test_battery_appears_after_startup(hass, hk_driver, caplog):
|
||||||
"""Test battery level appears after homekit is started."""
|
"""Test battery level appears after homekit is started."""
|
||||||
@ -514,6 +565,13 @@ async def test_battery_appears_after_startup(hass, hk_driver, caplog):
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert acc._char_battery is None
|
assert acc._char_battery is None
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||||
|
):
|
||||||
|
hass.states.async_remove(entity_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert acc._char_battery is None
|
||||||
|
|
||||||
|
|
||||||
async def test_call_service(hass, hk_driver, events):
|
async def test_call_service(hass, hk_driver, events):
|
||||||
"""Test call_service method."""
|
"""Test call_service method."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user