added entity callbacks
This commit is contained in:
@@ -37,12 +37,23 @@ class MotionSensor:
|
|||||||
assert self.sensor_entity.exists()
|
assert self.sensor_entity.exists()
|
||||||
assert self.ref_entity.exists()
|
assert self.ref_entity.exists()
|
||||||
|
|
||||||
base_kwargs = dict(
|
self.ref_entity.listen_state(self.light_state_callback, immediate=True)
|
||||||
entity_id=self.ref_entity_id,
|
self.match_new_state(new=self.sensor_entity.get_state())
|
||||||
immediate=True, # avoids needing to sync the state
|
self.logger.info('Initialized motion sensor')
|
||||||
)
|
|
||||||
self.ref_entity.listen_state(self.callback_light_on, attribute='all', **base_kwargs)
|
def entity_callbacks(self, entity_id: str | None = None) -> dict[str, dict]:
|
||||||
self.ref_entity.listen_state(self.callback_light_off, new='off', **base_kwargs)
|
callbacks = self.adapi.get_callback_entries()
|
||||||
|
if self.adapi.name in callbacks:
|
||||||
|
return {
|
||||||
|
handle: cb
|
||||||
|
for handle, cb in callbacks[self.adapi.name].items()
|
||||||
|
if cb.get('entity') == entity_id
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def sensor_callbacks(self) -> dict[str, dict]:
|
||||||
|
return self.entity_callbacks(entity_id=self.sensor_entity_id)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sensor_entity(self) -> Entity:
|
def sensor_entity(self) -> Entity:
|
||||||
@@ -64,47 +75,50 @@ class MotionSensor:
|
|||||||
def state_mismatch(self) -> bool:
|
def state_mismatch(self) -> bool:
|
||||||
return self.sensor_state != self.ref_state
|
return self.sensor_state != self.ref_state
|
||||||
|
|
||||||
def callback_light_on(self, entity: str, attribute: str, old: str, new: str, **kwargs: dict):
|
def light_state_callback(self, entity: str, attribute: str, old: str, new: str, **kwargs: dict):
|
||||||
"""Called when the light turns on"""
|
for handle in self.sensor_callbacks():
|
||||||
if new['state'] == 'on':
|
self.adapi.cancel_listen_state(handle)
|
||||||
self.logger.debug(f'Detected {entity} turning on')
|
self.match_new_state(new)
|
||||||
|
|
||||||
|
def match_new_state(self, new: Literal['on', 'off']):
|
||||||
|
match new:
|
||||||
|
case 'on':
|
||||||
duration = self.adapi.off_duration()
|
duration = self.adapi.off_duration()
|
||||||
self.listen_motion_off(duration)
|
self.listen_motion_off(duration)
|
||||||
|
case 'off':
|
||||||
def callback_light_off(self, entity: str, attribute: str, old: str, new: str, **kwargs: dict):
|
|
||||||
"""Called when the light turns off"""
|
|
||||||
self.logger.debug(f'Detected {entity} turning off')
|
|
||||||
self.listen_motion_on()
|
self.listen_motion_on()
|
||||||
|
|
||||||
def listen_motion_on(self):
|
def listen_motion_on(self):
|
||||||
"""Sets up the motion on callback to activate the room"""
|
"""Sets up the motion on callback to activate the room"""
|
||||||
# self.cancel_motion_callback()
|
# self.cancel_motion_callback()
|
||||||
self.adapi.listen_state(
|
self.sensor_entity.listen_state(
|
||||||
lambda *args, **kwargs: self.adapi.activate_all_off(cause='motion on'),
|
lambda *args, **kwargs: self.adapi.activate_all_off(cause='motion on'),
|
||||||
entity_id=self.sensor_entity_id,
|
|
||||||
new='on',
|
new='on',
|
||||||
oneshot=True,
|
oneshot=True,
|
||||||
)
|
)
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
f'Waiting for sensor motion on [friendly_name]{self.sensor_entity.friendly_name}[/]'
|
'Waiting for sensor motion on '
|
||||||
|
f'[friendly_name]{self.sensor_entity.friendly_name}[/]'
|
||||||
)
|
)
|
||||||
if self.sensor_state:
|
if self.sensor_state:
|
||||||
self.logger.warning(
|
self.logger.warning(
|
||||||
f'Sensor [friendly_name]{self.sensor_entity.friendly_name}[/] is already on',
|
'Sensor '
|
||||||
|
f'[friendly_name]{self.sensor_entity.friendly_name}[/] is already on',
|
||||||
)
|
)
|
||||||
|
|
||||||
def listen_motion_off(self, duration: timedelta):
|
def listen_motion_off(self, duration: timedelta):
|
||||||
"""Sets up the motion off callback to deactivate the room"""
|
"""Sets up the motion off callback to deactivate the room"""
|
||||||
# self.cancel_motion_callback()
|
# self.cancel_motion_callback()
|
||||||
self.adapi.listen_state(
|
self.sensor_entity.listen_state(
|
||||||
lambda *args, **kwargs: self.adapi.deactivate(cause='motion off'),
|
lambda *args, **kwargs: self.adapi.deactivate(cause='motion off'),
|
||||||
entity_id=self.sensor_entity_id,
|
|
||||||
new='off',
|
new='off',
|
||||||
duration=duration.total_seconds(),
|
duration=duration.total_seconds(),
|
||||||
oneshot=True,
|
oneshot=True,
|
||||||
)
|
)
|
||||||
self.logger.debug(
|
self.logger.debug(
|
||||||
f'Waiting for sensor [friendly_name]{self.sensor_entity.friendly_name}[/] to be clear for {duration}'
|
'Waiting for sensor '
|
||||||
|
f'[friendly_name]{self.sensor_entity.friendly_name}[/] '
|
||||||
|
f'to be clear for {duration}'
|
||||||
)
|
)
|
||||||
|
|
||||||
if not self.sensor_state:
|
if not self.sensor_state:
|
||||||
|
|||||||
Reference in New Issue
Block a user