Has anyone seen anything that achieves this? I’ve tried but I think it’s a little beyond my abilities at the moment and I’d love to see how it’s done!
first you have to have a button connected to the RPI and some python code to read the value from that button continiously.
but this is completely independant from HA, because HA cant read a switch that way.
Yeah I think I can get the events for the button on/off easily enough using appdaemon.
But making a loop that updates brightness with a delay between updates while pressed on. Then that loop being cancelled when the button is released.
I don’t know how to get the brightness to loop and then break it on the button release event all the while not using sleep.delay()!
a loop like:
def initialize(...):
self.going_up = True
self.delay = 1
self.minimum = 0
self.maximum = 255
self.step = 10
self.listen_state(self.startfunc,"switch_id")
def startfunc(self,entity,attributes,old,new,kwargs):
if new == "on":
self.run_in(self.runloop,self.delay)
def runloop(self.kwargs):
self.brightness = int(self.get_state("light.id","brightness")) #or float if that gives it back
if self.going_up:
self.brightness = self.brightness + self.lightstep
if self.brightness > self.maximum:
self.brightness = self.maximum
self.going_up = False
else:
self.brightness = self.brightness - self.lightstep
if self.brightness < self.minimum:
self.brightness = self.minimum
self.going_up = True
self.set_state("light.id",brightness=brightness)
if check_for_button_state():
self.run_in(self.runloop,self.delay)
def check_for_button_state():
if self.get_state("switch.id"):
return True
else:
return False
I’ve done that once and it works quite well: Rotating brightness for lights triggered by events
Thanks guys, I really appreciate the help!
I was really struggling to get my head around the recursion aspect of it all!
Got it working like this:
import appdaemon.appapi as appapi
class Test(appapi.AppDaemon):
def initialize(self):
self.log("Test App Started.")
self.going_up = True
self.delay = 1
self.minimum = 0
self.maximum = 255
self.step = 10
self.switch_id = "input_boolean.rain_switch"
self.light_id = "light.adams_study"
self.listen_state(self.startfunc, self.switch_id)
def startfunc(self, entity, attributes, old, new, kwargs):
if new == "on":
self.handle = self.run_in(self.runloop, self.delay)
def runloop(self, kwargs):
self.brightness = int(self.get_state(self.light_id, "brightness")) # or float if that gives it back
if self.going_up:
self.brightness += self.step
if self.brightness > self.maximum:
self.brightness = self.maximum
self.going_up = False
else:
self.brightness = self.brightness - self.step
if self.brightness < self.minimum:
self.brightness = self.minimum
self.going_up = True
self.turn_on(self.light_id, brightness=self.brightness)
if self.check_for_button_state():
self.run_in(self.runloop, self.delay)
def check_for_button_state(self):
if self.get_state(self.switch_id) == "on":
return True
else:
return False
Can I do a delay using run_in() with less that 1 second? eg. self.run_in(self.callback, 0.1)
It’s a little too slow for my liking and I’d like to speed it up!
i am not sure.
could be that it works, so just try out.
@aimc could tell you if you can have a run in shorter then 1 second.
I have tried, it doesn’t appear to work when i try it. It takes the value and defaults to 1 second and im definitely sending in a float < 1.0. I’d like it to be a little more responsive. Every second is really clunky
The AppDaemon scheduler runs at 1 second intervals, and I have no current plans to change this. Trying to send multiple ZWave or whatever messages to a light in a second is probably going to tax your network anyway.
Ok no worries, thanks for the response. I did originally try to achieve this using sleep.delay() and the light was surprisingly responsive, I had is strobing with 0.1 second delays and everything! But obviously that isn’t a real solution…
Not necessarily … you could have the strobing effect in a separate thread altogether. But then you’d need a new thread for each light you wish to strobe.
Does using the run_in() create a new thread in which I can do this? Can you suggest the best way you would achieve this?
I’m not at all familiar with creating a multiple thread app!
For anyone that may be interested, I finally learnt how to thread and can get delays below 1 second using time.sleep without breaking appdaemon!
Code:
import appdaemon.appapi as appapi
import threading
import time
### Comments ###
### Args ###
"""
# switch_id: {entity_id of switch}
# light_id: {entity_id of light}
# delay: {1 = one second. Can go below 1 second. Anything below 0.4 was not working well for me}
# step: {how many brightness steps to go up/down per change}
# minimum: {brightness to go to. Lowest = 0}
# maximum:{brightness to go to. Highest = 255}
EXAMPLE appdaemon.yaml entry:
adams_bedside_light_switch_LCB:
module: lights_cycle_brightness
class: Lights_Cycle_Brightness
switch_id: binary_sensor.switch_158
light_id: light.bedside_one
delay: 0.4
step: 25
minimum: 25
maximum: 250
"""
class Lights_Cycle_Brightness(appapi.AppDaemon):
def initialize(self):
self.log("LCB Started.")
self.going_up = True
self.delay = float(self.args["delay"])
self.minimum = int(self.args["minimum"])
self.maximum = int(self.args["maximum"])
self.step = int(self.args["step"])
self.switch_id = self.args["switch_id"]
self.light_id = self.args["light_id"]
for switch in self.split_device_list(self.switch_id):
self.listen_state(self.start_func, switch)
def start_func(self, entity, attributes, old, new, kwargs):
if new == "on":
self.t = threading.Thread(target=self.run_thread, args=(entity,))
self.t.start()
def run_thread(self, switch):
while(self.get_state(switch) == "on"):
if self.get_state(self.light_id) == "off":
self.turn_on(self.light_id)
try:
self.brightness = int(self.get_state(self.light_id, "brightness")) # get lights current brightness
except:
while(self.brightness == None and self.get_state(switch) == "on"):
try:
self.brightness = int(self.get_state(self.light_id, "brightness"))
except:
pass
if self.going_up:
self.brightness += self.step
if self.brightness > self.maximum:
self.brightness = self.maximum
self.going_up = False
else:
self.brightness = self.brightness - self.step
if self.brightness < self.minimum:
self.brightness = self.minimum
self.going_up = True
self.log("{} changed to brightness: {}".format(self.light_id, self.brightness))
self.turn_on(self.light_id, brightness=self.brightness)
time.sleep(self.delay)
that only works when you have 2 different entities for the switch and the light, but a nice workaround.
What do you mean? It works with one or more switch entitiy_id’s seperated by a comma?
i mean that it wont work if you dont have a seperate switch.
i dont have seperate switches and lights in HA.
but never mind, because without a seperate switch the app is useless, so i was thinking wrong
Oh, yeah that’s totally right. I just couldn’t think of using it any other way than with a held down switch