Recently HomeAssistant released a new feature, energy management. As we've been tracking our energy usage for a while and have never managed to find a good way of representing things, this was a huge change. Over the last few days I have finally found the time to look at integrating things.

As with most things in HA, what seemed like a great feature that will be easy to use turned out to need a lot more work than anticipated. HA suffers from supporting so many different systems and is growing at such a pace that often the documentation isn't great or complete. I realise it's an open source project but for some reason I find the internals very opaque and unwelcoming for me to want to contribute rather than simply use.


Energy Management data is provided by Statistics. Reading through the documentation it seemed all I needed to make things work was update the various sensors I had to use statistics and a suitable device_class (energy)  and all would be good. I made the changes to the sensor configurations and restarted. Heading to the configuration page for Energy I found nothing listed but a helpful message saying it could take a few hours. So I waited...

A few hours later I tried again and got the same results. Certainly not encouraging.

MQTT -> Modbus

While contemplating what was going on I also decided to change reading the inverter over to TCP Modbus rather than my home grown TCP Modbus to MQTT solution. I found some examples of the configuration needed online but none of them worked and it took a while for me to adjust things so data was flowing. The documentation isn't clear but you need the data_type to refer to the Modbus data type you want to extract not what the final number format will be. This caused me a few issues initially with missing data. Thankfully I had the registers and types I was interested in, so it was just a process of migrating things over.

This change wasn't strictly needed but it has further simplified my setup which is a constant work in progress :-)


Once I had the data being collected reliably I started to look again at what I needed for the energy management. The Energy device_class documentation specifies Wh or kWh and the energy management wants different statistics for each flow (Battery Charge & Discharge, Grid Import & Export).

The inverter recorded and updated some of the details but on a continual basis and I felt that having an hourly value would be more helpful for debugging and accuracy. While the data is available it's only available as an instant power register providing the data in Watts, and with a sign to signify the flow. Not ideal but there are ways to make this work.

I decided to start by creating 2 template sensors entities from the flow data, one for each direction. As they both now measure their respective flow the negative value needed converted. I ended up with templates like these,

  - platform: template
        friendly_name: "Battery Discharge Power"
        unit_of_measurement: "W"
        device_class: power
        value_template: >-
          {% if states('sensor.battery_power') | float < 0 %}
          {{ states('sensor.battery_power') | float * -1.0 }}
          {% else %}
          {% endif %}

This produces the power value as W, but I need it as as an energy value in kWh, so time to add another entity. In this case I used the Integration integration to generate a rolling value with the correct units,

  - platform: integration
    source: sensor.battery_discharge
    name: energy_battery_discharge
    unit_prefix: k
    unit_time: h
    round: 2

I now have hourly values of the flows which automatically reset and add up as required based on the immediate usage.

Back to Energy Management

Once I had added the various sensors I needed I revisited the energy configuration page and found the entities available for selection. Once I selected the correct entities data started flowing and the page came to life.

The data is shown well and it's certainly proving to be useful. The monetary calculations don't seem to work, but I'm not overly concerned about that for now.

There may be a better way to do this, but this was as simple as I could arrive at with a few hours of research and experimentation. Improvements are welcome :-)