Don't execute code if state is off [SOLVED]

Hello, I’m trying to convert some of my automations to appdaemon. So i got this frankencode from various sources and it kinda works.

class MotionLights(appapi.AppDaemon):

  def initialize(self):
    
    self.handle = None
    
    # Check some Params

    # Subscribe to sensors
    if "sensor" in self.args:
      self.listen_state(self.motion_on, self.args["sensor"])
      self.listen_state(self.motion_off, self.args["sensor"])
    else:
      self.log("No sensor specified, doing nothing")
    
  def motion_on(self, entity, attribute, old, new, kwargs):
    if new == "on":
      if "entity_id" in self.args:
        self.log("Motion detected: turning {} on".format(self.args["entity_id"]))
        self.turn_on(self.args["entity_id"], brightness = int(self.args["brightness"]), rgb_color = [self.args["rgb1"],self.args["rgb2"], self.args["rgb3"]])
        self.cancel_timer(self.handle)

  def motion_off(self, entity, attribute, old, new, kwargs):
    if new == "off":
        if "entity_id" in self.args:
              self.log("Motion stoped on: {}".format(self.args["sensor"]))
        if "delay" in self.args:
          delay = self.args["delay"]
        else:
          delay = 60
        self.cancel_timer(self.handle)
        self.handle = self.run_in(self.light_off, delay)
  
  def light_off(self, kwargs):
    if "entity_id" in self.args:
      self.log("Change brightness on {} for 10 seconds then turn off".format(self.args["entity_id"]))
      self.call_service("light/turn_on", entity_id = (self.args["entity_id"]), brightness = 50)
      self.cancel_timer(self.handle)
      self.handle =  self.run_in(self.light_off_delay, 10)
   
  def light_off_delay(self, kwargs):
    self.cancel_timer(self.handle)
    self.handle = self.turn_off(self.args["entity_id"])

  def cancel(self):
    self.cancel_timer(self.handle)

How can i stop this part of code to execute if state of light is off?

  def motion_off(self, entity, attribute, old, new, kwargs):
    if new == "off":
        if "entity_id" in self.args:
              self.log("Motion stoped on: {}".format(self.args["sensor"]))
        if "delay" in self.args:
          delay = self.args["delay"]
        else:
          delay = 60
        self.cancel_timer(self.handle)
        self.handle = self.run_in(self.light_off, delay)
  
  def light_off(self, kwargs):
    if "entity_id" in self.args:
      self.log("Change brightness on {} for 10 seconds then turn off".format(self.args["entity_id"]))
      self.call_service("light/turn_on", entity_id = (self.args["entity_id"]), brightness = 50)
      self.cancel_timer(self.handle)
      self.handle =  self.run_in(self.light_off_delay, 10)
   
  def light_off_delay(self, kwargs):
    self.cancel_timer(self.handle)
    self.handle = self.turn_off(self.args["entity_id"])

  def cancel(self):
    self.cancel_timer(self.handle)

I know that i have to use self.get_state(self.args[“entity_id”]) but i’m having trouble to figure that part.

Some lines from one of my apps might help

        if self.get_state(self.args["sensors"]) == "off":
            self.turn_off(self.args["lights"])
1 Like

Thanks. So something like this should work? I can’t test it now.

  def motion_off(self, entity, attribute, old, new, kwargs):
    if new == "off":
        if self.get_state(self.args["entity_id"]) == "on":
          if "entity_id" in self.args:
              self.log("Motion stoped on: {}".format(self.args["sensor"]))
          if "delay" in self.args:
              delay = self.args["delay"]
          else:
              delay = 60
          self.cancel_timer(self.handle)
          self.handle = self.run_in(self.light_off, delay)

That is correct.

However, what you are trying to achieve might be done more easily with the duration parameter of the listen_state() call

Something like

           self.listen_state(self.motion_stopped, self.args["sensors"],
                new = "off",
                duration = self.args["delay"])

which will only call motion_stopped when the state has been off for “delay” seconds

Like this?

  def motion_off(self, entity, attribute, old, new, kwargs):
        if self.get_state(self.args["entity_id"]) == "on":
           self.listen_state(self.motion_stopped, self.args["sensors"],
                new = "off",
                duration = self.args["delay"])
            self.cancel_timer(self.handle)
            self.handle = self.run_in(self.light_off, delay)

No, the listen_state goes in your inttialize routine.

def initialize(self):
...
    if "sensor" in self.args:
      self.listen_state(self.motion_on, self.args["sensor"])
      self.listen_state(self.motion_off, self.args["sensor"], new="off", duration=self.args["delay"])

Then motion_off will only be called when the sensor has been in state “off” for delay, and you can define motion off as

def motion_off(self, entity, attribute, old, new, kwargs):
    self.turn_off(self.args["entity_id"])
2 Likes

I see. That will shorten this code nicely. But i don’t want to turn off light immediately because it first change brightness to 50. I’ll play with code and try to include yours suggestions.

It seems that everything works. Thanks again.

1 Like

Do you how how i can mark your answer as solution? :smiley: