⏱ Scheduled Timeslot Automation (e.g., Vacuum)

Tags: #<Tag:0x00007f32651d9270>

Description:
Timeslot Scheduler (e.g. for vacuums) that allows to define an action to be executed within the specified timeslot and its condition. Personally, I use this blueprint to schedule my vacuum cleaner. As I’m now working mostly from home, I defined a scheduled timeslot for every room. For every room I defined a binary_sensor that checks if the room is ready to get cleaned (based on motion-detectors, media_players etc). Every minute, the timeslot, and its conditions are evaluated again. If all conditions are truthy within the specified timeslot the scheduler triggers the action. Once the action has been triggered, the current time is saved to a input_datetime helper to avoid another execution during the successive timeslot evaluation.

Blueprint:

Notes:

  • The automation and thus it’s conations is evaluated every minute
  • Use this Gist URL to import the blueprint to HA: https://gist.github.com/pavax/680ba1f2d34b0697bf0bbb5a73ed68d3
  • Do not specify seconds in the time input fields (as the automation is run every minute and not second)
  • Currently All conditions must match to trigger the action
  • A input.datetime helper entity must be defined to store the timestamp of the last-successful run of the action. This is needed to avoid that the same action runs multiple times within the same timeslot.

Tip & Ideas:

  • I defined several binary_sensor for my scheduled vacuum automations. The following example changes to the state off 15 minutes after the last motion was detected in my kitchen or immediately to on if a motion is detected

      presence_kitchen:
        friendly_name: "Kitchen Presence"
        value_template: >-
          {{ is_state('binary_sensor.pir_sensor_03_movement', 'on') }}
        delay_off: "00:15:00"
    

    … or the following once for the living room that’s state is changing to off if the tv is not playing nor the sonos media-player for 15 minutes

      presence_living_room:
        friendly_name: "Livingroom Presence"
        value_template: >-
          {{ 
              is_state('media_player.living_room_tv', 'playing') or 
              is_state('media_player.default_room','playing')
          }}
        delay_off: "00:15:00"
    
  • Since we anyway need to define a input.datetime helper entity I customized that to store additional attributes. In my case i defined the vacuum room coordinate on that helper entity, to extract them again in my vacuum dispatcher script:

      input_datetime.vacuum_kitchen_last_schedule_triggered:
        zone:  [[14541,24287,16345,26182,2]]
    

Gist:

This is known as the ‘polling’ approach. Instead of the resource telling you when it’s ready, you are continuously checking if the resource is ready. Simple example: you want to know when an employee is available to perform a task. In polling, you repeatedly ask them “Are you ready now? Are you ready now? Are you ready now?” In event-based, the employee informs you when they are ready.

Let me know if you are interested in learning more about how to implement an ‘event-based’ approach using triggers and conditions.

Thanks for the comment. I deliberately choose to use a polling approach. Assuming by event-based approach you’re referring to defining the various trigger items and still use the conditions.

The main reason was to sacrifice elegance over complexity :stuck_out_tongue: I know I’m lazy

So, your approach would be the following?

  • For every sensor (I called them condition sensors) I’d also have to write its own trigger element next to its condition element. I’d use a template-trigger element since that allows me somehow to check against if the sensor has been defined in the blueprint
  • I’d also have to define a time-trigger for the start of the timeslot
  • I’d also have to define a homeassistant start trigger to make it robust against restarts

Edit:

  • I didn’t find a way to define a trigger for the optional sensors 1 - 3. This ends up in an error as the variables condition_sensor_01 and condition_state_01 have not been defined yet during the trigger-phase:
    trigger:
      - platform: template
        value_template: "{{condition_sensor_01 != None and is_state(condition_sensor_01,condition_state_01) }}"
    
  • The following works fine but you’d have to define all sensors 1-3 in the blueprint (e.g., set all to the same value :confused: ). I hope in a future release of blueprints, it’s going to be possible to define optional input elements in triggers and easier to handle them in conditions and actions
    trigger:
      - platform: time
        at: !input time_to
    
      - platform: state
        entity_id: !input condition_sensor_01
        to: !input condition_state_01
    
      - platform: state
        entity_id: !input condition_sensor_02
        to: !input condition_state_02
    
      - platform: state
        entity_id: !input condition_sensor_03
        to: !input condition_state_03
    

might seem a stupid question. but what stops the automation to be ran endlessly if no presence is detected. it runs once lets say. then still no presence is detected, it starts again? since automations are checked every minute. lets say your kitchen takes 10 minutes to clean this means that in that hour, it could easily clean it 3 4 times… i’m asking because I want a different approach. my times are from 08:00 til 13:00, if no one is at home , the vacuum cleans the house once. but using your blueprint, i guess it would do it over and over…

Good question - but the automation won’t trigger multiple times within the same time-slot. A timestamp is stored in the input.datetime entity when the automation was triggered successfully (after all conditions evaluated to true in that time-slot). The following condition in the blueprint takes care of that:

  - condition: template
    value_template: >
        {% set current_date = now().strftime("%Y-%m-%d") %}
        {% set timeslot_begin = strptime(current_date + " " + time_from, "%Y-%m-%d %H:%M:%S") %}
        {% set timeslot_end = strptime(current_date + " " + time_to, "%Y-%m-%d %H:%M:%S") %}
        {% set last_triggered_at = strptime(states(last_triggered), "%Y-%m-%d %H:%M:%S") %}
        {% set already_triggered =  timeslot_begin <= last_triggered_at < timeslot_end %}
        {{ not already_triggered }}

This should make sure, that a vacuum won’t go crazy and starts cleaning over and over :slight_smile: I hope that’s gonna help you - let me know if it works for you. Happy to support.

im trying to use a different approach, since i found some written example . not sure im making any sense, but im working with what i know so far. im just starting up with HA . i guess ill have to manually make my automation, since your is a bit different. just read about input_boolean online (had no knowledge of it). i will make a ‘already_cleaned.input_boolean’, and use that as a condition (boolean off- start automation, on- dont start it)
so once the automation triggers, it will also change the state of boolean to on (make it as an action).
i’l then have to reset that boolean each night to off. i think i saw somewhere how to do it :smiley: also, i dont handle templates very well… since my wish to use boolean

My blueprint does exactify what you are looking for. Give it a try :slight_smile: Should you have struggles, don’t hesitate and post a screenshot of this blueprint and your configuration here.

PS: The input.datetime helper entity and the template that I posted handle the same thing as an manually defined input-boolean

I’m afraid i will struggle with the input.datetime creation… Told you I’m at the beginning… And I try to keep things as simple as possible. If interested, i can post my automation once it’s"polished" .

Easy - I can help you with that - as everythign is available from the UI - just go the the Menu Configuration -> Helper -> from there add a new Helper of Type Date and Time (make sure you select Data and time) and
give it a name (for example: Vacuum Last Cleaned At).

Then create an new automation based on my blueprint and select that helper-entity input_datetime.vacuum_last_cleaned_at

sweet. i will just give it a try in a sec. for the moment i used “my version”. this is the automation to do the cleanup. ill have to create a new one to reset the input_boolean to its off state each night at 12.
https://paste.ubuntu.com/p/9xQYw57xYs/

see anything wrong in mine for the moment?

im seting it up at the moment. noticed i need sensors also. why not place a basic entry, like device, state, etc. would prevent from creating extra sensors, and use what is already available in each ones config. dont take it as a complaint. myself i like to keep things as simple as possible, not create 600 sensors , entities, cause then i tend to lose myself in them ( select one instead of other, etc)

good - your automation starts vacuuming everytime when the input_boolean.mimi_cleaned_once changed to off BUT only between 08:00 and 15:00 and not is a home.

The Problem is that when the input_boolean.mimi_cleaned_once changes to off at 12:00 (night) your automation is triggered, it then checks the conditions which in your case are not fulfilled as the time is before 08:00 and thus the actions are not called.

That is exactly what my blueprint tries to address.

But will it not try to do it each minute etc. Until it reaches the 8 o’clock time? Thanks for pointing it out. I will make the second automation to reset the bolean at only 7:57. So it then tries to trigger it only 3 times

Based on your automation you can select all the corresponding entities from the UI within my blueprint:

Last Trigger At: select the input date time helper
condition sensor 01: choose your entity person_XXX and set the state to home
condition sensor 02: leave it empty
condition sensor 03: leave it empty
action: select vacuum.start

i have to do that using yaml i suspect. since selecting it in the ui doesnt give any other option related to person.xx

just ignore this one, im stupid and not paying attention. its exactly under condition sensor.

No need from yaml :slight_smile: Thanks to the blueprints you can do everything in the UI: Just install (Import) my blueprint (Configuration -> Blueprint) and then based on it create a automation (there is a screenshot of the UI on how my blueprint get’s rendered in my initial post)

i’ve set it up. it looks like this: https://paste.ubuntu.com/p/x8v5MsD5fP/
after looking at the blueprint i understood how it works. my basic understanding is that the blueprint is linked to the automation. and i noticed that the trigger for the blueprint, hence automation is the template you created, which is always modified by the automation itself using the ‘last triggered at’ field. that is nice indeed. i still got alot to read, and hopefully better understand templates. thanks for your help

The yaml (https://paste.ubuntu.com/p/x8v5MsD5fP/) looks fine - except I’m not so sure about the lines: #23-24

For the sake of a complete example here is also mine:

alias: '[Schedule] Vacuum Kitchen'
description: ''
use_blueprint:
  path: pavax/scheduled_timeslot.yaml
  input:
    time_from: '13:00:00'
    time_to: '14:00:00'
    monday_enabled: true
    wednesday_enabled: true
    friday_enabled: true
    tuesday_enabled: true
    thursday_enabled: true
    saturday_enabled: true
    last_triggered: input_datetime.vacuum_kueche_last_schedule_triggered
    condition_sensor_01: binary_sensor.presence_kitchen
    condition_state_01: 'off'
    condition_sensor_02: binary_sensor.presence_living_room
    condition_state_02: 'off'
    condition_sensor_03: vacuum.xiaomi_vacuum_cleaner
    condition_state_03: docked
    scheduled_action:
      - service: script.vacuum_dispatch
        data:
          room_name: Kueche

A blueprint defines an “off-the-shelf” automation - Thus it’s as powerful as an automation - It’s a scaffolding to allow you to define an automation without the need to copy-paste them but re-use them.

To understand what a blueprint does/is, I recommend you start learning what automations are and how they work. After you mastered that corner, you’ll understand the blueprints as they are an “abstraction” layer higher. Thus a blueprint’s automation is often more complex than you’d rather just write the automation by yourself - But you’d need to define it - the automation - multiple times. In my case I have up to 10 scheduled automations based on that blueprints. I still have 10 automations at the end, but if find a bug in the way on how the automation is defined, I’d only need to fix it in my blueprint (once).

More detailed explanation / knowhow :
The requirement that you have: start the vacuum when personX and personY are not home BUT only in a timeslot, could be defined like to following automation:

Example-A
alias: my-scheduler
description: ''
mode: single
trigger:
  - platform: state
    entity_id: person.x
    to: not_home
  - platform: state
    entity_id: person.y
    to: not_home
condition:
  - condition: time
    after: '08:00'
    before: '15:00'
    weekday:
      - mon
      - tue
      - wed
      - thu
      - fri
  - condition: state
    entity_id: input_boolean.mimi_cleaned_once
    state: 'off'
action:
  - service: vacuum.start
    data: {}
    entity_id: vacuum.xiaomi_vacuum_cleaner
  - service: input_boolean.turn_on
    data: {}
    entity_id: input_boolean.mimi_cleaned_once

This automation (A) now triggers as soon as any personX or personY changes their state to “not_home” (Hint: triggers are evaluated as OR) - Kinda annoying to start a vacuuming if only one of the two left the house :sweat_smile: To only run the vacuum when the last person has left the house, (among the other conditons such as time) you’d need to add these again as another condition (Hint: conditions are evaluated as AND) as shown in the next example B:

Example-B
alias: my-scheduler
description: ''
mode: single
trigger:
  - platform: state
    entity_id: person.y
    to: not_home
  - platform: state
    entity_id: person.y
    to: not_home
condition:
  - condition: time
    after: '08:00'
    before: '15:00'
    weekday:
      - mon
      - tue
      - wed
      - thu
      - fri
  - condition: state
    entity_id: input_boolean.mimi_cleaned_once
    state: 'off'
  - condition: state
    entity_id: person.x
    state: not_home
  - condition: state
    entity_id: person.y
    state: not_home
action:
  - service: vacuum.start
    data: {}
    entity_id: vacuum.xiaomi_vacuum_cleaner
  - service: input_boolean.turn_on
    data: {}
    entity_id: input_boolean.mimi_cleaned_once

Now, imagine if you have more complex criteria’s: Such as I have in my case: only vacuum in the given timeslot when:

  • conditon-1: motion sensor is not ON AND
  • conditon-2: tv is not playing AND
  • condition-3: person is home
  • etc…

It gets quite cumbersome to repeat that always as a trigger and as a condition. And of course, you’d still need to have to reset the input_boolean.mimi_cleaned_once at midnight (or use the mode: single but add a delay action of x hours). Now imagine doing all that for every scheduled automation having conditions (as in my case for different rooms having their separate set of conditions) … it gets quite difficult to maintain.

Limitations of current blueprint
The fact, that it’s not yet so easy to define more complex triggers with optional inputs in blueprints led me to define it with a simple minute-based time trigger. The automation is triggered on every minute and thus checks its conditions on every minute BUT it won’t execute on every minute (triggering != executing).

Example-C
alias: my-scheduler
description: ''
mode: single
trigger:
  - platform: time_pattern
    minutes: "*"
condition:
  - condition: time
    after: '08:00'
    before: '15:00'
    weekday:
      - mon
      - tue
      - wed
      - thu
      - fri
  - condition: state
    entity_id: input_boolean.mimi_cleaned_once
    state: 'off'
  - condition: state
    entity_id: person.x
    state: not_home
  - condition: state
    entity_id: person.y
    state: not_home
action:
  - service: vacuum.start
    data: {}
    entity_id: vacuum.xiaomi_vacuum_cleaner
  - service: input_boolean.turn_on
    data: {}
    entity_id: input_boolean.mimi_cleaned_once

Summa summarum: Therefore, I created this blueprint to avoid pitfalls (for beginners) and lower maintenance for managing multiple scheduled automations that rely on conditions

Just saw the reply. That is how the blueprint exported the automation. Just imported the blueprint, filled it in and saved it. Then went to yaml mode and pasted it here. I have a basic understanding of how automations work, not familiar with sensors, states, and what HA can actually do, to the last bit. It’s quite some info, and the documentation is not really up to date. Thanks for taking you time to explain this much, it’s more than i discovered in the discord server.

the noob is back. any ideea why this error ?

Logger: homeassistant.components.automation
Source: components/automation/init.py:517
Integration: Automation (documentation, issues)
First occurred: 5:19:08 PM (1 occurrences)
Last logged: 5:19:08 PM

Blueprint Scheduled Timeslot generated invalid automation with inputs OrderedDict([(‘time_to’, ‘25:00:00’), (‘monday_enabled’, True), (‘tuesday_enabled’, True), (‘wednesday_enabled’, True), (‘thursday_enabled’, True), (‘friday_enabled’, True), (‘time_from’, ‘8:00:00’), (‘condition_sensor_01’, ‘person.xxx’), (‘condition_state_01’, ‘not_home’), (‘condition_sensor_03’, ‘vacuum.mimi’), (‘condition_state_03’, ‘docked’), (‘condition_sensor_02’, ‘person.xxx’), (‘condition_state_02’, ‘not_home’), (‘scheduled_action’, [OrderedDict([(‘service’, ‘vacuum.start’), (‘data’, OrderedDict()), (‘entity_id’, ‘vacuum.mimi’)])]), (‘last_triggered’, ‘input’)]): Invalid time specified: 25:00:00 for dictionary value @ data[‘condition’][1][‘before’]. Got None