I’m new to AppDaemon and Python and I’m experimenting with an App.
I want to turn my lights on slowly every morning at a set time that I can modify via the frontend.
import appdaemon.plugins.hass.hassapi as hass
from datetime import datetime
class WakeUp(hass.Hass):
def initialize(self):
self.log("initializing wake up app")
time_str = self.get_state("input_datetime.set_wake_up_light")
time_dt = datetime.strptime(time_str, '%H:%M:%S').time()
self.bedroom_light = self.get_entity("light.the_bedroom_light")
self.listen_state(self.time_change, "input_datetime.set_wake_up_light")
self.run_daily(self.wake_up_light, time_dt)
self.log("end initialize")
def wake_up_light(self, kwargs):
self.log("in wake up light callback now")
self.bedroom_light.turn_on(transition = 60)
def time_change(self, entity, attribute, old, new, kwargs):
time_str = self.get_state("input_datetime.set_wake_up_light")
time_dt = datetime.strptime(time_str, '%H:%M:%S').time()
self.log("wake up light time now {}".format(time_str))
I begin by getting the datetime from an input_date helper on my front end, then I convert it to a datetime time, then I both listen for changes to the datetime helper, and I set a run_daily callback to run at time_dt.
When I add
self.log(type(time_dt)
I get the output:
<class 'datetime.time'>
which seems like the correct type since I don’t get any errors from the run_daily callback like I did when I put in the full datetime.
I do not get errors in the initialize, and my time_change callback works fine, I just can’t get the run_daily callback to trigger.
so it turns out I had some logic problems and my appdaemon time_zone config was wrong, which was preventing me from debugging the problem.
I changed my time zone in the appdaemon.yaml.
Your advice inspired me to think about why I got all wrapped up in using datetime, then I realized I needed to reinitialize the app if I want the wake up light callback to reinitialize with the new time set in the front end. I also added in a switch to turn on and off the wake up light. Here is what I ended up with
import appdaemon.plugins.hass.hassapi as hass
import time
class WakeUp(hass.Hass):
def initialize(self):
self.log("wake up light initializing ...")
self.listen_state(self.time_change, "input_datetime.set_wake_up_light")
self.run_daily(self.turn_on_light, (self.get_state("input_datetime.set_wake_up_light")))
def turn_on_light(self, kwargs):
self.switch = self.get_entity("input_boolean.wake_up_light_switch")
self.bedroom_light = self.get_entity("light.the_bedroom_light")
if self.switch.is_state("on"):
self.bedroom_light.turn_on(transition = 600)
else:
self.log("wake up ilght switch is off")
def time_change(self, entity, attribute, old, new, kwargs):
time.sleep(3)
self.restart_app("wakeup")
I’ll throw out a few suggestions. Instead of having time_change() restart the app, you’ll want it to cancel the run_daily() scheduler and re-create it. You can do this easily by storing the handle ID of run_daily() in a class variable. Also, you never want your callbacks to include time.sleep() because it is a blocking call.
awesome, thank you for the suggestions, I’ll work on implementing them.
The reason I added the sleep was because when you change a single digit on the input datetime helper, it triggers the callback to restart, so I wanted to prevent the restart until I finished editing the input datetime and I figured a delay would allow me to do that. I’ll take your advice though, thanks again.
Just add a duration argument with the desired amount of seconds to the listen_state callback and it wont fire until you stop editing the helper entity.