Time based template

Well, I did actually solve this a long time ago.
Here’s what my working code looks like now.

- service_template: >
      {% if now().strftime('%T') < '21:30:00' %}
        switch.turn_on
      {% else %} script.do_nothing
      {% endif %}           
    entity_id: 
      - switch.light_a
      - switch.light_b

As @petro mentioned, you need an else-state in order to make the if state work.
Therefore I have made a simple script called do_nothing that does nothing. That’s very useful whenever the else statement is required but I don’t want anything to happen. It doesn’t mather if i send some arguments into that script.

Here’s that code:

do_nothing:
  alias: Do nothing at all
  mode: parallel
  sequence:
    delay: 00:00:00

Not always. If it’s the only, or final, service call in the action then you can simply do this:

action:
- condition: template
  value_template: "{{ now().strftime('%T') < '21:30:00' }}"
- service: switch.turn_on
  target:           
    entity_id: 
      - switch.light_a
      - switch.light_b

It executes the service call only if the current time is before 21:30:00.

For more complex scenarios, choose can be used to execute different service calls based on multiple specific and unique conditions. The old kluge of using a do-nothing script still works but no longer the only way to address the issue.

1 Like

A note for future readers:

@123 Thanks for your clarification. Our solutions are a bit different.

My example sets a condition for that single service. If the condition/if-statement is met, then the service right after the if-statement will execute. If not, the service right after the else statement will be executed. This method does not affect the rest of the script. Services before as well as after the condition will still be executed.

In your example, the script will run all the way until it reaches that condition. If the condition is met, the script will continue to be executed. If the condition is not met, the whole script will stop and no future services will be executed.

What statement shall one use then? Well, that depends on if you want to set a condition to just one service, or if you want to stop the rest of the script from being executed. No method is “better” than the other.

yes, I use that too, and you can make it even smaller :wink:

continue:
  mode: parallel
  sequence: []
2 Likes

@Mariusthvdb So much better! I’ll use your example instead.

FWIW, your explanation was summarized in my previous post:

If it’s the only, or final, service call in the action then you can simply do this:

I also mentioned that the new-fashioned way is to use choose.

In the following example, there are three service calls. The first one is executed only if the time is before 21:30:00. The remaining service calls are all executed. This technique eliminates the need for a do-nothing script.

action:
- choose:
  - conditions: "{{ now().strftime('%T') < '21:30:00' }}"
    sequence:
    - service: switch.turn_on
      target:           
        entity_id: 
          - switch.light_a
          - switch.light_b
- service: another service call
- service: yet another service call
... etc ...

In pseudo-code it behaves like this:

action:
- IF now().strftime('%T') < '21:30:00' THEN Turn on switch.light_a, switch_light_b
- next service call
- next service call

choose can also be used to handle more complex situations. In the following example it turns on specific lights depending on the time of the day. If the time is not within any of the time ranges, no lights are turned on and the remaining service calls are executed.

action:
- variables:
    t: "{{ now().strftime('%T') }}"
- choose:
  - conditions: "{{ '07:10:00' <  t < '08:00:00' }}"
    sequence:
    - service: switch.turn_on
      entity_id: switch.light_a
  - conditions: "{{ '16:00:00' <  t < '18:30:00' }}"
    sequence:
    - service: switch.turn_on
      entity_id: switch.light_b
  - conditions: "{{ t < '21:30:00' }}"
    sequence:
    - service: switch.turn_on
      entity_id: 
      - switch.light_a
      - switch.light_b
- service: another service call
- service: yet another service call
... etc ...
2 Likes

you convinced me to rewrite several spots I use the Kluge as you call it (btw, had to google that: “Something that should not work, but does” :wink: ), but could not resist keeping in spots like this:

check_turn_down_the_house:
  alias: Check turn down the house
  mode: restart
  sequence:
    service: >
      script.{{'turn_down_the_house' if is_state('input_boolean.house_turned_down','off')
                else 'continue'}}

somehow I like the explicit notion of continuing without further action compared to the

sequence:
  - condition: template
    value_template: >
      {{is_state('input_boolean.house_turned_down','off')}}
  - service: script.turn_on
    target:           
      entity_id: script.turn_down_the_house

the latter would leave me with a feeling of uncertainty what happened…
anyways, thanks for your educational examples.

From my (old) copy of the The New Hacker’s Dictionary by Eric Raymond (now out of print):

kluge /klooj/ [from the German ‘klug’, clever]

  1. n. A Rube Goldberg (or Heath Robinson) device, whether in hardware or software. (A long-ago Datamation article by Jackson Granholme said: “An ill-assorted collection of poorly matching parts, forming a distressing whole.”)
  2. n. A clever programming trick intended to solve a particularly nasty case in an expedient, if not clear, manner. Often used to repair bugs. Often involves ad-hockery and verges on being a crock. In fact the TMRC Dictionary defined ‘kludge’ as “a crock that works”.
  3. n. Something that works for the wrong reason.
  4. vt. To insert a kludge into a program. “I’ve kludged this routine to get around that weird bug, but there’s probably a better way.”
  5. [WPI] n. A feature that is implemented in rude manner.
1 Like