Trigger automation every x Watt counted

Hello guys, as I diverted photovoltaic surplus to a water heater, I need an automation that turn on a pump every time the energy counter increases of a certain amount. As surplus energy is not constant, I’d like using a better solution than simple time pattern.
This is my actual code but it only triggers once at the beginning and not at the subsequent increments.

trigger:
  - platform: template
    value_template: '{{ (states ('sensor.heater_kwh_today') | float *8) | int }}'

the template you’re using can’t be used as a trigger.

a trigger has to be either “true” or “false”. the template you are using returns an integer value.

And the template requires you to use different quotation marks on the inside than on the outside.

so, since it looks like you want to trigger the automation whenever the value is a multiple of 8 then try this:

trigger:
  - platform: template
    value_template: "{{ (states ('sensor.heater_kwh_today') | float  % 8) > 0 }}"

Sorry, I forgot to explain the reason of that “*8”. As the sensor value is kWh and I want to trigger the automation every 125W, I simplified the original

trigger:
  - platform: template
    value_template: "{{ (states ('sensor.heater_kwh_today') | float *1000/125) | int }}"

The trigger is intended to start every time the resulting integer value changes.
Thanks for the different quotations advice that I was ignoring, even if I noticed HA already formatted it in the correct way.

I’m sure there are cleverer ways, but I’d do it by setting up an input_number helper. Then:

  • on first run (triggered by automation reload or HA restart), run an automation that reads the sensor value in your “number of 125Wh increments” units and store that integer value in the input_number.
  • then your second automation is triggered by a comparison of a new reading in 125Wh-units not being equal to the stored value. Run the pump and update the value in the input_number.
- alias: "Pump runner setup"
  trigger:
    - platform: homeassistant
      event: start
    - platform: event
      event_type: automation_reloaded
  action:
    - service: input_number.set_value
      data:
        entity_id: input_number.power_125wh_units
        value: "{{ (states('sensor.heater_kwh_today')|float *1000/125)|int }}"

- alias: "Pump runner"
  trigger:
    - platform: template
      value_template: "{{ (states('sensor.heater_kwh_today')|float *1000/125)|int != states('input_number.power_125wh_units')|int }}"
  action:
    - service: input_number.set_value
      data:
        entity_id: input_number.power_125wh_units
        value: "{{ (states ('sensor.heater_kwh_today')|float *1000/125)|int }}"
    - YOUR PUMP RUNNING CODE HERE

These could easily be combined by using trigger variables to not run the pump at startup , but this is a simple-to-understand starting point.

Note that as per @finity’s post above, the value_template must evaluate to true or false — this isn’t the same as a state trigger.

1 Like

Many thanks to all, guys.
According to finity’s suggestion I’m gonna trying this

trigger:
  - platform: template
    value_template: "{{ ((states ('sensor.heater_kwh_today') | float*1000)  % 125) > 0 }}"

Will come back in the evening to report results

@AlainGH — that will trigger for every sensor update when the value in Wh is not a multiple of 125.

And you can’t use == 0 instead of > 0 as the number you’re looking at might jump from 124Wh to 126Wh in one step. 2Wh in a 30-second sampling interval is 240W average power.

1 Like

Actually it seems to work exactly as finity said, when the value is multiple of 125.
But there is the problem you mentioned too: since sensor readings are about one every 10 seconds it often misses the exact value, especially at highest heater rate, and so the trigger does not start.
So tomorrow I’ll try the following in order to achieve less “granularity” and avoid holes in the sequence of values
{{ ((states ('sensor.heater_kwh_today') | float*200)|int % 25) >0 }}
In practice I reduced the values to a fifth of the original and cut off decimals

My suggestion above will be waiting when you realise this won’t work :stuck_out_tongue_winking_eye: .

Sorry to let you down :smile:, but it seems to be working fine.
I will monitor it a little more though.

1 Like

Genuinely interested what the trigger values are. By my testing, your template should trigger for any state update except a multiple of 125Wh and 4Wh after that multiple:

The entity the trigger is based on is a daily kWh counter that reset at midnight and measures the power of the heater and it normally reaches 5-6 kWh.

Here is the hystorical of my pump switch


Every time is triggered the pump switch on for 1 min twice, separated by a 1 min delay.
As you can see it seems all fine except for that time in which te pump doesn’t switch off.
I need to investigate further.

That’s probably related to the period when the template in my example is returning false.

If you compare the switch operation against the value of sensor.heater_kwh_today, you’ll probably find it’s triggering every time there is an update, regardless of value except at or shortly after a 125Wh increment.

Can you post the whole automation?

It’s a lot “work in progress” but here is

alias: Turn on Circolatore ACS for 1 min every 125 kWh of Heater's consumption
description: ''
trigger:
  - platform: template
    value_template: '{{ ((states (''sensor.heater_energy_today'') | float*200)|int  % 25) >0 }}'
  - platform: numeric_state
    entity_id: sensor.heater_energy_power
    below: '5'
    for: '00:00:10'
    value_template: |-
      {% if states('sensor.heater_energy_power')|float == 0 %}
        {{ states('input_number.pwm_duty_cycle')|float > 1200 }}
      {% endif %}
  - platform: numeric_state
    entity_id: sensor.heater_energy_power
    above: '1200'
    for: '00:06:00'
condition:
  - condition: sun
    before: sunset
    after: sunrise
    after_offset: '02:30:00'
    before_offset: '01:00:00'
  - condition: template
    value_template: >-
      {{ as_timestamp(now()) -
      (as_timestamp(state_attr("switch.sonoff_1000020f3c", "last_triggered")) or
      0) > 400 }}
action:
  - repeat:
      count: '2'
      sequence:
        - service: switch.turn_on
          target:
            entity_id: switch.sonoff_1000020f3c
        - delay:
            hours: 0
            minutes: 1
            seconds: 0
            milliseconds: 0
        - service: switch.turn_off
          target:
            entity_id: switch.sonoff_1000020f3c
        - delay:
            hours: 0
            minutes: 1
            seconds: 30
            milliseconds: 0
  - delay:
      hours: 0
      minutes: 0
      seconds: 10
      milliseconds: 0
  - choose:
      - conditions:
          - condition: state
            entity_id: switch.tasmota
            state: 'on'
        sequence:
          - service: switch.turn_off
            target:
              entity_id: switch.sonoff_1000020f3c
    default: []
mode: single

For brevity, you don’t have to specify the unused bit of the time, so:

  - delay:
      hours: 0
      minutes: 0
      seconds: 10
      milliseconds: 0

can be just:

  - delay:
      seconds: 10

or even just delay: 10.

If you give the automation an id, you can use the automation debugger to examine its triggering (I use UUID4 codes from here, but anything will do):

alias: Turn on Circolatore ACS for 1 min every 125 kWh of Heater's consumption
description: ''
id: e6ffb4b4-c6ff-47d9-838a-d297be91eca1
trigger:

Then you can see this sort of thing, showing which trigger fired and what the related variables and state changes were:

You get to that via Configuration / Automations and clicking the image icon against the automation you want to see.

Thank you very much for the precious hints :pray: :wink:

1 Like