👣 Direction Trigger Based Template Motion Sensor

Introduction

Hello everyone. Hope you are all well.

This template sensor attempts to detect the direction you’re moving (upstairs/downstairs, inside/outside) based on other sensors around a main sensor. It’s a single, self-contained solution. Great for doors and gates and can be used on stairs with a well positioned PIR sensor at the center of your stair way.

It solved an issue I was having with my previous implementations where the off state of sensors were captured and compared making the direction sensors think you’d walked back the other way after the sensors stopped detecting you. I found this more robust than just using the last_changed/last_updated states within home assistant.

It also requires less sensors overall as you can just use existing area sensors and another in the middle of those area’s which is perfect for doors.

Trigger Based Template - Direction Motion Sensor

This is a trigger based template sensor and should be placed in “/blueprints/template” path in your configuration. I’m not sure if the below link works or not properly as it opens the standard blueprint screen in home assistant for me. The blueprint code is at the bottom of the post.

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

Requirements

  • Main Sensor Placement: Place your main binary sensors (PIR, contact sensors) strategically – e.g., halfway up stairs for tracking upstairs movement, on doors for in/out detection.

  • Entry Entities: These are the initial sensors that trigger. (e.g. PIR sensors upstairs/downstairs, inside/outside sensors for doors)

  • Exit Entities: These are the final sensors that trigger. (e.g. PIR sensors upstairs/downstairs, inside/outside sensors for doors)

Important Notes:

  • Low Traffic: This system is best suited for low-traffic areas although shouldn’t matter too much in the case of doors and I’ve never noticed it cause an issue on my stairs as I use it for an early trigger on for my occupancy in the landing/hallway area’s.

  • Single Active State: The sensor will only be active when the primary movement sensor triggers on and the entry entities we’re the last triggered on. My PIR’s have a cool down of 10 seconds so they won’t detect me running up and down the stairs multiple times for example but it will capture that initial travel up/down the stairs.

How it Works:

This sensor leverages your existing binary sensors (contact, PIR, etc.) to track movement direction. It captures the last triggered on time of the entry and exit binary sensors. When the main sensor triggers, it compares the latest entry and exit times. If the entry sensor’s last triggered on time was most recent, the sensor turns on. The sensor will turn off if the entry/exit sensors update in the background, this prevents the sensor from being falsely triggered by background updates of the entry/exit sensors.

Example

Below is an example of how I’m using it on my stairs. The main sensors is on the banister of the stairs and my landing sensors are upstairs and my hallway sensors are downstairs. Just swap the entry/exit sensors to create the alternative sensor for up and downstairs. This makes my lighting in those area’s feel predictive rather than reactive.

template:
  - name: PIR Going Downstairs
    unique_id: pir_going_downstairs
    use_blueprint:           
        path: personal/direction_motion_sensor.yaml # relative to config/blueprints/template/  
        input:
          main_binary_sensor: binary_sensor.pir_stairs_wall_behind_banister_occupancy
          entry_entities:
            - binary_sensor.pir_landing_stairwell_occupancy
          exit_entities: 
            - binary_sensor.pir_hallway_ceiling_entrance_occupancy
            - binary_sensor.contact_hallway_back_door_contact
            - binary_sensor.pir_hallway_shoe_stand_occupancy
  - name: PIR Going Upstairs
    unique_id: pir_going_upstairs
    use_blueprint:           
        path: personal/direction_motion_sensor.yaml # relative to config/blueprints/template/  
        input:
          main_binary_sensor: binary_sensor.pir_stairs_wall_behind_banister_occupancy
          entry_entities:
            - binary_sensor.pir_hallway_ceiling_entrance_occupancy
            - binary_sensor.contact_hallway_back_door_contact
            - binary_sensor.pir_hallway_shoe_stand_occupancy
          exit_entities: 
            - binary_sensor.pir_landing_stairwell_occupancy```

Below is another example of my back door. The hallway is the last area before the back garden and I only have frigate detection outside. This has been great for disabling my security alerts as we go outside as it only triggers as we leave, and again the lights in the garden and hallway feel predictive rather than reactive. Frigate isn’t very fast at starting detection, and my hallway PIR’s don’t detect me until the door is open and I’m visible so it’s a nice additional trigger of occupancy without just relying on the door open trigger.

template:
  - name: PIR Back Door Going Outside
    unique_id: pir_back_door_going_outside  
    use_blueprint:           
        path: personal/direction_motion_sensor.yaml # relative to config/blueprints/template/  
        input:
          main_binary_sensor: binary_sensor.contact_hallway_back_door_contact
          entry_entities:
            - binary_sensor.pir_hallway_ceiling_entrance_occupancy
            - binary_sensor.pir_hallway_shoe_stand_occupancy
          exit_entities: 
            - binary_sensor.camera_back_garden_door_person_occupancy
            - binary_sensor.contact_back_garden_back_gate_contact
            - binary_sensor.zone_camera_back_garden_patio_person_occupancy
            - binary_sensor.zone_camera_back_garden_nook_person_occupancy
            - binary_sensor.zone_camera_back_garden_nook_person_occupancy
            - binary_sensor.zone_camera_back_garden_grass_area_person_occupancy                
            - binary_sensor.camera_back_garden_gate_person_occupancy
            - binary_sensor.camera_back_garden_door_person_occupancy
            - binary_sensor.camera_side_garden_person_occupancy
  - name: PIR Back Door Coming Inside
    unique_id: pir_back_door_coming_inside  
    use_blueprint:           
        path: personal/direction_motion_sensor.yaml # relative to config/blueprints/template/  
        input:
          main_binary_sensor: binary_sensor.contact_hallway_back_door_contact
          entry_entities:
            - binary_sensor.camera_back_garden_door_person_occupancy
            - binary_sensor.contact_back_garden_back_gate_contact
            - binary_sensor.zone_camera_back_garden_patio_person_occupancy
            - binary_sensor.zone_camera_back_garden_nook_person_occupancy
            - binary_sensor.zone_camera_back_garden_nook_person_occupancy
            - binary_sensor.zone_camera_back_garden_grass_area_person_occupancy                
            - binary_sensor.camera_back_garden_gate_person_occupancy
            - binary_sensor.camera_back_garden_door_person_occupancy
            - binary_sensor.camera_side_garden_person_occupancy
          exit_entities: 
            - binary_sensor.pir_hallway_ceiling_entrance_occupancy
            - binary_sensor.pir_hallway_shoe_stand_occupancy

Blueprint

blueprint:
  name: Direction Motion Sensor
  description: Creates a motion sensor that only triggers from a specific direction
  domain: template
  source_url: https://gist.notexpectedyet.com/notexpectedyet/041f0f0ed78b4489b824e2326e81e498/raw/HEAD/direction_motion_sensor.yaml
  input:
    main_binary_sensor:
      name: Main Binary Sensor
      description: The binary_sensor that you want to detect a direction when triggered. Should be inbetween the entry and exit sensors.
      selector:
        entity:
          domain: binary_sensor
    entry_entities:
      name: Entry entities
      description: The first set of entities that should trigger "on" before the main binary_sensor triggers.
      #multiple: true
      selector:
        entity:
          domain: binary_sensor
    exit_entities:
      name: Exit entities
      description: The last set of entities that should trigger "on" after the main binary_sensor triggers.
      #multiple: true
      selector:
        entity:
          domain: binary_sensor
variables:
  main_binary_sensor_input: !input main_binary_sensor
  entry_entities_input: !input entry_entities  
  exit_entities_input: !input exit_entities
triggers:
  - trigger: state
    id: Main Binary Sensor
    entity_id: !input main_binary_sensor
    from: "off"
    to: "on"  
  - trigger: state
    id: Main Binary Sensor
    entity_id: !input main_binary_sensor
    from: "on"
    to: "off" 
  - trigger: state
    id: Entry Entities
    entity_id: !input entry_entities
    from: "off"
    to: "on"      
  - trigger: state
    id: Exit Entities
    entity_id: !input exit_entities
    from: "off"
    to: "on" 
conditions:
  - condition: template
    value_template: >-
      {{ states(main_binary_sensor_input) not in ['unavailable', 'unknown'] }}  
binary_sensor:
  state: >
    {% if trigger.id == "Main Binary Sensor" %}
      {{ is_state(main_binary_sensor_input, 'on') and this.attributes.last_detected_entry|float(0) > this.attributes.last_detected_exit|float(0) }}
    {% else %}
      {{ false }}
    {% endif %}
  device_class: motion         
  attributes:
    last_detected_entry: >-
      {% if trigger.id == "Entry Entities" %}
          {{ as_timestamp(now()) }}
      {% else %}
          {{ this.attributes.last_detected_entry if "last_detected_entry" in this.attributes else "0" }}
      {% endif %}
    last_detected_exit: >-
      {% if trigger.id == "Exit Entities" %}
          {{ as_timestamp(now()) }}
      {% else %}
          {{ this.attributes.last_detected_exit if "last_detected_exit" in this.attributes else "0" }}
      {% endif %}
2 Likes