💡 On-Off schedule with state persistence

This blueprint is part of the Awesome HA Blueprints project.
Read more about it on the related Community Forum topic. :rocket:

Updates will be published on the project’s GitHub repository.

:arrow_down: Get Started

Option 1: My Home Assistant

Click the badge to import this Blueprint (needs Home Assistant Core 2021.3 or higher)

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

Option 2: Direct Link

Copy this link if you want to import the blueprint in your installation.

:link: Blueprint URL

:page_facing_up: Description

This blueprint provides a simple on-off schedule, with the addition of state persistence across server reboots, powercuts, or other disruptive events which could potentially alter the expected state of the targeted entities. The automation makes sure the target is always in the expected state, even in these situations, but always leaving the freedom to manually toggle the target state as desired. It can be used on critical targets which require a simple on-off schedule during every single day.

One common scenario where this could be useful is in the case of a server reboot or shutdown. For example, let’s assume you’ve an automation A set to turn on light L at 12:00. If for whatever reason Home Assistant goes offline at 11:59 and turns back on at 12:01, automation A scheduled for 12:00 is not executed, with the result of L not being in the state you’d expect to be, after 12:00.

Using this blueprint in the above example would have guaranteed the expected behaviour, with the automation A being run at Home Assistant startup, and setting the L state as described by the schedule.

Examples of disruptive scenarios could include server reboots, network outages or powercuts. Since every installation could be influenced by many different events and check for them in many different ways, the blueprints includes the flexibility to optionally supply a custom event type which the automation will listen to. When such event is fired, the automation is run.

The blueprint already implements the support for listening to Home Assistant startup events, but this functionality can be disabled as desired by the user.

Internally, the blueprint calculates time ranges based on the provided On-Off times, bound to the target expected state. Whenever one of the specified times is reached or a disruptive event occurs, the automation retrieves the expected state from the calculated ranges, and enforces it on the target.

:closed_book: Full Documentation

Full documentation regarding requirements, inputs and more is available here.

Docs provide all the information you need to properly configure this blueprint on your instance.

:information_source: Changelog

Updated list of changes and improvements is available here.

Happy automating to everyone! :fire:

5 Likes

When I click on the Contribution Guidelines link, I get a 404.


image
Maybe you should directly link to GitHub instead of a relative link?

Hi @KTibow,

you’re right, thank you for the report. Now it should be fixed. :+1:

Anyway, here’s the direct link to Contribution Guidelines.

Nice one. Can it be extended to not only have time pattern as trigger but also entity states?

E. g. when daylight sensor enters “golden_hour_2” state, turn on lights. In case HA was rebooting or some other parts of the infrastructure (ZigBee mesh etc.) wasn´t available at that moment, please turn on lights when possible.

I´m thinking of a mix of this one (in a basic feature set - choosing trigger entity) and yours.

1 Like

Nice!

small note: the value_template at line 64:
'{{ trigger.platform=="homeassistant" and trigger_at_homeassistant_startup or trigger.platform!="homeassistant"}}'

can be simplified to:
'{{ trigger.platform!="homeassistant" or trigger_at_homeassistant_startup}}'

Hi @e-raser,

thank you, that’s an interesting proposal! If I understood correctly, your idea is to provide some sort of “cache” for the automation action: if targets are not available when the automation gets triggered, the automation waits for the target to become available (maybe listening to an event), then placing it in the desired state.

Definitely a great idea. We should also consider different scenarios such as the one which would occur if multiple automation “runs” get enqueued, waiting for the target to become available.
By the way, I’d rather keep the two blueprints separate so code in this one doesn’t get too complex. :+1:

Hi @stefanroelofs,

thank you very much! Just applied your suggestion to the blueprint. :+1:

I have another (new) usage scenario: covers that need to open/close based on a daylight sensor (no fixed times).

I think the blueprints‘ core functionality to run missed automations (mostly during HA restarting etc.) is something so easy and powerful it should be integrated as an option into HA Core.

Without that current limitations cut down use-cases tremendously. I want to use this for several use-cases but it‘s always impossible.

1 Like

Hi @e-raser,
that’s a really good point, we should design a blueprint which addresses this issue.

As you said, this should not be limited to a specific action or service (such as for this blueprint), but should be in the form “execute the action at the specified time” with the added feature of automatically running the automation if it has been missed.

I’ll definitely take a look at this. By the way, I think we should create a brand new blueprint, to make sure users of this one don’t have to worry about reconfiguring it with the different set of inputs this use case would probably need.

Thank you for the suggestion!

First of all, thanks for the Blueprint :slight_smile:
About custom event, how do you enter one? I am very new to HA. I want this blueprint to run every day to check the state or do it manual true Lovelace.

/Thekholm

Hi @Thekholm,
thank you for your feedback, and welcome to Home Assistant! :slight_smile:

The blueprint checks the entity state whenever there’s an Home Assistant reboot, but cannot of course cover all the different scenarios it might be used in. Any installation might depend on different “critical” services, which could alter the state of the tracked entity. The custom event allows to run this automation whenever a certain critical event occur in your system (e.g. powercut, system reboot etc.).

How to enter a custom event?

  1. You’ve an integration which exposes the “critical” event on your HA instance(e.g, Network UPS Tools). You can simply input the name of the event fired by the integration. The blueprint will listen for events matching the provided name, and run whenever one with that specific name is fired.
  2. You have some entities/devices that signal a critical event based on their state (e.g. if your wifi plug is not available, there’s a network failure o a power outage). You need to create a separate automation for triggering the custom event as follows:
alias: Fire Critical Event
trigger:
  # whenever the entity/device moves into a critical state
  platform: state
  entity_id: sensor.my_wifi_plug
  to: unavailable
condition: []
action:
# fire the event
- event: my_critical_event

You can then assign to the Custom Trigger Event blueprint input the value my_critical_event.

Hope this helps you get the automation running on your system. If you have any doubts feel free to ask, I’m here to help. :+1:

1 Like

Many thanks for your reply, I will try to test that! I have your Blueprint working for six automations and it working perfectly when HA reboots.

/Thekholm

1 Like

Ciao Matteo,
Thanks for the awesome blueprint, I’ve been looking for this for days.

One question, is there a way to make the automation run whenever we change an input? Meaning that we want to reevaluate if the target entity should be on/off when we change the schedule.

Hi @a-reda, thank you for your feedback, happy to hear that this automation is useful. :slight_smile:

If I understood correctly, you refer to the on_time and off_time inputs.
Unfortunately there’s currently no way to check the entity state when those blueprint inputs change.

Maybe we could force the automation to run whenever it’s created or updated, even though I’m not sure it there’s a valid trigger for that in Home Assistant. I can look into this and see if there’s a way to implement the feature.

Hey Matteo, great work :slight_smile:
It took me a while to understand how to use the critical event, as I have never used the event bus before.
I got there in the end, and understood how to use it.

Perhaps you could add the additional information you’ve written above, on how to create a custom event, to your documentation, which adds missing context for people (like me) who were not familiar with the event bus.

In case anyone is interested to see how I did it:


I didn’t even know about the event bus prior to using this automation, but now I can see how it works.

Hi @Richard.Huish,

thank you so much for your precious feedback, I’m glad this blueprint is useful for you. :slight_smile: I agree that we should add additional info on how to setup the custom event directly in the documentation. I’ll update docs in the upcoming days. :wink:

Thanks again and happy automating! :rocket:

Hi @epmatt , is it possible to input_datetime instead of time selector?

I’ve tried to adapt your code but without success.

Hi @ajtudela, thank you for reporting.

What’s the behaviour you’d like to achieve with input_datetime instead of time selectors?

I guess you’d like the schedule to be on/off at a specific day and time. Are you willing to include the day as day of the week, day/month or day/month/year?

Thank you!

I have two input_datetime (only with has_time) to turn on and off my waterheater. My waterheater turns on/off every day but at differents hours. Those input_datetime change from one day to the next.

So, instead having a fixed schedule set with time selectors, will be “dynamic” with input_datetime.

Here is my code @epmatt . With this code the waterheater turns on at off_time and turns off at on_time. :confounded: Any tips?

blueprint:
  name: On-Off schedule with state persistence
  description: A simple on-off schedule, with the addition of state persistence across disruptive events, making sure the target device is always in the expected state.
  source_url: https://github.com/EPMatt/awesome-ha-blueprints/blob/e6e5ee1032237c4a6f4ced0f4cb1539103ff6d3f/blueprints/automation/on_off_schedule_state_persistence/on_off_schedule_state_persistence.yaml
  domain: automation
  input:
    automation_target:
      name: Automation target
      description: The target which the automation will turn on and off based on the provided schedule.
      selector:
        target:
    on_time:
      name: On Time
      description: Time when the target should be placed in the on state.
      default:
      selector:
        entity:
          domain: input_datetime
    off_time:
      name: Off Time
      description: Time when the target should be placed in the off state.
      default:
      selector:
        entity:
          domain: input_datetime
    custom_trigger_event:
      name: Custom Trigger Event
      description: (Optional) A custom event which can trigger the state check (eg. a powercut event reported by external integrations).
      default: ''
    trigger_at_homeassistant_startup:
      name: Trigger at Home Assistant startup
      description: Trigger the target state check and enforcement at Home Assistant startup.
      default: false
      selector:
        boolean: {}
variables:
  off_time: !input 'off_time'
  on_time: !input 'on_time'
  trigger_at_homeassistant_startup: !input 'trigger_at_homeassistant_startup'
  first_event: '{{ on_time if states[on_time].state < states[off_time].state else off_time }}'
  second_event: '{{ on_time if states[on_time].state >= states[off_time].state else off_time }}'
mode: single
max_exceeded: silent
trigger:
- platform: time
  at:
  - !input 'on_time'
  - !input 'off_time'
- platform: homeassistant
  event: start
- platform: event
  event_type: !input 'custom_trigger_event'
condition:
- condition: template
  value_template: '{{ trigger.platform!="homeassistant" or trigger_at_homeassistant_startup}}'
action:
- choose:
  - conditions:
    - condition: template
      value_template: '{{now().strftime("%H:%M:%S") >= states[first_event].state and now().strftime("%H:%M:%S") < states[second_event].state}}'
    sequence:
    - service: homeassistant.{{ "turn_on" if first_event == on_time else "turn_off"}}
      target: !input 'automation_target'
  default:
  - service: homeassistant.{{ "turn_on" if second_event == on_time else "turn_off"}}
    target: !input 'automation_target'