Improving Template Trigger Sensor ("condition")

Hi all,

I have this (under sensors);

  - platform: statistics
    name: "Statistics View of Max Grid"
    entity_id: sensor.nrgmonhse_house_watts_import_net
    state_characteristic: value_max
    max_age:
      hours: 24

I would like to improve it by adding time periods. One from 07:00 till 01:59 and the other from 02:00 through to 06:59. I’m seeking to measure the peaks in my energy import from the grid in the two tariff periods. I have had a look at template triggers and sensors but they do not seem to hold conditions.

I’m sure the answer is staring me in the face but I cannot see it. Can anyone help?

John.

Unfortunately, it’s impossible to set up static measurement windows like that w/ the statistics integration.

You can use a trigger-based template sensor to compare the current value of the sensor (states('sensor.nrgmonhse_house_watts_import_net')) to the current value of the template sensor (this.state) and keep the larger of the two. Add a condition for only updating during a certain time window.

Thanks Petro. I am not wedded to any platform in particular, just looking to solve the problem. Any suggestions on other approaches?

Trigger based template sensors do not accept conditions (the time periods) as far as I can tell. (Unless I’ve missed a change of course)

The only other way to get this information is to use an SQL sensor and do the math yourself.

You just add it as part of the template logic. Pseudo code:

If sensor_value > this.state AND time_window_start < now() < time_window_end
sensor_value
else
this.state
endif

You’ll also need a time-based trigger to set the template sensor’s value to the source sensor’s value at the start of the time window.

Here is a good starting point:

I took at stab at the code. Since trigger-based template sensors don’t support trigger_variables, I had to duplicate the sensor entity name and the start of the time window in 2 places in the code, so if you need to change them, make sure to change them in both places.

Another thing to think about is what you want the sensor to display during the active time window. At the start of the window do you want the sensor to show the current value of the energy import sensor, or instead do you want it to continue to hold the max of the previous window all the way until the current window ends, and then change to the max of the recently-ended window?

In other words:

  • Capture the max between 07:00 - 02:00 and start reporting it at 07:00
    -or-
  • Capture the max between 07:00 - 02:00 and start reporting it at 02:00

The code below does the first option. To implement the 2nd option, you’d have to take the code that is currently under state: and move it into an attribute, and then set the state equal to that attribute at the end of the time window.

template:
  - trigger:
      - platform: time
        at: "07:00:00"
      - platform: state
        entity_id: sensor.nrgmonhse_house_watts_import_net
        not_to:
          - unavailable
          - unknown
    sensor:
      - name: Statistics View of Max Grid 0700-0200
        unique_id: 6b33bf98-4bac-4f65-851e-f4537bff6423
        state: >
          {% if trigger.platform == 'time' %}
            {{ states('sensor.nrgmonhse_house_watts_import_net') | float(-999) }}
          {% else %}
            {% if today_at("07:00:00") <= now() or now() < today_at("02:00:00") %}
              {{ max(trigger.to_state.state | float, this.state | float(-999)) }}
            {% else %}
              {{ this.state }}
            {% endif %}
          {% endif %}

This is very kind of you. It’s a great example of something that I understand when I look at it but it was beyond my ability to write from scratch. I have duplicated it to capture the second time period too, changing the hours around.

I have a feeling that the time conditions may need to be “and” not “or”, but I say that from a position of less knowledge than you. I will have a play around over the coming 24hrs.

Many thanks again
John.

Variables are supported on triggers, and you can use anchors to ensure you always have the variable when you need it.

Secondly, you can use inline if statements like this 0 <= value <= 1.

Thirdly, today at supports HH:MM:SS or HH:MM.

Lastly, you can use elif insntead of nested ifs and get the same logic.

      - platform: state
        <<: &vars
          entity_id: sensor.nrgmonhse_house_watts_import_net
        not_to:
          - unavailable
          - unknown
        variables: *vars
      - platform: time
        at: "07:00:00"
        variables: *vars
    sensor:
      - name: Statistics View of Max Grid 0700-0200
        unique_id: 6b33bf98-4bac-4f65-851e-f4537bff6423
        state: >
          {% if trigger.platform == 'time' %}
            {{ states(entity_id) | float(-999) }}
          {% elif today_at("02:00") < now() < today_at("07:00") %}
            {{ max(trigger.to_state.state | float, this.state | float(-999)) }}
          {% else %}
            {{ this.state }}
          {% endif %}

today_at only outputs todays date attached to the datetime object. It should cross midnight perfectly fine, it will hit the else when crossing midnight.

Oh this is great, thanks petro! Still learning!

I didn’t know variables were supported here nor did I even consider anchors so I’m glad you suggested this.

The nested ifs was a brain fart. You should have seen how complicated my logic was while developing this; I stopped simplifying one step too soon.

Regarding the time comparison, I intentionally had it split into two comparisons because I was using the 19-hour duration from 07:00-02:00 which crosses midnight. Your code is looking at the 5 hour duration of 02:00-07:00. @SethKins which time window did you want to consider?

Thanks both. @mekaneck To answer the last question I would like to have two sensors, one recording max 0200-0700 and the second 0700-0200.

Makes sense. Make sure you change the time trigger to “02:00” for the 02:00-07:00 sensor that would use the logic posted by petro.

To answer your original question my logic intentionally uses ‘or’ since it need to match the start of the day or the end of the day but not the middle. For the 5-hour window you can do the comparison as petro suggested.

I’m not sure if the time in the time trigger is templatable, the docs don’t mention it and petro didn’t suggest it so I assume it is not. Which is why you’ll have to update the start of the time window in two places for each sensor.

It’s implemented and deployed. I’m feeling optimistic! I’ll come back and mark it as solved once I’ve seen the overnight results. Thanks again, I’m really pleased to have done this without a more involved ingress/grafana approach.