Motion Activated Light with Conditions

Hi everyone, I’m struggling to add a condition to the default Blueprint for a motion activated light. I have created a second blueprint to work with. I want to add a couple of conditions to streamline how the blueprint activates lights based on motion. I also customized a few settings on the light conditions (kelvin, brightness level, transition time).

I want to add the following conditions:

  1. Only turn on if the sun is below the horizon.
  2. Only turn activate if the previous state of the light was “off”.

I have successfully added the first condition, but I cannot get the second condition to work. Here is what I have so far:

blueprint:
  name: Motion-activated Light After Dark
  description: Turn on a light when motion is detected after the sun is below the horizon.
  domain: automation
  source_url: https://github.com/home-assistant/core/blob/551fb449752e1c3f55eb688d24509876020852d1/homeassistant/components/automation/blueprints/motion_light.yaml
  input:
    motion_entity:
      name: Motion Sensor
      selector:
        entity:
          domain: binary_sensor
          device_class: motion
    light_target:
      name: Light
      selector:
        target:
          entity:
            domain: light
    no_motion_wait:
      name: Wait time
      description: Time to leave the light on after last motion is detected.
      default: 120
      selector:
        number:
          min: 0
          max: 3600
          unit_of_measurement: seconds

# If motion is detected within the delay,
# we restart the script.
mode: restart
max_exceeded: silent

trigger:
  platform: state
  entity_id: !input motion_entity
  from: "off"
  to: "on"

condition:
  - condition: state
    entity_id: sun.sun
    state: below_horizon
  - condition: state
    entity_id: !input light_target
    state: "off"

action:
  - service: light.turn_on
    data:
      transition: 4
      brightness_pct: 60
      kelvin: 3000
    target: !input light_target
  - wait_for_trigger:
      platform: state
      entity_id: !input motion_entity
      from: "on"
      to: "off"
  - delay: !input no_motion_wait
  - service: light.turn_off
    target: !input light_target

Any help on this would be greatly appreciated!

The problem is that your light_target isn’t an entity_id
It’s a more complex object, and is meant to be used with a target property.
There are several ways to get around this:

  • make your input selector an entity selector instead of a target selector
  • as described here use a template condition to extract the entity_id from the target (something like {{ expand(light_target.entity_id) | selectattr('state','eq','on') | list | length == 0 }}). In this example light_target is a variable and needs to be declared as such (see here).

So my understanding I would just need to add a variable section something like this?

blueprint:
  name: Motion-activated Light After Dark
  description: Turn on a light when motion is detected after the sun is below the horizon.
  domain: automation
  source_url: https://github.com/home-assistant/core/blob/551fb449752e1c3f55eb688d24509876020852d1/homeassistant/components/automation/blueprints/motion_light.yaml
  input:
    motion_entity:
      name: Motion Sensor
      selector:
        entity:
          domain: binary_sensor
          device_class: motion
    light_target:
      name: Light
      selector:
        target:
          entity:
            domain: light
    no_motion_wait:
      name: Wait time
      description: Time to leave the light on after last motion is detected.
      default: 120
      selector:
        number:
          min: 0
          max: 3600
          unit_of_measurement: seconds

# making the input variable usable in the condition
variables:
  lights: !input "light_target"
...
- "{{ expand(lights.entity_id) | selectattr('state', '==', 'off') | list | count > 0 }}"

# If motion is detected within the delay,
# we restart the script.
mode: restart
max_exceeded: silent

trigger:
  platform: state
  entity_id: !input motion_entity
  from: "off"
  to: "on"

condition:
  - condition: state
    entity_id: sun.sun
    state: below_horizon
  - condition: state
    entity_id: !input light_target
    state: "off"

action:
  - service: light.turn_on
    data:
      transition: 4
      brightness_pct: 60
      kelvin: 3000
    target: !input light_target
  - wait_for_trigger:
      platform: state
      entity_id: !input motion_entity
      from: "on"
      to: "off"
  - delay: !input no_motion_wait
  - service: light.turn_off
    target: !input light_target

And this should allow the script to expand the selected light into an entity ID that the condition can use?

Sorry for the delay

Actually I might have misled you.
I still think that the issue with your script is that when you write entity_id: !input light_target in your condition, you are expecting light_target to be an entity_id. That’s a mismatch. A target can be a list of entities, but it is actually meant as a bag of various stuff: areas, devices and entities… So, according to the Home Assistant selector schema:

Targets are meant to be used with the target property of a service call in a script sequence

I don’t see any condition type that has a target property. Therefore if you really really wanted to stick to targets, you’d have to replace your state condition with a template condition and destructure light_target yourself using the templating language.
If you want to go that way, I found a blog post that explains exactly what I just wrote and what you need to make it work. That includes the finer point about the fact that inputs aren’t readable in the templates themselves and you have to first store them in variables:

But I personally don’t like this, because this will only work if your target only contains entities. If that’s a requirement, why have a target at all? You might as well just replace your target input with an entities input, as in:

    light_entities:
      name: Lights
      selector:
        entity:
          domain: light
          multiple: true

Note here: maybe don’t add the multiple: true just yet, try without and see if it works, I’m not 100% sure about it.

Now that should solve your condition, but that will break your actions, because those service calls do expect a target!
So now they need to become:

  - service: light.turn_on
    target:
      entity_id: !input light_entities
2 Likes

That did it, thank you very much! The “multiple: true” was indeed needed to select multiple light entries.

can you share your code?