from enum import Enum from typing import Any from appdaemon.adapi import ADAPI from appdaemon.adbase import ADBase class MoesButtons(int, Enum): TOP_LEFT = 1 TOP_RIGHT = 2 BOTTOM_LEFT = 3 BOTTOM_RIGHT = 4 class MoesActions(str, Enum): SINGLE_PRESS = 'single' DOUBLE_PRESS = 'double' LONG_PRESS = 'hold' class MoesBridge(ADBase): """Class for an app that listens for state changes generated by 4 button Moes Pads and makes the events more sensible with enums.""" adapi: ADAPI def initialize(self): self.adapi = self.get_ad_api() self.log = self.adapi.log self.event_handle = self.adapi.listen_state(self.handle_state_change) def handle_state_change(self, entity: str, attribute: str, old: Any, new: Any, **kwargs: Any) -> None: if new == '' or not new[0].isdigit(): return domain, ent = entity.split('.', 1) if domain == 'sensor' and ent.startswith('moes'): button, action = new.split('_') button = MoesButtons(int(button)) button_str = button.name.lower().replace('_', ' ') action = MoesActions(action) self.log(f'Moes Pad action detected: {action.value} on button {button_str}') self.adapi.fire_event( 'moes_pad', device=entity, button=button, action=action, ) class MoesPad(ADBase): """Specfic implementation of a Moes Pad.""" def initialize(self): self.adapi = self.get_ad_api() self.log = self.adapi.log self.event_handle = self.adapi.listen_event(self.handle_moes_event, 'moes_pad') self.bedroom_offs = ('bedroom_stick', 'bedroom_john', 'bedroom_sydney') self.main_offs = ('bar', 'server_lamp', 'living_room_stick') # self.set_many(self.main_offs, state='on') def handle_moes_event(self, event_name: str, data: dict[str, Any], **kwargs: Any) -> None: button = MoesButtons(data.get('button')) action = MoesActions(data.get('action')) self.log(f'Received Moes Pad event: {action} on button {button}') match action: case MoesActions.SINGLE_PRESS: self.handle_single_press(button) case MoesActions.DOUBLE_PRESS: self.handle_double_press(button) def handle_single_press(self, button: MoesButtons) -> None: match button: case MoesButtons.TOP_LEFT: self.adapi.call_service('light/toggle', entity_id='light.bedroom_sydney') case MoesButtons.TOP_RIGHT: self.adapi.call_service('light/toggle', entity_id='light.bedroom_john') case MoesButtons.BOTTOM_LEFT: self.adapi.call_service('light/toggle', entity_id='light.bedroom_stick') case MoesButtons.BOTTOM_RIGHT: any_on = any(self.adapi.get_state(f'light.{e}') == 'on' for e in self.bedroom_offs) scene = {'entities': {f'light.{e}': {'state': 'off' if any_on else 'on'}} for e in self.bedroom_offs} self.adapi.call_service('scene/apply', **scene) def handle_double_press(self, button: MoesButtons) -> None: match button: case MoesButtons.BOTTOM_RIGHT: all_lights = [*self.bedroom_offs, *self.main_offs] any_on = self.check_many(all_lights, state='on') new_state = 'off' if any_on else 'on' self.log(f'New state from double press: {new_state}') self.set_many(self.bedroom_offs, state=new_state) self.set_many(self.main_offs, state=new_state) def set_many(self, lights: set[str], state: str = 'off'): entity_ids = [f'light.{e}' if not e.startswith('light') else e for e in lights] scene = {'entities': {eid: {'state': state} for eid in entity_ids}} return self.adapi.call_service('scene/apply', **scene) def check_many(self, lights: set[str], state: str = 'off') -> bool: entity_ids = [f'light.{e}' if not e.startswith('light') else e for e in lights] return any(self.adapi.get_state(eid) == state for eid in entity_ids)