Single blueprint, multiple automations

See, I would say that’s over complex - the majority of your actions are turning on or off the other automations. If this was just one automation then the only actions would be to turn the light on and off.

Also it relies on timers and input numbers to determine the length of time a light should be on, rather than a for: statement in a trigger (for which you could still invite an end user to use an input_number if they so desired)

No offence, but this is easily reduced to one automation, and really should have been all along.

I would say this is a prime example of why blueprints are here, so that people aren’t making multiple automations like this when one will do.

2 Likes

I would like this exact automation.
Do you have an example with it all done in one automation?

Yeah. And I 100% get that. And that’s the tool we have at the moment, so, that’s how it is. I’m only saying, I can absolutely see a use for a single blueprint instance to result in more than one automation.

As a seasoned programmer who writes most of my automations in python (via pyscript), even then, I sometimes write two “automations” that could be one just because it’s easier to maintain, debug, or troubleshoot that way.

As I said, so do I. But the point is that maintenance of the automation is no longer required, because its in a (hopefully tried and tested!) blueprint.

So as I alluded to earlier I currently have 3 automations that I intend to combine into one blueprint. The first of those 3 already replaces the 4 automations posted by the OP - and then there’s 2 more that most people probably use multiple automations for. If we work on the same ratio, my single blueprint would replace 12 automations per entity for most users.

I think the extra effort to combine it into 1 is worth it to make it a single reproducible ‘package’ (not to be confused with packages, of course)

It is quite complex. However, it has the extra feature of, essentially, if someone changes this light while the automation is waiting out the delay to turn it off, then the automation will not turn off the light. (at least, the OP claims it does this in the code comments. I haven’t actually verified that in the code).

This added piece is possible with a complex nest of choose statements, but REALLY easy with an automation that can just be turned off.

Here’s the included blueprint for “see motion; turn on light”:

 blueprint:
  name: Motion-activated Light
  description: Turn on a light when motion is detected.
  domain: automation
  source_url: https://github.com/home-assistant/core/blob/4880a1d55a12c5ae0f8456a828aff69819f791d5/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"

action:
  - service: light.turn_on
    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

How would you modify this to NOT turn off the light if it was adjusted during the delay period?

2 Likes

I absolutely agree, the effort is worth it. Not only from your perspective, so that when you do make a change to how that logic works, all of your automations from that blueprint are automatically updated. But also because there will now be countless numbers of users who don’t have to go through the pain of dialing in every last detail just right to make it perfect, they can just use what you’ve done and move on to the next thing – no need to reinvent the wheel.

2 Likes

Well, for that as an example, I wouldn’t use a delay - I would use a ‘for’ in a second trigger and then condition that trigger out if it was adjusted.

So… as a start…

 blueprint:
  name: Motion-activated Light
  description: Turn on a light when motion is detected.
  domain: automation
  source_url: https://github.com/home-assistant/core/blob/4880a1d55a12c5ae0f8456a828aff69819f791d5/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"
  - platform: state
    entity_id: !input motion_entity
    from: "on"
    to: "off"
    for: !input no_motion_wait

action:
  - choose:
      - conditions:
          - condition: state
            entity_id: !input motion_entity
            state: 'on'
        sequence:
          - service: light.turn_on
            target: !input light_target
      - conditions:
          - condition: state
            entity_id: !input motion_entity
            state: 'off'
        sequence:
          - service: light.turn_off
            target: !input light_target

and then, somewhere in that, you would condition out if the light state has changed? How would you do that? How would you know the light had be dimmed or had the color change? With a second automation that gets turned on when this automation fires, I could look for any service calls for the light entity and cancel the sequence when that service call was seen.

So, perhaps you’d add an event trigger to this to look for the service call, and then some more choose statements to determine if it was the motion or the service call that triggered this, and some kind of input_boolean to mark that it shouldn’t be touched?

1 Like

The op uses the event, so you could use that and set an input boolean (you’d have to tell end users to create the boolean).

But personally, given that the automation turned the light on and therefore knows the brightness its supposed to be at, I would just compare the current brightness to the expected brightness and stop execution if they don’t match.

(You have to also consider that these aren’t my automations we’re talking about so I haven’t conceptualised them, I would have designed them differently from the start).

That’s a decent option… if the automation knows the brightness and color that it turned the light on with, it could easily check to see if that was still the case before turning it off.

And, yeah, it’s hard to consider automations that start from a different place than you might have started from or that take a different approach than you would.

In many of my (non-blueprint) automations, I look for lighting changes in order to know that someone really cares about the light in that room and doesn’t like the way the automation set it. However, I don’t keep the light from turning off, I just extend the “delay” time considerably until the entire motion event (and turning off of the light) has happened. Then the delay goes back the way it was. I’ve almost got the logic for it all wrapped up neatly enough to be what I’d truly consider “usable by others”. But the automation was too complicated for me to get any enjoyment out of trying to bash it through a rat’s nest of “choose” statements. So it’s all written in pyscript. However, I’m hoping to make it available as a “blueprint” by utilizing pyscript services. We’ll see if I get there. :slight_smile:

Yeah, that’s how I’d do it if it was my automation.

Also, people ‘live’ differently, so the vast majority of my automations for this sort of thing are in places where people don’t hang around (halls, landings) - then for the places people do (bathroom, kitchen) I’ve added different override methods, and then bedrooms have a completely different set of rules.

But yeah, what I’m saying is that it can be done, I think the key is to remember we’re not writing an automation (where we might say it’s easier just to do two), we’re writing a comprehensive blueprint which is an entirely different beast and should be approached as such.

Absolutely. “choose” is pretty powerful. And since Home Assistant allows multiple triggers on the same automation and all of the aspects of the trigger exposed to the action, I’m not brave enough to say “anything you can do with 5 automations you can do with 1 and a pile of choose statements”… but it’s likely true.

I imagine even, maybe, if you really wanted to, you could automate EVERYTHING with one single automation. But, I wouldn’t want to even TRY to write it. Though, if someone HAS done this, I’d love to see it.

You definitely can. Although I think chucking templates in tends to make it easier.

Again, you definitely could, but it would ruin my OCD. That said it equally ruins my OCD to use several automations for one function.

To me, an automation should cater for a situation. The only reason I have 3 instead of one (in the examples I was talking about above) is for maintenance purposes, and I only do that in very specific circumstances. Even then, as soon as blueprints were announced I knew they were getting merged :joy:

But I don’t think it will.

By design blueprints end up being more complex for the person writing them than the equivalent automation would be.

I agree that it makes it easier for the end user to implement the blueprint in the automation (even if that end user will be the author using it for different entities/details).

Have you seen the large amount of code that goes into a blueprint to define the metadata that the blueprint exposes to an automation? And then after the blueprint is properly commented and described to make it understandable to the end user (who didn’t write it) it’s ridiculously huge.

I honestly couldn’t imagine trying to combine all of those automations that you have now into one automation then try to translate that into a single blueprint. Even if the blueprint had the ability to have multiple different trigger/condition/action sections to incorporate many different automations into one huge blueprint (I think I realized that is what you are asking) the resulting blueprint would be unreadable and almost impossible to maintain.

You still have to dexscribe every single entity, trigger, condition, action, setting, option etc just like you do in an automation in the blueprint. And the add more to it. I can’t see how it makes it more simple.

That’s the reason why the response on discord is to use more than one automation - “It’s easier to write and troubleshoot two automations.” It would be exactly the same (only more so) for blueprints just due to their nature.

at least that’s my humble opinion… :wink:

2 Likes

In the two years I have been helping people fix their automations, this early batch of blueprints is revealing some of the most eyebrow-raising examples I’ve ever seen.

I’ve stated elsewhere that blueprints are proving to be the fastest way to distribute an unoptimized automation.

Now I see a request to allow a single blueprint to deliver multiple unoptimized automations.

Perhaps the focus should be on refinement prior to distribution.

5 Likes

Look forward to using a working version of this blueprint (or something like it)!

Hi there! I’m experimenting with blueprints for the first time, and also have encountered this desire – I’d love to have multiple automations generated by a single blueprint. I’m sure @anon43302295 will tell me I’m wrong to want this, but let me describe my needs so I can get shot down. :slight_smile:

  • I have 13 rooms in my home with motion sensors. I want their lights to turn on dimly if motion is sensed at night, and be able to turn the lights on and off with the wall switches at any time.
  • I’m using the Vantage Infusion custom component, and fully realize my code is useless to anyone else. So I have no intention of sharing my blueprint, or “optimizing my code” for sharing. My #1 goal is ease of maintenance.
  • Right now I’ve generated a template for my motion sensor automation, and have made 13 copies of that template and specialized each one by hand for each room. Each room has 5 automations in a single file.
    Which means if I want to change it, I have to make the change 13 times. Annoying!
  • I’ve been tempted to use GNU m4 or the like, but have not gone that far yet.
  • I figured blueprints should be perfect! But they don’t seem to support my template with multiple automations per room. And if I create 5 blueprints per room, the code is almost as awkward as what I already have.

Given the comments above about optimizing blueprints and combining automations into single mega-automations, I’m guessing my use case (“make code maintenance for my own code easier”) is not the goal use case for blueprints. Instead, the goal is to make it easy to share easy-to-use blueprints with others, at the cost of making blueprint creation somewhat more complex. Is this correct?

If it is helpful, here is my template which I specialize for each room:

- alias: '%NAME% lights button or off button pressed'
  trigger:
    - platform: event
      event_data:
        button: %BUTTON1%
      event_type: vantage_button_pressed
    - platform: event
      event_data:
        button: %BUTTON2%
      event_type: vantage_button_pressed
    - platform: event
      event_data:
        button: %BUTTON3%
      event_type: vantage_button_pressed
  action:
    # Suppress motion sensing for 10 seconds so the lights don't immediately
    # turn on just after I turn them off.
    - service: timer.start
      data:
        entity_id: timer.%LNAME%_nightlights_suppress_motion
        duration: '00:00:10'

- alias: '%NAME% motion sensor triggered, lights currently off'
  trigger:
    - platform: state
      entity_id: sensor.%MOTION%_motion
      to: Violated
  condition:
    - condition: state
      entity_id: sensor.%BSTATE%_lights_button_state
      state: '1.0' # Off
    # Only trigger at night:
    - condition: template
      value_template: '{{ state_attr("sun.sun", "elevation") < -2 }}'
    - condition: state
      entity_id: timer.%LNAME%_nightlights_suppress_motion
      state: idle
  action:
    # Potential race condition: what if the lights are turned on just as this
    # motion event arrives (a.k.a. the two automations are run in parallel)?
    # Unlikely to happen, but possible.

    # Turn the lights on dimly:
    - service: light.turn_on
      data:
        entity_id: light.%DIMLIGHTS%
        transition: 1
        brightness_pct: %PCT%
    # Set button to blue:
    - service: vantage.set_variable_vid
      data:
        vid: %VID% # A.k.a. sensor.%BSTATE%_lights_button_state
        value: 3 # Dimly lit

- alias: '%NAME% motion sensor no longer triggered'
  trigger:
    # Trigger once we've been in dim mode for 2 minutes, at least 2 minutes
    # after the last motion event.
    - platform: state
      entity_id: sensor.%MOTION%_motion
      to: Normal
      for: "00:02:00"
    - platform: state
      entity_id: sensor.%BSTATE%_lights_button_state
      to: '3.0' # Dimly lit
      for: "00:02:00"
  condition:
    - condition: state
      entity_id: sensor.%MOTION%_motion
      state: Normal
      for: "00:02:00"
    - condition: state
      entity_id: sensor.%BSTATE%_lights_button_state
      state: '3.0' # Dimly lit
      for: "00:02:00"
  action:
    # Another potential (but unlikely) race conditon: what if this condition
    # becomes true just as someone turns on the lights?

    # Turn off the lights
    - service: light.turn_off
      data:
        entity_id: light.%DIMLIGHTS%
        transition: 1
    # Set button to green:
    - service: vantage.set_variable_vid
      data:
        vid: %VID% # A.k.a. sensor.%BSTATE%_lights_button_state
        value: 1 # Off

- alias: '%NAME% empty, turn off lights'
  trigger:
    # Trigger once we haven't had motion for a long time:
    - platform: state
      entity_id: sensor.%MOTION%_motion
      to: Normal
      for: "00:15:00"
  action:
    # Turn off the lights
    - service: light.turn_off
      data:
        entity_id: light.%ROOM%
        transition: 1
    # Set button to green:
    - service: vantage.set_variable_vid
      data:
        vid: %VID% # A.k.a. sensor.%BSTATE%_lights_button_state
        value: 1 # Off

# If someone turns off the lights manually (such as with the Home Assistant
# UI), update the button state to match:
- alias: '%NAME% light turned off manually'
  trigger:
    # Trigger once we haven't had motion for a long time:
    - platform: state
      entity_id: light.%ROOM%
      to: 'off'
  action:
    # Set button to green:
    - service: vantage.set_variable_vid
      data:
        vid: %VID% # A.k.a. sensor.%BSTATE%_lights_button_state
        value: 1 # Off

Then you’re not looking at blueprints, and you can make as many automations to facilitate your needs as you desire.

Also, as blueprints only create automations and not timers, and several of your automation’s require timers, you’d be out of luck to blueprint them in the current state without additional work by the recipient.

However to transpose your idea in to blueprints, you don’t need a blueprint to make 5 automations, you can just make 5 blueprints. Or you can slim down your existing 5 automations into 4, 3, 2 or 1 automation(s) - ideally replacing the timer entities with better methods as you go so that whatever number you end up with are reproducible without additional configurations - and make that number of blueprints.

But nevertheless, the point is that from the very outset you don’t require blueprints. You currently have 5 automations per room, and if you blueprinted it in its current form, you would still need 5 automations per room, it’s just that they will be generated by the blueprint instead of copy and paste. If it’s not a shareable concept, then transforming them in to a blueprint is pointless.

Reducing them from 5 to any number lower than 5 will vastly improve your coding though, and you should aim for 1, for personal code-ninja glory if nothing else.

Edit - just as a simple optimisation to get you started, adding the trigger of automation 5 to automation 4, negates the need for the 5th automation before you’ve even started. And the action for automation 3 and 4 are exactly the same, so they’re clearly mergeable - so in less than 10 minutes, in spite of it being way past my bedtime, half of the work to reduce this to 1 automation is already done :man_shrugging:

1 Like

Thanks for confirming – it sounds like blueprints were not designed for my use case (of reducing redundant code).

I have to admit, in my career as a software engineer, I’ve never aimed for “personal code-ninja glory”. I aim for the opposite – easy to understand, easy to maintain, simple code. Of course, I don’t always achieve that. :wink:

1 Like

I would disagree that having those 5 automations are ‘easy to maintain’ and ‘simple’, given that 3 of the 5 are basically repetition. 3 times the code == 3 times the chances of a mistake creeping in.

2 Likes