diff --git a/apps/sleep.py b/apps/sleep.py index 9783508..dc7c02e 100755 --- a/apps/sleep.py +++ b/apps/sleep.py @@ -1,26 +1,26 @@ from appdaemon.entity import Entity -from appdaemon.plugins.hass import hassapi as hass +from appdaemon.plugins.hass.hassapi import Hass +from appdaemon.plugins.mqtt.mqttapi import Mqtt +import json - -class SleepSetter(hass.Hass): +class SleepSetter(Hass, Mqtt): def initialize(self): assert self.entity_exists(entity_id=self.variable), f'{self.variable} does not exist' + self.variable_entity.listen_state(callback=self.handle_state) if isinstance(self.button, list): for button in self.button: - self.listen_event(self.handle_button, event='deconz_event', id=button) + self.setup_button(button) else: - self.listen_event(self.handle_button, event='deconz_event', id=self.button) - - self.variable_entity.listen_state(callback=self.handle_state) + self.setup_button(button) self.log(f'{self.variable} can be set using {self.button}, currently {self.state}') - def handle_state(self, entity, attribute, old, new, kwargs): - self.log(f'{entity}: {old} -> {new}') - if self.state and self.sun_elevation < float(self.args['elevation_limit']): - self.all_off() - self.turn_on(self.scene) + def setup_button(self, name: str): + topic = f'zigbee2mqtt/{name}' + self.mqtt_subscribe(topic, namespace='mqtt') + self.listen_event(self.handle_button, "MQTT_MESSAGE", topic=topic, namespace='mqtt', button=name) + self.log(f'Listening for sleep setting on {name}') @property def button(self) -> str: @@ -53,20 +53,57 @@ class SleepSetter(hass.Hass): @property def sun_elevation(self) -> float: - return float(self.get_state('sun.sun', 'elevation')) + try: + return float(self.get_state('sun.sun', 'elevation')) + except: + self.log(f'Failed to return sun elevation') + return + + def handle_state(self, entity, attribute, old, new, kwargs): + self.log(f'{entity}: {old} -> {new}') + if self.state and self.sun_elevation < float(self.args['elevation_limit']): + self.all_off() + try: + self.call_service('scene/turn_on', entity_id=self.scene) + except: + return + else: + self.log(f'Turned on scene: {self.scene}') + # self.turn_on(self.scene) def handle_button(self, event_name, data, kwargs): + topic = data['topic'] + # self.log(f'Button event for: {topic}') if (elev := self.sun_elevation) < 0: - # long-press down - if data['event'] == 1001: - self.state = True - - # long-press up - # if data['event'] == 1003: - # self.state = True + try: + payload = json.loads(data['payload']) + action = payload['action'] + except json.JSONDecodeError: + self.log(f'Error decoding JSON from {data["payload"]}', level='ERROR') + except KeyError as e: + return + else: + self.handle_action(action) + else: self.log(f'Ignoring event because sun elevation {elev} > 0') + def handle_action(self, action: str): + if action == '': + return + elif action == 'hold': + self.state = True + elif action == 'double': + self.state = not self.state + if (on_apps := self.args.get('on_apps', None)) is not None: + for app_name in on_apps: + try: + self.get_app(app_name).activate() + except: + return + else: + self.log(f'Activated {app_name}') + def all_off(self): self.log(f'Deactivating apps') for app_name in self.args['off_apps']: diff --git a/apps/sleep.yaml b/apps/sleep.yaml index b8572ce..57148c6 100755 --- a/apps/sleep.yaml +++ b/apps/sleep.yaml @@ -2,7 +2,7 @@ sleep: module: sleep class: SleepSetter elevation_limit: -10 - scene: in_bed + scene: scene.in_bed variable: input_boolean.sleeping button: - Bedroom Button 1 @@ -13,6 +13,10 @@ sleep: - living_room - kitchen - bathroom + - closet off_entities: - light.patio - light.closet + on_apps: + - living_room + - bedroom