Energy Sensor Price - to handle changing energy tariff rates

In-case it helps anyone else, see sensor: created to adjust energy pricing tariff based on time of day. This may be overly complex compared to other countries but Ausgrid in Australia have peak periods during specific hours in Winter and Summer months, Shoulder period and then Offpeak rates per Time of use pricing - Ausgrid

  - platform: template
    sensors:
      energy_tariff:
        friendly_name: My Energy Tariff
        unit_of_measurement: 'AUD/kWh'
        value_template: >
          {% set tariff = { "Peak": 0.5, "Shoulder": 0.28, "OffPeak": 0.18 } %}
          {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "weekday": (now().weekday() | int ) } %}
          {%if (time.hour > 21) or (time.hour < 7) %}
              {{ tariff.OffPeak }}
          {%elif ((time.month > 10) or (time.month < 4)) and (time.weekday < 5) %}
             {%if (time.hour > 13) and (time.hour < 20) %}
              {{ tariff.Peak }}
             {%else%}
              {{ tariff.Shoulder }}
             {%endif%}
          {%elif ((time.month > 5) and (time.month < 9)) and (time.weekday < 5) %}
             {%if (time.hour > 16) and (time.hour < 21) %}
              {{ tariff.Peak }}
             {%else%}
              {{ tariff.Shoulder }}
             {%endif%}
          {%else%}
              {{ tariff.Shoulder }}
          {%endif%}

or

  - platform: template
    sensors:
      your_tariff:
        friendly_name: My Tariff
        unit_of_measurement: 'AUD/kWh'
        value_template: >
          {% set tariff = { "Peak": 0.5, "Shoulder": 0.28, "OffPeak": 0.18 } %}
          {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "weekday": (now().weekday() | int ) } %}
          {%if (time.hour > 21) or (time.hour < 7) %}
              {{ tariff.OffPeak }}
          {%elif ((time.month > 10) or (time.month < 4)) and (time.weekday < 5) and ((time.hour > 13) and (time.hour < 20)) %}
              {{ tariff.Peak }}
          {%elif ((time.month > 5) and (time.month < 9)) and (time.weekday < 5) and ((time.hour > 16) and (time.hour < 21)) %}
              {{ tariff.Peak }}
          {%else%}
              {{ tariff.Shoulder }}
          {%endif%}

EDIT: Added unit_of_measurement: 'AUD/kWh' which I realised I didnt copy over after seeing @nd100 post - unit_of_measuremeant: is required for Energy dashboard to use the sensor

5 Likes

Nice idea (those are some high peak prices!)

Here are two sensors for Powershop’s EV plan in NSW on Ausgrid which has 4 prices during the week, 2 on weekends.

  - platform: template
    sensors:
      ev_powershop_nsw:
        friendly_name: Powershop EV Tariff
        unit_of_measurement: 'AUD/kWh'
        value_template: >
          {% set tariff = { "Peak": 0.3641, "Shoulder": 0.1752, "OffPeak": 0.1348, "EVOffPeak": 0.0677 } %}
          {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "weekday": (now().weekday() | int ) } %}
          {%if (time.weekday < 5) %}
            {%if (time.hour >= 14) and (time.hour < 20) %}
              {{ tariff.Peak }}
            {%elif (time.hour >= 20) %}
              {{ tariff.OffPeak}}
            {%elif (time.hour < 4) %}
              {{ tariff.EVOffPeak }}
            {%elif (time.hour >= 4) and (time.hour < 7) %}
              {{ tariff.OffPeak }}
            {%elif (time.hour >= 7) and (time.hour < 14) %}
              {{ tariff.Shoulder }}
            {%endif%}
          {%else%}
            {%if (time.hour >= 7) and (time.hour < 22) %}
              {{ tariff.Shoulder }}
            {%else%}
              {{ tariff.OffPeak }}
            {%endif%}
          {%endif%}

  - platform: template
    sensors:
      ev_powershop_nsw_solar:
        friendly_name: Powershop EV Tariff Solar Export
        unit_of_measurement: 'AUD/kWh'
        value_template: 0.06

HI Scott - other than ease of reading - any difference (performance?) between the two Ausgrid templates?

Those two are the same, the second one is just cleaner as opposed to nested ‘ifs’

1 Like

cool. thanks.

(actually ended up creating three tariffs via Utility Meter, then I can track the usage separately in Energy monitor.)

I would like to implement this sensor to insert it into energy to monitor tariffs, I mainly have 2 tariffs and they are divided as follows:
F1 — workday 8-19
F23 — workday 19-8 and public holidays.

i modify the sensor in this:

    sensors:
      tariffa_f1_f23:
        friendly_name: ServizioEN Tafiffa
        unit_of_measurement: 'kWh'
        value_template: >
          {% set tariff = { "F1": 0.3641, "F23": 0.1752,} %}
          {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "workday": (now().workday() | int ) } %}
          {%if (time.workday == on) %}
            {%if (time.hour >= 8) and (time.hour < 19) %}
              {{ tariff.F1 }}
            {%elif (time.hour >= 19) and time.hour < 8) %}
              {{ tariff.F23}}
            {%endif%}
          {%else%}
            {{ tariff.Shoulder }}
              {{ tariff.F23 }}
            {%endif%}
          {%endif%}
1 Like

Hey there. I’m wondering if you could possibly assist me with modifying your version of the sensor code for just two tariffs? My provider is either offpeak or peak with peak being 0700-1100 and 1700-2100 Mon to Friday. I popped your code into the template editor as-is and got an error and coding is not my strength.

I am looking too.

do you know if you can also track demand? My utility has a demand charge Mon-Fri which is based on the peak energy used over a 30 minute window that covers billing cycle. So it be a method to look at peak energy usage in 30 minutes log peak, then compare that again to the next 30 minute window and keep the highest value. Do that for 30 days and then reset. For example lets say on Monday between 6:00-6:30 my peak energy usage was 5kw. It would store that value and track 30 minutes going forward so let say on Fri I had a peak of 9kw in a 30 minute segment it would then be 9. I would ultimately want to display this on a dashboard so I can see what peak has been to try and keep it lower.

Hi @smck83 hoping you might be able to help me. I’m also on time of use but have more rates based on time and month but can’t work out how to create the template.

  • Solar feed in of $0.13

@MatthewGrech you may find what I have done here useful, although the daily supply charge is a bit tricky from what I understand. We have the same plan (Powershop I assume?) so just copy mine.

@xbmcnut @Twig_Bark I will have one for two tariffs as well. Obviously you need to change the costs to represent yours.

Two Tariff Setup

First things first, you need a template sensor to determine which tariff you are currently on, i.e. peak or offpeak. Throw this in your template.yaml file

- sensor:
  - name: "Electricity Tariff"
    unique_id: 230e307a-6150-4c2e-8571-7634dec8fcd9
    state: >
      {% set n = now() %}
      {% if today_at('15:00') < n < today_at('21:00') and now().isoweekday() < 6 %}
          peak
      {% else %}
        offpeak
      {% endif %}

Then, you are going to need a helper to determine the dollar value of your tariff. Settings > Devices & Services > Helpers > + Create Helper > Number

Change the Min and Max value to match your tariffs (i.e. cheapest and most expensive)

Name: Electricity Tariff
Icon: mdi:currency-usd
Minimum value: 0.1960
Maximum value: 0.3340
Step size: 0.0001
Unit of measurement: AUD/kWh
Entity ID: input_number.electricity_tariff

You will also need a sensor in the utility_meter.yaml file. Add this into it.

daily_energy:
  source: sensor.solaredge_m1_imported_kwh
  cycle: daily
  tariffs:
    - peak
    - offpeak

Lastly, an automation to change the tariff when it needs changing.

Change the template to matcch your tariff values

alias: Set Electricity Tariff
description: ""
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 }}"
  - service: input_number.set_value
    target:
      entity_id: input_number.electricity_tariff
    data:
      value: >
        {% set tariff = dict(peak=0.3340, offpeak=0.1960) %} {{
        tariff[trigger.to_state.state] }}
mode: single

Then you will have two entities to add to your Energy Dashboard. Click on Add Consumption and add sensor.daily_energy_peak and sensor.daily_energy_offpeak This will allow you to see in the Energy Dashboard which tariffs are being used when within the graphs and it will show you the costs too.

Three Tariff Setup

First things first, you need a template sensor to determine which tariff you are currently on, i.e. peak or offpeak . Throw this in your template.yaml file

- sensor:
  - name: "Electricity Tariff"
    unique_id: ae0f8d9e-654e-4b54-b114-de64b1eb2ef0
    state: >
      {% set n = now() %}
      {% set summer = [ 11, 12, 1, 2, 3] %}
      {% set winter = [ 6, 7, 8 ] %}
      {% if today_at('07:00') < n < today_at('22:00') %}
        {% if ((now().month in summer and today_at('14:00') < n < today_at('20:00'))
            or (now().month in winter and today_at('17:00') < n < today_at('22:00'))) and now().isoweekday() < 6
        %}
          peak
        {% else %}
          shoulder
        {% endif %}
      {% else %}
        offpeak
      {% endif %}

Then, you are going to need a helper to determine the dollar value of your tariff. Settings > Devices & Services > Helpers > + Create Helper > Number

Change the Min and Max value to match your tariffs (i.e. cheapest and most expensive)

Name: Electricity Tariff
Icon: mdi:currency-usd
Minimum value: 0.2219
Maximum value: 0.494
Step size: 0.0001
Unit of measurement: AUD/kWh
Entity ID: input_number.electricity_tariff

You will also need a sensor in the utility_meter.yaml file. Add this into it.

daily_energy:
  source: sensor.solaredge_m1_imported_kwh
  cycle: daily
  tariffs:
    - peak
    - offpeak
    - shoulder

Lastly, an automation to change the tariff when it needs changing.

Change the template to matcch your tariff values

alias: Set Electricity Tariff
description: ""
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 }}"
  - service: input_number.set_value
    target:
      entity_id: input_number.electricity_tariff
    data:
      value: >
        {% set tariff = dict(peak=0.4940, shoulder=0.2383, offpeak=0.2219) %} {{
        tariff[trigger.to_state.state] }}
mode: single

Then you will have three entities to add to your Energy Dashboard. Click on Add Consumption and add sensor.daily_energy_shoulder, sensor.daily_energy_peak and sensor.daily_energy_offpeak This will allow you to see in the Energy Dashboard which tariffs are being used when within the graphs and it will show you the costs too.

A huge shoutout to @TheFes and @petro who persisted with me to make this possible and taught me a thing or two along the way about templating.

4 Likes

@BeastHouse , I have something similar but I can’t tweak your template sensor and make it work.

It won’t even pass the Developer Tools check configuration test.

I have a Winter and Summer rate. I tried this to modify your script for winter/summer.

Can you tell me what’s wrong with it. I’ve attached a jpg of my local rates and my configuration.yaml utility_meter and Automation.

My Daily and Monthly Energy charts work for offpeak, midpeak and peak, but I also want the cost.

- sensor:
  - name: "Electricity Tariff"
    unique_id: ae0f8d9e-654e-4b54-b114-de64b1eb2ef0
    state: >
      {% set n = now() %}
      {% set winter = [ 10, 11, 12, 1, 2, 3, 4, 5] %}
      {% set summer = [ 6, 7, 8, 9 ] %}
        {% if ((now().month in summer ) and now().isoweekday() < 6
        %}
          summerpeak
        {% else %}
          summermidpeak
        {% endif %}
      {% else %}
        summeroffpeak
      {% endif %}
      
            or (now().month in winter ) and now().isoweekday() < 6
        %}
          winterpeak
        {% else %}
          wintermidpeak
        {% endif %}
      {% else %}
        winteroffpeak
      {% endif %}

Automation:
alias: Utility Meter
description: Select Daily or Monthly Utility Tarrif Options
trigger:
  - platform: time
    at: "19:00:00"
    variables:
      tariff: offpeak
  - platform: time
    at: "13:00:00"
    variables:
      tariff: midpeak
  - platform: time
    at: "15:00:00"
    variables:
      tariff: peak
condition: []
action:
  - service: select.select_option
    data:
      option: "{{ tariff }}"
    target:
      entity_id: select.daily_energy
  - service: select.select_option
    data:
      option: "{{ tariff }}"
    target:
      entity_id: select.monthly_energy
mode: single

configuration.yaml:
utility_meter:
  daily_energy:
    source: sensor.smart_electric_meter_consumption
    name: daily energy
    cycle: daily
    tariffs:
      - offpeak
      - midpeak
      - peak
  monthly_energy:
    source: sensor.smart_electric_meter_consumption
    name: monthly energy
    cycle: monthly
    tariffs:
      - offpeak
      - midpeak
      - peak

i have a similar plan but it changes between summer / winter and shoulder months. How do we accommodate this?

For those of you in Arizona served by SRP I created a couple sensors for their complex tariffs:

I created 2 sensors - one for the SRP Energy Tariff EZ-3 and one for the plan label:

  - platform: template
    sensors:
      energy_tariff_ez_3:
        friendly_name: SRP Energy Tariff EZ-3
        unit_of_measurement: 'USD/kWh'
        value_template: >
          {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "weekday": (now().weekday() | int ) } %}
          {%if ((time.month <= 4) or (time.month > 10)) %} {# November through April - Winter #}
              {% set tariff = { "WeekdayPeak": 0.1157, "OffPeak": 0.8.32 } %}
              {%if ((time.hour >= 15) and (time.hour < 18)) and (time.weekday < 5) %}
                {{ tariff.WeekdayPeak }}
              {%else%}
                {{ tariff.OffPeak }}
              {%endif%}
          {%elif ((time.month == 7) or (time.month == 8)) %} {# July and August - Summer Peak #}
              {% set tariff = { "WeekdayPeak": 0.3520, "OffPeak": 0.0929 } %}
              {%if ((time.hour >= 15) and (time.hour < 18)) and (time.weekday < 5) %}
                {{ tariff.WeekdayPeak }}
              {%else%}
                {{ tariff.OffPeak }}
              {%endif%}
          {%else%} {# May June September October - Summer #}
              {% set tariff = { "WeekdayPeak": 0.2971, "OffPeak": 0.0905 } %}
              {%if ((time.hour >= 15) and (time.hour < 18)) and (time.weekday < 5) %}
                {{ tariff.WeekdayPeak }}
              {%else%}
                {{ tariff.OffPeak }}
              {%endif%}
          {%endif%}
          
  - platform: template
    sensors:
      energy_tariff_plan_ez_3:
        friendly_name: SRP Energy Tariff Plan
        value_template: >
          {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "weekday": (now().weekday() | int ) } %}
          {%if ((time.hour >= 15) and (time.hour < 18)) and (time.weekday < 5) %}
              Weekday Peak
          {%else%}
              Off Peak
          {%endif%}
1 Like

I also am part of a beta program called Daytime Saver:

That program adds another notch of complexity so I created these 3 sensors (SRP Energy Tariff Daytime Saver Pilot, SRP Energy Tariff Plan Daytime Saver Pilot and SRP Energy Tariff Season Daytime Saver Pilot):

  - platform: template
    sensors:
      energy_tariff:
        friendly_name: SRP Energy Tariff Daytime Saver Pilot
        unit_of_measurement: 'USD/kWh'
        value_template: >
          {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "weekday": (now().weekday() | int ) } %}
          {%if ((time.month <= 4) or (time.month > 10)) %} {# November through April - Winter #}
              {% set tariff = { "WeekdayPeak": 0.0987, "OffPeak": 0.0987, "SuperOffPeak": 0.0433 } %}
              {%if ((time.hour >= 18) and (time.hour < 21)) and (time.weekday < 5) %}
                {{ tariff.WeekdayPeak }}
              {%elif ((time.hour >= 9) and (time.hour < 15)) and (time.weekday < 5) %}
                {{ tariff.SuperOffPeak }}
              {%else%}
                {{ tariff.OffPeak }}
              {%endif%}
          {%elif ((time.month == 7) or (time.month == 8)) %} {# July and August - Summer Peak #}
              {% set tariff = { "WeekdayPeak": 0.3637, "OffPeak": 0.1180, "SuperOffPeak": 0.0433 } %}
              {%if ((time.hour >= 18) and (time.hour < 21)) and (time.weekday < 5) %}
                {{ tariff.WeekdayPeak }}
              {%elif ((time.hour >= 9) and (time.hour < 15)) and (time.weekday < 5) %}
                {{ tariff.SuperOffPeak }}
              {%else%}
                {{ tariff.OffPeak }}
              {%endif%}
          {%else%} {# May June September October - Summer #}
              {% set tariff = { "WeekdayPeak": 0.3572, "OffPeak": 0.1096, "SuperOffPeak": 0.0433 } %}
              {%if ((time.hour >= 18) and (time.hour < 21)) and (time.weekday < 5) %}
                {{ tariff.WeekdayPeak }}
              {%elif ((time.hour >= 9) and (time.hour < 15)) and (time.weekday < 5) %}
                {{ tariff.SuperOffPeak }}
              {%else%}
                {{ tariff.OffPeak }}
              {%endif%}
          {%endif%}

- platform: template
    sensors:
      energy_tariff_plan:
        friendly_name: SRP Energy Tariff Plan Daytime Saver Pilot
        value_template: >
          {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "weekday": (now().weekday() | int ) } %}
          {%if ((time.hour >= 18) and (time.hour < 21)) and (time.weekday < 5) %}
              Weekday Peak
          {%elif ((time.hour >= 9) and (time.hour < 15)) and (time.weekday < 5) %}
              Super Off Peak
          {%else%}
              Off Peak
          {%endif%}
          
  - platform: template
    sensors:
      energy_tariff_season:
        friendly_name: SRP Energy Tariff Season Daytime Saver Pilot
        value_template: >
          {% set time = { "month": (now().strftime('%m') | int ) } %}
          {%if ((time.month <= 4) or (time.month > 10)) %}
              SRP Winter
          {%elif ((time.month == 7) or (time.month == 8)) %}
              SRP Summer Peak
          {%else%}
              SRP Summer
          {%endif%}

2 Likes

Thanks so much for this! Made it so much easier to implement! Here is an updated (with the current prices as of 5/25/2024) of the EZ-3 3–6 p.m. weekdays

- platform: template
  sensors:
    energy_tariff_ez_3:
      friendly_name: SRP Energy Tariff EZ-3
      unit_of_measurement: "USD/kWh"
      value_template: >
        {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "weekday": (now().weekday() | int ) } %}
        {%if ((time.month <= 4) or (time.month > 10)) %} {# November through April - Winter #}
            {% set tariff = { "WeekdayPeak": 0.1257, "OffPeak": 0.0932 } %}
            {%if ((time.hour >= 15) and (time.hour < 18)) and (time.weekday < 5) %}
              {{ tariff.WeekdayPeak }}
            {%else%}
              {{ tariff.OffPeak }}
            {%endif%}
        {%elif ((time.month == 7) or (time.month == 8)) %} {# July and August - Summer Peak #}
            {% set tariff = { "WeekdayPeak": 0.3071, "OffPeak": 0.1005 } %}
            {%if ((time.hour >= 15) and (time.hour < 18)) and (time.weekday < 5) %}
              {{ tariff.WeekdayPeak }}
            {%else%}
              {{ tariff.OffPeak }}
            {%endif%}
        {%else%} {# May June September October - Summer #}
            {% set tariff = { "WeekdayPeak": 0.3620, "OffPeak": 0.1029 } %}
            {%if ((time.hour >= 15) and (time.hour < 18)) and (time.weekday < 5) %}
              {{ tariff.WeekdayPeak }}
            {%else%}
              {{ tariff.OffPeak }}
            {%endif%}
        {%endif%}

- platform: template
  sensors:
    energy_tariff_plan_ez_3:
      friendly_name: SRP Energy Tariff Plan
      value_template: >
        {% set time = { "month": (now().strftime('%m') | int), "hour": (now().strftime('%H') | int), "weekday": (now().weekday() | int ) } %}
        {%if ((time.hour >= 15) and (time.hour < 18)) and (time.weekday < 5) %}
            Weekday Peak
        {%else%}
            Off Peak
        {%endif%}

To give back, my build on config.yaml code from Beasthouse to also adjust for Daylight savings and keep tariffs aligned to AEST as per ‘most’ Australian electricity retailers.
This code is set for Globird TOU 3-tariff plan, and uses a separate DST binary sensor (separate code below), Thx.

  - sensor:
     name: "Electricity Tariff AEST"
     unique_id: electricity-tariff-aest
     state: >
      {% set n = now() %}
       {% if (is_state('binary_sensor.workday_sensor','on') and today_at('07:00') < n < today_at('23:00')) %}
       shoulder
      {% elif ((is_state('binary_sensor.daylight_savings_time','on') and today_at('08:00') < n < today_at('23:00'))
                 or (is_state('binary_sensor.daylight_savings_time','off') and today_at('07:00') < n < today_at('22:00'))) %}
        {% if (((is_state('binary_sensor.daylight_savings_time','on') and today_at('15:00') < n < today_at('21:00'))
            or ((is_state('binary_sensor.daylight_savings_time','off') and today_at('14:00') < n < today_at('20:00')))) and now().isoweekday() < 6) %}
          peak
        {% else %}
          shoulder
        {% endif %}
      {% else %}
        offpeak
      {% endif %}

DST sensor:

binary_sensor:
  - platform: template
    sensors:
      daylight_savings_time:
        friendly_name: 'Daylight Savings Time'
        unique_id: day-light-savings
        value_template: "{{ now().timetuple().tm_isdst == 1 }}"

Edit - added brackets to code for peak, as weekends were showing peak tariff

1 Like