Using an event in the wait_template of a script?

It does seem strange but my use case is that I just started using a CPAP machine. And for the insurance to pay up I have to use it for four hours in a 24 hour period.

And to complicate things my work schedule is a rotating 12 hour shift (4 days on days. 4 days off, 4 days on nights, 4 days off) so I can’t just use a regular time slot because I never really go to bed at a regular time.

So I figured I would setup an automation to turn on an indicator to tell me it’s been at least four hours that I have been wearing the mask. At night I turn on a Sonoff Basic that I have connected to an unused extension cord and I use the green glow of the LED to tell me I haven’t reached the 4 hour mark yet. It’s bright enough to see it on but not so bright it bugs my sleep.

When I work nights and sleep during the day I can’t see the green glow so I use a bedside lamp with a Z Wave bulb in it that I set to a minimum brightness and when it goes off I know I can remove the mask.

So I set up two automations for that triggered by two input booleans. One to turn on the nights indicator & one to turn on the days indicator. And I use a simple delay in the action to wait four hours to turn the indicators and booleans off. So far so good. Until today when I told Alexa to turn on the wrong boolean and my system failed me.

So I figured I could write it all into one automation and use one boolean to control everything. The problem is my services and entity_ids are different depending on which time of day I turn it on.

So I figured I could use the automation and call a script based on the time I turned on the boolean to either run the days script or the night script. easy right. Again, so far so good. But then I thought about the fact that what happens when I turn on either the days indicator when it’s light out and then it gets dark and then light being on will bug me? Or when I turn on the night indicator and it gets light and I can no longer see the green LED glow? So I set up a couple of transitional scripts that takes sunrise/sunset into account to turn off the days//nights indicator and turn on the nights/days indicator.

So I use a wait template to do the transition during the four hour window based oin the sun rising or setting. But then I can’t use another wait template to turn it off at four hours from the time it originally got turned on. So I figured I’d start a timer at the beginning of the script then take the last actions (turn off both the correct indicator and the boolean trigger) when the timer was finished.

So that leads to the question. How do I use the timer.finshed event in a wait_template.

Here is an example of my transitional script:

      - service: switch.turn_on
        entity_id: switch.extension_cord_3
      - service: timer.start
        entity_id: timer.cpap_transition
      - wait_template: "{{ is_state('sun.sun','above_horizon') }}"
      - service: light.turn_on    
        entity_id: light.zw_light_2_level
          brightness: 15
      - service: switch.turn_off
        entity_id: switch.extension_cord_3
      - wait_template: "{{ what_do_I_put_here_? }}" <---
      - service: light.turn_off
        entity_id: light.zw_light_2_level
      - service: input_boolean.turn_off
        entity_id: input_boolean.cpap_indicator

I don’t think the timer states are on or off. I believe they are active & idle.

But I think I’ve had issues with the correct state showing (idle) when the timer should be done.

Can you not then use ‘idle’ in the wait_template? While the timer is running it should then be ‘active’, allowing you to use the transition to ‘idle’ as the trigger for that last wait_template?

Yeah, I guess I could try it because I don’t have any hard evidence that the timer state is unreliable. just kind of a vague “I think I remember something about that”.

It would still be interesting to know the answer to the original question tho in case it comes up in another scenario.

I did a search and didn’t find anything with an answer.

A workaround would be to use an automation to set an input_boolean with the event, and then switch the boolean back off a second later. Then use the input_boolean turning on in the wait_template.

I thought about doing something like that as well. It would add another automation tho.

But it’s only one more automation so it’s not really a big deal.

Or instead of a timer I could set an input_datetime to four hours later and use that to reset everything. Which, TBH, would probably be more bullet proof since I think timers don’t survive restarts. But, OTOH, I doubt that’s a concern because I’m the only one who ever restarts HA and hopefully I’d be sleeping. :wink:

1 Like

Have you considered using the History Statistics Sensor?

  • It would monitor the the state of cpap_indicator.
  • An automation would monitor the HS Sensor for when it reaches 4 hours.
  • The HS Sensor resets itself every day at midnight.

The only thing I’m not sure is how this approach may be affected by your 12 hour shifts.

I think I would have to figure out how crossing the midnight boundary would affect it. If I go to bed at 10 then I could remove it at 2 but since the sensor gets reset at midnight then it would reach 4 hours until 4 am.

Also, the reset boundary for the cpap machine is noon. So there might be some strangeness trying to get those two things to work in tandem.

I’ll definitely look into it tho. Thanks for the suggestion.

I’ll admit that I didn’t grok the implications of the 12-hour shift cycle. FWIW, you can specify when the HS sensor resets itself. I said ‘midnight’ out of habit but the start option supports a template so it can be set to whatever hour you require. The example in the docs sets the time to 00:00:00.

# Example configuration.yaml entry
  - platform: history_stats
    name: Lamp ON today
    entity_id: light.my_lamp
    state: 'on'
    type: time
    start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
    end: '{{ now() }}'

I would seriously at least try my suggestion for the final wait_template to see if it works before writing it off and trying other more complicated solutions…

wait_template: "{{ is_state('timer.cpap_transition', 'idle') }}"

1 Like

It’s not a bug, it’s a feature! I got the same advice as you, to use an input_boolean.

1 Like

Actually I didn’t write it off because that is what I currently decided to go with right now and it seems to be working OK in the very limited testing I’ve done in the last couple of hours or so.

So, thanks for the suggestion. :wink:

I might change and go with the input_datetime option tho just to make it a bit more bullet-proof due to timer state retention issues as noted above.

Unfortunately that’s kind of the same conclusion I’ve come to myself.

But the timer going to idle seems to be working for now and I may switch to another solution.

But I guess for now the “solution” to the original question in this thread is there isn’t one. :frowning:

Well, after doing some more testing I realized that using an input_datetime in the script instead of a timer finished won’t make the script any more reliable. I didn’t think about the fact that scripts using a wait_template don’t survive HA restarts either just like timers. So the script would never get to the timer to “idle” or the input_datetime comparison either.

To really make this bullet-proof i will end up having to use an automation to cancel all of the actions that the script turns on (light or switch) at the pre-set input_datetime.

Since I realized I had to also take into account varying sunset/sunrise times and DST changes throughout the year this simple little exercise in writing two easy automations has bloomed into a mildly complex little project. :laughing:

I’m sure I can pare it down some, tho, if i eliminate some redundancy.

sounds like an appdaemon solution to me. I can help you with that if you need to get there. Or even node red. Either way, it’ll take alot with HA’s automation.

Thanks for the offer but I think I’ve got it acceptably worked out using HA scripts & automations.

I fudged the sunset transition automation 4 hour window a bit since the longest time difference for sunset throughout the year here is from 17:11 in the winter to 21:17 in the summer so it exceeds my 4 hour time by 6 minutes. The four hours is a minimum so I just bumped the delays/timers to 4:15.

And with me being the only one to restart HA I shouldn’t run into an inopportune restart anyway. and if I do it’s not anything super critical anyway.

But, OTOH, if you want to just have a play with it and see what you can come up with in AD I would be interested in seeing how it could be done there. I’ve never done anything at all with it and wouldn’t even know where to begin.

1 Like

Like you said, this…

and I’ll be honest I’ve only been following this in case I can pick up any new knowledge so am not entirely familiar with the details. However if it helps I have timers setup that survive restarts by knowing the start time and duration. It’s not exactly rocket science, I know but I’m happy to share if it might be useful.

If I’m just barking up the wrong tree, ignore me.

1 Like

Not at all. Go ahead and post how you accomplished it. The more information out here the better. :slightly_smiling_face:

I’m still playing around and tweaking it a bit so I might still use it.

OK. But first, my use of time in Linux (python, jinja… whatever) is not exactly up to scratch so @petro or anyone else please don’t laugh, but by all means feel free to offer improvements.

This is a part of a ‘Guest Mode’ package but this is the relevant bit. The whole package is in my GitHub (This is most definitely NOT a plug, my GitHub is not a true repository, it is just a place I put stuff that others have asked for and is too big to paste here).

  #=== Check Guest mode schedule timers at HA start up
  #=== If the house is not in holiday mode and
  #=== if they are turned on, it is the right day and
  #=== the time now is during the on time, then set
  #=== the timer to run until the scheduled end time.
  #=== Guest Schedule 1
  - alias: Guest mode schedule 1 check at startup
      - platform: homeassistant
        event: start

      - condition: state
        entity_id: binary_sensor.holiday_mode
        state: 'off'

      - condition: state
        entity_id: input_boolean.guest_mode_schedule_1
        state: 'on'

      - condition: or
          - condition: template
            value_template: "{{ states('input_select.guest_mode_schedule_1_day') == now().strftime('%A') }}"

          - condition: state
            entity_id: input_select.guest_mode_schedule_1_day
            state: 'Every Day'

      - condition: template
        value_template: >
          {% set time_now = as_timestamp(now()) %}
          {% set start_time = states('input_datetime.guest_mode_schedule_1_start_time') %}
          {% set start_time = as_timestamp(now()) | timestamp_custom('%Y-%m-%d') + ' ' + start_time %}
          {% set duration = states('input_number.guest_mode_schedule_1_duration') | int * 60 %}
          {% set end_time = as_timestamp(start_time) + duration %}

          {{ time_now > as_timestamp(start_time) and time_now < end_time }}

      - service: timer.start
          entity_id: timer.guest_mode_schedule_1_duration
          duration: >
            {% set time_now = as_timestamp(now()) %}
            {% set start_time = states('input_datetime.guest_mode_schedule_1_start_time') %}
            {% set start_time = as_timestamp(now()) | timestamp_custom('%Y-%m-%d') + ' ' + start_time %}
            {% set duration = states('input_number.guest_mode_schedule_1_duration') | int * 60 %}
            {% set end_time = as_timestamp(start_time) + duration %}
            {% set seconds_left = end_time - time_now %}
            {% set hours_left = seconds_left // 3600  %}
            {% set minutes_left = (seconds_left - (hours_left * 3600)) // 60 %}

            {{ '%02i' | format(hours_left) }}:{{ '%02i' | format(minutes_left) }}:01

And pictures can help so…


That looks interesting. I might be able to co-opt some of that and use the input boolean that starts my CPAP indicator system in motion to set the “start_time” and since the duration is always going to be the same that simplifies that a bit.

I think I can make that work…:thinking: :slightly_smiling_face:


1 Like