Callback delay within function?

This may be a naive question and showing how far my education in python has to go :slight_smile: but I’ve started migrating all my more complex automations to AppDaemon over the past couple of weeks - and just want to confirm the best way to achieve this.

I know this example below doesn’t work - but it’s the easiest way to show what I’m trying to accomplish - what would be the best way to go about achieving a similar result?

import appdaemon.appapi as appapi

#
# Test App
#

class TestApp(appapi.AppDaemon):

  def initialize(self):
     self.listen_state(self.test, entity='input_select.house', new="Sleep")

  def test(self, entity, attribute, old, new, kwargs):
      self.run_in(self.call_service("homeassistant/turn_off", entity_id="input_boolean.speech_notifications"), seconds=5)

Essentially (like everyone else here :grinning:), I have an app that sets house mode. Morning/Home/Sleep/Away etc.

When each mode is set, particularly with ‘Sleep’ and ‘Away’, I’d like certain things to happen in a particular order, with delays after specific actions.

I know I could just use self.run_in() as documented and define separate functions for the tasks that need to be delayed - but (and this is where perhaps I’m being naive) it seems like overkill to define a new function for a single callback to dim the lights, and another to turn off the TV, etc for the purposes of putting 30 seconds between them.

Happy to be corrected and told that is the correct way to do it, but just wanted to check there wasn’t a “cleaner” method.

If I created a specific worker thread via queue to handle these operations, would it be save to use time.sleep?

Thanks!

Separate functions are definitely the way to go, even just containing a single line. I’m not sure why you are so reticent about using them.

Thanks. That’s what I’ll do then.

I’m not sure why you are so reticent about using them.

Mostly inexperience I guess. Didn’t seem as ‘clean’ (not really the right word but it’s as accurate as I can come up with right now) as containing it all in a single function. As I said, happy to be corrected - just wanted to ensure I was doing it the ‘right’ way… I’m only about 3 to 4 weeks into picking up python, so trying to develop the right habits.

Thanks again!

Yes, run_in() with a new function is the way this is intended to work - also, don;t be tempted to use sleep() in a callback function as it will tie up your threads.

Thanks for commenting, I’ll stick with that then. Loving AppDaemon, for handling more complex logic, I should have added it a long time ago!

One more quick one since you’re here if you don’t mind - I did note in the documentation not to use time.sleep() due to tying up threads… The reason I asked if it was valid to use if I imported queue was because I saw you’ve used this in your Announce app:

time.sleep(int(self.args["length"]))

Curious as to how that does or doesn’t impact?

1 Like

If I recall the code, I am actually using my own thread created in the App to read the queue so it isn’t tying up any of the worker threads.

Yeah, it’s a thread created in the App. So it doesn’t tie it up in that case. That’s what I was hoping to understand.

Thanks again!

1 Like