Reduce context switching in homekit state updates (#35147)
parent
2e018ad841
commit
742e36ba26
|
@ -313,7 +313,7 @@ class HomeAccessory(Accessory):
|
|||
Run inside the Home Assistant event loop.
|
||||
"""
|
||||
state = self.hass.states.get(self.entity_id)
|
||||
await self.async_update_state_callback(None, None, state)
|
||||
self.async_update_state_callback(None, None, state)
|
||||
async_track_state_change(
|
||||
self.hass, self.entity_id, self.async_update_state_callback
|
||||
)
|
||||
|
@ -329,7 +329,9 @@ class HomeAccessory(Accessory):
|
|||
ATTR_BATTERY_CHARGING
|
||||
)
|
||||
async_track_state_change(
|
||||
self.hass, self.linked_battery_sensor, self.async_update_linked_battery
|
||||
self.hass,
|
||||
self.linked_battery_sensor,
|
||||
self.async_update_linked_battery_callback,
|
||||
)
|
||||
else:
|
||||
battery_state = state.attributes.get(ATTR_BATTERY_LEVEL)
|
||||
|
@ -341,17 +343,16 @@ class HomeAccessory(Accessory):
|
|||
async_track_state_change(
|
||||
self.hass,
|
||||
self.linked_battery_charging_sensor,
|
||||
self.async_update_linked_battery_charging,
|
||||
self.async_update_linked_battery_charging_callback,
|
||||
)
|
||||
elif battery_charging_state is None:
|
||||
battery_charging_state = state.attributes.get(ATTR_BATTERY_CHARGING)
|
||||
|
||||
if battery_state is not None or battery_charging_state is not None:
|
||||
self.hass.async_add_executor_job(
|
||||
self.update_battery, battery_state, battery_charging_state
|
||||
)
|
||||
self.async_update_battery(battery_state, battery_charging_state)
|
||||
|
||||
async def async_update_state_callback(
|
||||
@ha_callback
|
||||
def async_update_state_callback(
|
||||
self, entity_id=None, old_state=None, new_state=None
|
||||
):
|
||||
"""Handle state change listener callback."""
|
||||
|
@ -371,12 +372,11 @@ class HomeAccessory(Accessory):
|
|||
):
|
||||
battery_charging_state = new_state.attributes.get(ATTR_BATTERY_CHARGING)
|
||||
if battery_state is not None or battery_charging_state is not None:
|
||||
await self.hass.async_add_executor_job(
|
||||
self.update_battery, battery_state, battery_charging_state
|
||||
)
|
||||
await self.hass.async_add_executor_job(self.update_state, new_state)
|
||||
self.async_update_battery(battery_state, battery_charging_state)
|
||||
self.async_update_state(new_state)
|
||||
|
||||
async def async_update_linked_battery(
|
||||
@ha_callback
|
||||
def async_update_linked_battery_callback(
|
||||
self, entity_id=None, old_state=None, new_state=None
|
||||
):
|
||||
"""Handle linked battery sensor state change listener callback."""
|
||||
|
@ -384,19 +384,17 @@ class HomeAccessory(Accessory):
|
|||
battery_charging_state = None
|
||||
else:
|
||||
battery_charging_state = new_state.attributes.get(ATTR_BATTERY_CHARGING)
|
||||
await self.hass.async_add_executor_job(
|
||||
self.update_battery, new_state.state, battery_charging_state,
|
||||
)
|
||||
self.async_update_battery(new_state.state, battery_charging_state)
|
||||
|
||||
async def async_update_linked_battery_charging(
|
||||
@ha_callback
|
||||
def async_update_linked_battery_charging_callback(
|
||||
self, entity_id=None, old_state=None, new_state=None
|
||||
):
|
||||
"""Handle linked battery charging sensor state change listener callback."""
|
||||
await self.hass.async_add_executor_job(
|
||||
self.update_battery, None, new_state.state == STATE_ON
|
||||
)
|
||||
self.async_update_battery(None, new_state.state == STATE_ON)
|
||||
|
||||
def update_battery(self, battery_level, battery_charging):
|
||||
@ha_callback
|
||||
def async_update_battery(self, battery_level, battery_charging):
|
||||
"""Update battery service if available.
|
||||
|
||||
Only call this function if self._support_battery_level is True.
|
||||
|
@ -427,7 +425,8 @@ class HomeAccessory(Accessory):
|
|||
"%s: Updated battery charging to %d", self.entity_id, hk_charging
|
||||
)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@ha_callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Handle state change to update HomeKit value.
|
||||
|
||||
Overridden by accessory types.
|
||||
|
|
|
@ -12,6 +12,7 @@ from pyhap.const import CATEGORY_CAMERA
|
|||
|
||||
from homeassistant.components.camera.const import DOMAIN as DOMAIN_CAMERA
|
||||
from homeassistant.components.ffmpeg import DATA_FFMPEG
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.util import get_local_ip
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
|
@ -144,7 +145,8 @@ class Camera(HomeAccessory, PyhapCamera):
|
|||
options=options,
|
||||
)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Handle state change to update HomeKit value."""
|
||||
pass # pylint: disable=unnecessary-pass
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ from homeassistant.const import (
|
|||
STATE_OPEN,
|
||||
STATE_OPENING,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .accessories import TYPES, HomeAccessory, debounce
|
||||
from .const import (
|
||||
|
@ -92,7 +93,7 @@ class GarageDoorOpener(HomeAccessory):
|
|||
self.char_target_state = serv_garage_door.configure_char(
|
||||
CHAR_TARGET_DOOR_STATE, value=0, setter_callback=self.set_state
|
||||
)
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def set_state(self, value):
|
||||
"""Change garage state if call came from HomeKit."""
|
||||
|
@ -108,7 +109,8 @@ class GarageDoorOpener(HomeAccessory):
|
|||
self.char_current_state.set_value(HK_DOOR_CLOSING)
|
||||
self.call_service(DOMAIN, SERVICE_CLOSE_COVER, params)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update cover state after state changed."""
|
||||
hass_state = new_state.state
|
||||
target_door_state = DOOR_TARGET_HASS_TO_HK.get(hass_state)
|
||||
|
@ -184,7 +186,8 @@ class WindowCoveringBase(HomeAccessory):
|
|||
|
||||
self.call_service(DOMAIN, SERVICE_SET_COVER_TILT_POSITION, params, value)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update cover position and tilt after state changed."""
|
||||
# update tilt
|
||||
current_tilt = new_state.attributes.get(ATTR_CURRENT_TILT_POSITION)
|
||||
|
@ -230,7 +233,7 @@ class WindowCovering(WindowCoveringBase, HomeAccessory):
|
|||
self.char_position_state = self.serv_cover.configure_char(
|
||||
CHAR_POSITION_STATE, value=HK_POSITION_STOPPED
|
||||
)
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
@debounce
|
||||
def move_cover(self, value):
|
||||
|
@ -241,7 +244,8 @@ class WindowCovering(WindowCoveringBase, HomeAccessory):
|
|||
params = {ATTR_ENTITY_ID: self.entity_id, ATTR_POSITION: value}
|
||||
self.call_service(DOMAIN, SERVICE_SET_COVER_POSITION, params, value)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update cover position and tilt after state changed."""
|
||||
current_position = new_state.attributes.get(ATTR_CURRENT_POSITION)
|
||||
if isinstance(current_position, (float, int)):
|
||||
|
@ -271,7 +275,7 @@ class WindowCovering(WindowCoveringBase, HomeAccessory):
|
|||
if self.char_position_state.value != HK_POSITION_STOPPED:
|
||||
self.char_position_state.set_value(HK_POSITION_STOPPED)
|
||||
|
||||
super().update_state(new_state)
|
||||
super().async_update_state(new_state)
|
||||
|
||||
|
||||
@TYPES.register("WindowCoveringBasic")
|
||||
|
@ -295,7 +299,7 @@ class WindowCoveringBasic(WindowCoveringBase, HomeAccessory):
|
|||
self.char_position_state = self.serv_cover.configure_char(
|
||||
CHAR_POSITION_STATE, value=HK_POSITION_STOPPED
|
||||
)
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
@debounce
|
||||
def move_cover(self, value):
|
||||
|
@ -322,7 +326,8 @@ class WindowCoveringBasic(WindowCoveringBase, HomeAccessory):
|
|||
self.char_current_position.set_value(position)
|
||||
self.char_target_position.set_value(position)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update cover position after state changed."""
|
||||
position_mapping = {STATE_OPEN: 100, STATE_CLOSED: 0}
|
||||
hk_position = position_mapping.get(new_state.state)
|
||||
|
@ -341,4 +346,4 @@ class WindowCoveringBasic(WindowCoveringBase, HomeAccessory):
|
|||
if self.char_position_state.value != HK_POSITION_STOPPED:
|
||||
self.char_position_state.set_value(HK_POSITION_STOPPED)
|
||||
|
||||
super().update_state(new_state)
|
||||
super().async_update_state(new_state)
|
||||
|
|
|
@ -26,6 +26,7 @@ from homeassistant.const import (
|
|||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
from .const import (
|
||||
|
@ -80,13 +81,13 @@ class Fan(HomeAccessory):
|
|||
|
||||
if CHAR_ROTATION_SPEED in chars:
|
||||
# Initial value is set to 100 because 0 is a special value (off). 100 is
|
||||
# an arbitrary non-zero value. It is updated immediately by update_state
|
||||
# an arbitrary non-zero value. It is updated immediately by async_update_state
|
||||
# to set to the correct initial value.
|
||||
self.char_speed = serv_fan.configure_char(CHAR_ROTATION_SPEED, value=100)
|
||||
|
||||
if CHAR_SWING_MODE in chars:
|
||||
self.char_swing = serv_fan.configure_char(CHAR_SWING_MODE, value=0)
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
serv_fan.setter_callback = self._set_chars
|
||||
|
||||
def _set_chars(self, char_values):
|
||||
|
@ -146,7 +147,8 @@ class Fan(HomeAccessory):
|
|||
params = {ATTR_ENTITY_ID: self.entity_id, ATTR_SPEED: speed}
|
||||
self.call_service(DOMAIN, SERVICE_SET_SPEED, params, speed)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update fan after state change."""
|
||||
# Handle State
|
||||
state = new_state.state
|
||||
|
|
|
@ -23,6 +23,7 @@ from homeassistant.const import (
|
|||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
from .const import (
|
||||
|
@ -77,7 +78,7 @@ class Light(HomeAccessory):
|
|||
|
||||
if CHAR_BRIGHTNESS in self.chars:
|
||||
# Initial value is set to 100 because 0 is a special value (off). 100 is
|
||||
# an arbitrary non-zero value. It is updated immediately by update_state
|
||||
# an arbitrary non-zero value. It is updated immediately by async_update_state
|
||||
# to set to the correct initial value.
|
||||
self.char_brightness = serv_light.configure_char(CHAR_BRIGHTNESS, value=100)
|
||||
|
||||
|
@ -100,7 +101,7 @@ class Light(HomeAccessory):
|
|||
if CHAR_SATURATION in self.chars:
|
||||
self.char_saturation = serv_light.configure_char(CHAR_SATURATION, value=75)
|
||||
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
serv_light.setter_callback = self._set_chars
|
||||
|
||||
|
@ -138,7 +139,8 @@ class Light(HomeAccessory):
|
|||
|
||||
self.call_service(DOMAIN, service, params, ", ".join(events))
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update light after state change."""
|
||||
# Handle State
|
||||
state = new_state.state
|
||||
|
|
|
@ -5,6 +5,7 @@ from pyhap.const import CATEGORY_DOOR_LOCK
|
|||
|
||||
from homeassistant.components.lock import DOMAIN, STATE_LOCKED, STATE_UNLOCKED
|
||||
from homeassistant.const import ATTR_CODE, ATTR_ENTITY_ID, STATE_UNKNOWN
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
from .const import CHAR_LOCK_CURRENT_STATE, CHAR_LOCK_TARGET_STATE, SERV_LOCK
|
||||
|
@ -45,7 +46,7 @@ class Lock(HomeAccessory):
|
|||
value=HASS_TO_HOMEKIT[STATE_LOCKED],
|
||||
setter_callback=self.set_state,
|
||||
)
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def set_state(self, value):
|
||||
"""Set lock state to value if call came from HomeKit."""
|
||||
|
@ -62,7 +63,8 @@ class Lock(HomeAccessory):
|
|||
params[ATTR_CODE] = self._code
|
||||
self.call_service(DOMAIN, service, params)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update lock after state changed."""
|
||||
hass_state = new_state.state
|
||||
if hass_state in HASS_TO_HOMEKIT:
|
||||
|
|
|
@ -36,6 +36,7 @@ from homeassistant.const import (
|
|||
STATE_STANDBY,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
from .const import (
|
||||
|
@ -150,7 +151,7 @@ class MediaPlayer(HomeAccessory):
|
|||
self.chars[FEATURE_TOGGLE_MUTE] = serv_toggle_mute.configure_char(
|
||||
CHAR_ON, value=False, setter_callback=self.set_toggle_mute
|
||||
)
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def generate_service_name(self, mode):
|
||||
"""Generate name for individual service."""
|
||||
|
@ -189,7 +190,8 @@ class MediaPlayer(HomeAccessory):
|
|||
params = {ATTR_ENTITY_ID: self.entity_id, ATTR_MEDIA_VOLUME_MUTED: value}
|
||||
self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update switch state after state changed."""
|
||||
current_state = new_state.state
|
||||
|
||||
|
@ -321,7 +323,7 @@ class TelevisionMediaPlayer(HomeAccessory):
|
|||
serv_input.configure_char(CHAR_CURRENT_VISIBILITY_STATE, value=False)
|
||||
_LOGGER.debug("%s: Added source %s.", self.entity_id, source)
|
||||
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def set_on_off(self, value):
|
||||
"""Move switch state to value if call came from HomeKit."""
|
||||
|
@ -375,7 +377,8 @@ class TelevisionMediaPlayer(HomeAccessory):
|
|||
params = {ATTR_ENTITY_ID: self.entity_id}
|
||||
self.call_service(DOMAIN, service, params)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update Television state after state changed."""
|
||||
current_state = new_state.state
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ from homeassistant.const import (
|
|||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
from .const import (
|
||||
|
@ -64,7 +65,7 @@ class SecuritySystem(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def set_security_state(self, value):
|
||||
"""Move security state to value if call came from HomeKit."""
|
||||
|
@ -77,7 +78,8 @@ class SecuritySystem(HomeAccessory):
|
|||
params[ATTR_CODE] = self._alarm_code
|
||||
self.call_service(DOMAIN, service, params)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update security state after state changed."""
|
||||
hass_state = new_state.state
|
||||
if hass_state in HASS_TO_HOMEKIT:
|
||||
|
|
|
@ -10,6 +10,7 @@ from homeassistant.const import (
|
|||
STATE_ON,
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
from .const import (
|
||||
|
@ -89,9 +90,10 @@ class TemperatureSensor(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update temperature after state changed."""
|
||||
unit = new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS)
|
||||
temperature = convert_to_float(new_state.state)
|
||||
|
@ -118,9 +120,10 @@ class HumiditySensor(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update accessory after state change."""
|
||||
humidity = convert_to_float(new_state.state)
|
||||
if humidity and self.char_humidity.value != humidity:
|
||||
|
@ -145,9 +148,10 @@ class AirQualitySensor(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update accessory after state change."""
|
||||
density = convert_to_float(new_state.state)
|
||||
if density:
|
||||
|
@ -181,9 +185,10 @@ class CarbonMonoxideSensor(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update accessory after state change."""
|
||||
value = convert_to_float(new_state.state)
|
||||
if value:
|
||||
|
@ -218,9 +223,10 @@ class CarbonDioxideSensor(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update accessory after state change."""
|
||||
value = convert_to_float(new_state.state)
|
||||
if value:
|
||||
|
@ -248,9 +254,10 @@ class LightSensor(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update accessory after state change."""
|
||||
luminance = convert_to_float(new_state.state)
|
||||
if luminance and self.char_light.value != luminance:
|
||||
|
@ -281,9 +288,10 @@ class BinarySensor(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update accessory after state change."""
|
||||
state = new_state.state
|
||||
detected = self.format(state in (STATE_ON, STATE_HOME))
|
||||
|
|
|
@ -24,7 +24,7 @@ from homeassistant.const import (
|
|||
SERVICE_TURN_ON,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import split_entity_id
|
||||
from homeassistant.core import callback, split_entity_id
|
||||
from homeassistant.helpers.event import call_later
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
|
@ -71,7 +71,7 @@ class Outlet(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def set_state(self, value):
|
||||
"""Move switch state to value if call came from HomeKit."""
|
||||
|
@ -80,7 +80,8 @@ class Outlet(HomeAccessory):
|
|||
service = SERVICE_TURN_ON if value else SERVICE_TURN_OFF
|
||||
self.call_service(DOMAIN, service, params)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update switch state after state changed."""
|
||||
current_state = new_state.state == STATE_ON
|
||||
if self.char_on.value is not current_state:
|
||||
|
@ -106,7 +107,7 @@ class Switch(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def is_activate(self, state):
|
||||
"""Check if entity is activate only."""
|
||||
|
@ -136,7 +137,8 @@ class Switch(HomeAccessory):
|
|||
if self.activate_only:
|
||||
call_later(self.hass, 1, self.reset_switch)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update switch state after state changed."""
|
||||
self.activate_only = self.is_activate(new_state)
|
||||
if self.activate_only:
|
||||
|
@ -162,7 +164,8 @@ class DockVacuum(Switch):
|
|||
service = SERVICE_START if value else SERVICE_RETURN_TO_BASE
|
||||
self.call_service(VACUUM_DOMAIN, service, params)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update switch state after state changed."""
|
||||
current_state = new_state.state in (STATE_CLEANING, STATE_ON)
|
||||
if self.char_on.value is not current_state:
|
||||
|
@ -191,7 +194,7 @@ class Valve(HomeAccessory):
|
|||
)
|
||||
# Set the state so it is in sync on initial
|
||||
# GET to avoid an event storm after homekit startup
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def set_state(self, value):
|
||||
"""Move value state to value if call came from HomeKit."""
|
||||
|
@ -201,7 +204,8 @@ class Valve(HomeAccessory):
|
|||
service = SERVICE_TURN_ON if value else SERVICE_TURN_OFF
|
||||
self.call_service(DOMAIN, service, params)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update switch state after state changed."""
|
||||
current_state = 1 if new_state.state == STATE_ON else 0
|
||||
if self.char_active.value != current_state:
|
||||
|
|
|
@ -51,6 +51,7 @@ from homeassistant.const import (
|
|||
TEMP_FAHRENHEIT,
|
||||
UNIT_PERCENTAGE,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
from .const import (
|
||||
|
@ -220,7 +221,7 @@ class Thermostat(HomeAccessory):
|
|||
CHAR_CURRENT_HUMIDITY, value=50
|
||||
)
|
||||
|
||||
self._update_state(state)
|
||||
self._async_update_state(state)
|
||||
|
||||
serv_thermostat.setter_callback = self._set_chars
|
||||
|
||||
|
@ -391,7 +392,8 @@ class Thermostat(HomeAccessory):
|
|||
DOMAIN_CLIMATE, SERVICE_SET_HUMIDITY, params, f"{value}{UNIT_PERCENTAGE}"
|
||||
)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update thermostat state after state changed."""
|
||||
if self._state_updates < 3:
|
||||
# When we get the first state updates
|
||||
|
@ -414,9 +416,10 @@ class Thermostat(HomeAccessory):
|
|||
)
|
||||
self._state_updates += 1
|
||||
|
||||
self._update_state(new_state)
|
||||
self._async_update_state(new_state)
|
||||
|
||||
def _update_state(self, new_state):
|
||||
@callback
|
||||
def _async_update_state(self, new_state):
|
||||
"""Update state without rechecking the device features."""
|
||||
features = new_state.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||
|
||||
|
@ -544,7 +547,7 @@ class WaterHeater(HomeAccessory):
|
|||
)
|
||||
|
||||
state = self.hass.states.get(self.entity_id)
|
||||
self.update_state(state)
|
||||
self.async_update_state(state)
|
||||
|
||||
def get_temperature_range(self):
|
||||
"""Return min and max temperature range."""
|
||||
|
@ -586,7 +589,8 @@ class WaterHeater(HomeAccessory):
|
|||
f"{temperature}{self._unit}",
|
||||
)
|
||||
|
||||
def update_state(self, new_state):
|
||||
@callback
|
||||
def async_update_state(self, new_state):
|
||||
"""Update water_heater state after state change."""
|
||||
# Update current and target temperature
|
||||
temperature = new_state.attributes.get(ATTR_TEMPERATURE)
|
||||
|
|
|
@ -100,19 +100,19 @@ async def test_home_accessory(hass, hk_driver):
|
|||
hass.states.async_set(entity_id, "on")
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.update_state"
|
||||
) as mock_update_state:
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_update_state.assert_called_with(state)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
|
||||
hass.states.async_remove(entity_id)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_update_state.call_count == 1
|
||||
assert mock_async_update_state.call_count == 1
|
||||
|
||||
with pytest.raises(NotImplementedError):
|
||||
acc.update_state("new_state")
|
||||
acc.async_update_state("new_state")
|
||||
|
||||
# Test model name from domain
|
||||
entity_id = "test_model.demo"
|
||||
|
@ -130,52 +130,82 @@ async def test_battery_service(hass, hk_driver, caplog):
|
|||
await hass.async_block_till_done()
|
||||
|
||||
acc = HomeAccessory(hass, hk_driver, "Battery Service", entity_id, 2, None)
|
||||
acc.update_state = lambda x: None
|
||||
assert acc._char_battery.value == 0
|
||||
assert acc._char_low_battery.value == 0
|
||||
assert acc._char_charging.value == 2
|
||||
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
|
||||
assert acc._char_battery.value == 50
|
||||
assert acc._char_low_battery.value == 0
|
||||
assert acc._char_charging.value == 2
|
||||
|
||||
hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_battery.value == 15
|
||||
assert acc._char_low_battery.value == 1
|
||||
assert acc._char_charging.value == 2
|
||||
|
||||
hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: "error"})
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: "error"})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_battery.value == 15
|
||||
assert acc._char_low_battery.value == 1
|
||||
assert acc._char_charging.value == 2
|
||||
assert "ERROR" not in caplog.text
|
||||
|
||||
# Test charging
|
||||
hass.states.async_set(
|
||||
entity_id, None, {ATTR_BATTERY_LEVEL: 10, ATTR_BATTERY_CHARGING: True}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
hass.states.async_set(
|
||||
entity_id, None, {ATTR_BATTERY_LEVEL: 10, ATTR_BATTERY_CHARGING: True}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
|
||||
acc = HomeAccessory(hass, hk_driver, "Battery Service", entity_id, 2, None)
|
||||
acc.update_state = lambda x: None
|
||||
assert acc._char_battery.value == 0
|
||||
assert acc._char_low_battery.value == 0
|
||||
assert acc._char_charging.value == 2
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
):
|
||||
acc = HomeAccessory(hass, hk_driver, "Battery Service", entity_id, 2, None)
|
||||
assert acc._char_battery.value == 0
|
||||
assert acc._char_low_battery.value == 0
|
||||
assert acc._char_charging.value == 2
|
||||
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_battery.value == 10
|
||||
assert acc._char_low_battery.value == 1
|
||||
assert acc._char_charging.value == 1
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id, None, {ATTR_BATTERY_LEVEL: 100, ATTR_BATTERY_CHARGING: False}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
):
|
||||
hass.states.async_set(
|
||||
entity_id, None, {ATTR_BATTERY_LEVEL: 100, ATTR_BATTERY_CHARGING: False}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc._char_battery.value == 100
|
||||
assert acc._char_low_battery.value == 0
|
||||
assert acc._char_charging.value == 0
|
||||
|
@ -197,11 +227,15 @@ async def test_linked_battery_sensor(hass, hk_driver, caplog):
|
|||
2,
|
||||
{CONF_LINKED_BATTERY_SENSOR: linked_battery},
|
||||
)
|
||||
acc.update_state = lambda x: None
|
||||
assert acc.linked_battery_sensor == linked_battery
|
||||
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_battery.value == 50
|
||||
assert acc._char_low_battery.value == 0
|
||||
assert acc._char_charging.value == 2
|
||||
|
@ -212,13 +246,19 @@ async def test_linked_battery_sensor(hass, hk_driver, caplog):
|
|||
assert acc._char_low_battery.value == 1
|
||||
|
||||
# Ignore battery change on entity if it has linked_battery
|
||||
hass.states.async_set(entity_id, "open", {ATTR_BATTERY_LEVEL: 90})
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
):
|
||||
hass.states.async_set(entity_id, "open", {ATTR_BATTERY_LEVEL: 90})
|
||||
await hass.async_block_till_done()
|
||||
assert acc._char_battery.value == 10
|
||||
|
||||
# Test none numeric state for linked_battery
|
||||
hass.states.async_set(linked_battery, "error", None)
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
):
|
||||
hass.states.async_set(linked_battery, "error", None)
|
||||
await hass.async_block_till_done()
|
||||
assert acc._char_battery.value == 10
|
||||
assert "ERROR" not in caplog.text
|
||||
|
||||
|
@ -234,15 +274,20 @@ async def test_linked_battery_sensor(hass, hk_driver, caplog):
|
|||
2,
|
||||
{CONF_LINKED_BATTERY_SENSOR: linked_battery, CONF_LOW_BATTERY_THRESHOLD: 50},
|
||||
)
|
||||
acc.update_state = lambda x: None
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_battery.value == 20
|
||||
assert acc._char_low_battery.value == 1
|
||||
assert acc._char_charging.value == 1
|
||||
|
||||
hass.states.async_set(linked_battery, 100, {ATTR_BATTERY_CHARGING: False})
|
||||
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
|
||||
|
@ -264,23 +309,37 @@ async def test_linked_battery_charging_sensor(hass, hk_driver, caplog):
|
|||
2,
|
||||
{CONF_LINKED_BATTERY_CHARGING_SENSOR: linked_battery_charging_sensor},
|
||||
)
|
||||
acc.update_state = lambda x: None
|
||||
assert acc.linked_battery_charging_sensor == linked_battery_charging_sensor
|
||||
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_battery.value == 100
|
||||
assert acc._char_low_battery.value == 0
|
||||
assert acc._char_charging.value == 1
|
||||
|
||||
hass.states.async_set(linked_battery_charging_sensor, STATE_OFF, None)
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
hass.states.async_set(linked_battery_charging_sensor, STATE_OFF, None)
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_charging.value == 0
|
||||
|
||||
hass.states.async_set(linked_battery_charging_sensor, STATE_ON, None)
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
hass.states.async_set(linked_battery_charging_sensor, STATE_ON, None)
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_charging.value == 1
|
||||
|
||||
|
||||
|
@ -307,11 +366,15 @@ async def test_linked_battery_sensor_and_linked_battery_charging_sensor(
|
|||
CONF_LINKED_BATTERY_CHARGING_SENSOR: linked_battery_charging_sensor,
|
||||
},
|
||||
)
|
||||
acc.update_state = lambda x: None
|
||||
assert acc.linked_battery_sensor == linked_battery
|
||||
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_battery.value == 50
|
||||
assert acc._char_low_battery.value == 0
|
||||
assert acc._char_charging.value == 1
|
||||
|
@ -356,11 +419,15 @@ async def test_missing_linked_battery_sensor(hass, hk_driver, caplog):
|
|||
2,
|
||||
{CONF_LINKED_BATTERY_SENSOR: linked_battery},
|
||||
)
|
||||
acc.update_state = lambda x: None
|
||||
assert not acc.linked_battery_sensor
|
||||
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
|
||||
assert not acc.linked_battery_sensor
|
||||
assert acc._char_battery is None
|
||||
|
@ -377,15 +444,22 @@ async def test_battery_appears_after_startup(hass, hk_driver, caplog):
|
|||
acc = HomeAccessory(
|
||||
hass, hk_driver, "Accessory without battery", entity_id, 2, None
|
||||
)
|
||||
acc.update_state = lambda x: None
|
||||
assert acc._char_battery is None
|
||||
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
) as mock_async_update_state:
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
mock_async_update_state.assert_called_with(state)
|
||||
assert acc._char_battery is None
|
||||
|
||||
hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
|
||||
):
|
||||
hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
|
||||
await hass.async_block_till_done()
|
||||
assert acc._char_battery is None
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,27 @@ MOCK_END_POINTS_TLV = "ARAzA9UDF8xGmrZykkNqcaL2AgEAAxoBAQACDTE5Mi4xNjguMjA4LjUDA
|
|||
MOCK_START_STREAM_SESSION_UUID = UUID("3303d503-17cc-469a-b672-92436a71a2f6")
|
||||
|
||||
|
||||
async def _async_start_streaming(hass, acc):
|
||||
"""Start streaming a camera."""
|
||||
acc.set_selected_stream_configuration(MOCK_START_STREAM_TLV)
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def _async_setup_endpoints(hass, acc):
|
||||
"""Set camera endpoints."""
|
||||
acc.set_endpoints(MOCK_END_POINTS_TLV)
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def _async_stop_stream(hass, acc):
|
||||
"""Stop a camera stream."""
|
||||
await acc.stop()
|
||||
await acc.run_handler()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def run_driver(hass):
|
||||
"""Return a custom AccessoryDriver instance for HomeKit accessory init."""
|
||||
|
@ -92,9 +113,9 @@ async def test_camera_stream_source_configured(hass, run_driver, events):
|
|||
assert acc.aid == 2
|
||||
assert acc.category == 17 # Camera
|
||||
|
||||
acc.set_endpoints(MOCK_END_POINTS_TLV)
|
||||
session_info = acc.sessions[MOCK_START_STREAM_SESSION_UUID]
|
||||
await _async_setup_endpoints(hass, acc)
|
||||
working_ffmpeg = _get_working_mock_ffmpeg()
|
||||
session_info = acc.sessions[MOCK_START_STREAM_SESSION_UUID]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.demo.camera.DemoCamera.stream_source",
|
||||
|
@ -103,8 +124,8 @@ async def test_camera_stream_source_configured(hass, run_driver, events):
|
|||
"homeassistant.components.homekit.type_cameras.HAFFmpeg",
|
||||
return_value=working_ffmpeg,
|
||||
):
|
||||
acc.set_selected_stream_configuration(MOCK_START_STREAM_TLV)
|
||||
await hass.async_block_till_done()
|
||||
await _async_start_streaming(hass, acc)
|
||||
await _async_stop_stream(hass, acc)
|
||||
|
||||
expected_output = (
|
||||
"-map 0:v:0 -an -c:v libx264 -profile:v high -tune zerolatency -pix_fmt "
|
||||
|
@ -132,11 +153,10 @@ async def test_camera_stream_source_configured(hass, run_driver, events):
|
|||
"homeassistant.components.homekit.type_cameras.HAFFmpeg",
|
||||
return_value=working_ffmpeg,
|
||||
):
|
||||
acc.set_selected_stream_configuration(MOCK_START_STREAM_TLV)
|
||||
await acc.stop_stream(session_info)
|
||||
await _async_start_streaming(hass, acc)
|
||||
await _async_stop_stream(hass, acc)
|
||||
# Calling a second time should not throw
|
||||
await acc.stop_stream(session_info)
|
||||
await hass.async_block_till_done()
|
||||
await _async_stop_stream(hass, acc)
|
||||
|
||||
turbo_jpeg = mock_turbo_jpeg(
|
||||
first_width=16, first_height=12, second_width=300, second_height=200
|
||||
|
@ -195,8 +215,7 @@ async def test_camera_stream_source_configured_with_failing_ffmpeg(
|
|||
assert acc.aid == 2
|
||||
assert acc.category == 17 # Camera
|
||||
|
||||
acc.set_endpoints(MOCK_END_POINTS_TLV)
|
||||
session_info = acc.sessions[MOCK_START_STREAM_SESSION_UUID]
|
||||
await _async_setup_endpoints(hass, acc)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.demo.camera.DemoCamera.stream_source",
|
||||
|
@ -205,11 +224,10 @@ async def test_camera_stream_source_configured_with_failing_ffmpeg(
|
|||
"homeassistant.components.homekit.type_cameras.HAFFmpeg",
|
||||
return_value=_get_failing_mock_ffmpeg(),
|
||||
):
|
||||
acc.set_selected_stream_configuration(MOCK_START_STREAM_TLV)
|
||||
await acc.stop_stream(session_info)
|
||||
await _async_start_streaming(hass, acc)
|
||||
await _async_stop_stream(hass, acc)
|
||||
# Calling a second time should not throw
|
||||
await acc.stop_stream(session_info)
|
||||
await hass.async_block_till_done()
|
||||
await _async_stop_stream(hass, acc)
|
||||
|
||||
|
||||
async def test_camera_stream_source_found(hass, run_driver, events):
|
||||
|
@ -229,8 +247,7 @@ async def test_camera_stream_source_found(hass, run_driver, events):
|
|||
assert acc.aid == 2
|
||||
assert acc.category == 17 # Camera
|
||||
|
||||
acc.set_endpoints(MOCK_END_POINTS_TLV)
|
||||
session_info = acc.sessions[MOCK_START_STREAM_SESSION_UUID]
|
||||
await _async_setup_endpoints(hass, acc)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.demo.camera.DemoCamera.stream_source",
|
||||
|
@ -239,9 +256,8 @@ async def test_camera_stream_source_found(hass, run_driver, events):
|
|||
"homeassistant.components.homekit.type_cameras.HAFFmpeg",
|
||||
return_value=_get_working_mock_ffmpeg(),
|
||||
):
|
||||
acc.set_selected_stream_configuration(MOCK_START_STREAM_TLV)
|
||||
await acc.stop_stream(session_info)
|
||||
await hass.async_block_till_done()
|
||||
await _async_start_streaming(hass, acc)
|
||||
await _async_stop_stream(hass, acc)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.demo.camera.DemoCamera.stream_source",
|
||||
|
@ -250,9 +266,8 @@ async def test_camera_stream_source_found(hass, run_driver, events):
|
|||
"homeassistant.components.homekit.type_cameras.HAFFmpeg",
|
||||
return_value=_get_working_mock_ffmpeg(),
|
||||
):
|
||||
acc.set_selected_stream_configuration(MOCK_START_STREAM_TLV)
|
||||
await acc.stop_stream(session_info)
|
||||
await hass.async_block_till_done()
|
||||
await _async_start_streaming(hass, acc)
|
||||
await _async_stop_stream(hass, acc)
|
||||
|
||||
|
||||
async def test_camera_stream_source_fails(hass, run_driver, events):
|
||||
|
@ -272,8 +287,7 @@ async def test_camera_stream_source_fails(hass, run_driver, events):
|
|||
assert acc.aid == 2
|
||||
assert acc.category == 17 # Camera
|
||||
|
||||
acc.set_endpoints(MOCK_END_POINTS_TLV)
|
||||
session_info = acc.sessions[MOCK_START_STREAM_SESSION_UUID]
|
||||
await _async_setup_endpoints(hass, acc)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.demo.camera.DemoCamera.stream_source",
|
||||
|
@ -282,9 +296,8 @@ async def test_camera_stream_source_fails(hass, run_driver, events):
|
|||
"homeassistant.components.homekit.type_cameras.HAFFmpeg",
|
||||
return_value=_get_working_mock_ffmpeg(),
|
||||
):
|
||||
acc.set_selected_stream_configuration(MOCK_START_STREAM_TLV)
|
||||
await acc.stop_stream(session_info)
|
||||
await hass.async_block_till_done()
|
||||
await _async_start_streaming(hass, acc)
|
||||
await _async_stop_stream(hass, acc)
|
||||
|
||||
|
||||
async def test_camera_with_no_stream(hass, run_driver, events):
|
||||
|
@ -302,9 +315,9 @@ async def test_camera_with_no_stream(hass, run_driver, events):
|
|||
assert acc.aid == 2
|
||||
assert acc.category == 17 # Camera
|
||||
|
||||
acc.set_endpoints(MOCK_END_POINTS_TLV)
|
||||
acc.set_selected_stream_configuration(MOCK_START_STREAM_TLV)
|
||||
await hass.async_block_till_done()
|
||||
await _async_setup_endpoints(hass, acc)
|
||||
await _async_start_streaming(hass, acc)
|
||||
await _async_stop_stream(hass, acc)
|
||||
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.async_add_executor_job(
|
||||
|
@ -344,7 +357,7 @@ async def test_camera_stream_source_configured_and_copy_codec(hass, run_driver,
|
|||
assert acc.aid == 2
|
||||
assert acc.category == 17 # Camera
|
||||
|
||||
acc.set_endpoints(MOCK_END_POINTS_TLV)
|
||||
await _async_setup_endpoints(hass, acc)
|
||||
session_info = acc.sessions[MOCK_START_STREAM_SESSION_UUID]
|
||||
|
||||
working_ffmpeg = _get_working_mock_ffmpeg()
|
||||
|
@ -356,9 +369,8 @@ async def test_camera_stream_source_configured_and_copy_codec(hass, run_driver,
|
|||
"homeassistant.components.homekit.type_cameras.HAFFmpeg",
|
||||
return_value=working_ffmpeg,
|
||||
):
|
||||
acc.set_selected_stream_configuration(MOCK_START_STREAM_TLV)
|
||||
await acc.stop_stream(session_info)
|
||||
await hass.async_block_till_done()
|
||||
await _async_start_streaming(hass, acc)
|
||||
await _async_stop_stream(hass, acc)
|
||||
|
||||
expected_output = (
|
||||
"-map 0:v:0 -an -c:v copy -tune zerolatency -pix_fmt yuv420p -r 30 -b:v 299k "
|
||||
|
|
Loading…
Reference in New Issue