Quick TLDR on how to create multi-tariff energy meters

I get asked this a lot, so thought I’d create a quick HOWTO on how to create a multi-tariff energy measurement system, for the dashboard etc. YMMV.

How to do multi-tariff power monitoring on Home Assistant. Assumes that you have some existing sensor that provides power consumption (W), or energy consumption (Wh).

  1. if your input sensor is only power (W) you convert it to energy (Wh) using an “Integration - Riemann sum integral” Helper from http://homeassistant.local:8123/config/helpers
  • name = daily energy
  • input sensor = sensor.import (or wherever you get your consumption W)
  • integration method = left
  • others as defaults
  • use the new sensor that this creates (in Wh) for all the future steps
  1. Create Number helpers for each tariff/rate at http://homeassistant.local:8123/config/helpers and set them to real values

    • input_number.electricity_peak_rate
    • input_number.electricity_offpeak_rate
  2. create a template sensor that picks the right tariff (as a string) based on the logic that your location uses. Make sure it only outputs the tariffs you defined above.

    eg (I have two separate tariff - one for import, one for export)

    template:
    - sensor:
        # peak time is 3pm-9pm every day
        - name: "Electricity Tariff"
            unique_id: 230e307a-6150-4c2e-8571-7634dec8fcd9
            state: "{{ 'peak' if today_at('15:00') < now() < today_at('21:00') else 'offpeak' }}"
    
        # Time Of Use (TOU) – Local time Feed-In rates
        # Peak (4pm – 9pm)
        # Sholder (9pm – 10am) & (2pm-4pm)
        # Off-Peak (10am-2pm)
        - name: "Electricity Export Tariff"
            unique_id: 541d7af3-7518-42b4-ad78-7fba858c7770
            state: "{{ 'peak' if today_at('16:00') < now() < today_at('21:00') else ('offpeak' if today_at('10:00') < now() < today_at('14:00') else 'shoulder') }}"
    
  3. in order to create the multiple sensors that apply your tariffs, use utility meter helper

    • create a utility_meter at http://homeassistant.local:8123/config/helpers
    • call it something like “daily energy”
    • input sensor = your Wh sensor
    • meter reset cycle = daily
    • supported tariffs = add each of the tariffs you created in step 3 (as labels)
    • this will create a “base” sensor (which controls which tariff is currently in use), and one sensor for each tariff (which counts the amount of energy used on each tariff)
  4. now, you need a bit of automation to change the utility meter selection (from step 3) whenever the current tariff changes (from step 2)

    1. create an new/empty automation at http://homeassistant.local:8123/config/automation/dashboard
    2. the trigger is “When Electricity Tariff changes state or any attributes”
      1. type=state
      2. entity=the sensor you created in step 3
    3. the action is to set the current tariff into the (first) sensor created by the utility meter
      1. type = call service
      2. service = select: select
      3. target = (entity) the first sensor you created in step 5
      4. option = “{{ trigger.to_state.state if ‘to_state’ in trigger else ‘offpeak’ }}”

    you can also create this in YAML mode:

alias: Set Electricity Tariff
trigger:
  - platform: state
    entity_id: sensor.electricity_tariff
    not_to:
      - unavailable
      - unknown
action:
  - service: select.select_option
    target:
      entity_id: select.daily_energy
    data:
      option: "{{ trigger.to_state.state if 'to_state' in trigger else 'offpeak' }}"
mode: single

  1. Now you have two energy sensors, which accumulate during the day, depending on which tariff you are currently in. You can add them into your energy dashboard individually (so you can get accurate pricing, and different colours)

When you add the utility_meter (say peak) to the energy dashboard, you pick the usage sensor (A) and you also configure a pricing sensor (B). Make sure you align peak-usage with peak-price, offpeak-usage with offpeak-price, etc

Afterwards, your energy dashboard should look something like this.

And the graphs on the Energy Dashboard should show multiple shades of the blue (import) or purple (export) as configured

8 Likes

To debug your tariff selector, you can use the template editor. Change the now() to a local variable (nowish) then you can loop across the whole day and check the results. For example

{% for offset in range(24) %}
{% set nowish = today_at('00:05') + timedelta(hours=offset) -%}
{{ nowish }} "{{ 'peak' if today_at('16:00') < nowish < today_at('21:00')
else ('offpeak' if today_at('10:00') < nowish < today_at('14:00') else 'shoulder') }}"
{%- endfor %}

emits

2023-06-28 00:05:00+10:00 "shoulder"
2023-06-28 01:05:00+10:00 "shoulder"
2023-06-28 02:05:00+10:00 "shoulder"
2023-06-28 03:05:00+10:00 "shoulder"
2023-06-28 04:05:00+10:00 "shoulder"
2023-06-28 05:05:00+10:00 "shoulder"
2023-06-28 06:05:00+10:00 "shoulder"
2023-06-28 07:05:00+10:00 "shoulder"
2023-06-28 08:05:00+10:00 "shoulder"
2023-06-28 09:05:00+10:00 "shoulder"
2023-06-28 10:05:00+10:00 "offpeak"
2023-06-28 11:05:00+10:00 "offpeak"
2023-06-28 12:05:00+10:00 "offpeak"
2023-06-28 13:05:00+10:00 "offpeak"
2023-06-28 14:05:00+10:00 "shoulder"
2023-06-28 15:05:00+10:00 "shoulder"
2023-06-28 16:05:00+10:00 "peak"
2023-06-28 17:05:00+10:00 "peak"
2023-06-28 18:05:00+10:00 "peak"
2023-06-28 19:05:00+10:00 "peak"
2023-06-28 20:05:00+10:00 "peak"
2023-06-28 21:05:00+10:00 "shoulder"
2023-06-28 22:05:00+10:00 "shoulder"
2023-06-28 23:05:00+10:00 "shoulder"
1 Like

Thanks for this. Im getting my head around it. My question is what would the code for the template look like for 2 lots of peak rates during the day? For example, my peak rates are 7am-9am and 5pm-8pm, my shoulder times (2 lots 9am-5pm, 8pm-10pm) and off peak time (10pm-7am) would be covered by the above example. Thanks in advance.
edit: also my energy is provided in kWh, how do I change this using the reimann sensor to Wh?

1 Like

Thanks for the tutorial. I noticed this did not quite work in 2023.10.3 where I added the automation through the UI.

The automation kept failing because trigger.to_state.state kept returning state: "offpeak" instead of just off-peak

I used the code below to strip out that extra text and now it worked perfectly.

service: select.select_option
target:
  entity_id: select.daily_energy
data:
  option: >-
    {{ trigger.to_state.state.strip('state: "').strip('"') if 'to_state' in
    trigger else 'offpeak' }}

I have been pullin my hair out to get this to work. I have a emporia vue 2 sensor on my main feed and its measured in watts. I have created a Integration - Riemann sum integral sensor to convert it to kWh. but i cant figure out how to get the tier to work properly. I have a 2 tier set up where the first 1350kwH are priced at $0.0975 and anything above is $0.1405. my utility company is set up on a bi-monthly billing cycle so i have added a cron to my utility yaml but i’m not sure i added it correctly.

cron: "0 0 6 2,4,6,8,10,12 * " so it resets on the 6th day of every even month

I am on a tarrif that changes it’s rates every 30 minutes (Agile Octopus in the UK). I use an HA integration that reports the current tarrif at any time.

I’d like to track the cost of charging my car. I’ve got the energy rate in kWh as a Reimann integration sensor.

I think I should be able to create a Utility Meter helper that has the Reimann integration as input, but giving the tariff sensor as the Supported Tariff is just returning the name of the tariff entity. I don’t understand how the tariff input works - it isn’t documented in enough detail. Any pointers?