Creating Motion Sensor Automation in Home Assistant with AppDaemon

Last Updated: 2022-07-27

Do you struggle with slow automation in your home assistant when it comes to turning on the lights? I had the same issue and went on a quest to find a quicker and more dependable solution. After researching various approaches, I stumbled upon AppDaemon and thought it could be the answer to my problem.

In this blog post, I’ll share my experience with using AppDaemon to create motion sensor automation in home assistant. I’ll also walk you through the process of creating a new template sensor to include multiple sensors in the template. Keep reading to find out how you can make your home automation quicker and more efficient.

So you start by developing a Python application.

kitchen_motion.py

import hassapi as hass


class KitchenMotion(hass.Hass):
	def initialize(self):
            self.listen_state(
                self.motion_sensor_state_changed_cb,
                entity_id="binary_sensor.kitchen_motion",
            )
            self.log("Listening for motion events in kitchen")

Firstly, we import the Hass API and proceed to build a class along with an initialize function that listens to an event, specifically a binary_sensor. When the binary sensor state changes, the method to call is self.motion_sensor_state_changed_cb. Additionally, using self. provides access to the class’s methods.

def motion_sensor_state_changed_cb(self, light, attribute, old, new, kwargs):
    motion_sensor_state = new
    is_got_illuminance = self.get_state('sensor.kitchen_motion_illuminance')
    is_daytime = self.now_is_between("05:00:00", "01:00:00")

    if motion_sensor_state == 'on' and is_daytime:
      # Check if kitchen has sun light over 55%
      if (float(is_got_illuminance) > 55.0):
        self.log('To much light in guest bathroom: %s', float(is_got_illuminance))
      else:
        self.log("Kitchen Motion detected")
        self.turn_on("script.turn_on_kitchen_lights")
    elif motion_sensor_state == 'off':
        self.log("Kitchen Motion ended")
        self.turn_on("script.turn_off_kitchen_lights")

Under the initialize function, a set of instructions are listed. It checks if it’s daytime between 05:00:00 and 01:00:00. There’s also a check for an illuminance sensor to see if the sunlight is above 55%. If these conditions are met, the kitchen lights can be switched on. Once the motion stops, the kitchen lights will turn off.

Just adding a regular motion sensor binary sensor won’t do the trick. To keep up with the motion calls and reset the timer, a custom template binary sensor needs to be added.

Create a templates.yaml

- binary_sensor:
    - name: "Kitchen Motion Sensor [TEMPLATE]"
      unique_id: "kitchen_motion"
      state: >
        {{ is_state("binary_sensor.kitchen_motion_home_security_motion_detection", "on") }}
      availability: >
        {{ is_state('input_boolean.reset_all_motion_sensors', 'off') }}
      delay_off:
        minutes: 10

So start with binary sensor and then give the template sensor a name.

Let’s break down the different components of the custom template binary sensor:

  • Unique_id: This is the identifier used in the Python script.
  • State: This variable represents the actual binary sensor state from the motion sensor that is checked to see if it’s turned on.
  • Availability: To allow for a quick reset of the motion sensors, an input boolean is included. If the boolean is off and availability is on, the reset is enabled. When the boolean is enabled, the availability is disabled.
  • Delay_off: If you’re using a regular sensor, a template sensor is required to keep track of the on and off times. The template sensor will turn off if the state doesn’t change within 10 minutes. If there’s any status change within 0 to 10 minutes, the timer resets.

kitchen_motion.py

import hassapi as hass


class KitchenMotion(hass.Hass):
	def initialize(self):
            self.listen_state(
                self.motion_sensor_state_changed_cb,
                entity_id="binary_sensor.kitchen_motion",
            )
            self.log("Listening for motion events in kitchen")
            
    def motion_sensor_state_changed_cb(self, light, attribute, old, new, kwargs):
        motion_sensor_state = new
        is_got_illuminance = self.get_state('sensor.kitchen_motion_illuminance')
        is_daytime = self.now_is_between("05:00:00", "01:00:00")

        if motion_sensor_state == 'on' and is_daytime:
          # Check if kitchen has sun light over 55%
          if (float(is_got_illuminance) > 55.0):
            self.log('To much light in guest bathroom: %s', float(is_got_illuminance))
          else:
            self.log("Kitchen Motion detected")
            self.turn_on("script.turn_on_kitchen_lights")
        elif motion_sensor_state == 'off':
            self.log("Kitchen Motion ended")
            self.turn_on("script.turn_off_kitchen_lights")

With the Python motion script set up, the next step is to add it to apps.yaml.

kitchen_motion:
  module: kitchen_motion
  class: KitchenMotion

Once you’ve added the Python motion script to apps.yaml, you may need to restart AppDaemon in the add-ons for it to take effect. Once that’s done, you’ll have a fully functional motion sensor that can turn the lights on and off and reset the timer. With the custom template binary sensor and the Python script in place, you can now enjoy a faster and more reliable automation system in your home.