diff --git a/apps/apps.yaml b/apps/apps.yaml index ea7b2af..a75d050 100644 --- a/apps/apps.yaml +++ b/apps/apps.yaml @@ -43,7 +43,7 @@ my_timer: LightColorTest: module: color_test class: TapDial - entity: sensor.tapdial03_action + entity: sensor.tapdial01a_action init_brightness: 200 max_brightness: 254 step_size: 25 diff --git a/apps/color_test.py b/apps/color_test.py index 39f5617..265e65c 100644 --- a/apps/color_test.py +++ b/apps/color_test.py @@ -7,7 +7,7 @@ class TapDial(Hass): def initialize(self): self.tap_dial.listen_state(self.handle_state_change) - self.log(f'0.0 Tap Dial entity: {self.tap_dial.entity_id}') + self.log(f'010 Tap Dial entity: {self.tap_dial.entity_id}') @property def tap_dial(self) -> Entity: @@ -29,8 +29,6 @@ class TapDial(Hass): def active_entity_is_on(self) -> bool: return self.active_entity.get_state() == 'on' - # Experiment to read and write various properties to a light.... - @property def light_brightness(self) -> int: return self.active_entity.attributes['brightness'] @@ -56,47 +54,48 @@ class TapDial(Hass): return self.active_entity.turn_on(effect=val) def handle_state_change(self, entity: str, attribute: str, old: str, new: str, **kwargs): - self.log(f'0.1 {new}') + self.log(f'059 {new}') # Dial actions if new.startswith('dial_rotate') and self.active_entity_is_on: - self.log('Ignore dial_rotate commands for now...') + self.log('063 Ignore dial_rotate commands for now...') # Button actions elif new.endswith('release'): _, n, typ, _ = new.split('_', 4) # type will be either press or hold - self.log(f'2.1 Button {n} {typ}') + self.log(f'069 Button {n} {typ}') if eid := self.args.get(f'button{n}'): self.active_entity = self.get_entity(eid) - self.log(f'2.1.1 Set active entity to: {self.active_entity.name}') - + self.log(f'073 Set active entity to: {self.active_entity.name}') + self.log(json.dumps(self.active_entity.get_state('all'), indent=4)) domain, entity = eid.split('.') + self.log(f'076 domain: {domain}, entity: {entity}') match domain: case 'light': # Set the light to maximum brightness if the button is held. if typ == 'hold': - self.log('Ignore button_hold command for now...') + self.log('080 Ignore button_hold command for now...') else: if self.active_entity_is_on: - self.log(f'Current values for Brightness: {self.light_brightness}, RGB Color: {self.light_color}, Effect: {self.light_effect}') + self.log(f'083 6Current values for Brightness: {self.light_brightness}, RGB Color: {self.light_color}, Effect: {self.light_effect}') # self.log(f'New values for Color: {self.args.get(f"color{n}")} and Effect: {self.args.get(f"effect{n}")}') hex = self.args.get(f"color{n}") # self.log(f'Translate {self.args.get(f"color{n}")} to RGB {self.hex_to_rgb(hex)} ') br_val = self.args.get(f'brightness{n}') match n: case '1': # do nothing - self.log(f'Made it to case{n}') + self.log(f'090 Made it to case{n}') # self.active_entity.turn_on(brightness=br_val,rgb_color=self.hex_to_rgb(hex),transition=10) self.active_entity.turn_on(brightness=br_val,rgb_color=self.hex_to_rgb(hex)) # self.active_entity.turn_on(rgb_color=self.hex_to_rgb('FFFFFF')) # self.active_entity.turn_on(effect='candle') # self.light_color = self.hex_to_rgb(hex) # self.light_effect = self.args.get(f'effect{n}') - # self.log(json.dumps(self.active_entity.get_state('all'), indent=4)) + self.log(json.dumps(self.active_entity.get_state('all'), indent=4)) case '2': # attempt to change brightness, color - self.log(f'Made it to case{n}') + self.log(f'099 Made it to case{n}') # self.active_entity.turn_on(brightness=br_val,rgb_color=self.hex_to_rgb(hex),transition=10) self.active_entity.turn_on(brightness=br_val,rgb_color=self.hex_to_rgb(hex)) # self.active_entity.turn_on(rgb_color=self.hex_to_rgb('FFFFFF')) @@ -105,13 +104,13 @@ class TapDial(Hass): # self.light_effect = self.args.get(f'effect{n}') # self.log(json.dumps(self.active_entity.get_state('all'), indent=4)) case '3': # attempt to apply 'candle' effect - self.log(f'Made it to case{n}') + self.log(f'108 Made it to case{n}') self.active_entity.turn_on(effect='stop_hue_effect') # self.active_entity.turn_on(effect='candle') self.active_entity.set_state(effect='fireplace') # self.log(json.dumps(self.active_entity.get_state('all'), indent=4)) case '4': # json.dump - self.log(f'Made it to case{n}') + self.log(f'114 Made it to case{n}') # self.active_entity.turn_on(brightness=br_val,rgb_color=self.hex_to_rgb(hex),transition=10) # self.active_entity.turn_on(brightness=br_val,rgb_color=self.hex_to_rgb(hex)) # self.active_entity.turn_on(rgb_color=self.hex_to_rgb('FFFFFF')) @@ -121,9 +120,9 @@ class TapDial(Hass): self.log(json.dumps(self.active_entity.get_state('all'), indent=4)) else: - self.log('The light is off...') + self.log('124 The light is off...') case 'switch': - self.log('Ignore non-light entities for now...') + self.log('126 Ignore non-light entities for now...') # This function was written by chatgpt... def hex_to_rgb(self, hex_color: str) -> list: @@ -133,7 +132,7 @@ class TapDial(Hass): # Check if the string has a valid length if len(hex_color) != 6: - raise ValueError(f"Invalid hex color: {hex_color}. Must be 6 characters long.") + raise ValueError(f"136 Invalid hex color: {hex_color}. Must be 6 characters long.") try: # Split the hex color into its RGB components and convert to integers @@ -142,4 +141,4 @@ class TapDial(Hass): b = int(hex_color[4:6], 16) return [r, g, b] except ValueError: - raise ValueError(f"Invalid hex color: {hex_color}. Must contain only valid hex digits.") + raise ValueError(f"145 Invalid hex color: {hex_color}. Must contain only valid hex digits.") diff --git a/apps/tap_dial.py b/apps/tap_dial.py index d44df17..f950247 100644 --- a/apps/tap_dial.py +++ b/apps/tap_dial.py @@ -1,12 +1,12 @@ from appdaemon.entity import Entity from appdaemon.plugins.hass.hassapi import Hass +import json class TapDial(Hass): active_entity: Entity def initialize(self): self.tap_dial.listen_state(self.handle_state_change) - self.log(f'0.0 Tap Dial entity: {self.tap_dial.entity_id}') @property def tap_dial(self) -> Entity: @@ -29,16 +29,36 @@ class TapDial(Hass): return self.active_entity.get_state() == 'on' @property - def current_brightness(self) -> int: + def light_brightness(self) -> int: return self.active_entity.attributes['brightness'] + @light_brightness.setter + def light_brightness(self, val: int): + return self.active_entity.turn_on(brightness=val) + + @property + def light_color(self) -> list[int]: + return self.active_entity.get_state('rgb_color') + + @light_color.setter + def light_color(self, val: list[int]): + return self.active_entity.turn_on(rgb_color=val) + + @property + def light_effect(self) -> str: + return self.active_entity.get_state('effect') + + @light_effect.setter + def light_effect(self, val: str): + return self.active_entity.turn_on(effect=val) + def handle_state_change(self, entity: str, attribute: str, old: str, new: str, **kwargs): - self.log(f'0.1 {new}') - + self.log(f'056 State change: {new}') + # Dial actions if new.startswith('dial_rotate') and self.active_entity_is_on: _, _, dir, speed = new.split('_', 4) - self.log(f'1.1 Direction {dir} speed {speed}') + self.log(f'061 Direction {dir} speed {speed}') match speed: case 'step': rate = self.step_size @@ -47,51 +67,61 @@ class TapDial(Hass): case 'fast': rate = 3 * self.step_size val = self.active_entity.attributes['brightness'] - self.log(f'1.2 Brightness value = {val} Change rate = {rate}') + self.log(f'070 Brightness value = {val} Change rate = {rate}') if dir == 'right': - val += rate - self.active_entity.turn_on(brightness=val) - self.log(f'1.2.1 Brightness value = {val}') + if val < self.max_brightness: + if (val + rate) > self.max_brightness: + val = self.max_brightness + else: + val += rate + self.active_entity.turn_on(brightness=val) + self.log(f'078 Brightness value = {val}') else: - val -= rate - self.active_entity.turn_on(brightness=val) - self.log(f'1.2.2 Brightness value = {val}') - + if val > 0: + if (val - rate) < 0: + val = 0 + else: + val -= rate + self.active_entity.turn_on(brightness=val) + self.log(f'086 Brightness value = {val}') + # Button actions elif new.endswith('release'): _, n, typ, _ = new.split('_', 4) # type will be either press or hold - self.log(f'2.1 Button {n} {typ}') + self.log(f'092 Button {n} {typ}') if eid := self.args.get(f'button{n}'): self.active_entity = self.get_entity(eid) - self.log(f'2.1.1 Set active entity to: {self.active_entity.name}') + self.log(f'096 Set active entity to: {self.active_entity.name}') + self.log(json.dumps(self.active_entity.get_state('all'), indent=4)) domain, entity = eid.split('.') + self.log(f'099 Curent domain: {domain}, entity: {entity}') match domain: case 'light': # Set the light to maximum brightness if the button is held. if typ == 'hold': self.active_entity.turn_on(brightness=self.max_brightness) - self.log(f'2.1.1 Set {self.active_entity.friendly_name} to maximum brightness {self.max_brightness}') + self.log(f'105 Set {self.active_entity.friendly_name} to maximum brightness {self.max_brightness}') else: if self.active_entity_is_on: self.active_entity.turn_off() - self.log(f'2.1.2 Turn {self.active_entity.friendly_name} off') + self.log(f'109 Turn off {self.active_entity.friendly_name}') else: self.active_entity.turn_on(brightness=self.init_brightness) - self.log(f'2.1.3 Turn {self.active_entity.friendly_name} on with brightness {self.init_brightness}') + self.log(f'112 Turn on {self.active_entity.friendly_name} with brightness {self.init_brightness}') case 'switch': self.active_entity.toggle() - self.log(f'2.1.4 Toggle on/off power to {self.active_entity.friendly_name}') + self.log(f'115 Toggle on/off power to {self.active_entity.friendly_name}') elif switch := self.args.get(f'button{n}'): self.active_entity = self.get_entity(switch) - self.log(f'2.2 Set active entity to: {self.active_entity.friendly_name}') + self.log(f'119 Set active entity to: {self.active_entity.friendly_name}') onoff = self.active_entity.get_state() - self.log(f'2.2 {self.active_entity.friendly_name} is currently {onoff}') + self.log(f'114 {self.active_entity.friendly_name} is currently {onoff}') self.active_entity.toggle() - self.log(f'2.2 Toggle on/off power to {self.active_entity.friendly_name}') + self.log(f'116 Toggle on/off power to {self.active_entity.friendly_name}') # This function was written by chatgpt! def hex_to_rgb(self, hex_color: str) -> list: @@ -101,7 +131,7 @@ class TapDial(Hass): # Check if the string has a valid length if len(hex_color) != 6: - raise ValueError(f"Invalid hex color: {hex_color}. Must be 6 characters long.") + raise ValueError(f"126 Invalid hex color: {hex_color}. Must be 6 characters long.") try: # Split the hex color into its RGB components and convert to integers @@ -110,5 +140,5 @@ class TapDial(Hass): b = int(hex_color[4:6], 16) return [r, g, b] except ValueError: - raise ValueError(f"Invalid hex color: {hex_color}. Must contain only valid hex digits.") + raise ValueError(f"135 Invalid hex color: {hex_color}. Must contain only valid hex digits.")