Using Home Assistant to calculate my energy bill using data from my Solar Inverter

Yes my history is set up with nothing excluded (or “included”).

It is working for every other sensor I expect to work, so I am now going through and copying your config almost line for line - just changing some sensor names to keep it separate from my usual set-up.

Well I have now tried multiple variations and so far what seems to make a difference is to set up the Utility Meter to measure the daily energy import or export (kWh) under YAML, not via the Helper menu (sub-menu of Settings). The only difference is in the YAML version I set the Tariffs option.

If I compare the two, I get the same kWh readings, but it appears the way the UI version is handled in the maths equation of the Template Sensor is different.

I will let it run for 24 hours and then I will add a Tariff to the UI version and see what happens. Maybe I am dreaming and need to triple check my settings, but I now have three variations running and only one is giving me history - the YAML Utility Meter!

EDIT:
Well I feel like a goose. After much trial and error, I found I had two problems:

1. Extraneous characters in my maths/state code; and
2. I hadn’t twigged to the obvious, that when I set up a new sensor, it will return an error in a formula until it has some data. So setting up a new solar generation sensor after sunset will most likely return “unknown” results on an equation until tomorrow. If only I had just waited 12 hours.

I did spend a bit of time working out how I want naming conventions, because quite a few of my sensors across HA don’t conform to any pattern. So as I was re-doing my energy set-up based on @del13r advice, I started re-naming or creating them like this:

sensor.
        grid
            _power  	##(instant import W)

            _energy	## kWh importing Currently all-time: sensor.grid_import_energy
                  _daily  		# Utility Meter single kWh EXISTS in config already 

                  _tou  		### Utility Meter parent of below
                    _peak       ### use "peak" for single tariff instead of daily?
                    _shoulder
                    _offpeak

            _supply_charge		# $
            _tariff  		# single $/kWh eg $0.3142
                _tou	## used in automation if TOU
                _peak	## if TOU - use "peak" for single tariff?
                _shoulder
                _off-peak
            _cost    		# single tariff calculated by above (kWh * tariff)
                _daily
                _peak    ## if TOU - use "peak" for single tariff instead of "daily"?
                _shoulder
                _off-peak

       consumption
            _power 		##(instant W)
                _net  	##(instant production minus import W)

I thought this would be a simple & quick process, but so far I am up to 35 sensors (including allowing for future ToU and capped exports) I’m sure there are a couple I have missed- but there might be some I can collapse. I haven’t started on planning naming conventions for battery sensors yet!

I did start with explanatory names like “sensor.grid_energy_import_daily” but the names started getting too long and related-sensors weren’t grouped. I identified tier-1 names like “grid”, “solar” & “consumption” to allow a quick search of all “children” sensors.

1 Like

So you’re working ok now? When I was setting these up, I always used the dev tools / template page to test my maths and logic in a live and interactive fashion. Saved me a lot of headaches and reboots.

1 Like

Yes - all good now. I just need to follow your examples on the automation for switching TOU - it will allow me to do some what-if scenarios for when I do have to swap to a smart-meter with TOU.

I found the template page invaluable to test the maths and the formatting. It’s not 100% on everything, and sometimes it’s hard to work out the error message, but it does save a lot of frustration.

I am planning on doing the same calculation for my solar panels but I have not yet figured out how to do it.
Have a similar challange since the price changes every hour.
Want to be able to track the total savings from the solar panels to track when the investment have payed off.

Would you mind sharing how you solved it?

As a follow up regarding payback from my PV system, here’s what I’ve done so far on this topic. There’s lots of room for improvement, so suggestions and feedback are appreciated.

its only been a year, but I have finally moved to this solution and its great!

Alrighty guys,

Here is the fully manual solution I came up with using just the rest sensor for Enphase Envoy on D7 firmware.
It’s a lengthy guide with lots of explanation.
Hopefully it helps someone else out.

I’m reaching out to say a massive thankyou for the very well documented and detailed explanations including code - that was a massive effort in documenting so well and its appreciated. I’m setting up our solar system (and learning HA) here in Northern NSW, with three FIT tariffs (Two Peak periods week days) and from your information Im pretty sure I can work it out now. At this stage if been making notes, copying and modifying your original YAML code to match my Retailer and sensors etc. Our Bill has one additional Item which Ive yet to get to, its a Hot Water TOU rate ie CL2. They state on bill its “Controlled load 2 rates generally available for 10 to 18 hours per day”. I’m assuming you don’t have such a charge? yet to get my head around how I would apply it since it doesn’t appear (TBC) I can know in advance how many hours per day I’ll be charged for that service (for purposes of Bill estimation and Daily Costs etc.

Hi there @LozinOz,

Thanks for the compliment. I go to the effort of trying to be as clear as possible in documentation to help new users and reduce confusion as much as possible. Glad you like it.

I had a hot water system on controlled load as well, however the solar system does not see that usage as it only measures what the solar system sends to the main meter or pulls from the main meter.

The controlled load is actually a seperate wire that only goes to the hot water system coming out of my smart meter which only activates when the energy provider sends a signal to activate it. That’s the “controlled” part. See Zellweger off-peak - Wikipedia
The “load” part is the 3.6kW load your hot water system will likely pull until the thermostat hits a certain temperature.

The ct clamp your solar system comes with will not clamp around the controlled load wire, and therefore it won’t see the hot water consumption unfortunately.

Here is a crude diagram.

Example real life pic

Blue wire is for controlled load and White wire is for the rest of the house. Black clamp goes to my solar system.

As far as I know, the only way to measure the total grid import of your house inclusive of controlled load is some sort of device that can read/count the flashing led light pulses from the smart meter.

I have some experience with a device that measures the consumption flashes called powerpal, however it was not possible to integrate it with home assistant last time i checked.

The drawback of such a device is that it only flashes when power is imported, and there is no flash for export, so that’s where the solar system is better.

There may be some other 3rd party solution that uses another ct clamp for measuring the controlled load consumption. This example can measure up to 12kW load via the ct clamp. My hot water system pulls less than 4kW. Shelly EM Wi-Fi Energy Meter - SmartHome

Since then, I purchased a solar diverter for my hot water system so I can now see how much energy my hot water system consumes for free from the sun so I no longer use controlled load and I disconnected and stopped using the powerpal.

Here is an image displaying my solar diverter using up all of the available production to heat my hot water first thing in the morning until it reaches a certain temperature and then my consumption returns back to normal. The great thing about the diverter is that it never pulls from the grid. It only uses what would otherwise be exported to the grid, to instead heat the water.

I’ve called my water heater ESPaladin32.

Hi There @ [del13r]
Thanks for your again informative reply and information. We moved from Vic to Northern NSW, currently renting so adding Shelly (which I’d love to do) isn’t feasible for me to measure Controlled Load unfortunately. additionally whilst I’ve used powerpal for years in the past, our current smart-meter just doesn’t EVER produce the necessary flashing led light pulses (ever) I’m aware there is no flash for export - I’m in dialogue with retailer to correct this - so far no luck. so I’m currently working with what I’ve got. From your helpful diagram and description am I correct to conclude that controlled load charge from retailer is in addition to the measured TOU Grid Draw that I intend using this automation to derive. For energy bill Cost estimation purposes I would therefore guestimate a daily kWh usage in hours x Controlled Load tariff charge?
Many thanks

Hi @LozinOz
I was able to find a good example on a previous bill where I had switched back to controlled load for just 1 day while I installed an esp32 board into my diverter so I could get it talking to home assistant.
This will help show the effect of using controlled load on your bill for just 1 day.

The last line was what my hot water system pulled that day (5.472 kWh) multiplied by the $0.1764180 rate and then how much it cost me = $0.963881856
On the bill it is $0.97 (they don’t round up the daily amount. It only gets rounded up to the next cent for the total energy amount at the end of 90 days).

Super obvious question, but I have to ask it anyway, if you have solar, you would have the best chance of checking for led pulses at night as there would be barely any grid import occurring in the day and therefore barely any led flashes in the day.

Another thing I found with the powerpal was that for some smart meters a flash could mean 1Wh or 10Wh or 100Wh and you have to adjust powerpal accordingly to each type of smart meter.

You could do like this diagram says for the shelly EM
(Just replace washer with hot water)

1 Like

Hi
Yes fair to ask but alas no, I’ve check extensively (including at night) for those elusive pluses without success. Had energy company check meter & he confirmed it should (but was not) producing the pulses & would recommend a meter replacement. I’ve used power pal for years before moving with more than one meter so had a pretty good idea what i was looking for.

Actually that’s a good idea - thank you. I’ll Investigate further.
Appreciate suggestion
Cheers
Loz

1 Like

Hi
General question regarding calculating & tracking energy Bills please.
I have currently setup sensors to define Peak, Offpeak, Shoulder (and several more), my thinking being define the value ONCE (charge per kWh for each of above) then use the sensor value anywhere else in HA that uses these values for calculations. (example below). My question is is this approach flawed? ie: if (when) the tariffs change from retailer for whatever reason, I would change the tariff definition values - but would that then (incorrectly ) apply the (now current) updated tariffs to all historic records HA retains for previous bill calculations? Not a big deal in the order of things but asking as there may be good reason others have approached this differently I may not have considered
Thanks
example my sensors:

     energy_tariff_re_offpeak:
        unique_id: energy_tariff_re_offpeak_loz
        friendly_name: "RE OffPeak Tariff"
        value_template: "0.26928"
        icon_template: mdi:speedometer-slow
        unit_of_measurement: "$"

      energy_tariff_re_shoulder:
        unique_id: energy_tariff_re_shoulder_loz
        friendly_name: "RE Shoulder Tariff"
        value_template: "0.35695"
        icon_template: mdi:speedometer-medium
        unit_of_measurement: "$"

Not at all. I had the same idea recently and implemented it and it works perfectly.

Here is where I documented it

Using the ‘Energy Meter’ integration (installed via HACS), that provided a utility meter like function but with the ability to call a cost sensor (or compensation for export FIT), I moved to using this, that is for the current Red Energy - ToU plan. Usual 7-9am and 5-8pm peaks, plus shouler and off-peak etc.

This creates the cost and compensation sensors with the current price to buy or sell energy, then creates all the meters to track usage in the different tariff periods, then groups them up to get a daily/weekly/monthly/years total for all the imported and exported kWh and $.

Finally an automation that 30sec after the tariff period has changed, it calls the selector and updates the peak/shoulder/offpeak period thats currently in operation. 30 sec delay is as I’m pulling data from the inverter/power meter using modbus, that can be >30s between polls.

# Based upon Australian energy retailer 'Red Energy' and their Time of Use Tariff Plan.
# v1.0 - Updated 1 July 2023 for new Red Energy Rates
# v1.1 - Updated 1 October 2023 for new Red Energy Rates
# v2.0 - Updated 4 January 2024 to replace static FIT rate with a sensor that allows for use with variable FIT providers

template:
  - sensor:

#  Electricity_Price provides a method to allow selecting the 'Use an entity with current rate' in Energy Dashboard.
#
#  This tariff plan is based upon a Time of Use (ToU) plan with different charges at the following times:
#
#  Peak      : $0.41745 p/kWh. Monday to Friday between 7am - 9am and 5pm - 8pm.
#  Shoulder  : $0.35695 p/kWh. Monday to Friday between 9am - 5pm and 8pm - 10pm.
#  Off-Peak  : $0.26928 p/kWh. Monday to Friday between 10pm and 7am. Saturday and Sunday - All Day.
#
#  Note: If you energy provider plan has different times, you must update them here AND also in the Automation (that updates the Selector) at the bottom.
#

    - name: "Electricity - Price" 
      unique_id: electricity_price
      unit_of_measurement: "$/kWh"
      device_class: monetary
      state:  "
        {%set Peak = 0.41745 %}
        {%set WeekdayShoulder = 0.35695 %}
        {%set OffPeak = 0.26928 %}
        {%set H = as_timestamp(now())|timestamp_custom ('%-H')|float(0) %} {##Hour (24-hour clock) as a decimal number. 0, 1, 2, ... 23##}
        {%set w = as_timestamp(now())|timestamp_custom ('%w')|float(0) %} {##HWeekday as a decimal number, where 0 is Sunday and 6 is Saturday.	0, 1, …, 6##}	 
        {##0 for weekday, 1 for weekend##}
        {% if (w == 0) or  (w == 6) %} {% set weekday = 0 %}
        {% else %} {% set weekday = 1 %}
        {% endif %}
        {% set charge = 0 %}
        {##peak##}
        {% if (weekday == 1) and (H >= 7) and (H < 9) %} {{Peak}}
        {% elif (weekday == 1) and (H >= 17) and (H < 20) %} {{Peak}}
        {##weekday shoulder##}
        {% elif (weekday == 1) and (H >= 9) and (H < 17) %} {{WeekdayShoulder}}
        {% elif (weekday == 1) and (H >= 20) and (H < 22) %} {{WeekdayShoulder}}
        {##off peak##}
        {% else %} {{OffPeak}}
        {% endif %}
        "

#########################
#
# ALTERNATIVE VERSION TO ABOVE SENSOR VERSION
#

#    - name: "Electricity - Price" 
#      unique_id: electricity_price
#      unit_of_measurement: "$/kWh"
#      device_class: monetary
#      state:  "
#        value_template: >
#          {% set tariff = { "Peak": 0.42790, "Shoulder": 0.36498, "OffPeak": 0.27698 } %}
#          {% 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%}
#         "
#


#########################
#
#  Current Feed in Tariff (FIT) / Export rate, rate 1 & 2 allows setting a second rate if variable FIT rates (i.e. $0.15 for first 10kWh, then $0.07 thereafter)
#
    - name: "Electricity - FIT"
      unique_id: electricity_fit
      unit_of_measurement: "$/kWh"
      device_class: monetary
      icon: mdi:cash-plus
      state: >
        {## Enter compensation per kWh rates below ##}
        {% set rate1 = 0.07 %}
        {% set rate2 = 0.07 %}
        {% set fit_exported_today = states('sensor.grid_exported_daily') | float %}
        {% if fit_exported_today <= 10 %} {{rate1}}
        {% else %} {{rate2}}
        {% endif %}


####################################
# IMPORT UTILITY METERS
# See: https://github.com/zeronounours/HA-custom-component-energy-meter

energy_meter:

  grid_imported_daily:
    unique_id: grid_imported_daily
    name: Grid - Imported Daily
    source: sensor.power_meter_consumption
    source_type: from_grid
    cycle: daily
    price_entity: &electricity-price sensor.electricity_price
    tariffs:
      - peak
      - shoulder
      - offpeak

  grid_imported_monthly:
    unique_id: grid_imported_monthly
    name: Grid - Imported Monthly
    source: sensor.power_meter_consumption
    source_type: from_grid
    cycle: monthly
    price_entity: *electricity-price
    tariffs:
      - peak
      - shoulder
      - offpeak

  grid_imported_yearly:
    unique_id: grid_imported_yearly
    name: Grid - Imported Yearly
    source: sensor.power_meter_consumption
    source_type: from_grid
    cycle: yearly
    price_entity: *electricity-price
    tariffs:
      - peak
      - shoulder
      - offpeak


#########################
# EXPORT UTILITY METERS
# See: https://github.com/zeronounours/HA-custom-component-energy-meter

  grid_exported_daily:
    unique_id: grid_exported_daily
    name: Grid - Exported Daily
    source: sensor.power_meter_exported
    source_type: to_grid
    cycle: daily
    price_entity: &fit-rate sensor.electricity_fit

  grid_exported_monthly:
    unique_id: grid_exported_monthly
    name: Grid - Exported Monthly
    source: sensor.power_meter_exported
    source_type: to_grid
    cycle: monthly
    price_entity: *fit-rate

  grid_exported_yearly:
    unique_id: grid_exported_yearly
    name: Grid - Exported Yearly
    source: sensor.power_meter_exported
    source_type: to_grid
    cycle: yearly
    price_entity: *fit-rate


#########################
#
# GROUP - TO SUM UP THE DAILY / MONTHLY / YEARLY IMPORT KWH and $ SENSORS
#         TO GIVE A TOTAL OF EACH
#

sensor:

# DAILY
  - platform: group
    name: Grid - Imported Daily - Total kWh
    unique_id: grid_imported_daily_total_kwh
    unit_of_measurement: "kWh"
    device_class: energy
    type: sum
    entities:
      - sensor.grid_imported_daily_peak
      - sensor.grid_imported_daily_shoulder
      - sensor.grid_imported_daily_offpeak

  - platform: group
    name: Grid - Imported Daily - Total Cost
    unique_id: grid_imported_daily_total_cost
    unit_of_measurement: '$'
    device_class: monetary
    type: sum
    entities:
      - sensor.grid_imported_daily_cost_peak
      - sensor.grid_imported_daily_cost_shoulder
      - sensor.grid_imported_daily_cost_offpeak

# MONTHLY
  - platform: group
    name: Grid - Imported Monthly - Total kWh
    unique_id: grid_imported_monthly_total_kwh
    unit_of_measurement: "kWh"
    device_class: energy
    type: sum
    entities:
      - sensor.grid_imported_monthly_peak
      - sensor.grid_imported_monthly_shoulder
      - sensor.grid_imported_monthly_offpeak

  - platform: group
    name: Grid - Imported Monthly - Total Cost
    unique_id: grid_imported_monthly_total_cost
    unit_of_measurement: '$'
    device_class: monetary
    type: sum
    entities:
      - sensor.grid_imported_monthly_cost_peak
      - sensor.grid_imported_monthly_cost_shoulder
      - sensor.grid_imported_monthly_cost_offpeak

# YEARLY
  - platform: group
    name: Grid - Imported Yearly - Total kWh
    unique_id: grid_imported_yearly_total_kwh
    unit_of_measurement: "kWh"
    device_class: energy
    type: sum
    entities:
      - sensor.grid_imported_yearly_peak
      - sensor.grid_imported_yearly_shoulder
      - sensor.grid_imported_yearly_offpeak

  - platform: group
    name: Grid - Imported Yearly - Total Cost
    unique_id: grid_imported_yearly_total_cost
    unit_of_measurement: '$'
    device_class: monetary
    type: sum
    entities:
      - sensor.grid_imported_yearly_cost_peak
      - sensor.grid_imported_yearly_cost_shoulder
      - sensor.grid_imported_yearly_cost_offpeak


#######################
#
# Checks the time and based upon TOU rate times, updates Selector for the 'grid_imported_daily/monthly/yearly' entities to use Peak / Shoulder / OffPeak tariff.
# Given the WLCRS pulls data from Huawei Inverters using Modbus and this is at 30 second intervals, the triggers are set for the tariff changes time + 30 seconds.
#

automation:
### adjust the time triggers below to match when your standard electricity tariff changes (peak, shoulder, offpeak). Adjust the template in the action block as required to match your plan.
  - alias: Set Electricity Tariff
    description: 'Set Electricity Tariff (Huawei Solar) depending upon the day of week and time'
    trigger:
      - platform: time
        at: '07:00:30'
      - platform: time
        at: '09:00:30'
      - platform: time
        at: '17:00:30'
      - platform: time
        at: '20:00:30'
      - platform: time
        at: '22:00:30'
      - platform: homeassistant
        event: start
    condition: []
    action:
      - service: select.select_option
        data:
          option: >-
            {% set t = now() %}
            {%- if (( t.hour >= 7 and t.hour < 9 ) or ( t.hour >= 17 and t.hour < 20 )) and
            is_state('binary_sensor.workday_sensor', 'on') %}
              peak
            {%- elif (( t.hour >= 9 and t.hour < 17 ) or ( t.hour >= 20 and t.hour < 22 )) and 
            is_state('binary_sensor.workday_sensor', 'on') %}
              shoulder
            {%- else -%}
              offpeak
            {%- endif -%}
        target:
          entity_id:
#  Selectors used by utility_meter / energy_meter
            - select.grid_imported_daily
            - select.grid_imported_monthly
            - select.grid_imported_yearly
    mode: single

#######################


Thanks both of you for sharing - sorry my belated reply I’m caught up in Jury Duty at the moment, will be able to revisit once done. Again thanks!