Skip to content

Commit

Permalink
Fix fallback to polling HomeKit devices that fail to subscribe
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco committed Aug 25, 2024
1 parent 8bc9fd2 commit fcc10e3
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
9 changes: 4 additions & 5 deletions homeassistant/components/homekit_controller/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -849,16 +849,15 @@ async def async_update(self, now: datetime | None = None) -> None:
"""Poll state of all entities attached to this bridge/accessory."""
to_poll = self.pollable_characteristics
accessories = self.entity_map.accessories

pairing = self.pairing
if (
not self._full_update_requested
and pairing.supports_subscribe

Check failure on line 855 in homeassistant/components/homekit_controller/connection.py

View workflow job for this annotation

GitHub Actions / Check mypy

"AbstractPairing" has no attribute "supports_subscribe" [attr-defined]
and len(accessories) == 1
and self.available
and not (to_poll - self.watchable_characteristics)
and self.pairing.is_available
and await self.pairing.controller.async_reachable(
self.unique_id, timeout=5.0
)
and pairing.is_available
and await pairing.controller.async_reachable(self.unique_id, timeout=5.0)
):
# If its a single accessory and all chars are watchable,
# only poll the firmware version to keep the connection alive
Expand Down
30 changes: 30 additions & 0 deletions tests/components/homekit_controller/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,3 +439,33 @@ def _create_accessory(accessory: Accessory) -> Service:
await time_changed(hass, DEBOUNCE_COOLDOWN)
await hass.async_block_till_done()
assert len(mock_get_characteristics.call_args_list[0][0][0]) > 1


async def test_device_has_broken_subscribe(
hass: HomeAssistant, get_next_aid: Callable[[], int]
) -> None:
"""Test device that does not support subscribe."""

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)
helper.pairing.supports_subscribe = False

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 everything is polled because subscribe is not supported
assert len(mock_get_characteristics.call_args_list[0][0][0]) > 1

0 comments on commit fcc10e3

Please sign in to comment.