Programmed trigger

To water plants i want to start watering manually. I do this by starting an automation using a button on the dashboard.
The watering should end after 1 hour. So i’m looking how i could make HA to fire a trigger at now()+1hour.
what if have tried does not work: It never fires.

alias: '_HA000 - Test action: time triggers'
description: ''
trigger:
  - platform: time
    id: Stop-it
    at: '22:29'
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: Stop-it
        sequence:
          - service: telegram_bot.send_message
            data:
              message: 'HA000.2 - Triggered action: Stop pump'
    default:
      - service: telegram_bot.send_message
        data:
          message: 'HA000.1 - default action: start pump'
      - service: input_datetime.set_datetime
        data:
          time: '08:33:00'
        target:
          entity_id: input_datetime.trigger_one_har_later
mode: single

I use choose: The default path starts the pump. Than HA should fire at 8:33 (fix time to test the automation). Later it should be dynamic now()+1hour. When fired the choose path for trigger-id “stop-it” will stop the pump.

That is the idea. Two problems: Trigger not fired and i have not found the right way to generate the “HH:MM:SS” sequence.

Trigger on your pumps being on for one hour and turn them off in the action.

trigger:
  platform: state
  entity_id: switch.your_pump_here
  to: 'on'
  for:
    hours: 1
action:
  service: switch.turn_off
  target:
    entity_id: switch.your_pump_here
1 Like

Hi Tom.
When starting an automation manually (run automation), the trigger section is skipped. Ergo nothing happens. Wouldn’t in your solution the trigger fire after the state is ‘on’ for one hour?

I’m not sure how that is relevant. You are not going to be triggering this manually. And the action still fires.

Yes, which is exactly what you asked for:

This does not replace how you turn on the pump. Just how it turns off.

1 Like

Tom, now i understand. I’m using now your solution. Before i had one automation that started the pump and after an hour stopped it again. But this means having a wait time of one hour: the automation stays active.

I Learned that automations get cancelled (without a warning) whenever any other automation is edit and saved. Therefore i was looking for an alternative. The risk that the pump runs forever i cannot accept.

thank you for helping me.

1 Like

Ok, if this time is critical there is still the possibility that the pump will run longer than an hour. Say you start the pump then 30 minutes later you restart home assistant or reload automations. This will reset the for: time on all automations. The off automation will run 1 hour from the restart/reload (1 hour and 30 minutes total).

There is a way around this.

Start a 1 hour timer in your automation that turns the pump on.

Trigger the pump off automation when the timer expires.

Timers won’t be affected by automations being reloaded and can be restored after a restart using this method by 123:

There’s another technique, that I have been employing in my own automations, where you use a Time Trigger based on an input_datetime (I learned it from finity). It requires a bit less overhead than a timer (and doesn’t require the use of a timer restoration system). It’s not as feature-complete as a timer but more than adequate for creating a simple delay (that can survive a restart).

In a nutshell:
When the pump is turned on, the input_datetime is set to one hour in the future. The Time Trigger triggers at that time and turns off the pump.

The Time Trigger is unaffected by a restart (unless the restart occurs exactly at the time the Time Trigger should trigger or Home Assistant is offline right through the scheduled time).

1 Like

Hi @Pedro34 ,

Here is a similar approach in detail:

  1. when the pump is started set the desired end time stamp like you do in your original code.
    here is a dynamic way to do it:
service: input_datetime.set_datetime
data:
  timestamp: |-
    {{ (utcnow().strftime("%s") | float + (1*60*60)) }}
target:
  entity_id: input_datetime.trigger_one_har_later
  1. Define a binary sensor that checks if current time is later than target time.
binary_sensor:
 - platform: template
    sensors:
      stop_pump_trigger:
        value_template: >
          {{ (utcnow().strftime("%s") | float > states('input_datetime.trigger_one_har_later') | float ) }}
  1. Then have a trigger based on the binary sensor is true.
trigger:
  - platform: state
    entity_id: binary_sensor.stop_pump_trigger
    to: 'on'
    id: Stop-it

This way you will trigger the action that stops the pump whenever the system is running and the target time is passed.

Please try it and let me know if you face any challenges.

Kind regards,
Ghassan

Good point, I do that too, with an adjustable run time stored in an input number.

on automation

  action:
  - service: switch.turn_on
    entity_id: switch.lounge_dehumidifier_power
  - service: input_datetime.set_datetime
    data:
      datetime: "{{ now() + timedelta(hours=states('input_number.lounge_dehumidifier_run_time')|int) }}"
    target:
      entity_id: input_datetime.lounge_dehumidifier_stop_time

off automation

- id: efafc2cc-ec20-44d0-9d63-419a8f0863f6
  alias: 'Lounge Dehumidifier Max Runtime Stop'
  trigger:
  - platform: time
    at: input_datetime.lounge_dehumidifier_stop_time

I also have a time remaining sensor:

template:
- sensor:
  - name: "lounge_dehumidifier_time_remaining" # Customized as, friendly_name: Time Remaining
    icon: "mdi:timelapse"
    state: >
      {% if is_state('switch.lounge_dehumidifier_power', 'on') and (as_timestamp(states('input_datetime.lounge_dehumidifier_stop_time')) - as_timestamp(now())) > 0 %}
        {{ (as_timestamp(states('input_datetime.lounge_dehumidifier_stop_time')) - as_timestamp(now()))|timestamp_custom('%H:%M',false) }}
      {% else %}
        00:00
      {% endif %}

Hi,

Instead of having the trigger at an exact time, it is more safe to check if the target time is passed. This will work even though the system is down at the target time. and the action will be triggered as soon as the system is up and running again.

See my approach above.

Kind regards,
Ghassan

1 Like

That’s a good point. Except there’s only a 100*1/(24x60) = 0.7% chance of this happening in any 24 hour period and in my case it’s not that critical.

So I won’t bother changing my automation but Peter should take that advice.

1 Like

Change that to 'on' (because a binary_sensor’s state value, in its asserted state, isn’t True).

FWIW, this can also be done with an additional trigger that detects a restart event along with a condition to check if the current time is past the scheduled time and the pump is on. Easily achieved within the automation without the need of a Template Binary Sensor (just an input_datetime).

For future reference, this:

timestamp: "{{ (utcnow().strftime("%s") | float + (1*60*60)) }}"

can be reduced to this:

timestamp: "{{ now().timestamp() + 3600 }}"

Right thanks, but in prefer the format 1*60*60 so it is more clear(easy) if you want to adjust to for example 7 hours then it becomes 7*60*60 or to 30 minutes then it is 30*60 etc.

The point of the example was to show that the initial gymnastics involving strftime and float aren’t needed because now() has a timestamp() method.

If your preference is to show the time offset as a calculation, that can still be done in the alternative example.

FWIW, my preference is to use timedelta when the time units must be clearly defined.

{{ (now() + timedelta(hours=1)).timestamp() }}

Very Nice. I will use it.

I am not that experienced on handling the time, but I can see that you are :slight_smile:

Hi guys and girls (are there any in this community?).

Thank you all for all the interesting ideas. I will try and test them out (i have to to understand it). :grinning:

i put this sensor definition into configuration.yaml. When verifying i get err:

Error loading /config/configuration.yaml: mapping values are not allowed here in “/config/configuration.yaml”, line 275, column 12

Line 275 is the line with “sensors:”

Wrong place?

Wrong indentation. Should be:

binary_sensor:
 - platform: template
   sensors:
     stop_pump_trigger:
       value_template: >
         {{ (utcnow().strftime("%s") | float > states('input_datetime.trigger_one_har_later') | float ) }}

This is using thge legacy template sensor platform. You should consider using the newer template integration as it supports more features:

template:
  - binary_sensor:
      - name: "Stop Pump Trigger:
        state: "{{ (utcnow().strftime("%s") | float(0) > states('input_datetime.trigger_one_har_later') | float(0) ) }}"

But you don’t really need a binary sensor for this at all. You can use a template trigger directly:

trigger:
  - platform: template
    value_template: "{{ (utcnow().strftime("%s") | float(0) > states('input_datetime.trigger_one_har_later') | float(0) ) }}"

Generally creating a binary template sensor is only worthwhile if you are going to use it in more than one place.

1 Like

Hi Tom, can you point me to the documentation for the “Template language”? Syntax, functions and functions.
The second example has a few misplaced and nested apostrophes.

To the third example: In the future (when the time trigger has passed) the comparison results always in TRUE. Will it therefore be executed constantly? Resulting in a loop switching the power off?

For the moment i changed my automations so that the time helper “one-hr-later” is set to now+1hr. This helper is used to trigger the stop automation. I tested and found that the set time survives a server restart.