I have created a virtual mains battery. Probably not the first, but I did not find any reference to something similar on the forum. So:
I have a solar installation in combination with a good old fashioned bidirectional utility meter. I can feed power back into the net and recuperate that energy at a later moment. So essentially I have a 100% efficient battery with infinite capacity.
I get the produced power from my solar installation and I measure the power consumption of the house. With those two numbers I can calculate the power going into the battery and the power taken from the utility. Power will flow into the virtual battery if the produced power is higher than the consumed power. Power will flow out the virtual battery if the solar power is less than the consumed power and the virtual battery is not empty.
Part of my dashboard looks like this:
The battery is now empty. But in the Power balance you can see we had some sun yesterday, that charged the battery, until it was again discharged in the early morning hours. This is one day in December, in the summer the battery will accumulate charge that will be consumed over weeks if not months after.
The relavant configuration.yaml file snippets:
# Sensors
sensor:
# SMA inverter
- platform: template
sensors:
solar_power:
value_template: "{{ states('sensor.sma_grid_power') | float(0) | round(0) }}"
unit_of_measurement: "W"
# calculate electric power flows
- platform: template
sensors:
battery_power:
value_template: >
{% if is_state("binary_sensor.battery_empty", "off") %}
{{ '%0.0f' | format(states('sensor.solar_power') | float - states('sensor.mains_power') | float) }}
{% else %}
{{ '%0.0f' | format([ (states('sensor.solar_power') | float - states('sensor.mains_power') | float), 0 ] | max) }}
{% endif %}
unit_of_measurement: 'W'
utility_power:
value_template: >
{{ '%0.0f' | format(states('sensor.mains_power') | float - states('sensor.solar_power') | float + states('sensor.battery_power') | float) }}
unit_of_measurement: 'W'
actual_power:
value_template: >
{{ '%0.0f' | format(states('sensor.mains_power') | float - states('sensor.solar_power') | float) }}
unit_of_measurement: 'W'
actual_current:
value_template: >
{{ '%0.1f' | format(states('sensor.mains_current') | float - states('sensor.sma_current_numeric') | float) }}
unit_of_measurement: 'A'
# calculate electric energy
- platform: integration
source: sensor.solar_power
name: energy_produced
method: left
unit_prefix: k
unit_time: h
round: 3
- platform: integration
source: sensor.battery_power
name: energy_stored
method: left
unit_prefix: k
unit_time: h
round: 3
- platform: integration
source: sensor.mains_power
name: energy_consumed
method: left
unit_prefix: k
unit_time: h
round: 3
- platform: integration
source: sensor.utility_power
name: energy_imported
method: left
unit_prefix: k
unit_time: h
round: 3
# Battery storage (virtual mains battery)
- platform: template
sensors:
battery_empty:
value_template: "{{ states('sensor.energy_stored_meter') <= '0' }}"
icon_template: >
{% if is_state('binary_sensor.battery_empty', 'on') %}
mdi:battery-alert
{% else %}
mdi:battery
{% endif %}
# Meters
utility_meter:
# Electric energy meters
# solar
energy_produced_meter:
source: sensor.energy_produced
cycle: yearly
# virtual battery (charge or discharge)
energy_stored_meter:
source: sensor.energy_stored
net_consumption: true
cycle: yearly
# consumption
energy_consumed_meter:
source: sensor.energy_consumed
cycle: yearly
# net consumption
energy_imported_meter:
source: sensor.energy_imported
cycle: yearly
NOTES:
There is no battery state of charge calculation because the capacity is infinitive.
There is very small monthly fee (13 euro) that I pay to be allowed to feed back into the net. That is a very good price for 100% efficient battery with infinite capacity!
Once a year I pay the balance for net consumption, or if I have over-produced loose that overproduction. The annual meter reset takes care of that.