Skip to content

Commit

Permalink
Ensure all chars are polling when requesting manual update in homekit…
Browse files Browse the repository at this point in the history
…_controller (home-assistant#124582)

related issue home-assistant#123963
  • Loading branch information
bdraco authored and Gigatrappeur committed Aug 28, 2024
1 parent 245632f commit 0959ac6
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
7 changes: 6 additions & 1 deletion homeassistant/components/homekit_controller/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ def __init__(
self._pending_subscribes: set[tuple[int, int]] = set()
self._subscribe_timer: CALLBACK_TYPE | None = None
self._load_platforms_lock = asyncio.Lock()
self._full_update_requested: bool = False

@property
def entity_map(self) -> Accessories:
Expand Down Expand Up @@ -841,6 +842,7 @@ def async_update_available_state(self, *_: Any) -> None:

async def async_request_update(self, now: datetime | None = None) -> None:
"""Request an debounced update from the accessory."""
self._full_update_requested = True
await self._debounced_update.async_call()

async def async_update(self, now: datetime | None = None) -> None:
Expand All @@ -849,7 +851,8 @@ async def async_update(self, now: datetime | None = None) -> None:
accessories = self.entity_map.accessories

if (
len(accessories) == 1
not self._full_update_requested
and len(accessories) == 1
and self.available
and not (to_poll - self.watchable_characteristics)
and self.pairing.is_available
Expand Down Expand Up @@ -879,6 +882,8 @@ async def async_update(self, now: datetime | None = None) -> None:
firmware_iid = accessory_info[CharacteristicsTypes.FIRMWARE_REVISION].iid
to_poll = {(first_accessory.aid, firmware_iid)}

self._full_update_requested = False

if not to_poll:
self.async_update_available_state()
_LOGGER.debug(
Expand Down
40 changes: 40 additions & 0 deletions tests/components/homekit_controller/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import pytest

from homeassistant.components.homekit_controller.const import (
DEBOUNCE_COOLDOWN,
DOMAIN,
IDENTIFIER_ACCESSORY_ID,
IDENTIFIER_LEGACY_ACCESSORY_ID,
Expand All @@ -22,12 +23,14 @@
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity_component import async_update_entity

from .common import (
setup_accessories_from_file,
setup_platform,
setup_test_accessories,
setup_test_component,
time_changed,
)

from tests.common import MockConfigEntry
Expand Down Expand Up @@ -399,3 +402,40 @@ def _create_accessory(accessory: Accessory) -> Service:
state = await helper.poll_and_get_state()
assert state.state == STATE_OFF
assert mock_get_characteristics.call_count == 8


async def test_manual_poll_all_chars(
hass: HomeAssistant, get_next_aid: Callable[[], int]
) -> None:
"""Test that a manual poll will check all chars."""

def _create_accessory(accessory: Accessory) -> Service:
service = accessory.add_service(ServicesTypes.LIGHTBULB, name="TestDevice")

on_char = service.add_char(CharacteristicsTypes.ON)
on_char.value = 0

brightness = service.add_char(CharacteristicsTypes.BRIGHTNESS)
brightness.value = 0

return service

helper = await setup_test_component(hass, get_next_aid(), _create_accessory)

with mock.patch.object(
helper.pairing,
"get_characteristics",
wraps=helper.pairing.get_characteristics,
) as mock_get_characteristics:
# Initial state is that the light is off
await helper.poll_and_get_state()
# Verify only firmware version is polled
assert mock_get_characteristics.call_args_list[0][0][0] == {(1, 7)}

# Now do a manual poll to ensure all chars are polled
mock_get_characteristics.reset_mock()
await async_update_entity(hass, helper.entity_id)
await time_changed(hass, 60)
await time_changed(hass, DEBOUNCE_COOLDOWN)
await hass.async_block_till_done()
assert len(mock_get_characteristics.call_args_list[0][0][0]) > 1

0 comments on commit 0959ac6

Please sign in to comment.