How to 'record' the duration of an action in an automation

with a lot of patience, I was helped by @TheFes in editing my sun-boiler automation. I wanted a notification with the period the boiler was heated (and thus optimize the duration between runs…)

this is what I have now, and it works acceptably well. It does however have an ‘issue’.

The first switch binary sensor turn_on action takes a while to happen, after the automation has been successfully triggered. It thus makes the final message in the notification report the incorrect time. It state the full time of the automation, and not exactly the time the switch binary has been on for:

  - alias: Zonneboiler schakelen
    id: zonneboiler_schakelen
    trigger:
      platform: time
      at: '05:00:00'
    condition:
      - >
        {% set delay = states('input_number.zonneboiler_periode')|int(default=23) %}
        {{now() - this.attributes.last_triggered > timedelta(hours=delay) if
          this.attributes.last_triggered is not none else true}}
    action:
      - condition: >
          {{states('binary_sensor.opentherm_dhw_state') not in ['unavailable','unknown']}}
      - service: switch.turn_on
        entity_id: switch.opentherm_dhw_comfort_mode
      - wait_template: >
          {{is_state('binary_sensor.opentherm_dhw_state','on')}}
      - wait_template: >
          {{is_state('binary_sensor.opentherm_dhw_state','off')}}
      - service: switch.turn_off
        entity_id: switch.opentherm_dhw_comfort_mode
# this next wait_template is required to prevent the message from templating the 'former' trigger, as the switch has not been turned_off immediately
      - wait_template: >
          {{is_state('switch.opentherm_dhw_comfort_mode','off')}}
      - condition: state
        entity_id: input_boolean.notify_appliance
        state: 'on'
      - service: notify.mobile_app_marijn
        data:
          title: >
            {% set time = now().strftime('%X') %}
            {{time}}: Zonneboiler schakelaar
          message: >
            Zonneboiler is weer opgewarmd, en uitgeschakeld na
            {{(states.switch.opentherm_dhw_comfort_mode.last_changed -
              state_attr(this.entity_id,'last_triggered')).seconds
             |timestamp_custom('%M:%S',False)}} minuten
            Alternatief:
              {{(now() - trigger.now).seconds|timestamp_custom('%M:%S',False)}}

I have been wondering about a timer to set. turn_on switch binary, turn_on timer, wait for the switch binary to be turned_off, and then turn_off timer.

Next, template the time the timer was on, and report that in the message… But how?

Or, maybe even more verbosely, use an input_datetime to record the turn_on, and another for turn off, and then template the time difference…? Would be really nice if we could do this, (and we probably can, I just couldn’t figure out how).

      - service: input_datetime.set_datetime
        target:
          entity_id: input_datetime.zonneboiler_aan
        data:
          timestamp: >
            {{ now().timestamp()}}
# or use 
# datetime: "{{now().strftime('%Y-%m-%d %H:%M:%S')}}"
      - wait_template: >
          {{is_state('binary_sensor.opentherm_dhw_state','on')}}
      - wait_template: >
          {{is_state('binary_sensor.opentherm_dhw_state','off')}}
      - service: switch.turn_off
        entity_id: switch.opentherm_dhw_comfort_mode
      - service: input_datetime.set_datetime
        target:
          entity_id: input_datetime.zonneboiler_uit
        data:
          timestamp: >
            {{now().timestamp()}}

on for

{{(as_timestamp(states('input_datetime.zonneboiler_uit'))
    - 
   as_timestamp(states('input_datetime.zonneboiler_aan')))
  |timestamp_custom('%M:%S',False)}}

so, please have a look if you can help me find a way to do so.
thx!

this test automation seems to work ok:

  - alias: Test datetime template
    id: test_datetime_template
    trigger:
      platform: state
      entity_id: input_boolean.test
      to: 'on'
    action:
      - wait_template: >
          {{is_state('input_boolean.test','on')}}
      - service: input_datetime.set_datetime
        target:
          entity_id: input_datetime.test_aan
        data:
          datetime: "{{now().strftime('%Y-%m-%d %H:%M:%S')}}"
      - wait_template: >
          {{is_state('input_boolean.test','off')}}

      - service: input_datetime.set_datetime
        target:
          entity_id: input_datetime.test_uit
        data:
          datetime: "{{now().strftime('%Y-%m-%d %H:%M:%S')}}"
      - service: notify.mobile_app_marijn
        data:
          title: >
            {% set time = now().strftime('%X') %}
            {{time}}: Test boolean
          message: >
            Test boolean is weer reset, en uitgeschakeld na
            {{(as_timestamp(states('input_datetime.test_uit'))
                -
               as_timestamp(states('input_datetime.test_aan')))
              |timestamp_custom('%M:%S',False)}} minuten

though it might be a bit convoluted…

update

again, TheFes suggested a better way:

  - alias: Test datetime template 2
    id: test_datetime_template_2
    trigger:
      platform: state
      entity_id: input_boolean.test
      to: 'on'
    action:
      - wait_template: >
          {{is_state('input_boolean.test','on')}}
      - variables:
          sensor_on: "{{ now() }}"
      - wait_template: >
          {{is_state('input_boolean.test','off')}}
      - variables:
          sensor_off: "{{ now() }}"
      - service: notify.mobile_app_marijn
        data:
          title: >
            {% set time = now().strftime('%X') %}
            {{time}}: Test boolean variables
          message: >
            Test boolean is weer reset, en uitgeschakeld na
            {{(as_datetime(sensor_off) - as_datetime(sensor_on)).seconds
               |timestamp_custom('%M:%S',False)}} minuten

which is way shorter, and more importantly doesnt need extra entities, but uses variables created inside the automation. Nice!

result for the both of them:

which is spot on, except for the odd second difference here and there, but that’s of no relevance for my endgoal…
thanks Martijn (TheFes!)