Motion-controlled light with manual override

One of the simplest home automations is the Motion-Controlled Light (MCL):

  • Auto-on: The light is turned on when motion is detected.
  • Auto-off: The light is turned off when no motion is detected for several minutes.

The only entities required are:

  • a light or switch
  • a binary_sensor that detects motion

However, in practice, the first deficiency one experiences is the light might turn off while the room is still occupied. You might be sitting quietly and, after a few minutes of no detected motion, the light automatically turns off (leaving you in a dark room and unimpressed).

To prevent this undesirable behavior you can use additional methods of presence detection or by simply commanding the system to (temporarily) disable the MCL feature (i.e. manual override). The question is: “How do you make the manual override command convenient?”

An input_boolean can be used to enable/disable the MCL feature. However, in practice, it may be inconvenient to access the Lovelace UI to turn off the input_boolean (even if you have your phone handy). Perhaps the most convenient would be to tell your favorite voice assistant something like “Disable automatic living room light.” This would require creating a custom skill to enable/disable the input_boolean (and is something I plan to try in the future).

An alternative method is to use the light switch itself. If the light is controlled by a physical switch (such as a wall-mounted switch), it can be used to turn the input_boolean on or off. It works like this:

  • When you enter the room, and the light is automatically turned on, turn the light switch off then back on. This quick toggling action serves to turn off the input_boolean.
  • To re-enable the MCL feature, simply repeat the action: turn the light switch off then back on. This will serve to turn on the input_boolean.
  • To summarize, the action of turning the light switch off then back on serves to toggle the state of the input_boolean.

NOTE:

Some switches can transmit events when they are double-tapped (and the event can be used to enable/disable the MCL feature). The approach I’m describing assumes your switch either doesn’t have this capability or you are already using it for another purpose.

Lastly, an automation is used to turn the input_boolean back on after it has been off for an hour. This ensures the MCL feature is restored in case you disabled it but forgot to re-enable it.

What is required

  • light or switch entity
  • binary_sensor that detects motion
  • input_boolean to enable/disable the MCL feature
  • timer to help implement the manual override feature
  • two automations to implement the MCL feature
  • two automations to implement the manual override feature

The following examples use:

light.kitchen
binary_sensor.kitchen

You will need to create a 3-second timer and an input_boolean.

timer:
  kitchen_mcl:
    duration: '00:00:03'

input_boolean:
  kitchen_mcl:
    name: Motion-Controlled Kitchen Light
    initial: true

The first two automations simply create a Motion-Controlled kitchen light. The light is turned on by motion and turned off after several minutes of no motion. If you turn off the input_boolean, the MCL feature is disabled.

# -------------------------------------------------------------------
# Automations for a Motion-Controlled kitchen light

# Turn on light when binary_sensor detects motion
# only if light is currently off and input_boolean is on

- alias: 'Kitchen light Auto-on'
  trigger:
    platform: state
    entity_id: binary_sensor.kitchen
    from: 'off'
    to: 'on'
  condition:
    - condition: state
      entity_id: light.kitchen
      state: 'off'
    - condition: template
      value_template: "{{ is_state('input_boolean.kitchen_mcl', 'on') }}"
  action:
    service: light.turn_on
    entity_id: light.kitchen


# Turn off light when binary_sensor detects no motion for 3 minutes
# only if input_boolean is on

- alias: 'Kitchen light Auto-off'
  trigger:
    platform: state
    entity_id: binary_sensor.kitchen
    to: 'off'
    for: '00:03:00'
  condition:
    - condition: template
      value_template: "{{ is_state('input_boolean.kitchen_mcl', 'on') }}"
  action:
    service: light.turn_off
    entity_id: light.kitchen

The next two automations implement the manual override feature (i.e. ability to toggle the input_boolean by turning the light switch off and then back on).

# -------------------------------------------------------------------
# Automations to allow for manually disabling the Motion-Controlled Light feature
# by simply turning the light switch off then back on within 3 seconds

# Start timer when light is turned off

- alias: 'Kitchen light turned off'
  trigger:
    platform: state
    entity_id: light.kitchen
    from: 'on'
    to: 'off'
  action:
    service: timer.start
    entity_id: timer.kitchen_mcl


# Toggle input_boolean when light is turned on
# only if timer is active

- alias: 'Kitchen light turned on'
  trigger:
    platform: state
    entity_id: light.kitchen
    from: 'off'
    to: 'on'
  condition:
    - condition: template
      value_template: "{{ is_state('timer.kitchen_mcl', 'active') }}"
  action:
    service: input_boolean.toggle
    entity_id: input_boolean.kitchen_mcl

There is an optional automation to re-enable the MCL feature after it has been off for an hour.

# -------------------------------------------------------------------
# OPTIONAL automation to re-enable the input_boolean after 1 hour

- alias: 'Kitchen MCL Re-Enable'
  trigger:
    platform: state
    entity_id: input_boolean.kitchen_mcl
    to: 'off'
    for: '01:00:00'
  action:
    service: input_boolean.turn_on
    entity_id: input_boolean.kitchen_mcl

Yet another optional automation announces the state of the MCL feature.

# -------------------------------------------------------------------
# OPTIONAL automation to announce enabling/disabling of the input_boolean

- alias: 'Kitchen MCL Announce State'
  trigger:
    platform: state
    entity_id: input_boolean.kitchen_mcl
  action:
    service: tts.amazon_polly_say
    data_template:
      entity_id: media_player.kitchen
      message: >
        {% set mode = 'automatic' if trigger.to_state.state == 'on' else 'manual' %}
        <speak> Kitchen light is now in {{mode}} mode. </speak>

One useful enhancement is to constrain the MCL feature to work only between sunset and sunrise. You can do this by adding conditions to the first two automations.


NOTE:

If you would prefer to have the manual override feature used exclusively for disabling MCL, and not to toggle MCL’s state, then make the following change. In automation.kitchen_light_turned_on replace:

input_boolean.toggle
with:
input_boolean.turn_off

This will prevent the light switch from being used to re-enable MCL. You will have to use input_boolean directly to re-enable MCL or wait an hour for the auto-re-enable automation to do it for you.

7 Likes

I use a Google home voice command via IFTTT to set an input select to either On. Off. Motion night. Or motion always.

Randomly came across this.

I am using a kind of similar method, but with some changes to make it more non-smart user friendly.
For each light, I have an override boolean for manual control only, plus I have a boolean for all lights (it doesn’t change the individual lights’ boolean value, but rather globally turns off and on autolights. This is a simple switch for my wife who doesn’t really understand most of what is going on in the house).
The way to move to / from manual control is the following:

  • If in automatic control and light switch is turned on manually , turn off manual control for 1.5 hours
  • If in automatic control and light switch is turned off manually, turn off manual control for 5 minutes
  • Every night at 3am, reset all controls to automatic.
  • There is also an automatic control page, that turns on and off the individual booleans as well as the control all boolean.

9 posts were split to a new topic: Split topic - Motion control lights manual override

Sorry for bumping this tread, but I just need to express my appreciation. What sheer luck for me to come over this project! My WAF, especially regarding lights in my home until now, has been pretty low, but this project really made my day! Thanks!

2 Likes

I am new to home assistant and have created few automations using the automation section in HA. I have also used some using BluePrint, but how do i add these automations? how do i make it work? Please suggest.

It involves more than just automations. All of the required entities are listed in the first post and you must create all of them. If you don’t know how to copy-paste the posted YAML into the correct files on your system, you will have to create them from scratch using the user-interface.

My only issue with these types of automations are they don’t survive ha restarts and reloads of the automations. Anything spanning more than a few seconds I typically rely on a timer or state of an input helper. New people don’t realize this and are left with lights that didn’t do what they were supposed to or in this case the override not re-enabling.

  1. This topic’s main goal was to demonstrate a specific technique, namely how to signal a manual override by employing a timer.
  2. The use of the for is completely secondary to the main principle of the override (in fact, it’s part of an optional automation).
  3. The use of for can be replaced by a more robust method that survives restarts such as a restorable timer or other restart-survivable technique (Time Trigger monitoring an input_datetime with a computed duration).
  4. I leave it to others to re-design the optional automation (it’s not difficult but isn’t the focus of this topic).

No I totally agree. I wasn’t trolling. I just think it is good to keep the new people that implement things like this understanding of ‘why’ it didn’t work at times. When I started with HA, I used ‘for’ durations a lot and took my time to understand why they didn’t work and had to refactor to fix it. I actually use this ‘toggle’ method for enabling child safety alarms when my nephew comes over.

1 Like

I apologize if I sounded too forceful and defensive; I can definitely empathize with your experience.

Learning how various things don’t survive restarts came from reading forum posts as opposed to discovering it in the documentation. I haven’t reviewed the documentation lately (it’s always updated with new information) but I suspect it may still be undocumented.

Here’s one for users of the Visual Automation Editor, when you click the Save button it validates all automations and then reloads all of them. That means any automation that was in progress at that moment, such as waiting for a delay to expire, or looping through a repeat, or executing a wait_template or wait_for_trigger, etc is immediately terminated and reset.

At this time in Home Assistant’s evolution, it doesn’t support the concept of an incremental reload; it cannot reload just the one automation you created/modified but must reload all of them (thereby interrupting all the ones that are busy executing their actions).

hi @123, first, thank you for all the contributions you make to this community, as i get more familiar with HA, i have been scouring the forums for examples of code and somehow your name always comes up! I don’t want to hijack a thread, so would be happy to post this elsewhere, but… do you have an example of the above? i’ve been noticing that (especially now since i am changing things a good bit) surviving restarts is something that i need to tackle.

This is one way. Also from Taras.

You can also use a timer which are restored on a restart to do it.

1 Like