improved scene detect

This commit is contained in:
John Lancaster
2024-06-11 23:03:59 -05:00
parent 5b56c29999
commit bc175f75d9
6 changed files with 74 additions and 48 deletions

3
.gitignore vendored
View File

@@ -7,4 +7,5 @@ secrets.yaml
*.ipynb *.ipynb
logs/ logs/
*.json

View File

@@ -1,7 +1,3 @@
hello_world:
module: hello_world
class: HelloWorld
rich_logging: rich_logging:
module: console module: console
global: true global: true

View File

@@ -1,29 +0,0 @@
from datetime import datetime
from appdaemon.plugins.hass.hassapi import Hass
class HelloWorld(Hass):
def initialize(self):
self.log('Hello World')
now: datetime = self.get_now()
eid = self.args['eid']
self.log(eid)
self.listen_state(self.my_callback, eid)
self.set_state(eid, state=now.isoformat(), attributes=dict(name='Test Fade Start'))
self.log(f'Set state to {now.time()}')
def my_callback(self, entity, attribute, old, new, kwargs):
new = self.convert_time(new)
old = self.convert_time(old)
self.log(f'{attribute} {old} -> {new}')
def convert_time(self, time_str: str) -> datetime:
dt = datetime.fromisoformat(time_str)
try:
dt = self.AD.tz.localize(dt)
except ValueError:
dt = dt.astimezone(self.AD.tz)
finally:
return dt

49
apps/hello_world/hello.py Normal file
View File

@@ -0,0 +1,49 @@
import asyncio
import json
from appdaemon.adapi import ADAPI
from appdaemon.plugins.hass.hassapi import Hass
class HelloWorld(Hass):
def initialize(self):
self.log('Hello World')
# self.listen_state(
# callback=self.temp_callback,
# entity_id='sensor.temperature_nest',
# attribute='state',
# threshold=65.0,
# )
# self.listen_state(
# callback=self.temp_callback,
# entity_id='light.living_room',
# attribute='state',
# threshold=65.0,
# )
async def temp_callback(self, entity, attribute, old, new, kwargs):
self.log('Temp callback')
temp = await self.get_state('sensor.temperature_nest')
# self.log(json.dumps(temp, indent=4))
self.AD.loop.create_task(self.unreliable_call())
if float(temp) <= kwargs['threshold']:
self.log(f'{entity} is below the threshold')
self.AD.loop.create_task(self.unreliable_call())
self.log('Doing some other, more reliable stuff')
await asyncio.sleep(2.0)
self.log(f'{entity} done')
async def unreliable_call(self):
self.log('Calling unreliable cloud service....')
await asyncio.sleep(5.0)
# await self.call_service('climate/set_temperature', entity_id='climate.living_room', temperature=70)
self.log('Cloud service returned')
def entities_ending_with(self, ending_str: str):
entities = [
entity_id
for entity_id, state in self.get_state().items()
if entity_id.endswith(ending_str)
]
return entities

View File

@@ -0,0 +1,3 @@
HelloWorld:
module: hello
class: HelloWorld

View File

@@ -1,4 +1,8 @@
import json
import re
from appdaemon.plugins.hass.hassapi import Hass from appdaemon.plugins.hass.hassapi import Hass
from room_control import Motion
class SceneDetector(Hass): class SceneDetector(Hass):
@@ -15,25 +19,27 @@ class SceneDetector(Hass):
) )
self.log(f'Waiting for {self.scene_entity.friendly_name} to activate') self.log(f'Waiting for {self.scene_entity.friendly_name} to activate')
def event_callback(self, event_name, data, cb_args): async def event_callback(self, event_name, data, cb_args):
entity_id = data['service_data']['entity_id'] entity_id = data['service_data']['entity_id']
if entity_id == self.scene_entity.entity_id: if entity_id == self.scene_entity.entity_id:
self.scene_detected() await self.scene_detected()
def scene_detected(self): async def scene_detected(self):
self.log(f'Detected scene activation: {self.scene_entity.friendly_name}') self.log(f'Detected scene activation: {self.scene_entity.friendly_name}')
class MotionCanceller(SceneDetector): class MotionCanceller(SceneDetector):
def scene_detected(self): async def scene_detected(self):
super().scene_detected() await super().scene_detected()
app = self.get_app(self.args['app']) app: Motion = await self.get_app(self.args['app'])
try: all_callbacks = await self.get_callback_entries()
self.run_in(callback=lambda *args, **kwargs: app.cancel_motion_callback(), delay=0.5) app_callbacks = all_callbacks[app.name]
except Exception:
self.log( for handle, info in app_callbacks.items():
f'Error cancelling motion callback for {self.args["app"]}', if info['entity'] == app.sensor.entity_id and 'new=off' in info['kwargs']:
level='ERROR', self.log(f'Cancelling motion callback for {app.name}')
) await self.AD.state.cancel_state_callback(handle, app.name)
# self.log(json.dumps(info, indent=4))
break
else: else:
self.log('Cancelled motion callback') self.log('Did not cancel anything', level='WARNING')