Resolve homekit not updating motion sensors (#34282)
Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io>pull/34319/head
parent
97609576cb
commit
b87b618c94
|
@ -60,16 +60,16 @@ from .util import convert_to_float, density_to_air_quality, temperature_to_homek
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
BINARY_SENSOR_SERVICE_MAP = {
|
||||
DEVICE_CLASS_CO2: (SERV_CARBON_DIOXIDE_SENSOR, CHAR_CARBON_DIOXIDE_DETECTED),
|
||||
DEVICE_CLASS_DOOR: (SERV_CONTACT_SENSOR, CHAR_CONTACT_SENSOR_STATE),
|
||||
DEVICE_CLASS_GARAGE_DOOR: (SERV_CONTACT_SENSOR, CHAR_CONTACT_SENSOR_STATE),
|
||||
DEVICE_CLASS_GAS: (SERV_CARBON_MONOXIDE_SENSOR, CHAR_CARBON_MONOXIDE_DETECTED),
|
||||
DEVICE_CLASS_MOISTURE: (SERV_LEAK_SENSOR, CHAR_LEAK_DETECTED),
|
||||
DEVICE_CLASS_MOTION: (SERV_MOTION_SENSOR, CHAR_MOTION_DETECTED),
|
||||
DEVICE_CLASS_OCCUPANCY: (SERV_OCCUPANCY_SENSOR, CHAR_OCCUPANCY_DETECTED),
|
||||
DEVICE_CLASS_OPENING: (SERV_CONTACT_SENSOR, CHAR_CONTACT_SENSOR_STATE),
|
||||
DEVICE_CLASS_SMOKE: (SERV_SMOKE_SENSOR, CHAR_SMOKE_DETECTED),
|
||||
DEVICE_CLASS_WINDOW: (SERV_CONTACT_SENSOR, CHAR_CONTACT_SENSOR_STATE),
|
||||
DEVICE_CLASS_CO2: (SERV_CARBON_DIOXIDE_SENSOR, CHAR_CARBON_DIOXIDE_DETECTED, int),
|
||||
DEVICE_CLASS_DOOR: (SERV_CONTACT_SENSOR, CHAR_CONTACT_SENSOR_STATE, int),
|
||||
DEVICE_CLASS_GARAGE_DOOR: (SERV_CONTACT_SENSOR, CHAR_CONTACT_SENSOR_STATE, int),
|
||||
DEVICE_CLASS_GAS: (SERV_CARBON_MONOXIDE_SENSOR, CHAR_CARBON_MONOXIDE_DETECTED, int),
|
||||
DEVICE_CLASS_MOISTURE: (SERV_LEAK_SENSOR, CHAR_LEAK_DETECTED, int),
|
||||
DEVICE_CLASS_MOTION: (SERV_MOTION_SENSOR, CHAR_MOTION_DETECTED, bool),
|
||||
DEVICE_CLASS_OCCUPANCY: (SERV_OCCUPANCY_SENSOR, CHAR_OCCUPANCY_DETECTED, int),
|
||||
DEVICE_CLASS_OPENING: (SERV_CONTACT_SENSOR, CHAR_CONTACT_SENSOR_STATE, int),
|
||||
DEVICE_CLASS_SMOKE: (SERV_SMOKE_SENSOR, CHAR_SMOKE_DETECTED, int),
|
||||
DEVICE_CLASS_WINDOW: (SERV_CONTACT_SENSOR, CHAR_CONTACT_SENSOR_STATE, int),
|
||||
}
|
||||
|
||||
|
||||
|
@ -274,8 +274,12 @@ class BinarySensor(HomeAccessory):
|
|||
else BINARY_SENSOR_SERVICE_MAP[DEVICE_CLASS_OCCUPANCY]
|
||||
)
|
||||
|
||||
self.format = service_char[2]
|
||||
service = self.add_preload_service(service_char[0])
|
||||
self.char_detected = service.configure_char(service_char[1], value=0)
|
||||
initial_value = False if self.format is bool else 0
|
||||
self.char_detected = service.configure_char(
|
||||
service_char[1], value=initial_value
|
||||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
|
@ -283,7 +287,7 @@ class BinarySensor(HomeAccessory):
|
|||
def update_state(self, new_state):
|
||||
"""Update accessory after state change."""
|
||||
state = new_state.state
|
||||
detected = state in (STATE_ON, STATE_HOME)
|
||||
detected = self.format(state in (STATE_ON, STATE_HOME))
|
||||
if self.char_detected.value != detected:
|
||||
self.char_detected.set_value(detected)
|
||||
_LOGGER.debug("%s: Set to %d", self.entity_id, detected)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Test different accessory types: Sensors."""
|
||||
from homeassistant.components.homekit import get_accessory
|
||||
from homeassistant.components.homekit.const import (
|
||||
DEVICE_CLASS_MOTION,
|
||||
PROP_CELSIUS,
|
||||
THRESHOLD_CO,
|
||||
THRESHOLD_CO2,
|
||||
|
@ -256,11 +257,55 @@ async def test_binary(hass, hk_driver):
|
|||
assert acc.char_detected.value == 0
|
||||
|
||||
|
||||
async def test_motion_uses_bool(hass, hk_driver):
|
||||
"""Test if accessory is updated after state change."""
|
||||
entity_id = "binary_sensor.motion"
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_UNKNOWN, {ATTR_DEVICE_CLASS: DEVICE_CLASS_MOTION}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
acc = BinarySensor(hass, hk_driver, "Motion Sensor", entity_id, 2, None)
|
||||
await acc.run_handler()
|
||||
|
||||
assert acc.aid == 2
|
||||
assert acc.category == 10 # Sensor
|
||||
|
||||
assert acc.char_detected.value is False
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_DEVICE_CLASS: DEVICE_CLASS_MOTION})
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_detected.value is True
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_OFF, {ATTR_DEVICE_CLASS: DEVICE_CLASS_MOTION}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_detected.value is False
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_HOME, {ATTR_DEVICE_CLASS: DEVICE_CLASS_MOTION}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_detected.value is True
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_NOT_HOME, {ATTR_DEVICE_CLASS: DEVICE_CLASS_MOTION}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_detected.value is False
|
||||
|
||||
hass.states.async_remove(entity_id)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_detected.value is False
|
||||
|
||||
|
||||
async def test_binary_device_classes(hass, hk_driver):
|
||||
"""Test if services and characteristics are assigned correctly."""
|
||||
entity_id = "binary_sensor.demo"
|
||||
|
||||
for device_class, (service, char) in BINARY_SENSOR_SERVICE_MAP.items():
|
||||
for device_class, (service, char, _) in BINARY_SENSOR_SERVICE_MAP.items():
|
||||
hass.states.async_set(entity_id, STATE_OFF, {ATTR_DEVICE_CLASS: device_class})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
|
Loading…
Reference in New Issue