Fix HomeKit handling of unavailable state (#101021)

pull/101028/head
J. Nick Koston 2023-09-27 16:34:25 -05:00 committed by GitHub
parent 6a52283ce0
commit 7d07694496
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 4 deletions

View File

@ -465,7 +465,9 @@ class HomeAccessory(Accessory): # type: ignore[misc]
def async_update_state_callback(self, new_state: State | None) -> None: def async_update_state_callback(self, new_state: State | None) -> None:
"""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: # HomeKit handles unavailable state via the available property
# so we should not propagate it here
if new_state is None or new_state.state == STATE_UNAVAILABLE:
return return
battery_state = None battery_state = None
battery_charging_state = None battery_charging_state = None

View File

@ -74,17 +74,19 @@ async def test_garage_door_open_close(hass: HomeAssistant, hk_driver, events) ->
assert acc.char_obstruction_detected.value is True assert acc.char_obstruction_detected.value is True
hass.states.async_set( hass.states.async_set(
entity_id, STATE_UNAVAILABLE, {ATTR_OBSTRUCTION_DETECTED: False} entity_id, STATE_UNAVAILABLE, {ATTR_OBSTRUCTION_DETECTED: True}
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_current_state.value == HK_DOOR_OPEN assert acc.char_current_state.value == HK_DOOR_OPEN
assert acc.char_target_state.value == HK_DOOR_OPEN assert acc.char_target_state.value == HK_DOOR_OPEN
assert acc.char_obstruction_detected.value is False assert acc.char_obstruction_detected.value is True
assert acc.available is False
hass.states.async_set(entity_id, STATE_UNKNOWN) hass.states.async_set(entity_id, STATE_UNKNOWN)
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_current_state.value == HK_DOOR_OPEN assert acc.char_current_state.value == HK_DOOR_OPEN
assert acc.char_target_state.value == HK_DOOR_OPEN assert acc.char_target_state.value == HK_DOOR_OPEN
assert acc.available is True
# Set from HomeKit # Set from HomeKit
call_close_cover = async_mock_service(hass, DOMAIN, "close_cover") call_close_cover = async_mock_service(hass, DOMAIN, "close_cover")

View File

@ -13,6 +13,7 @@ from homeassistant.const import (
ATTR_CODE, ATTR_CODE,
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
STATE_LOCKED, STATE_LOCKED,
STATE_UNAVAILABLE,
STATE_UNKNOWN, STATE_UNKNOWN,
STATE_UNLOCKED, STATE_UNLOCKED,
) )
@ -68,10 +69,32 @@ async def test_lock_unlock(hass: HomeAssistant, hk_driver, events) -> None:
assert acc.char_current_state.value == 3 assert acc.char_current_state.value == 3
assert acc.char_target_state.value == 0 assert acc.char_target_state.value == 0
hass.states.async_remove(entity_id) # Unavailable should keep last state
# but set the accessory to not available
hass.states.async_set(entity_id, STATE_UNAVAILABLE)
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_current_state.value == 3 assert acc.char_current_state.value == 3
assert acc.char_target_state.value == 0 assert acc.char_target_state.value == 0
assert acc.available is False
hass.states.async_set(entity_id, STATE_UNLOCKED)
await hass.async_block_till_done()
assert acc.char_current_state.value == 0
assert acc.char_target_state.value == 0
assert acc.available is True
# Unavailable should keep last state
# but set the accessory to not available
hass.states.async_set(entity_id, STATE_UNAVAILABLE)
await hass.async_block_till_done()
assert acc.char_current_state.value == 0
assert acc.char_target_state.value == 0
assert acc.available is False
hass.states.async_remove(entity_id)
await hass.async_block_till_done()
assert acc.char_current_state.value == 0
assert acc.char_target_state.value == 0
# Set from HomeKit # Set from HomeKit
call_lock = async_mock_service(hass, DOMAIN, "lock") call_lock = async_mock_service(hass, DOMAIN, "lock")