How would I automate a timer between specified hours with on/off switch?

What would be an efficient way (in terms of HA workload) to automate a binary_sensor whos value is predicated on the time of day being between “on” and “off” times (both specified as input_datetime) and also moded on the associated switch:

yaml

  # PROGRAMMER

 # Flag moded on programme selector and on/off times.

  input_boolean:
    
    # True/False to mode overall programme status
    # Set TRUE if programme is selected (On by user) and system time is within user set time range.
 
    programmer_running:
      name: programmer_running

    # Programme 1 selector On/Off appearing in lovelace as a button card.
    # User can tap this to toggle between On and Off.
 
    programme_1_enabled:
      name: programme_1_enabled

    # Programme 2 selector On/Off appearing in lovelace as a button card.
    # User can tap this to toggle between On and Off.

    programme_2_enabled:
      name: programme_2_enabled

  input_datetime:

    # Programme On/Off times.
    # User can set this in lovelace card.

    programme_timer_1_on:
      name: programme_timer_1_on
      has_date: false
      has_time: true

    programme_timer_1_off:
      name: programme_timer_1_off
      has_date: false
      has_time: true

    programme_timer_2_on:
      name: programme_timer_2_on
      has_date: false
      has_time: true

    programme_timer_2_off:
      name: programme_timer_2_off
      has_date: false
      has_time: true

The logic is:

IF programme_1_enabled [= TRUE] 
AND
IF <time-of-day> BETWEEN (programme_timer_1_on AND programme_timer_1_off)
THEN
   SET programmer_running = TRUE

I have seen many options using triggers, “ORing” and “ANDing” these, and also combining these with conditions, again “ORed” and “ANDed”. What I dont fully appreciate is how - if at all - this can be coded in yaml efficiently or inefficiently. I mean, by this, that for example if I triggered on time, then does that mean HA needs to check this every second - which would be inefficient?
e.g.

  automation:

    alias: Set programmer running on timer 1
    trigger:
      - platform: time
        after: input_datetime.programme_timer_1_on
        before: input_datetime.programme_timer_1_off
    condition:
      condition: state
      entity_id: input_boolean.programme_1_enabled
      state: 'true'
    action:
      - service: input_boolean.turn_on
        entity_id: input_boolean.programmer_running

    alias: Set programmer off on timer 1
    trigger:
      - platform: time
        before: input_datetime.programme_timer_1_on
        after: input_datetime.programme_timer_1_off
    condition:
      condition: state
      entity_id: input_boolean.programme_1_enabled
      state: 'true'
    action:
      - service: input_boolean.turn_off
        entity_id: input_boolean.programmer_running


Card:

image

The purpose of this is to have one overall flag, that represents whether the timer programmer is On or Off, that is dependent upon one of the two selectable programmes being On, and the system time is within the associated time range(s) for the given selected programme(s). - as per card.

I am conscious that there are many ways to cut this, so I’m looking for “best practice” and efficient coding. Is there a better way?

I’m sure some clever guru will have a better way. Thank you for reading.

Template binary sensor for each ‘program’, using the logic you described here…

IF programme_1_enabled [= TRUE] 
AND
IF <time-of-day> BETWEEN (programme_timer_1_on AND programme_timer_1_off)
THEN
   SET programmer_running = TRUE

Then either a template binary sensor that is on when either is on, or just group the two you made and use the state of the group as the ‘master’ monitor.

Yes, thank you, but what would that look like in code please. That’s the OP purpose, to elicit help on how to code this up. What I have above is not working, the triggered event doesnt fire. I suspect the event only gets created twice, once the time is “after” and once the time is “before” ?? I dont know - but it isnt working

Thank you.

I don’t know how the input_datetimes output their state, but it would be something like this…

binary_sensor:
  - platform: template
    sensors:
      program_1:
        value_template: >
          {{ is_state('input_boolean.program_1', 'on') and
              states('input_datetime.programme_timer_1_on')
              < now() [SOMETHING HERE TO COMPARE THE OUTPUT OF NOW() WITH THE OUTPUT OF THE INPUT_DATETIMES]
              < states('input_datetime.programme_timer_1_off') }}

      program_2:
        value_template: >
          [ SIMILAR TEMPLATE BUT REFERENCING PROGRAM 2s THINGS]

      master_program:
        value_template: >
         {{ is_state('binary_sensor.program_1', 'on') and
            is_state('binary_sensor.program_2', 'on') }}
1 Like

@anon43302295
You’re a STAR.

With your help I crafted this and it works perfectly. Not only that, but a chunk of automation has vanished too!
Thank you.

  # PROGRAMMER

    # True/False to mode overall programme status
    # Set TRUE if programme is selected (On by user) and system time is within user set time range.


  binary_sensor:
    - platform: template
      sensors:
        programmer_running:
          value_template: >
            {{ (now().strftime('%H:%M:%S') >=  states('input_datetime.programme_timer_1_on')) and
               (now().strftime('%H:%M:%S') <=  states('input_datetime.programme_timer_1_off')) and
               (states('input_boolean.programme_1_enabled') == 'on') }}

  input_boolean:

    # Selectable programmes

    programme_1_enabled:
      name: programme_1_enabled

    programme_2_enabled:
      name: programme_2_enabled

  input_datetime:

    programme_timer_1_on:
      name: programme_timer_1_on
      has_date: false
      has_time: true

    programme_timer_1_off:
      name: programme_timer_1_off
      has_date: false
      has_time: true

    programme_timer_2_on:
      name: programme_timer_2_on
      has_date: false
      has_time: true

    programme_timer_2_off:
      name: programme_timer_2_off
      has_date: false
      has_time: true

Edit

One minor flaw, this only works for time ranges within one day. On/Off programme times than span 24hrs - doesnt work. This is due to strfprint formatting and the comparisons . For me, I don’t need this but members arriving here via search should be aware of this and adjust accordingly.

1 Like

For those that need it, and the input_datetime includes date and time, the calculation may be performed using timestamps:

          value_template: >
            {{ state_attr('input_datetime.programme_timer_1_on', 'timestamp') 
               <=  now().timestamp() <=  
               state_attr('input_datetime.programme_timer_1_off', 'timestamp') 
               and is_state('input_boolean.programme_1_enabled', 'on') }}
2 Likes

Ah, excellent.
One query I and others will have,.

Where are all the useful methods, functions, data structures and models, , types, operators, and programming reference documens that explain how to access HA exposed data. The HA docs are woefully missing on this so perhaps they are elsewhere?

Home Assistant uses the Jinja2 templating language.

The documentation doesn’t attempt to explain the syntax but directs the reader to the official documentation for the Jinja2 project.

We will not go over the basics of the syntax, as Jinja2 does a great job of this in their templates documentation.

What the reader will find in the Templating section are examples of how Jinja2 templates are used in Home Assistant along with a description of the functions that are available (if you’re familiar with python, you’ll recognize many of them).

FWIW I did find Jinja2’s documentation to be thorough but not written for a home automation audience (to be fair, it’s not meant to be tailored for a specific use-case). It’s a language reference so it tends to be a bit dry (possibly even opaque for a new user). Having said that, ages ago, when I first read K&R’s C Programming Language, that was a more engaging experience than the Jinja2 docs. :slight_smile:

Yes, I read the [very brief glib] documentation on Templates and Jinja. The issue for me and many I assume, is that Jinja is a language - not the explanation of HA. As a developer - albeit in a formal environment within a major IT corporation - one is used to the “usual” software artefacts such as but not limited to (and may use different vernacular across corporations):-1:

  • Concept
  • Requirements
  • Architecture
  • Top level Design
  • Detail Design
  • Code / module reference manual (properties , procedures/functions with argument explanations, constants, library rountine references, etc).

Without this it’s difficult but not impossible to get “engaged” with HA and it’s left to the reader to work things out for themselves. Good software comes with good documentation. without it HA “custodians” make it less appealing to get involved and contribute to development roadpath. As a newcomer, I’m more inclined to share my dev experience in projects more welcoming and inviting. We will all have a view on this and my view will not be “THE view” - but surely FOSS benefits from a good and growing dev community underpinned by robust supportive documentation. the easy answer is “we don’t have time” - read “we can’t be bothered - learn it yourself”

Back to my point,
Jinja says dilly nothing about HA and the above insight. But thank you for joining the discussion and sharing the link.

Ditto; thanks for the description of what a corporate software developer expects.

Wouldn’t know. I’m not a corporate developer.
Freelance - I mix it up and get involved in various environments, from the undocumented bizarre and mystery dark arts - to pen pushing mandrolic formal lifecycles.
Good guess - no cigar :slight_smile:

I see. Your previous statement suggested otherwise.

So you’re not a corporate developer but a freelance developer working for corporate clients.

Whatever it is that you do, if you expect to find documentation written to corporate standards, I believe you already know that’s unlikely to happen unless someone takes the time to do it. Given this project’s age, it clearly hasn’t been anyone’s priority to date. You, and all Home Assistant users, are encouraged to contribute to it.

1 Like