Follow Me Lights Automation Implementation

Hi all,

I am finished with the initial implementation of the “Follow Me Lights” automation and wanted to share the solution for those who may be interested in a similar setup.

Use Case:
When only one person is present in the house, we want the lights to “follow” the person as they move around the house and only be ON in the room where person is located. As they enter a particular room, the lights in that room turn ON and lights in every other room in the house immediately turn OFF. Thus it will feel as the lights follow the person around the house.

General Implementation Description:

Prerequisites :

  • You have motion sensors in every room you want covered in the automation.
  • You have already implemented presence detection in your HA (either router or own tracks, or others)

General Solution Description:

Using our presence detection sensors, we will determine how many people are present in the house. If we can detect only ONE person in the house, we will trigger “follow me lights” mode ON. Once we detect more than ONE person in the house, we will trigger “follow me lights” mode OFF.

When “follow me lights” mode is ON, the following will occur : Every time we detect motion in a particular room, we will trigger a script that will turn a specific light in this room ON and will compute the list of lights to turn off. It will then turn off all “other” lights in the house. At this moment, I have a hard-coded list of “all lights” I want to be affected. It is very easy to turn that list into a dynamic list pulled from one of those “light.all” groups , but I only wanted to affect some main ceiling lights in my house and ignore the small lights that also exist.

Finally, the automation presented also use a secondary condition of “motion detection” switch being ON and sun being under horizon. So, follow me lights is a secondary condition to “motion detection” being ON. When Motion detection is OFF, the lights don’t respond to movement around the house at all. I turn off motion detection from a different automation when we sit to watch movies and I don’t want lights to come ON if anybody moves off the couch to fetch something.

Automation Code:

First we create a couple of “input_boolean” switches. These are used to enable/disable motion detection and follow me lights mode:

 motion_detection:
    name: Motion Detection
    initial: on
    icon: mdi:car

  follow_me_lights:
    name: Follow Me Lights
    initial: off
    icon: mdi:lightbulb

Next we create a template sensor that determines how many people are home.
Note here we assume you already setup your device_trackers and can determine when somebody is home.
This sensor will automatically be set to “everybody” when both people are home and to “somebody” when only one person is home.

- platform: template
  sensors:

    eveybody_home:
        friendly_name: 'Everyone Home'
        value_template: >-
          {% if is_state("device_tracker.dmitry", "home") and  is_state("device_tracker.eileen", "home") -%}
            everybody
          {% elif is_state("device_tracker.dmitry", "home") or  is_state("device_tracker.eileen", "home") -%}
            somebody
          {%- else -%}
            nobody
          {%- endif -%}

Next we create an automation to flip the “follow me lights” input_boolean to ON, when everybody_home sensor changes it’s state to “somebody” and we flip the input_boolean to OFF when it changes to “everybody” or “nobody”

- alias: 'Follow Me Lights Mode On'
  trigger:
    platform: state
    entity_id: sensor.eveybody_home
    to: 'somebody'
  action:
    service: input_boolean.turn_on
    data:
      entity_id: input_boolean.follow_me_lights

- alias: 'Follow Me Lights Mode Off'
  trigger:
    platform: state
    entity_id: sensor.eveybody_home
    to: 'everybody'
  action:
    service: input_boolean.turn_off
    data:
      entity_id: input_boolean.follow_me_lights

Next we create a script to turn ON a specific light, which is passed into a script as a parameter:

  follow_me_lights_on:
  sequence:
   - service: homeassistant.turn_on
     data_template:
       entity_id: > 
        {{ light_id }}

   - service: switch.turn_off
     data_template: 
       entity_id: > 
        {%- set light_remove =  [ light_id ]  %}
        {%- set all_lights = ['switch.bedroom_ceiling_light_switch' , 'switch.family_room_ceiling_light_switch', 'switch.office_lights_switch_2' ] %}
        {%- if is_state('input_boolean.follow_me_lights', 'on') -%}
        {%- for light in all_lights if (light not in light_remove) -%}
        {{light}}{% if not loop.last %}{{", "}}{% endif %} 
        {%- endfor -%}
        {%- else -%}
         switch.null.switch 
        {%- endif -%}

   - service: light.turn_off
     data_template:
       entity_id: >
        {%- set light_remove =  [ light_id ]  %}
        {%- set all_lights = ['light.living_room_ceiling_light_1_level', 'light.living_room_ceiling_light_2_level' ] %}
        {%- if is_state('input_boolean.follow_me_lights', 'on') -%}
        {%- for light in all_lights if (light not in light_remove) -%}
        {{light}}{% if not loop.last %}{{", "}}{% endif %}
        {%- endfor -%}
        {%- else -%}
         light.null.light 
        {%- endif -%}

In the above script: light_id is being passed in that this will be the light to turn ON… the all_lights variable is set with a list of hardcoded lights and switches I want to affect. (again, this list could be generated dynamically, but I only want to affect a few specific lights… Another complication here was that we must handle “switches” and “lights” separately in two separate loops… I could not figure out how to do it in one loop as homeassistant.turn_on service was not working on both types combined.

PROBLEM with ABOVE SCRIPT: As you see I am calling a non-existing: “light.null.light” entity_id in case “follow me light switch” is OFF. If I did not call something on the “else” part of statement , the YAML would fail. I do not know how to solve this issue at this time. If somebody can find a nice solution to this, please let me know.
Is there a way to have some sort of “/dev/null” type of call, to call a “null” switch to turn off, to have HA to just ignore it?
At this moment, if NO other lights are ON at the time, I will call to turn off the “light.null.light” just to make HA happy. so as a result, I have “ERROR” messages in the log file every time, there are NO lights to turn-off…

This ELSE also will be needed, if I wanted to check if the light is already OFF and only turn it OFF if it was ON.
If all the OTHER lights were already OFF, again we would face the same issue and needed to call some service in the “else” part of the “if” condition.

Finally, for every room that you want to be part of this we create an automation triggered by motion detection:

- alias: Familiy  Room Lights ON
  trigger:
    platform: state
    entity_id: sensor.family_room_motion
    to: 'Burglar'
  condition:
    condition: and
    conditions:
      - condition: state
        entity_id: sun.sun
        state: 'below_horizon'
      - condition: state
        entity_id: input_boolean.motion_detection
        state: 'on'
  action:
    service:  script.follow_me_lights_on
    data_template:
      light_id: switch.family_room_ceiling_light_switch

In the above automation: we detect motion, check conditions: is sun sunset, do we have “motion detection” on?
If the answer is yes, we call our script “follow_me_lights_on” and we pass in the entity_id of the light we want to turn on.

And that is it folks! Enjoy the automation, comment on the ways to further improve it and let the lights follow you :slight_smile:

6 Likes

Nice! Glad to see someone else doing something similar to what had setup.

Few questions for you. I’m curious what type of motion sensors you’re using and what time-out they’re set to. For example, many z-wave motion sensors do not allow you to set the time-out to anything less than 15 seconds which would make it impractical if you transitioned between two rooms in under 15 seconds because HA would not know what room you’re actually in within that 15 second window.

Second, do you have any issues with false positives? Like motion triggers happening out of order or in such a way that the desired lights do not get turned on correctly?

Basically the above questions are related to issues I faced and am curious if you’ve faced them how you’ve overcome them. In my case the fibaro multi sensors allow for the time-out to be set really small so the sensors can be read to receive another “ON” message within 2 seconds which in my case is less time that it takes to transition between rooms.

However that did not help solve the problem of transitioning into a room out of a room and back into that room quickly. Especially if that transition was under 2 seconds (such is the case for quickly grabbing something like a paper towel from the kitchen)

My solution to the second problem was to uncouple the turning off of the lights from the motion sensor activation event and instead turn off lights based on the last room occupied motion sensor going off. That way transitions between rooms multiple times just effectively keeps the lights in both rooms on until I “stop” for at least two seconds in one room.

Hopefully that makes sense and I’d be curious what issues you’ve ran into like this if any.

1 Like

Great questions!
Since I just finished this, I am only discovering the issues and I have exactly the same as you described.

This is the reason I specifically excluded many small lights in my apartment and only included major ones that takes more than 1-2 seconds. But yes, quick transitions are an issue. I have not considered how to solve it yet, but your solution seem interesting…

I will give it a bit more thought and will revert back if I find a better solution than yours.

Here is my code for reference:

automation:

  - alias : Update last_motion_triggered from motion sensor last triggered.

    trigger:
      platform: state
      entity_id:
        - binary_sensor.fibaro_system_fgms001zw5_motion_sensor_sensor
        - binary_sensor.fibaro_system_fgms001zw5_motion_sensor_sensor_2
        - binary_sensor.fibaro_system_fgms001zw5_motion_sensor_sensor_3
        - binary_sensor.fibaro_system_fgms001zw5_motion_sensor_sensor_4
      to: 'on'

    action:
      - service: input_select.select_option
        data_template:
          entity_id: input_select.last_motion_triggered
          option: "{{ trigger.to_state.attributes.friendly_name | replace(' Motion', '') }}"

      - service: light.turn_on
        data_template:
          entity_id: "group.{{ trigger.to_state.attributes.friendly_name | replace(' Motion', '') | lower }}_motion_on"
          transition: 0

  - alias : Turn off lights based on last montion triggered

    trigger:
      platform: state
      entity_id:
        - binary_sensor.fibaro_system_fgms001zw5_motion_sensor_sensor
        - binary_sensor.fibaro_system_fgms001zw5_motion_sensor_sensor_2
        - binary_sensor.fibaro_system_fgms001zw5_motion_sensor_sensor_3
        - binary_sensor.fibaro_system_fgms001zw5_motion_sensor_sensor_4
      to: 'off'

    condition:
      condition: state
      entity_id: input_boolean.guest_mode
      state: 'off'

    action:
      - service: light.turn_off
        data_template:
          entity_id: >
              {% if is_state('group.motion_sensors', 'off')  %}
                  group.{{ trigger.to_state.attributes.friendly_name | replace(' Motion', '') | lower }}_motion_off
              {% elif is_state('group.motion_sensors', 'on') and (trigger.to_state.attributes.friendly_name | replace(' Motion', '') != states.input_select.last_motion_triggered.state) %}
                  group.{{ trigger.to_state.attributes.friendly_name | replace(' Motion', '') | lower }}_motion_on
              {% endif %}
          transition: 3

The meat of the code is the if else statement that looks to see if the group of the motion sensors are off, in which case the motion sensor that just turned off, was the last to turn off and it is likely that I am still in that room, else I want to wait to turn off the lights in the room that was triggered directly before.

Hello!

Im doing the same idea as you guys (with tradfri lights and PIRs).

I have that problem where my PIRs sends out the motion detected signal after i moved. So if i keep moving infront of the sensor, it will wait till I stop to report the motion. I found videos examples (for guides) where the PIRs riport instantly.