Battery monitor kWh reporting

Hi!

I've got next situation:

My victron battery monitor gives via MQTT all kind of info.

But unfortunately I don't see the kWh that day charged or discharged.
I do see what at that moment is the charge or discharge.

Also I can see the kWh in total charged and discharged, ever.

I was thinking it would be possible to take, at 00:00h the kWh and than take the present kWh and than minus the 00:00h kWh.

I just have difficulties to get this done, since I have no idea what the right formula would be or how to approach the MQTT only at a certain time.

Someone an idea to help me out?

OK so the Inverter is reporting Watts/KW at that precise moment - so you have an issue in terms of your sampling rate as KWh is the number of KW used during a 1 hr period.

So to start with - lets say you get an MQTT message every second with the current watts

You need to accumulate those number (add them together as they come in) until you get 3600 samples - once you have that you now have the KW used in that hour - or the KWh.

Continue doing that each hour and at the end of the day add them all together and you have your daily KHw

Craig

That would be ideal, unfortunately the battery monitor (not an Inverter) is not producing it's W every second, but randomly.

That's why I wanted to take the kWh in total ever produced.

If I take this number at midnight 00:00h and than reduce the present kWh from the midnight number, I have the correct kWh produced until that present time, right?

Do you mean that at random intervals it publishes to MQTT the current Watts and the total ever kWh? Can you feed that into a debug node and show us exactly what you get please, to help us understand. When you say randomly do you mean every few seconds, minutes or hours or what?

Are you already using Influxdb for saving data?

Is it just today's usage you want to show or do you need to see yesterdays, the last months usage, etc?

Yes, so the intervals depends on the updates in the monitor.
It only gives me an update when the numbers have changed:

11-9-2021 22:15:11node: 243e5459.de873cN/7c010a8eed8e/battery/256/Dc/0/Power : msg.payload : Object
{ value: -97.77300262451172 }
11-9-2021 22:15:17node: 243e5459.de873cN/7c010a8eed8e/battery/256/Dc/0/Power : msg.payload : Object
{ value: -95.26599884033203 }
11-9-2021 22:15:23node: 243e5459.de873cN/7c010a8eed8e/battery/256/Dc/0/Power : msg.payload : Object
{ value: -92.75900268554688 }
11-9-2021 22:15:37node: 243e5459.de873cN/7c010a8eed8e/battery/256/Dc/0/Power : msg.payload : Object
{ value: -95.26599884033203 }
11-9-2021 22:15:42node: 243e5459.de873cN/7c010a8eed8e/battery/256/Dc/0/Power : msg.payload : Object
{ value: -97.77300262451172 }
11-9-2021 22:15:48node: 243e5459.de873cN/7c010a8eed8e/battery/256/Dc/0/Power : msg.payload : Object
{ value: -92.75900268554688 }
11-9-2021 22:15:50node: 243e5459.de873cN/7c010a8eed8e/battery/256/Dc/0/Power : msg.payload : Object
{ value: -97.77300262451172 }
11-9-2021 22:15:54node: 243e5459.de873cN/7c010a8eed8e/battery/256/Dc/0/Power : msg.payload : Object
{ value: -95.26599884033203 }
11-9-2021 22:15:56node: 243e5459.de873cN/7c010a8eed8e/battery/256/Dc/0/Power : msg.payload : Object
{ value: -97.77300262451172 }

So I don't see how I could normalize this into kWh, since there is no certain time interval.

I'm going to implement this outcome in HomeAssistant, which has it's database and then I will be able to see graph by day.

In the end I will be interested in history as well.

Because of these difficulties I was looking at the way of :
MQTT topic: N/7c010a8eed8e/battery/256/History/DischargedEnergy

[{"id":"d5f8d939.a5d6b8","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"fe246fee.a34d9","type":"mqtt in","z":"d5f8d939.a5d6b8","name":"","topic":"N/7c010a8eed8e/battery/256/History/DischargedEnergy","qos":"2","datatype":"json","broker":"51ed7aaa.a7200c","nl":false,"rap":true,"rh":0,"x":230,"y":40,"wires":[["b37e34dd.fc4058"]]},{"id":"b37e34dd.fc4058","type":"bigtimer","z":"d5f8d939.a5d6b8","outtopic":"","outpayload1":"","outpayload2":"","name":"allow on 00:00","comment":"","lat":0,"lon":0,"starttime":5001,"endtime":1425,"starttime2":0,"endtime2":0,"startoff":0,"endoff":0,"startoff2":0,"endoff2":0,"offs":0,"outtext1":"","outtext2":"","timeout":1440,"sun":true,"mon":true,"tue":true,"wed":true,"thu":true,"fri":true,"sat":true,"jan":true,"feb":true,"mar":true,"apr":true,"may":true,"jun":true,"jul":true,"aug":true,"sep":true,"oct":true,"nov":true,"dec":true,"day1":0,"month1":0,"day2":0,"month2":0,"day3":0,"month3":0,"day4":0,"month4":0,"day5":0,"month5":0,"day6":0,"month6":0,"day7":0,"month7":0,"day8":0,"month8":0,"day9":0,"month9":0,"day10":0,"month10":0,"day11":0,"month11":0,"day12":0,"month12":0,"d1":0,"w1":0,"d2":0,"w2":0,"d3":0,"w3":0,"d4":0,"w4":0,"d5":0,"w5":0,"d6":0,"w6":0,"xday1":0,"xmonth1":0,"xday2":0,"xmonth2":0,"xday3":0,"xmonth3":0,"xday4":0,"xmonth4":0,"xday5":0,"xmonth5":0,"xday6":0,"xmonth6":0,"xday7":0,"xmonth7":0,"xday8":0,"xmonth8":0,"xday9":0,"xmonth9":0,"xday10":0,"xmonth10":0,"xday11":0,"xmonth11":0,"xday12":0,"xmonth12":0,"xd1":0,"xw1":0,"xd2":0,"xw2":0,"xd3":0,"xw3":0,"xd4":0,"xw4":0,"xd5":0,"xw5":0,"xd6":0,"xw6":0,"suspend":false,"random":false,"randon1":false,"randoff1":false,"randon2":false,"randoff2":false,"repeat":true,"atstart":true,"odd":false,"even":false,"x":240,"y":120,"wires":[["5d2f3e67.6fb03"],[],[]]},{"id":"243e5459.de873c","type":"debug","z":"d5f8d939.a5d6b8","name":"","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":640,"y":220,"wires":[]},{"id":"5d2f3e67.6fb03","type":"function","z":"d5f8d939.a5d6b8","name":"function to substract","func":"\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":220,"wires":[["243e5459.de873c"]]},{"id":"c8bc5115.afcf48","type":"mqtt in","z":"d5f8d939.a5d6b8","name":"N/7c010a8eed8e/battery/256/History/DischargedEnergy    but now","topic":"N/7c010a8eed8e/battery/256/History/DischargedEnergy","qos":"2","datatype":"json","broker":"51ed7aaa.a7200c","nl":false,"rap":true,"rh":0,"x":260,"y":320,"wires":[["5d2f3e67.6fb03"]]},{"id":"51ed7aaa.a7200c","type":"mqtt-broker","name":"CCGX","broker":"192.168.0.50","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

But how to do this, I find a little difficult.

You can easily calculate the energy used in each period. Save the time of the previous sample and then when the next sample comes in you can multiply the power by the time since the last one to give you the energy (which is what kWh is).

I use Influx, so I save each kWh figure into the database and then I can get the energy for the day (or any period) by performing a SUM query in influx.

1 Like

...or use node-red-contrib-watt2kwh to calculate it for you.

2 Likes

Ah!

Thank you so much for your help!

I'm almost there, thanks to this node:
Just I want to see separated Charged and discharged.
I'm using 2 different ways, but somehow this doesn't work.

What am I doing wrong?

[{"id":"29f34b4f.df682c","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"5eb66b22.1a4de4","type":"watt2kwh","z":"29f34b4f.df682c","format":"kwh","maximum":"5","maximumunit":"mins","name":"","x":460,"y":60,"wires":[["92e84adc.45c5e8"]]},{"id":"92e84adc.45c5e8","type":"function","z":"29f34b4f.df682c","name":"Store kwh","func":"var inputVal = msg.payload;\nif (inputVal == \"reset\"){\n flow.set(\"energyVal\",0); \n } else {\nvar savedVal = flow.get('energyVal')||0;\nsavedVal += inputVal;\nflow.set(\"energyVal\",savedVal);\nmsg.payload = savedVal;\nreturn msg;\n}","outputs":1,"noerr":0,"x":610,"y":80,"wires":[["486cc458.d7051c"]]},{"id":"486cc458.d7051c","type":"debug","z":"29f34b4f.df682c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":630,"y":140,"wires":[]},{"id":"6a75c8e5.1ee598","type":"inject","z":"29f34b4f.df682c","name":"reset","props":[{"p":"payload","v":"reset","vt":"str"},{"p":"topic","v":"","vt":"string"}],"repeat":"","crontab":"00 00 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"reset","payloadType":"str","x":470,"y":100,"wires":[["92e84adc.45c5e8"]]},{"id":"28fe84cf.763174","type":"mqtt in","z":"29f34b4f.df682c","name":"Power","topic":"N/7c010a8eed8e/battery/256/Dc/0/Power","qos":"2","datatype":"json","broker":"51ed7aaa.a7200c","nl":false,"rap":true,"rh":0,"x":50,"y":60,"wires":[["a178f91f.bd2678"]]},{"id":"a178f91f.bd2678","type":"join","z":"29f34b4f.df682c","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":190,"y":60,"wires":[["ce84f947.8e3de","4f4c187.2002a68"]]},{"id":"ce84f947.8e3de","type":"function","z":"29f34b4f.df682c","name":"Only +","func":"if (msg.payload[\"N/7c010a8eed8e/battery/256/Dc/0/Power\"].value < 0) {\n    msg.payload = 0\n}\nelse {\n  msg.payload = msg.payload[\"N/7c010a8eed8e/battery/256/Dc/0/Power\"].value;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":60,"wires":[["5eb66b22.1a4de4"]]},{"id":"2013f35f.1cbba4","type":"watt2kwh","z":"29f34b4f.df682c","format":"kwh","maximum":"5","maximumunit":"mins","name":"","x":460,"y":240,"wires":[["66b2c15b.2d3088"]]},{"id":"66b2c15b.2d3088","type":"function","z":"29f34b4f.df682c","name":"Store kwh","func":"var inputVal = msg.payload;\nif (inputVal == \"reset\"){\n flow.set(\"energyVal\",0); \n } else {\nvar savedVal = flow.get('energyVal')||0;\nsavedVal += inputVal;\nflow.set(\"energyVal\",savedVal);\nmsg.payload = savedVal;\nreturn msg;\n}","outputs":1,"noerr":0,"x":610,"y":260,"wires":[["57ffea8e.5c5ba4"]]},{"id":"57ffea8e.5c5ba4","type":"debug","z":"29f34b4f.df682c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":630,"y":320,"wires":[]},{"id":"160c54ce.226fcb","type":"inject","z":"29f34b4f.df682c","name":"reset","props":[{"p":"payload","v":"reset","vt":"str"},{"p":"topic","v":"","vt":"string"}],"repeat":"","crontab":"00 00 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"reset","payloadType":"str","x":470,"y":280,"wires":[["66b2c15b.2d3088"]]},{"id":"4f4c187.2002a68","type":"function","z":"29f34b4f.df682c","name":"Only -","func":"if (msg.payload[\"N/7c010a8eed8e/battery/256/Dc/0/Power\"].value > 0) {\n  msg.payload = 0\n} else {\n  msg.payload = msg.payload[\"N/7c010a8eed8e/battery/256/Dc/0/Power\"].value;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":240,"wires":[["2013f35f.1cbba4"]]},{"id":"51ed7aaa.a7200c","type":"mqtt-broker","name":"CCGX","broker":"192.168.0.50","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

No, that definitely will not work.
Normally, in a inverter setting (same would apply with battery charging), two measurements would be taken, the power consumed, and the power generated.
Using just one measurement, it would be impossible to determine either, because you could be consuming power at the same time as charging, and one would cancel out the other.
Unless of course I misunderstand your data format...

Thank you for your respond.

The main objective I want is to monitor the amount of energy that went IN and OUT my batteries.

All the rest is given by the inverter/charger.
The monitor is connected to a shunt directly after the batteries, so this gives the most accurate number.
"+" is Watt going in
"-" is Watt going out.

I adjusted the nodes now and am going to compare this the coming days with the N/7c010a8eed8e/battery/256/History/ChargedEnergy.. (which shows me the charged Energy ever in this Battery)
and
N/7c010a8eed8e/battery/256/History/DischargedEnergy..

I'm now using this setup:

[{"id":"29f34b4f.df682c","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"5eb66b22.1a4de4","type":"watt2kwh","z":"29f34b4f.df682c","format":"kwh","maximum":"5","maximumunit":"mins","name":"","x":460,"y":60,"wires":[["92e84adc.45c5e8"]]},{"id":"92e84adc.45c5e8","type":"function","z":"29f34b4f.df682c","name":"Store kwh","func":"var inputVal = msg.payload;\nif (inputVal == \"reset\"){\n flow.set(\"energyVal1\",0); \n } else {\nvar savedVal = flow.get('energyVal1')||0;\nsavedVal += inputVal;\nflow.set(\"energyVal1\",savedVal);\nmsg.payload = savedVal;\nreturn msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":80,"wires":[["7ad02888.9e6b"]]},{"id":"6a75c8e5.1ee598","type":"inject","z":"29f34b4f.df682c","name":"reset","props":[{"p":"payload","v":"reset","vt":"str"},{"p":"topic","v":"","vt":"string"}],"repeat":"","crontab":"00 00 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"reset","payloadType":"str","x":470,"y":100,"wires":[["92e84adc.45c5e8"]]},{"id":"28fe84cf.763174","type":"mqtt in","z":"29f34b4f.df682c","name":"Power","topic":"N/7c010a8eed8e/battery/256/Dc/0/Power","qos":"2","datatype":"json","broker":"51ed7aaa.a7200c","nl":false,"rap":true,"rh":0,"x":50,"y":60,"wires":[["a178f91f.bd2678"]]},{"id":"a178f91f.bd2678","type":"join","z":"29f34b4f.df682c","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":190,"y":60,"wires":[["ce84f947.8e3de","4f4c187.2002a68"]]},{"id":"ce84f947.8e3de","type":"function","z":"29f34b4f.df682c","name":"Only +","func":"if (msg.payload[\"N/7c010a8eed8e/battery/256/Dc/0/Power\"].value < 0) {\n    msg.payload = 0\n}\nelse {\n  msg.payload = msg.payload[\"N/7c010a8eed8e/battery/256/Dc/0/Power\"].value;\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":60,"wires":[["5eb66b22.1a4de4"]]},{"id":"2013f35f.1cbba4","type":"watt2kwh","z":"29f34b4f.df682c","format":"kwh","maximum":"5","maximumunit":"mins","name":"","x":460,"y":240,"wires":[["66b2c15b.2d3088"]]},{"id":"66b2c15b.2d3088","type":"function","z":"29f34b4f.df682c","name":"Store kwh","func":"var inputVal = msg.payload;\nif (inputVal == \"reset\"){\n flow.set(\"energyVal2\",0); \n } else {\nvar savedVal = flow.get('energyVal2')||0;\nsavedVal += inputVal;\nflow.set(\"energyVal2\",savedVal);\nmsg.payload = savedVal;\nreturn msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":260,"wires":[["16495737.c32ef1"]]},{"id":"160c54ce.226fcb","type":"inject","z":"29f34b4f.df682c","name":"reset","props":[{"p":"payload","v":"reset","vt":"str"},{"p":"topic","v":"","vt":"string"}],"repeat":"","crontab":"00 00 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"reset","payloadType":"str","x":470,"y":280,"wires":[["66b2c15b.2d3088"]]},{"id":"4f4c187.2002a68","type":"function","z":"29f34b4f.df682c","name":"Only -","func":"if (msg.payload[\"N/7c010a8eed8e/battery/256/Dc/0/Power\"].value > 0) {\n  msg.payload = 0\n} else {\n  msg.payload = msg.payload[\"N/7c010a8eed8e/battery/256/Dc/0/Power\"].value;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":240,"wires":[["2013f35f.1cbba4"]]},{"id":"7b6b3610.3f3bc","type":"ha-entity","z":"29f34b4f.df682c","name":"","server":"a996490d.ff3548","version":1,"debugenabled":true,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Charged_Battery"},{"property":"device_class","value":"energy"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"kWh"}],"state":"payload","stateType":"msg","attributes":[],"resend":false,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":610,"y":200,"wires":[[]]},{"id":"a44fb4f8.60bda","type":"ha-entity","z":"29f34b4f.df682c","name":"","server":"a996490d.ff3548","version":1,"debugenabled":true,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Discharged_Battery"},{"property":"device_class","value":"energy"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"kWh"}],"state":"payload","stateType":"msg","attributes":[],"resend":false,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":610,"y":380,"wires":[[]]},{"id":"7ad02888.9e6b","type":"change","z":"29f34b4f.df682c","name":"afrond","rules":[{"t":"set","p":"payload","pt":"msg","to":"$round(payload, 4)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":140,"wires":[["7b6b3610.3f3bc"]]},{"id":"16495737.c32ef1","type":"change","z":"29f34b4f.df682c","name":"afrond","rules":[{"t":"set","p":"payload","pt":"msg","to":"$round(payload, 4)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":320,"wires":[["a44fb4f8.60bda"]]},{"id":"51ed7aaa.a7200c","type":"mqtt-broker","name":"CCGX","broker":"192.168.0.50","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"a996490d.ff3548","type":"server","name":"Home Assistant","addon":true}]

Anything to polish it up? Or am I going in the right direction?

Thank you all for your help!

Sam