Self-consumed solar energy, calculating per phase, but needs balanced

Hi,

i’ve set up my Shelly 3em with home-assistant, and really love the information it gives me. But the “Self-consumed solar energy” is calculated wrong/different, compared to how the realy energy meter in the house works.
Maybe there is a different way to configure it correctly:

I have added each of the three phases (Energy) as a seperate entry in “Grid consumption”.
Also each of the three returns of each phase in “Return to grid”.

This gives me a per phase view/calculation. But the energy meter balances returns with consumption, only if in total there is any return it really counts.

Is there any specific settings to define this, or to i need to configure summed-up values for consumption and return to use in the energy dashboard? I quite like to be able to see each phase there.

1 Like

I’m having exactly the same challenge. Shelly 3EM, three phase supply and solar PV production on a single phase.

Power:

I can get my head around using the three instant power sensors:

P = A+B+C

If P is positive I’m importing power from the grid and if P is negative I’m exporting my excess solar power. Easy enough to setup a template to calculate P. The important thing with net metering is they cancel each other out. If I’m consuming 2kW on each phase A & B, but exporting 5 kW on phase C, my net power is exporting 1 kW.

Energy:

The Shelly 3EM has six energy sensors, one for each phase counting imported energy and one for each phase counting returned energy.

Using the example above and assuming steady state for one hour. Phase A & B total energy counters will go up by 2 kWh each (4 kWh total import) and Phase C energy returned counter will go up by 5 kWh. But my net energy has been to export only 1 kWh.

This is important as I may pay 30c / kWh for import and only receive 10c/ kWh for export.

So the trick is to somehow net the energy over a specific time period (maybe 15 mins or hourly) depending on your supplier.

I’m currently looking at using utility meter with quarter_hourly cycle and net_consumption options to do the calculations.

I’ll let you know how I fare.

1 Like

How did you fare?

I have the Shelly 3EM enroute at the moment, and have been looking at how to implement it with my 3-phase and 2 x solar single phase inverters (on different phases), with NET metering.

I found the details the new Shelly native integration uses here:
https://shelly-api-docs.shelly.cloud/gen1/#shelly-3em-coiot

Wondering if it would be better to use the total energy counter, which I think is an inclining counter given:

“Note, that energy and returned_energy do not survive power cycle or reboot – this is how the value is implemented on other Shellies. Shelly 3EM features a persisted version which is not affected by power cycling or lack of connectivity. To get the persisted counters use total and total_returned .”

total, number, Total consumed energy, Wh
total_returned, number, Total returned energy, Wh

So for Net metering: (*concept yaml need to turn into sensor templates once assumptions are verified)

Import:
{if (total - total_returned) > 0}
  {{(total - total_returned)}}
{else } 
  {{0}}

Export:
{if (total - total_returned) < 0 }
  {{(total - total_returned) < 0 * -1}} 
{else} 
  {{0}}

Consumption:
{if  (total - total_returned) > 0}   #importing
   {{total + solargen - total_returned}} 
 {else}
   {{solargen - total_retured + total}}   # exporting

This assumes that total does does already have the solar(total_returned) removed, solargen is total solar generation from inverters not form Shelly 3em

if total and total_returned are inclining and don’t reset daily, might have to use a utility sensor template to create one for daily. monthly etc.

Thoughts?

I’m halfway there but it is still not satisfactory.

I can correctly calculate the 3 phase net metering over a time period; 15 minutes, hourly, but it still doesn’t account correctly for short term spikes. Of course as the time period gets smaller the accuracy improves, so it maybe good enough.

Certainly a lot more accurate for three phase net metering than just using the raw Shelly energy sensors for each phase:

Configuration, not dissimilar to your concept description:

template:
# Create sum of shelly energy across three phases and take away energy_returned from single phase PV inverter
# Check availability of sensors to exclude zero entries
# Could replace with persistent shelly_total_energy when included in integration (not yet available)
  - sensor:
      - name: "Shelly Energy Total"
        unique_id: shelly_energy
        state: "{{ 
              states('sensor.shelly_channel_a_energy')|float + 
              states('sensor.shelly_channel_b_energy')|float +
              states('sensor.shelly_channel_c_energy')|float -
              states('sensor.shelly_channel_c_energy_returned')|float
              }}"
        availability: "{{ 
            [ states('sensor.shelly_channel_a_energy'), 
              states('sensor.shelly_channel_b_energy'),
              states('sensor.shelly_channel_c_energy'),
              states('sensor.shelly_channel_c_energy_returned')
            ] | map('is_number') | min
          }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total

utility_meter:
# Break shelly total energy up into utility meters to create measurement periods
  settlement_energy:
    source: sensor.shelly_energy_total
    cron: "*/30 * * * *"
    net_consumption: true
  hourly_energy:
    source: sensor.shelly_energy_total
    cycle: hourly
    net_consumption: true
  daily_energy:
    source: sensor.shelly_energy_total
    cycle: daily
    net_consumption: true
  monthly_energy:
    source: sensor.shelly_energy_total
    cycle: monthly
    net_consumption: true
  yearly_energy:
    source: sensor.shelly_energy_total
    cycle: yearly
    net_consumption: true
# For the settlement period (defined in cron:) create a meter that sums the last_period
# for import and export - this feeds the Energy Dashboard
  settlement_import:
    source: sensor.settlement_import_last_period
    delta_values: true
  settlement_export:
    source: sensor.settlement_export_last_period
    delta_values: true

)

# template sensors
# split +ve settlement(shelly)_energy into import
    settlement_import_last_period:
      value_template: "{{max(0,state_attr('sensor.settlement_energy', 'last_period')|float)}}"
      unit_of_measurement: kWh

# split -ve settlement(shelly)_energy into export
    settlement_export_last_period:
      value_template: "{{(min(0,state_attr('sensor.settlement_energy', 'last_period')|float))|abs}}"
      unit_of_measurement: kWh

1 Like

I am also going to see if we can get shelly to add these NET counters to the firmware so they are accurate: total_import, total_export
Have started a thread at shelly, if you could add support that would be great.

1 Like

Have submitted a feature request to Shelly/Allterco, suggest as many people as possible do the same at:
https://shelly.cloud/support/devices-and-features-requests/

I actually think you want to calculate the Net energy on as short time frame as you can: eg every 1 second or however often the counters are updated. If the power counters are updated more frequently you can use them to create a template sensor for net power import and export then create energy counters using:

  # Sensor for Riemann sum of energy import (W -> Wh)
  - platform: integration
    source: sensor.power_import
    name: energy_import_sum
    unit_prefix: k
    round: 1
    method: left

  # Sensor for Riemann sum of energy export (W -> Wh)
  - platform: integration
    source: sensor.power_export
    name: energy_export_sum
    unit_prefix: k
    round: 1
    method: left

This should give you much better accuracy on short spikes, in the mean time until we hopefully get shelly to add native net meter counters.

Hello everyone,

I put a NodeRed-Flow together which should measure the energy offtake and injection correctly with an Shelly 3EM.

The Wh-values of the Shelly get injected with MQTT every 60 seconds, added together with Join/Function-Node and written either to the injection-value (if solar-plant produces more than house consumption) or written to the offtake-value. For those values I used an input_number.

To view those values in the energy dashboard, I created a template in yaml to convert the input_numbers into global sensors.

I attach the code below.

I’ll post in the next weeks, if the values match with our official digital meter of the grid opterator.

[{"id":"7f6ef726678ad590","type":"tab","label":"Saldierend MQTT","disabled":false,"info":"","env":[]},{"id":"4dff564fddf1349b","type":"change","z":"7f6ef726678ad590","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"val1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":200,"wires":[["4c52d95c665211b3"]]},{"id":"4c52d95c665211b3","type":"join","z":"7f6ef726678ad590","name":"Join","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"6","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":550,"y":340,"wires":[["8da9218cb3398bc2"]]},{"id":"10cb7b8d85d7a2fa","type":"change","z":"7f6ef726678ad590","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"val2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":260,"wires":[["4c52d95c665211b3"]]},{"id":"8da9218cb3398bc2","type":"function","z":"7f6ef726678ad590","name":"SUM","func":"msg.payload = Object.values(msg.payload).reduce((a,b) => a + parseFloat(b),0)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":690,"y":340,"wires":[["8d416518864612c1"]]},{"id":"64752c3a9565984f","type":"change","z":"7f6ef726678ad590","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"val3","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":320,"wires":[["4c52d95c665211b3"]]},{"id":"e4d717b0237efdde","type":"change","z":"7f6ef726678ad590","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"val4","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":380,"wires":[["4c52d95c665211b3"]]},{"id":"e47f49165029675d","type":"change","z":"7f6ef726678ad590","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"val5","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":440,"wires":[["4c52d95c665211b3"]]},{"id":"034bfe8cc4b41258","type":"change","z":"7f6ef726678ad590","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"val6","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":500,"wires":[["4c52d95c665211b3"]]},{"id":"f2b7093a5a53258c","type":"switch","z":"7f6ef726678ad590","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"0","vt":"num"},{"t":"lt","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":1130,"y":340,"wires":[["92ab0d4b40973e6f","757ceaf1c9becdd6"],["cdfb66ae02312698","5668137c24d52fc3"]]},{"id":"92ab0d4b40973e6f","type":"change","z":"7f6ef726678ad590","name":"Neuer Wh-Wert","rules":[{"t":"set","p":"topic","pt":"msg","to":"val1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":740,"wires":[["7e2d8ba285b1535e","72d1836556a284af"]]},{"id":"cdfb66ae02312698","type":"change","z":"7f6ef726678ad590","name":"Neuer Wh-Wert","rules":[{"t":"set","p":"topic","pt":"msg","to":"val1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":1040,"wires":[["3c732a44a7805e20"]]},{"id":"7e2d8ba285b1535e","type":"join","z":"7f6ef726678ad590","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":690,"y":760,"wires":[["52fd1354476abad7"]]},{"id":"3c732a44a7805e20","type":"join","z":"7f6ef726678ad590","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"1","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":680,"y":1060,"wires":[["71566bcc7728e54a"]]},{"id":"52fd1354476abad7","type":"function","z":"7f6ef726678ad590","name":"Add","func":"msg.payload =  Object.values(msg.payload).reduce((a,b) => a + (parseFloat(b)  || 0),0)\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":760,"wires":[["3b0ac6f89791d5cb"]]},{"id":"71566bcc7728e54a","type":"function","z":"7f6ef726678ad590","name":"Add","func":"msg.payload = Object.values(msg.payload).reduce((a,b) => a + (parseFloat(b) || 0),0)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":870,"y":1060,"wires":[["a755706f5666bc26"]]},{"id":"57e2be01613f64ed","type":"change","z":"7f6ef726678ad590","name":"Alter Netzbezug-Wert","rules":[{"t":"set","p":"topic","pt":"msg","to":"val2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":780,"wires":[["7e2d8ba285b1535e","b46ffb1857d49102"]]},{"id":"188cdb768d45659a","type":"change","z":"7f6ef726678ad590","name":"Alter Einspeise-Wert","rules":[{"t":"set","p":"topic","pt":"msg","to":"val2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":1080,"wires":[["3c732a44a7805e20"]]},{"id":"407268debb09a15a","type":"mqtt in","z":"7f6ef726678ad590","name":"Wh L1","topic":"shellies/shellyem3-C45BBE5F6156/emeter/0/energy","qos":"0","datatype":"auto","broker":"59474d9ba318645d","nl":false,"rap":true,"rh":0,"inputs":0,"x":170,"y":200,"wires":[["4dff564fddf1349b"]]},{"id":"e5cdf1949053b415","type":"mqtt in","z":"7f6ef726678ad590","name":"Wh L2","topic":"shellies/shellyem3-C45BBE5F6156/emeter/1/energy","qos":"0","datatype":"auto","broker":"59474d9ba318645d","nl":false,"rap":true,"rh":0,"inputs":0,"x":170,"y":260,"wires":[["10cb7b8d85d7a2fa"]]},{"id":"f8462feb8c7a1e2c","type":"mqtt in","z":"7f6ef726678ad590","name":"Wh L3","topic":"shellies/shellyem3-C45BBE5F6156/emeter/2/energy","qos":"0","datatype":"auto","broker":"59474d9ba318645d","nl":false,"rap":true,"rh":0,"inputs":0,"x":170,"y":320,"wires":[["64752c3a9565984f"]]},{"id":"3e93ba02ce86c0e1","type":"mqtt in","z":"7f6ef726678ad590","name":"Wh Return L1","topic":"shellies/shellyem3-C45BBE5F6156/emeter/0/returned_energy","qos":"0","datatype":"auto","broker":"59474d9ba318645d","nl":false,"rap":true,"rh":0,"inputs":0,"x":150,"y":380,"wires":[["e4d717b0237efdde"]]},{"id":"4eaa4eacf543d11f","type":"mqtt in","z":"7f6ef726678ad590","name":"Wh Return L2","topic":"shellies/shellyem3-C45BBE5F6156/emeter/1/returned_energy","qos":"0","datatype":"auto","broker":"59474d9ba318645d","nl":false,"rap":true,"rh":0,"inputs":0,"x":150,"y":440,"wires":[["e47f49165029675d"]]},{"id":"c23e75b93cd23e29","type":"mqtt in","z":"7f6ef726678ad590","name":"Wh Return L3","topic":"shellies/shellyem3-C45BBE5F6156/emeter/2/returned_energy","qos":"0","datatype":"auto","broker":"59474d9ba318645d","nl":false,"rap":true,"rh":0,"inputs":0,"x":150,"y":500,"wires":[["034bfe8cc4b41258"]]},{"id":"8d416518864612c1","type":"function","z":"7f6ef726678ad590","name":"/ 60000 => kWh","func":"var x = msg.payload\nmsg.payload = x/60000\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":340,"wires":[["46a32ae0c2f7464c"]]},{"id":"72d1836556a284af","type":"debug","z":"7f6ef726678ad590","name":"Neuer Wert für WH","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"","statusType":"msg","x":605,"y":680,"wires":[],"l":false},{"id":"b46ffb1857d49102","type":"debug","z":"7f6ef726678ad590","name":"Netzbezug Alt","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":585,"y":840,"wires":[],"l":false},{"id":"bfdd6cfc3580756b","type":"poll-state","z":"7f6ef726678ad590","name":"Input-Number: Einspeisung Total","server":"6f93cefd.a282a","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"updateinterval":"10","updateIntervalType":"num","updateIntervalUnits":"seconds","outputinitially":false,"outputonchanged":false,"entity_id":"input_number.einspeisung_total","state_type":"str","halt_if":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"x":170,"y":1080,"wires":[["188cdb768d45659a"]]},{"id":"481ea78526b01390","type":"comment","z":"7f6ef726678ad590","name":"----------------------------------------------------------------------------   NETZBEZUG BERECHNEN   ----------------------------------------------------------------------------","info":"","x":660,"y":600,"wires":[]},{"id":"76cc8c2e5b960f53","type":"comment","z":"7f6ef726678ad590","name":"----------------------------------------------------------------------------   WATTSTUNDEN ALLER SECHS SENSOREN ADDIEREN   ----------------------------------------------------------------------------","info":"","x":690,"y":120,"wires":[]},{"id":"6a96a7a8b3956c5a","type":"comment","z":"7f6ef726678ad590","name":"----------------------------------------------------------------------------   EINSPEISUNG BERECHNEN   ----------------------------------------------------------------------------","info":"","x":640,"y":960,"wires":[]},{"id":"c21c1fd6d2fff8da","type":"poll-state","z":"7f6ef726678ad590","name":"Input-Number: Netzbezug Total","server":"6f93cefd.a282a","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"updateinterval":"10","updateIntervalType":"num","updateIntervalUnits":"seconds","outputinitially":false,"outputonchanged":false,"entity_id":"input_number.netzbezug_total","state_type":"str","halt_if":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"x":170,"y":780,"wires":[["57e2be01613f64ed"]]},{"id":"3b0ac6f89791d5cb","type":"api-call-service","z":"7f6ef726678ad590","name":"Neuen Netzbezug setzen","server":"6f93cefd.a282a","version":3,"debugenabled":false,"service_domain":"input_number","service":"set_value","entityId":"input_number.netzbezug_total","data":"{\"value\":payload}","dataType":"jsonata","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1130,"y":760,"wires":[["16ac7fda9aab1997"]]},{"id":"16ac7fda9aab1997","type":"debug","z":"7f6ef726678ad590","name":"Neuer Netzbezug_Total","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1290,"y":680,"wires":[]},{"id":"757ceaf1c9becdd6","type":"debug","z":"7f6ef726678ad590","name":"Neuer Wert für WH","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"","statusType":"msg","x":1265,"y":260,"wires":[],"l":false},{"id":"5668137c24d52fc3","type":"debug","z":"7f6ef726678ad590","name":"Neuer Wert für WH","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"","statusType":"msg","x":1265,"y":420,"wires":[],"l":false},{"id":"46a32ae0c2f7464c","type":"function","z":"7f6ef726678ad590","name":"Round","func":"msg.payload = Number(msg.payload.toFixed(7));\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1010,"y":340,"wires":[["f2b7093a5a53258c"]]},{"id":"a755706f5666bc26","type":"api-call-service","z":"7f6ef726678ad590","name":"Neue Einspeisung setzen","server":"6f93cefd.a282a","version":3,"debugenabled":false,"service_domain":"input_number","service":"set_value","entityId":"input_number.einspeisung_total","data":"{\"value\":payload}","dataType":"jsonata","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1130,"y":1060,"wires":[["e3928a8d20f685be"]]},{"id":"e3928a8d20f685be","type":"debug","z":"7f6ef726678ad590","name":"Neuer Einspeisung_Total","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1350,"y":960,"wires":[]},{"id":"59474d9ba318645d","type":"mqtt-broker","name":"HomeAssistant","broker":"192.168.0.208","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""},{"id":"6f93cefd.a282a","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]```
1 Like

I don’t quite understand your code. Shouldn’t there be an invoice somewhere?

How can I calculate with previous values in HA? So with the current consumption in W I have already created a sensor, but what I haven’t figured out yet is how I can process the kWh accordingly?
My goal is to determine the energy fed in (exactly per minute would be enough). So that I can estimate how much more energy I’m generating than I’m using. The energy dashboard already shows it to me per hour. But this is not meaningful if I consume a total of 2kWh and generate 1kWh during this time. Since at times the generation is e.g. 200W higher than the consumption, this would not be taken into account spread over the hour. Do you know what I mean?
Shelly could easily solve this in FW if they wanted to.

Hi,

I have created new Net metering templates using the power sensors that update every second for best accuracy!