The quick and lazy way would be to have just 1 tariff in utility meter and then use the if statement logic to continually evaluate and update the price of the tariff price template sensor depending on time of day. Sorry, on mobile. Will do better reply when I get time
Well, with my basic HA skills, I gave up on changing the state of select.daily_energy
using the template above. Even though this seems like a basic task, I couldn’t find a neat way.
I did find that automations can be triggered at time intervals and also have before and after conditions, so I created a bunch of automations which seems to be working and will update a tariff if it is wrong for at least 30 seconds. It’s a lot more lines of code but it works.
- id: '1655331243871'
alias: Tariff Select Peak
description: Change tariff during peak times
trigger:
- platform: time_pattern
minutes: '*'
hours: '*'
seconds: /30
- platform: time
at: '17:00:01'
condition:
- condition: template
value_template: '{{(17 <= now().hour <= 19) and (now().weekday()<5)}}'
action:
- service: utility_meter.select_tariff
data:
tariff: peak
target:
entity_id: utility_meter.daily_energy
mode: single
- id: '1655331713299'
alias: Tariff Select Shoulder
description: Change tariff during shoulder times
trigger:
- platform: time_pattern
minutes: '*'
hours: '*'
seconds: /30
- platform: time
at: 07:00:01
- platform: time
at: '20:00:01'
condition:
- condition: template
value_template: '{{(now().hour >= 7 and now().hour < 17) or (now().hour >= 20
and now().hour < 22) and (now().weekday() <5)}}'
action:
- service: utility_meter.select_tariff
data:
tariff: shoulder
target:
entity_id: utility_meter.daily_energy
mode: single
- id: '1655333102052'
alias: Tariff Select Offpeak
description: Change tariff during off peak times
trigger:
- platform: time_pattern
minutes: '*'
hours: '*'
seconds: /30
- platform: time
at: '22:00:01'
- platform: time
at: 00:00:01
condition:
- condition: template
value_template: '{{(now().hour >= 22 or now().hour < 7) or (now().weekday() >=5)}}'
action:
- service: utility_meter.select_tariff
data:
tariff: offpeak
target:
entity_id: utility_meter.daily_energy
mode: single
edit:
It also looks like you can set month conditions e.g.
- condition: template
value_template: '{{ now().month >= 10 or now().month <= 4 }}'
edit 2: single automations per tariff using template
yep, you will find there are ‘many ways to skin a cat’ with home assistant.
My solution is vulnerable to home assistant outage at tariff changeover.
Absolutely. I’m sure there’s a tidier or more efficient way but I think this will work. I’ll watch the tariff history over the next week to confirm.
I updated the code block above as I realised I could use the template to avoid having multiple automations for tariffs with multiple windows.
This would be quite simple to include logic for months, I’m just not sure if having an automation trigger every 30 seconds should be avoided for any reason.
I would exclude the history of that automation in the recorder so it doesnt fill up the database
Good thought - have done and also from logbook.
I came up with a much simpler tariff automation that doesn’t have an ‘at’ or ‘delay’ time trigger that I think is working well. It triggers on state change as well as on boot so should pick up any missed triggers for whatever reason.
Template sensor: (this could easily have seasonal/monthly logic written in to it)
- sensor:
- name: Tariff Logic
state: >
{% if (22 <= now().hour or now().hour < 7 or now().isoweekday() > 5) %}
offpeak
{% elif 17 <= now().hour < 20 %}
peak
{% else%}
shoulder
{% endif %}
Automation:
alias: Switch tariffs
description: ''
trigger:
- platform: state
entity_id:
- sensor.tariff_logic
- platform: homeassistant
event: start
action:
- service: utility_meter.select_tariff
data_template:
tariff: '{{states(''sensor.tariff_logic'')}}'
target:
entity_id: utility_meter.daily_energy
mode: single
Looking good.
Thanks but there is no need to manually enter holiday dates that you will have to update ad finitum. Use the Workday integration instead. i.e.
binary_sensor:
# Whether it is a workday or not - binary_sensor.workday_sensor
- platform: workday
country: AU
province: NSW
template:
# Australian Ausgrid NSW Peak-shoulder-offpeak sensor defined
# https://www.ausgrid.com.au/Your-energy-use/Meters/Time-of-use-pricing
# Peak: 2pm - 8pm on working weekdays 1 November - 31 March;
# Peak: 5pm - 9pm on working weekdays 1 June - 31 August
# Off-peak: 10pm - 7am
# Shoulder: all other times
- sensor:
name: TOU Period
icon: mdi:clock-time-three-outline
state: >
{% set tou_period = 'shoulder' %}
{% set n_month = now().month %}
{% set n_hour = now().hour %}
{% set is_summer = (n_month <= 3 or n_month >= 11) %}
{% set is_winter = (6 <= n_month <= 8 ) %}
{% if n_hour >= 22 or n_hour < 7 %}
{% set tou_period = 'offpeak' %}
{% elif ((is_summer and (14 <= n_hour <= 19))
or (is_winter and (17 <= n_hour <= 20)))
and (is_state("binary_sensor.workday_sensor", "on")) %}
{% set tou_period = 'peak' %}
{% endif %}
{{tou_period}}
- sensor:
name: Electricity Cost
icon: mdi:currency-usd
unit_of_measurement: AUD/kWh
state: >
{% if is_state('sensor.tou_period', 'peak') %}
{{ 0.3465 }}
{% elif is_state('sensor.tou_period', 'offpeak') %}
{{ 0.1397 }}
{% else %}
{{ 0.1727 }}
{% endif %}
FYI - just noticed this in my logs:
The 'utility_meter.select_tariff' service has been deprecated and will be removed in HA Core 2022.7. Please use 'select.select_option' instead
I haven’t updated anything at my end yet due to time but will likely affect us all unless you’ve already changed it.
@del13r this is amazing!
Have you or anyone else applied this data to calculating the payback of your solar system?
I had mine installed in Feb, so I’m just now getting data to build out my payback model. Thinking this could be a cool next step on top of this to see when it will pay for itself. And then a counter for how much it’s earned after that time.
Thanks.
I haven’t thought that far ahead.
I got solar installed last year and a few months later I started using Home Assistant.
Due to this, I am comparing current bills with bills from before I got solar installed.
The problem with my historical bills are that they are quarterly which doesn’t allow me to get an accurate daily cost over a 90 day period as the months and seasons aren’t clear cut.
Yeah, it’s unnecessarily complicated.
I’ve got TOU rates as well, but I changed to that when I got solar. So I’m thinking of doing something like this if I can figure out how to set it up:
Total monthly calculated total cost for grid power already done by HA + monthly solar payment (I’m doing a loan, so this is static) = how much I have paid out in cash that month.
Then calculate the WHAT IF I had no solar. Total monthly consumption in kWh times the going rate per kWh regardless of Time of Use (since I wouldn’t be using it if I didn’t have solar).
The difference between these two numbers would represent whatever I’m contributing to my payback. Then I just have to figure out how to build out how to project that out for a payback date that changes each month. New to this part, so this is what you have inspired me to figure out!
Hello all
Very good topic!
I’m using Shelly EM and i`m not exporting energy, so in my case this should be simpler to implement!
My Shelly gives me negative values in the consumption when I’m not consuming all the solar production energy so I would like to know if del13r Envoy works the same way?
Thanks
Pedro Fonseca
I’m not sure how that works.
You cannot throttle the output of solar panels. If you are not exporting energy, then where does the excess solar production go?
If you are seeing negative values on your consumption, that would indicate the excess production is being detected via the Shelly EM and you can still use the 0,MAX logic to only record positive values.
Hi @apnafonseca
In your isolated case, I would try this.
I made up the sensor name as I don’t know anything about Shelly em
- sensor:
name: Grid Import Power
state_class: measurement
icon: mdi:transmission-tower
unit_of_measurement: W
device_class: power
state: >
{{ [0, states('sensor.shelly_em_current_power_consumption') | int ] | max }}
This code has 1 job, and that is to ignore negative values so that the integration sensor can count only positive values for the consumption energy odometer needed by energy dashboard.
I’m just going back to add in my monthly billing cycles to my own set up and noticed that you can use cron in the documentation here under Advanced Configuration:
if you replace cycle:
with cron: "0 0 13 * *"
then it should reset for you on the 13th of each month.
Edit cron: "0 0 13 */3 *"
for quarterly on the 13th
It would be complicated to do true payback in HA using utility meter. Not impossible, but complicated.
I have done it in excel using exported data from my enphase. It accounted for energy sold, self consumption and time of use of that consumption. It was (is) a beast of a spreadsheet and when enphase changed the format of their export data I didn’t go back and maintain it… I really should.
There would be a great opportunity (for someone cleverer than me) for a solar payback integration that is built specifically with this in mind, I think.
Sorry for triple post, have been working on my energy views
This is a great idea - I’ve taken this approach and applied it to my monthly billing. As you’ll see, I’ve done this in a similar way to you but laid it out in a way that I found easier to work with.
Have also after scratching my head for a while, worked out how to get the last billing period calculating too:
- name: Monthly Energy Total Cost #calculating energy cost for this billing period.
device_class: monetary
state_class: measurement
unit_of_measurement: AUD
state: >
{% set peak = states('sensor.monthly_energy_peak') | float %}
{% set p_tariff = states('input_text.peak') | float %}
{% set shoulder = states('sensor.monthly_energy_shoulder') | float %}
{% set s_tariff = states('input_text.shoulder') | float %}
{% set offpeak = states('sensor.monthly_energy_offpeak') | float %}
{% set o_tariff = states('input_text.offpeak') | float %}
{% set buyback = states('sensor.monthly_energy_export_buyback') | float %}
{% set b_tariff = states('input_text.feedin') | float %}
{% set daily = states('input_text.daily') | float %}
{% set reset = state_attr('sensor.monthly_energy_offpeak','last_reset') |as_datetime %}
{% set days_in = ((now() - reset)).days %}
{{ (peak * p_tariff + shoulder * s_tariff + offpeak * o_tariff + buyback * b_tariff + daily * days_in) | round(2) }}
- name: Last Month Energy Total Cost #calculating energy cost for previous billing period
device_class: monetary
unit_of_measurement: AUD
state: >
{% set peak_last = state_attr('sensor.monthly_energy_peak','last_period') | float %}
{% set p_tariff = states('input_text.peak') | float %}
{% set shoulder_last = state_attr('sensor.monthly_energy_shoulder','last_period') | float %}
{% set s_tariff = states('input_text.shoulder') | float %}
{% set offpeak_last = state_attr('sensor.monthly_energy_offpeak','last_period') | float %}
{% set o_tariff = states('input_text.offpeak') | float %}
{% set buyback_last = state_attr('sensor.monthly_energy_export_buyback','last_period') | float %}
{% set b_tariff = states('input_text.feedin') | float %}
{% set daily = states('input_text.daily') | float %}
{% set last_month = now().month - 1 if now().month - 1 >= 1 else 12 %}
{% set last_year = now().year - 1 if now().month == 1 else now().year %}
{% set reset = state_attr('sensor.monthly_energy_offpeak','last_reset') |as_datetime %}
{% set last_reset = reset.replace(year=last_year, month=last_month) %}
{% set last_days = (reset - last_reset).days %}
{{ (peak_last * p_tariff + shoulder_last * s_tariff + offpeak_last * o_tariff + buyback_last * b_tariff + daily * last_days) | round(2) }}