Zoals toegezegd de volgende versie en hier zit nu het tonen en opslaan van berekende draaischijf waarden in. Ik kan dat hier op een tiende kW/h berekenen en het klopt ook nog eens. Ik bereken de waarde uit de beginstand - export + import.
Ik ben in de tussentijd naar NodeRed 2.0 gegaan en er zijn optisch wat verschillen en voorheen kreeg ik bij een delay het aan seconden wachttijd te zien nu zie ik dat er payload wacht. Geen vooruitgang in mijn ogen.
:no_upscale():strip_icc():fill(white):strip_exif()/f/image/i0nB9P4ImdpMEqplIBexQOQX.jpg?f=user_large)
Ik zend mijn gegevens naar PVOutput en ondertussen ook Tarrifs ontdekt en nu zie ik ook hoeveel geld mijn stroom opbengt onder aftrek van vaste kosten en wat ik aan stroom heb geïmporteerd. De engergie belasting laat ik buiten beschouwing want dat is te ontduikelijk voor mij. Ik wil mijn initele stand doorgeven aan mijn leverancier en ik wacht nog op antwoord hoe dat gaat.
Ik verbruik veel minder dan ik produceer en ik zit nu al ergens in december 2020 met mijn stroom teruglevering. Dat zou erop neerkomen dat ik geen energie belasting betaal en dus ook geen heffingskorting krijg (ongeveer 527 Euro). Dat is toch weer een nadeel van zonnepanelen dat je heffingskorting misloopt.
Of zie ik dat verkeerd en gaat de heffinskorting per dag en is onafhankelijk van het verbruik?
Ik betaalde vorig jaar al bijna niets voor mijn stroom omdat de heffingskort net zo veel was wat ik verbruikte. In een heel jaar moest ik 35 Euro betalen aan stroom.
Ik ben in de tussentijd naar NodeRed 2.0 gegaan en er zijn optisch wat verschillen en voorheen kreeg ik bij een delay het aan seconden wachttijd te zien nu zie ik dat er payload wacht. Geen vooruitgang in mijn ogen.
:no_upscale():strip_icc():fill(white):strip_exif()/f/image/i0nB9P4ImdpMEqplIBexQOQX.jpg?f=user_large)
code:
1
| [{"id":"801b0f90.623ea8","type":"tab","label":"Inverter2PVOutput","disabled":false,"info":"Scripted by msatter\nversion: 20210811-1.05\n**Only for non-comercial usage**\n\nDiscussion about getting data from the Goodwe inverters (XS series)\n\n[https://gathering.tweakers.net/forum/list_messages/1799239](Tweakers forum (Dutch))\n\nMy profile on Tweakers.net\n\n[https://tweakers.net/gallery/1582350/]()"},{"id":"ff01618d.60809","type":"subflow","name":"PVOutput upload","info":"Provided by **Vster Lee**\n[https://community.openenergymonitor.org/t/pvoutput-org-nodered/779/3]()\n\nAdapted for Goodwe UDP over WiFi by **msatter** [https://tweakers.net/gallery/1582350/]()\n\nVersio 20210526-1.15","category":"","in":[{"x":50,"y":120,"wires":[{"id":"b387fa24.de24"},{"id":"1a1e9c44.bce1f4"},{"id":"ba84d31bc6af60fc"}]}],"out":[],"env":[],"meta":{"module":"Upload to PVOutput - status api","license":"Non-commercial"},"color":"#87A980","icon":"font-awesome/fa-line-chart","status":{"x":800,"y":60,"wires":[{"id":"d68b8d43.29747","port":0},{"id":"ba0c10e4.0b273","port":0}]}},{"id":"b583cfc4.481a7","type":"subflow","name":"Fan control (Fritz!box)","info":"Using a AVM DECT 200/210 to switch a external fan to cool the inverter if keep a good temperature in the inverter.\nYou can just give a normal and high temperature of use als the ambient temperature measured by the DECT 200/210 and put a delta on it.\nThis way it compenstates when the ambient temperature is very hig. This way the fan won't try to reach a normal temparature when that will take a long cooling period. Or the normal temperature can't even be reached in this situation.\nThen is an 'emergency' fan activation when the temperature in the inverter is above 70 degrees celcius.","category":"","in":[{"x":40,"y":60,"wires":[{"id":"d671f425.eeccb8"}]}],"out":[],"env":[],"meta":{},"color":"#3FADBB","icon":"font-awesome/fa-thermometer-3","status":{"x":700,"y":40,"wires":[{"id":"a8384cad.fe0fa8","port":0}]}},{"id":"38eaa938.5c6d36","type":"group","z":"801b0f90.623ea8","name":"Fan ON/OFF based on temperature of the inverter","style":{"stroke":"none","fill":"#ffC000","label":true,"label-position":"n","color":"#ffffff","fill-opacity":"0.72"},"nodes":["df5787e.5542578","197029da.e9aa8e","fb618501.400cb8"],"x":54,"y":279,"w":682,"h":82},{"id":"8ae4ca85.96da48","type":"group","z":"801b0f90.623ea8","name":"Retrieve values from the inverter and kWh meter, storing these values every X seconds (24/7)","style":{"stroke-opacity":"0","fill":"#7fb7df","label":true,"color":"#ffffff","label-position":"n"},"nodes":["516a7514.fae094","8277276e.aa4838","61584504.656bb4","4d1994b6.e68d54","f253db9e.62f168","20b092ab.afa95e","b6dc2565.805b88","671524d1.923f6c","682d652e.797f7c","23c7dabd.782b7e","ed785906.26fe78"],"x":54,"y":19,"w":682,"h":132},{"id":"4b48967c.fcfc3","type":"group","z":"801b0f90.623ea8","name":"Transfer (stored) values to PVOutput, interval 5 minutes (24/7)","style":{"stroke":"none","fill":"#addb7b","label":true,"label-position":"n","color":"#ffffff"},"nodes":["407e80c8.75639","3de325a.37c68da","adf4fe67.082f88","93b11507.07f84","5144e0a6.1432f","8c79c62.c195d38","f72364d9.d212f8"],"x":54,"y":149,"w":682,"h":134},{"id":"25c84cff.e5e5fc","type":"fritzbox-config","name":"7590","host":"fritz.box","port":"49000","ssl":false,"user":"fritzuser"},{"id":"7a08bc0a.6b386c","type":"modbus-client","name":"Eastron reader","clienttype":"serial","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"tcpHost":"127.0.0.1","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB0","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","unit_id":1,"commandDelay":50,"clientTimeout":1000,"reconnectOnTimeout":false,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true},{"id":"40f20c7f.13a934","type":"modbus-client","name":"Serial_9600_8_N_1","clienttype":"serial","bufferCommands":true,"stateLogEnabled":false,"tcpHost":"127.0.0.1","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB0","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","unit_id":"","commandDelay":"30","clientTimeout":"2000","reconnectTimeout":"5000"},{"id":"d68b8d43.29747","type":"http request","z":"ff01618d.60809","name":"Post","method":"POST","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":490,"y":60,"wires":[["d7346137.28cba","b638e83a.a1c888"]]},{"id":"71cd2d97.8e32d4","type":"function","z":"ff01618d.60809","name":"Prepare Post","func":"msg.action = msg.payload;\nPVOsystemid = msg.payload.PVOsystemid;\nPVOAPIkey = msg.payload.PVOAPIkey;\n\nmsg.headers = {};\n//msg.headers['X-Pvoutput-Apikey'] = 'b9ebfcaa419189c2a8595617ad6bd8250ed8a2d9';\nmsg.headers['X-Pvoutput-Apikey'] = PVOAPIkey;\nmsg.headers['X-Pvoutput-SystemId'] = PVOsystemid;\nmsg.headers['Content-Type'] = 'application/x-www-form-urlencoded';\n\n////////////////////////////////////////////\nmsg.url = \"https://pvoutput.org/service/r2/addstatus.jsp\";\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":80,"wires":[["d68b8d43.29747","ac542fdb.fa626"]],"icon":"font-awesome/fa-align-left"},{"id":"d7346137.28cba","type":"function","z":"ff01618d.60809","name":"Check Status 1st","func":"var d=new Date();\nvar hours=('00' + d.getHours()).slice(-2);\nvar minutes=('00' + (d.getMinutes()+1)).slice(-2);\n// adding a space behind the time so that the lenght of the line is 314 characters in the log\nTime = hours+\":\"+minutes+\" \"\n\nif (msg.statusCode == 200) { \n var stat = \"\";\n flow.set('pvostat','200'); // this clears the outstanding PVO data, so it won't be uploaded again\n var msg1 = null;\n var msg2 = null;\n} else {\n var time = new Date().toString();\n flow.set('pvostat', msg.statusCode);\n stat = \"FAILED: Time:\" + time + \" StatusCode:\" + msg.statusCode + \" StatusMsg:\" + msg.payload;\n}\nreturn msg;\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":730,"y":100,"wires":[[],["fe3a3389.3b9b2"]],"icon":"font-awesome/fa-search"},{"id":"fe3a3389.3b9b2","type":"file","z":"ff01618d.60809","name":"PVO error log","filename":"/opt/goodwe/pvoutput/pvo_errors.log","appendNewline":true,"createDir":true,"overwriteFile":"false","x":920,"y":120,"wires":[[]]},{"id":"ac542fdb.fa626","type":"function","z":"ff01618d.60809","name":"Store PVO data","func":"//store the PVO data in case it doesn't upload correctly\nflow.set ('pvodata',msg.payload);\nreturn msg;","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":100,"wires":[],"icon":"node-red/redis.png"},{"id":"ba0c10e4.0b273","type":"http request","z":"ff01618d.60809","name":"Re-Post","method":"POST","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":520,"y":200,"wires":[["82678181.eee75"]]},{"id":"9f08c692.4c46a8","type":"function","z":"ff01618d.60809","name":"Prepare retransmit","func":"msg.action = msg.payload;\nPVOsystemid = msg.payload.PVOsystemid;\nPVOAPIkey = msg.payload.PVOAPIkey;\n\nmsg.headers = {};\nmsg.headers['X-Pvoutput-Apikey'] = PVOAPIkey;\nmsg.headers['X-Pvoutput-SystemId'] = PVOsystemid;\nmsg.headers['Content-Type'] = 'application/x-www-form-urlencoded';\n\n////////////////////////////////////////////\nmsg.url = \"https://pvoutput.org/service/r2/addstatus.jsp\";\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":200,"wires":[["ba0c10e4.0b273"]],"icon":"node-red/white-globe.svg"},{"id":"82678181.eee75","type":"function","z":"ff01618d.60809","name":"Check Status 2nd","func":"if (msg.statusCode == 200) { \n var time = new Date().toString();\n var stat =\"\";\n flow.set('pvostat', 200); // this clears the outstanding PVO status, so it won't be uploaded again\n var stat = \"RetransmitOK: Time:\" + time + \" StatusCode:\" + msg.statusCode + \" StatusMsg:\" + msg.payload;\n// var msg1 = null;\n// var msg2 = null;\n var msg1 = { payload: stat };\n var msg2 = { payload: stat };\n} else {\n var time = new Date().toString();\n flow.set('pvostat', msg.statusCode);\n var stat = \"RetransmitFAIL: Time:\" + time + \" StatusCode:\" + msg.statusCode + \" StatusMsg:\" + msg.payload;\n// var msg1 = null;\n// var msg2 = null;\n var msg1 = { payload: stat };\n var msg2 = { payload: stat };\n}\nreturn (msg1, msg2);","outputs":"2","noerr":0,"initialize":"","finalize":"","libs":[],"x":730,"y":200,"wires":[["bc2c0f21.a7735"],["30cf215d.ab8d0e"]],"icon":"font-awesome/fa-search"},{"id":"30cf215d.ab8d0e","type":"file","z":"ff01618d.60809","name":"Retransmit fail","filename":"/opt/goodwe/pvoutput/pvo_errors.log","appendNewline":true,"createDir":true,"overwriteFile":"false","x":920,"y":220,"wires":[[]]},{"id":"b638e83a.a1c888","type":"function","z":"ff01618d.60809","name":"Fetch PVO data","func":"// Retransmit the PVO data in case it doesn't upload correctly the first time\n\nif (msg.statusCode != 200) { \n \n// retrieve local stored data\n var pvodata = flow.get('pvodata')||\"\";\n msg.payload = pvodata;\n\nreturn msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":160,"y":200,"wires":[["9f08c692.4c46a8"]],"icon":"node-red/redis.png"},{"id":"8d14e679.b29678","type":"file","z":"ff01618d.60809","name":"PVO Data","filename":"/opt/goodwe/pvoutput/PVO_data.log","appendNewline":true,"createDir":true,"overwriteFile":"false","x":900,"y":80,"wires":[[]]},{"id":"2696b14a.d9694e","type":"comment","z":"ff01618d.60809","name":"Check data sent OK and if not retransmit once","info":"The PVO website is busy and sometimes can't respond quickly enough and we get timeouts.\nThe next bit of code catches any errors and resubm its the code until it's sent OK.\n\nThat said, if it can't resend the data before the next data packet has to be sent (5 mins) then\nthe current packet will be lost. This is pretty rare though and won't be noticable on the graphs.\n","x":200,"y":160,"wires":[]},{"id":"5f830eb6.38a358","type":"comment","z":"ff01618d.60809","name":"Prepare values and then transfer those to PVOuput.org","info":"","x":230,"y":20,"wires":[]},{"id":"1a1e9c44.bce1f4","type":"function","z":"ff01618d.60809","name":"Prepare values","func":"var date=new Date();\nd = ( date.getFullYear() + ('00' + (date.getMonth()+1)).slice(-2) + ('00' + date.getDate()).slice(-2) ); \nt = ( ('00' + date.getHours()).slice(-2) + ':' + ('00' + date.getMinutes()).slice(-2) );\nvar c1 = 3; // Only v3 consumption is a lifetime energy value. (= reset every day by PVOutput)\nvar PVOsystemid = msg.PVOsystemid; var PVOAPIkey = msg.PVOAPIkey; // needed log-in data for using PVOutput\n\nvar resetday = msg.resetday;\nglobal.set('resetday',resetday);\n\n// only upload if there is an kwh meter present and the inverter is currently off-line\nif ( global.get('meterValues') != null) {\n meterValues = global.get('meterValues') ||\"\";\n v3 = Number(meterValues.importkWh * 1000) || 0; // imported kW/h from the kwh meter\n// when the inverter is off-line, use kWh meter values if those are present\n if (global.get('PVwatt') == null) { \n meterValues = global.get('meterValues')||\"\";\n v4 = meterValues.watt || 0; // real watt from the kW/h meter\n v5 = meterValues.ambientTemp || 0; // ambient temperature provided by the Fritz earlier\n v6 = meterValues.volt || 0; // voltage from the kW/h meter\n msg.payload = {d,t,v3,v4,v5,v6,c1,PVOsystemid,PVOAPIkey}; // transfer values to payload for sending those to PVOutput\n } // END IF - inverter is offline\n} // END IF - kWh meter present\n\n// when the inverter is online \nif (global.get('PVwatt') != null) {\n var PValues = global.get('PValues')||\"\";\n v1 = PValues.eDay || 0; v5 = PValues.PVtemp || 0; v6 = PValues.PVvolt || 0;\n// retrieve accumulated watt's (PV = solar panels) and the caluclated internal usage and then clear them later for a new round\n var PVwatt = global.get('PVwatt') || \"\";\n var DCwattavg = PVwatt.DCwatt || 0; var ACwattavg = PVwatt.ACwatt || 0;\n var PVcount = PVwatt.wattcount || 1; var DCvolt = PVwatt.DCvolt || 0;\n\n if (DCvolt != 0) {v6 = Number((DCvolt / PVcount).toFixed(1))} // avaraging the DC voltage from the solar panels\n v2 = Number(( DCwattavg / PVcount ).toFixed(0)); // averaging DC Watt from the inverter \n v4 = Number(( ACwattavg / PVcount ).toFixed(0)); // averaging AC Watt from the inverter\n //v4 = Number(ACwattavg); // v4 is set to the calculate AC wattage from the inverter \n if ( v4 < 0 ) { v4 = 0 } // make v4 sure it is not negative\n \n// transfer values to payload to be used by the node sending it to PVOutput\nif ( global.get('meterWatt') != null) { msg.payload = {d,t,v1,v2,v3,v4,v5,v6,c1,PVOsystemid,PVOAPIkey}} // when kWh meter is present\nif ( global.get('meterWatt') == null) { msg.payload = {d,t,v1,v2,v5,v6,c1,PVOsystemid,PVOAPIkey}} // when kWh meter is not present\n\n} // END IF - inverter is online\n\n// Reset stored data every time after an upload to PVOutput\nglobal.set('PVwatt',null);\nglobal.set('meterWatt',null);\nif ( resetday) {\n global.set('PValues',null)\n //global.set('meterValues',null)\n //global.set('tempValues',null)\n //global.set('fancontrol',null)\n}\n\n// returning payload and PVOutput can now be updated\nreturn msg;\n\n// #######################################################################################################################\n // obsolete code\n // correction for AC cable length and/or measurements compenstions\n // default correctionfactor\n //var correctionfactor = 0; // Set your own correction factor\n //correctionfactor = 0.0 ; // in percent without the %\n //correctionfactor = ((100 - correctionfactor) / 100); // calculate the uses multiplier\n //v1 = v1 * correctionfactor; // Production during the day\n //v2 = v2 * correctionfactor; // Production in Watt\n //v6 = v6 * correctionfactor; // Voltage AC side","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":160,"y":120,"wires":[["efb6026b.a87808"]],"icon":"node-red/batch.svg"},{"id":"106f84dd.f8d73b","type":"file","z":"ff01618d.60809","name":"save-values","filename":"/opt/goodwe/nodered/saved-values.txt","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"ascii","x":510,"y":20,"wires":[[]]},{"id":"bc2c0f21.a7735","type":"file","z":"ff01618d.60809","name":"Retransmit OK","filename":"/opt/goodwe/pvoutput/PVO_data.log","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"none","x":920,"y":180,"wires":[[]]},{"id":"5c2b263.51bdc58","type":"fritzbox-in","z":"b583cfc4.481a7","device":"25c84cff.e5e5fc","name":"Fritz.box","service":"urn:dslforum-org:service:X_AVM-DE_Homeauto:1","action":"SetSwitch","arguments":"{\n \"NewAIN\": \"value\",\n \"NewSwitchState\": \"value\"\n}","x":900,"y":100,"wires":[[]]},{"id":"a8384cad.fe0fa8","type":"function","z":"b583cfc4.481a7","name":"","func":"var temp_inverter = msg.payload;\nvar temp_ambient = msg.temp_ambient;\nvar tempValues = global.get('tempValues') || \"\";\nvar temp_high = tempValues.temp_high || 0;\nvar temp_normal = tempValues.temp_normal || 0;\nvar temp_delta = tempValues.temp_delta || 0;\n\n// retrieve saved values\nvar fancontrol = global.get('fancontrol') || \"\";\nvar fan_on = fancontrol.fan_on || false;\nvar highest_temp= fancontrol.highest_temp || 0;\n\n//var fan_on = global.get('fan_on')||false;\n//var highest_temp = global.get('highest_temp')||\"\";\nif ( temp_inverter == null ) {temp_inverter = temp_ambient}\nvar temperature = temp_inverter;\n\n// only use ambient and delta temp if their sum is higher than the normal temp\n//if ((temp_ambient + temp_delta) >= temp_normal ) {\n// if (temp_delta > 0) { \n// temp_high = (temp_ambient + temp_delta)\n// temp_normal = (temp_ambient + (temp_delta - 5))\n//} }\n\n// emergency cooling, overwrite any calculated tem high value\nif (temperature >= 70) {temp_high = 65}\n \n if (temperature >= temp_high) {\n fan = \" (FAN ON)\"\n filldot = \"red\"\n fan_on = true\n highest_temp = temperature\n fancontrol = { fan_on, highest_temp }\n global.set('fancontrol',fancontrol)\n }\n \n if (fan_on) {\n if (highest_temp >= temperature)\n { fan=\"FAN ON (delay)\"\n filldot = \"yellow\"}\n }\n \n if (temperature < temp_normal) {\n fan = \" (FAN OFF)\"\n filldot = \"blue\"\n fan_on = false;\n highest_temp = temperature;\n fancontrol = { fan_on, highest_temp }\n global.set('fancontrol',fancontrol)\n }\n\n let statusMsg = { fill:filldot, shape:\"dot\", text:\"Temp.: \" + temperature + \" celcius\" + fan };\n return {payload: statusMsg};\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":50,"wires":[["39bc750d.14c832"]],"info":"20210802"},{"id":"39bc750d.14c832","type":"switch","z":"b583cfc4.481a7","name":"Switch fan \\n ON/OFF","property":"payload.fill","propertyType":"msg","rules":[{"t":"eq","v":"red","vt":"str"},{"t":"eq","v":"yellow","vt":"str"},{"t":"eq","v":"blue","vt":"str"},{"t":"null"}],"checkall":"true","repair":false,"outputs":4,"x":710,"y":100,"wires":[["d08ac806.2a5868"],["d08ac806.2a5868"],["486d1d19.7d7034"],["486d1d19.7d7034"]]},{"id":"d08ac806.2a5868","type":"trigger","z":"b583cfc4.481a7","name":"Fan ON","op1":"","op2":"{\"NewAIN\":\"08761 0164169\",\"NewSwitchState\":\"ON\"}","op1type":"nul","op2type":"json","duration":"250","extend":false,"overrideDelay":false,"units":"ms","reset":"","bytopic":"all","topic":"payload","outputs":1,"x":880,"y":60,"wires":[["5c2b263.51bdc58"]]},{"id":"486d1d19.7d7034","type":"trigger","z":"b583cfc4.481a7","name":"Fan OFF","op1":"","op2":"{\"NewAIN\":\"08761 0164169\",\"NewSwitchState\":\"OFF\"}","op1type":"nul","op2type":"json","duration":"250","extend":false,"overrideDelay":false,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":880,"y":140,"wires":[["5c2b263.51bdc58"]]},{"id":"47f51c61.1e6d64","type":"switch","z":"b583cfc4.481a7","name":"","property":"payload","propertyType":"msg","rules":[{"t":"nnull"},{"t":"null"}],"checkall":"true","repair":false,"outputs":2,"x":350,"y":60,"wires":[["a8384cad.fe0fa8"],["39bc750d.14c832"]],"info":"When the inverter does not answer due to communication error or not running then the fan is switched OFF."},{"id":"d671f425.eeccb8","type":"change","z":"b583cfc4.481a7","name":"Fritz-request","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"NewAIN\":\"08761 0164169\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":170,"y":60,"wires":[["3955d49f.0d8e74"]]},{"id":"3955d49f.0d8e74","type":"fritzbox-in","z":"b583cfc4.481a7","device":"25c84cff.e5e5fc","name":"DECT200","service":"urn:dslforum-org:service:X_AVM-DE_Homeauto:1","action":"GetSpecificDeviceInfos","arguments":"{\n \"NewAIN\": \"value\"\n}","x":180,"y":100,"wires":[["4fb6bb70.5f44dc"]]},{"id":"4fb6bb70.5f44dc","type":"function","z":"b583cfc4.481a7","name":"Prepare values","func":"var ambientTemp = msg.payload.NewTemperatureCelsius;\n\nPValues = global.get('PValues') || \"\";\ntemp_inverter = PValues.PVtemp || null;\n\nif ( ambientTemp > 0 ) { ambientTemp = (ambientTemp * 0.1)}\n//global.set('ambientTemp',ambientTemp);\n\n// adding ambientTemp to exisiting object meterValues\nvar meterValues = global.get('meterValues') || null;\nif (meterValues != null) {\n tmp_ambientTemp = { ambientTemp }\n let metervalues = Object.assign( meterValues,tmp_ambientTemp );\n global.set('meterValues',meterValues);\n}\n//return {payload: temp_inverter, temp_high, temp_normal, temp_delta, temp_ambient};\nreturn {payload: temp_inverter, ambientTemp};","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":100,"wires":[["47f51c61.1e6d64"]]},{"id":"86b20d8d.cef91","type":"file","z":"ff01618d.60809","name":"save-values","filename":"/opt/goodwe/nodered/saved-pf-freq.txt","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"ascii","x":520,"y":140,"wires":[[]]},{"id":"b387fa24.de24","type":"function","z":"ff01618d.60809","name":"","func":"var date=new Date();\ndm = ( ('00' + date.getDate()).slice(-2) + '/' + ('00' + (date.getMonth()+1)).slice(-2) ) ; \nt = ( ('00' + date.getHours()).slice(-2) + ':' + ('00' + date.getMinutes()).slice(-2) );\nd = (dm + ' ' + t) \n\nmeterValues = global.get('meterValues') || \"\";\npf = meterValues.PowerFactor;\n\n//if ( pf < 0 ) {pf = pf * -1}\npf = (' ' + pf).slice(-5);\nmsg.payload = { pf,\n d };\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":130,"wires":[["86b20d8d.cef91"]]},{"id":"efb6026b.a87808","type":"switch","z":"ff01618d.60809","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"null","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":190,"y":70,"wires":[[],["71cd2d97.8e32d4","106f84dd.f8d73b"]]},{"id":"df5787e.5542578","type":"function","z":"801b0f90.623ea8","g":"38eaa938.5c6d36","name":"Define temperature values to be used","func":"// set temperature values to be used\nvar temp_normal = 50;\nvar temp_high = 55;\nvar temp_delta = 15;\n\ntempValues = { temp_high, temp_normal, temp_delta };\nglobal.set('tempValues',tempValues)\nmsg.payload = \"\";\n\nvar date=new Date();\nlastTime = ( ('00' + date.getHours()).slice(-2) + 'H' + ('00' + date.getMinutes()).slice(-2) ); // + \":\" + ('00' + date.getSeconds()).slice(-2) );\nnode.status({text:\"Last check and control: \" + lastTime});\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":320,"wires":[["197029da.e9aa8e"]],"icon":"font-awesome/fa-thermometer-3"},{"id":"197029da.e9aa8e","type":"subflow:b583cfc4.481a7","z":"801b0f90.623ea8","g":"38eaa938.5c6d36","name":"","env":[],"x":610,"y":320,"wires":[],"icon":"node-red/swap.svg"},{"id":"fb618501.400cb8","type":"link in","z":"801b0f90.623ea8","g":"38eaa938.5c6d36","name":"Temperature/fan-control entry","links":["5144e0a6.1432f"],"x":95,"y":320,"wires":[["df5787e.5542578"]],"icon":"font-awesome/fa-arrow-right"},{"id":"516a7514.fae094","type":"udp out","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","addr":"","iface":"","port":"8899","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":255,"y":60,"wires":[],"icon":"node-red/bridge.svg","l":false},{"id":"8277276e.aa4838","type":"udp in","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"8899","iface":"","port":"8899","ipv":"udp4","multicast":"false","group":"","datatype":"buffer","x":295,"y":60,"wires":[["61584504.656bb4"]],"outputLabels":["got data"],"icon":"font-awesome/fa-assistive-listening-systems","l":false},{"id":"61584504.656bb4","type":"function","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"CRC-check","func":"var inverter_reply = msg.payload;\n\nvar message1 = inverter_reply.slice(2); // Remove 'AA55' from start of message\n//var message = message.slice(0, -2); //Remove two CRC bytes from end of message\nvar message = message1.slice(0, -2); //Remove two CRC bytes from end of message\n\nfunction crc16(buffer) {\n var crc = 0xFFFF;\n var odd;\n\n for (var i = 0; i < buffer.length; i++) {\n crc = crc ^ buffer[i];\n\n for (var j = 0; j < 8; j++) {\n odd = crc & 0x0001;\n crc = crc >> 1;\n if (odd) {\n crc = crc ^ 0xA001;\n }\n }\n }\n return crc.toString(16);\n}\n\nvar buflen = inverter_reply.length\nif (buflen == 153) {\n \n//Calculate CRC ourselves\nvar calculated_crc = crc16(message);\n\n//Get CRC from inverter reply and un-reverse it\nvar reply_crc = inverter_reply.slice(-2).toString('hex');\nvar crc1 = reply_crc.slice(0, 2);\nvar crc2 = reply_crc.slice(-2);\nvar new_crc = crc2 + crc1;\n\nif (new_crc == calculated_crc) {\n// If the checksum is not correct retry to get a good string.\n msg.complete = true;\n// shows underneat the node the last time a PVOutput transmit was done\n var date=new Date();\n lastTime = ( ('00' + date.getHours()).slice(-2) + 'H' + ('00' + date.getMinutes()).slice(-2) + \":\" + ('00' + date.getSeconds()).slice(-2) );\n \n //if (msg.complete) { node.status({fill:\"green\",shape:\"dot\",text:\"At \" + lastTime + \" Check: OK \"}) }\n if (msg.complete) { node.status({text:\" Check: OK at \" + lastTime }) } else {\n node.status({fill:\"red\",shape:\"dot\",text:\"at \" + lastTime + \" NOT OK \"}) }\n return msg;\n} //new_crc\n} //buflen\n\n// clear node status so it will show nothing if nothing arrives and if the inverter is off-line then that is shown\nif (global.get(\"PVwatt\") == null)\n { node.status({text:\"The inverter is off-line...\"}) } else {\n node.status({fill:\"yellow\",shape:\"dot\",text:\"The inverter did not answer in time. Retrying the next interval.\"})\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":60,"wires":[["4d1994b6.e68d54"]],"outputLabels":["good"],"icon":"font-awesome/fa-check-square-o"},{"id":"4d1994b6.e68d54","type":"function","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Average Watt PV","func":"var inverter_reply = msg.payload;\n// check if the buffer is large enough to be used\nvar buflen = inverter_reply.length\nvar pvofactor = 1; // fallback value\nvar lastwatt = 0; // fallback value\n// only start when the bufflen = 153\nif (buflen == 153) {\n var date=new Date(); lastTime = ( ('00' + date.getHours()).slice(-2) + 'H' + ('00' + date.getMinutes()).slice(-2) );\n var eDay = Number(parseFloat(inverter_reply.readUInt16BE(93) * 100).toFixed(1));\n var PVtemp = Number(parseFloat(inverter_reply.readUInt16BE(87) * 0.1).toFixed(1));\n var PVvolt = Number(parseFloat(inverter_reply.readUInt16BE(11) * 0.1).toFixed(1));\n var PVfreq = Number(parseFloat(inverter_reply.readUInt16BE(53) * 0.01).toFixed(2));\n var eTotal = Number(parseFloat(inverter_reply.readUInt16BE(97) * 0.1).toFixed(2));\n\n// Get PVwatt object\n PVwatt = global.get('PVwatt') || \"\";\n var DCwatt = PVwatt.DCwatt || 0; var ACwatt = PVwatt.ACwatt || 0;\n var wattcount = PVwatt.wattcount || 0; var DCvolt = PVwatt.DCvolt || 0;\n// only when stored meterValues exists\n if (global.get('meterValues') != null) {\n var meterValues = global.get('meterValues') || \"\";\n var pvofactor = meterValues.PowerFactor || 1;\n var pvoapparant = meterValues.apparant || 0;\n var lastwatt = meterValues.watt || 0;\n } // END IF meterValues exist\n \n//PV wattage DC side and store\n PVwattRead = inverter_reply.readUInt16BE(61);\n DCwatt = DCwatt + PVwattRead;\n// peak watt performance completed with the time of reached\n PValuesTemp = global.get ('PValues') || \"\";\n peakWatt = PValuesTemp.peakWatt || 0;\n if ( PVwattRead > peakWatt ) {\n peakWatt = PVwattRead;\n peakText = \"Peak : \" + peakWatt + \" Watt at: \" + lastTime\n global.set('PVpeakWatt', peakText)\n } // END IF peakWatt\n// store new PValues \n PValues = { eDay,peakWatt,eTotal,PVtemp,PVvolt,PVfreq }; global.set ('PValues',PValues);\n// Read Watt on the AC side, calculated from voltage * Amp\n vacRead = inverter_reply.readUInt16BE(41);\n iacRead = inverter_reply.readUInt16BE(47);\n ACwatttmp = Number(((vacRead * iacRead) * 0.01).toFixed(0));\n\n// if needed, change the pvofactor \n if (pvofactor < 0) { pvofactor = Number(pvofactor * -1) }\n //if (pvofactor < 0.8 ) {pvofactor = Number((0.9 + (pvofactor * 0.2)))}\n //pvofactor = Number(0.9 + (pvofactor * 0.2))\n// test pf\n// pvofactor = pvofactor * -0.2; // reversing polarity and at the same time compress to 20% range\n// pvofactor = 1 + pvofactor; // pivot around 100% and the it range is 80-120%\n //global.set('pvofactor',pvofactor);\n //pvofactor =1; \n \n// ignore inverter production till it gets over a defined point\n if (ACwatttmp <= 200 && lastwatt > 5 ) { ACwatttmp = 0 } \n \n// AC is now being power factor corrected. lastwatt was already corrected in the kWh meter \n //ACwatttmp = Number((ACwatttmp * pvofactor).toFixed(0));\n calcWatt = Number(ACwatttmp + lastwatt);\n// cummulate\n ACwatt = ACwatt + calcWatt; //global.set ('ACwatt',ACwatt);\n wattcount = (wattcount+1); //global.set ('PVwattcount',PVwattcount);\n // add PVvolt to DCvolt (averaging it) \n DCvolt = Number((DCvolt + PVvolt).toFixed(1));\n// and store\n PVwatt = { wattcount,ACwatt,DCwatt,DCvolt};\n global.set('PVwatt',PVwatt);\n// shows underneat the node the last time a inverter readout was done\n// node.status({text:((ACwatt / wattcount).toFixed(0)) + \" Watt at \" + lastTime + \" (\" + wattcount +\" samples)\"});\n node.status({text:((ACwatt / wattcount).toFixed(0)) + \" Watt avg. \" + \" (\" + wattcount +\" samples)\"});\n } else {\n node.status({});\n //node.status({text:\"Average watt : N/A\" + \" (N/A samples)\"});\n} // END IF buflen = 153 \n","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":60,"wires":[],"icon":"font-awesome/fa-braille"},{"id":"f253db9e.62f168","type":"function","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Average Watt kW/h","func":"var rawData = new ArrayBuffer(88) || null;\nvar intView = new Uint16Array(rawData);\nvar fltView = new Float32Array(rawData);\n\n//len = msg.payload.length;\n//global.set('lengte',len);\n\nif ( msg.payload.length > 8 ) {\n\n// Power Factor\nintView[0] = msg.payload[31]; //low\nintView[1] = msg.payload[30]; //high\nPowerFactor = Number(parseFloat(fltView[0]).toFixed(2));\n// frequency\nintView[0] = msg.payload[71]; //low\nintView[1] = msg.payload[70]; //high\nfrequency = Number(parseFloat(fltView[0]).toFixed(2));\n// Apparent Power VA\nintView[0] = msg.payload[19]; //low\nintView[1] = msg.payload[18]; //high\napparant = Number(parseFloat(fltView[0]).toFixed(0));\n// Voltage\nintView[0] = msg.payload[1]; //low\nintView[1] = msg.payload[0]; //high\nvolt = Number(parseFloat(fltView[0]).toFixed(2));\n// total imported kW/h\nintView[0] = msg.payload[73]; //low\nintView[1] = msg.payload[72]; //high\nimportkWh = parseFloat((fltView[0]).toFixed(3));\n// total exported kW/h\nintView[0] = msg.payload[75]; //low\nintView[1] = msg.payload[74]; //high\nexportkWh = parseFloat((fltView[0]).toFixed(3));\n//active watt (already PF corrected in meter)\nintView[0] = msg.payload[13]; //low\nintView[1] = msg.payload[12]; //high\nwatt = parseFloat(fltView[0].toFixed(0));\n\n// adding previous ambientTemp to meterValues\nvar meterValues = global.get('meterValues') || null;\nvar ambientTemp = 0;\nif (meterValues != null) { ambientTemp = meterValues.ambientTemp }\n// store meter values and ambient temperature\nmeterValues = { PowerFactor,frequency,watt,apparant,volt,importkWh,exportkWh,ambientTemp};\nglobal.set('meterValues',meterValues);\n\n// Averaging values during a 5 minute period\n// cummulate watt and count each accumulation\nvar meterWatt = global.get('meterWatt') || \"\";\nvar pvowatt = meterWatt.pvowatt || 0;\nvar pvocount = meterWatt.pvocount || 0;\n\npvowatt = Number(pvowatt + watt); // pvowatt = active watt (real)\npvocount = (pvocount+1); // increase the counter\nmeterWatt = {pvocount,pvowatt}; // store watt\nglobal.set('meterWatt',meterWatt); // store values in Global\n\n// shows underneat the node the last time a PVOutput transmit was done\nvar date=new Date();\nlastTime = ( ('00' + date.getHours()).slice(-2) + 'H' + ('00' + date.getMinutes()).slice(-2) );\nnode.status({text:((pvowatt / pvocount).toFixed(0)) + \" Watt at \" + lastTime + \" (\" + pvocount +\" samples)\"});\n\n} else { \nnode.status({fill:\"yellow\",shape:\"dot\",text:\"kWh meter not answering\"});\n}\n","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":110,"wires":[],"icon":"font-awesome/fa-braille"},{"id":"20b092ab.afa95e","type":"modbus-getter","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"kWh meter","showStatusActivities":true,"showErrors":true,"logIOActivities":true,"unitid":"1","dataType":"InputRegister","adr":"0","quantity":"96","server":"7a08bc0a.6b386c","useIOFile":false,"ioFile":"","useIOForPayload":true,"emptyMsgOnFail":true,"keepMsgProperties":true,"x":450,"y":110,"wires":[["f253db9e.62f168"],[]],"outputLabels":["Buffer",""]},{"id":"b6dc2565.805b88","type":"inject","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Interval","props":[{"p":"payload"},{"p":"ip","v":"10.10.100.253","vt":"str"}],"repeat":"","crontab":"*/5 5-23 * * *","once":true,"onceDelay":0.1,"topic":"","payload":"[127,3,117,148,0,73,213,194]","payloadType":"bin","x":160,"y":110,"wires":[["23c7dabd.782b7e"]],"outputLabels":["Retrieve values"],"icon":"font-awesome/fa-clock-o","info":"msg.delay determines the interval. The interval is repeated and then renewed every 5 minutes\nYou hav to enter is in ms so 2 seconds is 2000 ms."},{"id":"407e80c8.75639","type":"subflow:ff01618d.60809","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Status transmit: PVOutput","env":[],"x":600,"y":240,"wires":[]},{"id":"3de325a.37c68da","type":"function","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"PVO credentials & \\n reset day values","func":"// needed loging data for PVOutput\nvar PVOsystemid = 'XXXXX';\nvar PVOAPIkey = 'your PVoutputkey'\nvar resetday = msg.resetday;\n\n// Reset peak Watt at the end of the day\nif (resetday) {\n text = global.get('PVpeakWatt');\n newtext = (\"Prev. day, \" + text)\n global.set('PVpeakWatt',newtext)\n// global.set('PValues',null)\n} // END IF resetday\n\n// shows underneat the node the last time a PVOutput transmit was done\nvar date=new Date();\nlastTime = ( ('00' + date.getHours()).slice(-2) + 'H' + ('00' + date.getMinutes()).slice(-2) ); //+ \":\" + ('00' + date.getSeconds()).slice(-2) );\nnode.status({text:\"Transmit time: \" + lastTime});\n\n// set payload to contain the needed PVOutput credentials\nreturn { PVOsystemid,PVOAPIkey,resetday };\n//return msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":390,"y":230,"wires":[["f72364d9.d212f8","407e80c8.75639"]],"outputLabels":["Faraday","PVOresult"],"icon":"font-awesome/fa-clock-o"},{"id":"adf4fe67.082f88","type":"delay","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"2 seconds delay","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":265,"y":200,"wires":[["3de325a.37c68da"]],"l":false,"info":"This delay gives time to retrieve the ambient temperature so this can be sent instead of the temperature of the inverter, when it is off-line."},{"id":"93b11507.07f84","type":"inject","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Interval","props":[],"repeat":"","crontab":"*/5 0-23 * * *","once":false,"onceDelay":0.1,"topic":"","payloadType":"str","x":160,"y":230,"wires":[["adf4fe67.082f88","5144e0a6.1432f"]],"outputLabels":["every 5 min."],"icon":"font-awesome/fa-clock-o","info":"Prefix max. 6 charactes/numbers\nWhen sending also to PVOoutput.org then add the\nfollowing string (a-z)\n\npayload.PVOid = your PVO system-id (five numbers)"},{"id":"5144e0a6.1432f","type":"link out","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Temperature/fan-control trigger","links":["fb618501.400cb8"],"x":265,"y":230,"wires":[],"icon":"font-awesome/fa-arrow-down"},{"id":"8c79c62.c195d38","type":"inject","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"23H59","props":[{"p":"resetday","v":"true","vt":"bool"}],"repeat":"","crontab":"59 23 * * *","once":false,"onceDelay":0.1,"topic":"","x":160,"y":200,"wires":[["adf4fe67.082f88"]],"outputLabels":["once a day"],"icon":"node-red/timer.svg","info":"Prefix max. 6 charactes/numbers\nWhen sending also to PVOoutput.org then add the\nfollowing string (a-z)\n\npayload.PVOid = your PVO system-id (five numbers)"},{"id":"671524d1.923f6c","type":"delay","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"clearer","pauseType":"delayv","timeout":"5","timeoutUnits":"minutes","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":355,"y":110,"wires":[["f253db9e.62f168"]],"icon":"node-red-node-rbe/rbe.png","l":false,"info":"This triggers after a number of seconds after the interval. If the interval is changed set tot the same value.\nThis delay is used to clear the values if there are none present. It displays under the CRC-check Node a message if there are no answers coming from the Inverter.\nThat message is normal when the inverter is off-line, This can be that there is no power from the soloar panels is provided or any other status that the inverter is not working.\nIt could also indicate a communication problem with the inverter."},{"id":"682d652e.797f7c","type":"trigger","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","op1":"","op2":"0","op1type":"pay","op2type":"str","duration":"-25","extend":false,"overrideDelay":true,"units":"hr","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":285,"y":110,"wires":[["671524d1.923f6c","516a7514.fae094","20b092ab.afa95e","ed785906.26fe78"]],"icon":"font-awesome/fa-repeat","l":false,"info":"Repeats the interval given by the inject node."},{"id":"23c7dabd.782b7e","type":"function","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","func":"if (global.get('PVwatt') == null) { \n msg.delay = 60000 } else { msg.delay = 5000 } // night and day\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":245,"y":110,"wires":[["682d652e.797f7c"]],"icon":"node-red/timer.svg","l":false},{"id":"ed785906.26fe78","type":"delay","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"clearer","pauseType":"delayv","timeout":"5","timeoutUnits":"minutes","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":355,"y":60,"wires":[["61584504.656bb4","4d1994b6.e68d54"]],"icon":"node-red-node-rbe/rbe.png","l":false,"info":"This triggers after a number of seconds after the interval. If the interval is changed set tot the same value.\nThis delay is used to clear the values if there are none present. It displays under the CRC-check Node a message if there are no answers coming from the Inverter.\nThat message is normal when the inverter is off-line, This can be that there is no power from the soloar panels is provided or any other status that the inverter is not working.\nIt could also indicate a communication problem with the inverter."},{"id":"f72364d9.d212f8","type":"function","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Calc. kWh meter value","func":"//start of the measuring year was: 12345\n\nmaxvalue = 99999; // maxvalue the meter can display\nstartmeter = 96847.1;\n\nif (global.get('meterWatt') != null) {\n meterValues = global.get('meterValues');\n imported = meterValues.importkWh;\n exported = meterValues.exportkWh;\n\n calculated = ((startmeter - exported) + imported ).toFixed(1);\n\n // round counter?\n if ( calculated < 0 ) {calculated = Number(maxvalue + calculated)}\n if ( calculated > maxvalue ) {calculated = Number(calculated - maxvalue)}\n\nnode.status({text:\"Faradaymeter: \" + calculated + \" kW/h\"});\n} else {\n node.status({text:\"No meterValues present.\"});\n}\n//return msg;","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":190,"wires":[],"icon":"font-awesome/fa-soccer-ball-o"},{"id":"ba84d31bc6af60fc","type":"function","z":"ff01618d.60809","name":"Calculate kWhmeter value","func":"//start of the measuring year was: 96443 \n\nvar d=new Date();\ndate = (('00' + d.getDate()).slice(-2) + '-' + ('00' + (d.getMonth()+1)).slice(-2)) ;\ntime = (('00' + d.getHours()).slice(-2) + ':' + ('00' + (d.getMinutes())).slice(-2)) ;\nt = (('00' + d.getMinutes()).slice(-2)).slice(-1);\n\nmaxvalue = 99999; // maxvalue the meter can display\nstartmeter = 96847.1;\nkWhmeter = 0;\n\n//if (date.getDate() == 1 && d.getHours() == 1 ) { // first of the month at one hour in the night\nif ( t == 0) { // every 10 minutes\n if (global.get('meterValues') != null) {\n meterValues = global.get('meterValues');\n kWhmeter = ((startmeter - meterValues.exportkWh) + meterValues.importkWh ).toFixed(1);\n\n // did the counter zeroed counter (overflow)?\n if ( kWhmeter < 0 ) {kWhmeter = Number(maxvalue + kWhmeter)}\n if ( kWhmeter > maxvalue ) {kWhmeter = Number(kWhmeter - maxvalue)}\n msg.payload = { date,time,kWhmeter};\n return msg;\n }\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":290,"y":240,"wires":[["a44a73dbcb94d743"]],"icon":"font-awesome/fa-soccer-ball-o"},{"id":"a44a73dbcb94d743","type":"file","z":"ff01618d.60809","name":"save-kWhmeter","filename":"/opt/goodwe/nodered/meterstand.txt","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"ascii","x":510,"y":240,"wires":[[]]}] |
Ik zend mijn gegevens naar PVOutput en ondertussen ook Tarrifs ontdekt en nu zie ik ook hoeveel geld mijn stroom opbengt onder aftrek van vaste kosten en wat ik aan stroom heb geïmporteerd. De engergie belasting laat ik buiten beschouwing want dat is te ontduikelijk voor mij. Ik wil mijn initele stand doorgeven aan mijn leverancier en ik wacht nog op antwoord hoe dat gaat.
Ik verbruik veel minder dan ik produceer en ik zit nu al ergens in december 2020 met mijn stroom teruglevering. Dat zou erop neerkomen dat ik geen energie belasting betaal en dus ook geen heffingskorting krijg (ongeveer 527 Euro). Dat is toch weer een nadeel van zonnepanelen dat je heffingskorting misloopt.
Of zie ik dat verkeerd en gaat de heffinskorting per dag en is onafhankelijk van het verbruik?
Ik betaalde vorig jaar al bijna niets voor mijn stroom omdat de heffingskort net zo veel was wat ik verbruikte. In een heel jaar moest ik 35 Euro betalen aan stroom.