[{"id":"801b0f90.623ea8","type":"tab","label":"Inverter2PVOutput","disabled":false,"info":"Scripted by msatter\nversion: 20210526-1.10\nOnly for non-comercial usage"},{"id":"25c26ce6.9d762c","type":"subflow","name":"Prepare for PVOutput.org","info":"Version:20210526-1.10","category":"","in":[{"x":40,"y":40,"wires":[{"id":"4e1640a7.b10de8"}]}],"out":[{"x":380,"y":160,"wires":[{"id":"e883ef0a.9d7f5","port":1}]}],"env":[],"meta":{},"color":"#AAAA66","icon":"font-awesome/fa-filter","status":{"x":540,"y":200,"wires":[{"id":"a0cff14b.2baee8","port":0}]}},{"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":40,"y":80,"wires":[{"id":"1a1e9c44.bce1f4"}]}],"out":[],"env":[],"meta":{},"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":"4b48967c.fcfc3","type":"group","z":"801b0f90.623ea8","name":"Handing over to subflow nodes, status diplayed","style":{"stroke":"none","fill":"#addb7b","label":true,"label-position":"se","color":"#ffffff"},"nodes":["6e0fb1a2.416948","407e80c8.75639","930318c6.0ba1a"],"x":534,"y":199,"w":332,"h":150},{"id":"8ae4ca85.96da48","type":"group","z":"801b0f90.623ea8","name":"Retrieve values from the inverter, with time-out detection / CRC check with retry till TTL has become invalid.","style":{"stroke-opacity":"0","fill":"#7fb7df","label":true,"color":"#ffffff"},"nodes":["516a7514.fae094","f06e70e4.9be698","8277276e.aa4838","c3f1b711.3b982","2d33f88c.5b3218","39c47589.21ca4a","97508752.1cd3a8","11627800.6500a","57ba3d31.c82a94","61584504.656bb4","c48649f.4f33938","ca20bfa3.9a4018","97d4ca32.f3eab","8d4b9241.9ebfb"],"x":54,"y":19,"w":812,"h":162},{"id":"d6e3f503.b6b34","type":"group","z":"801b0f90.623ea8","name":"Request values, transfer API-key and System-id","style":{"stroke":"none","fill":"#3f5787","label":true,"label-position":"se","color":"#ffffff"},"nodes":["b7d1e792.f544b","7326dc17.928594","576863d4.d2162c","69f5a1ee.df6a48","3921663d.c36b9a"],"x":54,"y":199,"w":432,"h":210},{"id":"4e1640a7.b10de8","type":"change","z":"25c26ce6.9d762c","name":"Not needed values","rules":[{"t":"delete","p":"payload.ipa","pt":"msg"},{"t":"delete","p":"payload.TTL","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":210,"y":40,"wires":[["fdd4f465.f60b3"]],"icon":"font-awesome/fa-filter"},{"id":"fdd4f465.f60b3","type":"join","z":"25c26ce6.9d762c","name":"Put values in a array","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"[32]","joinerType":"bin","accumulate":false,"timeout":"290","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":220,"y":80,"wires":[["5edda9f.62c3158"]],"info":"A time-out of 297 seconds after the first message so that all is cleaned up for the next update. "},{"id":"e883ef0a.9d7f5","type":"switch","z":"25c26ce6.9d762c","name":"Array [0] well formed","property":"payload[0].PVOid","propertyType":"msg","rules":[{"t":"empty"},{"t":"nempty"}],"checkall":"true","repair":false,"outputs":2,"x":220,"y":160,"wires":[[],["a0cff14b.2baee8"]],"icon":"node-red/white-globe.svg"},{"id":"6e0fb1a2.416948","type":"link in","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Prepare PVO+system-id","links":["2d33f88c.5b3218","7326dc17.928594"],"x":575,"y":240,"wires":[["930318c6.0ba1a"]],"icon":"font-awesome/fa-arrow-right"},{"id":"407e80c8.75639","type":"subflow:ff01618d.60809","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Transmit values to PVOutput","env":[],"x":720,"y":300,"wires":[]},{"id":"930318c6.0ba1a","type":"subflow:25c26ce6.9d762c","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Prepare values for PVOutput","env":[],"x":720,"y":240,"wires":[["407e80c8.75639"]]},{"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":310,"y":60,"wires":[],"icon":"node-red/bridge.svg"},{"id":"f06e70e4.9be698","type":"function","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Req. values","func":"var inverter_ask = Buffer.from(\"7F0375940049D5C2\",\"hex\");\nvar ipaddress = msg.payload.ipa;\n\nmsg.ip = ipaddress;\nmsg.payload = inverter_ask;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":150,"y":60,"wires":[["516a7514.fae094"]],"icon":"font-awesome/fa-sticky-note"},{"id":"8277276e.aa4838","type":"udp in","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","iface":"","port":"8899","ipv":"udp4","multicast":"false","group":"","datatype":"buffer","x":460,"y":60,"wires":[["61584504.656bb4"]],"icon":"node-red/bridge.svg"},{"id":"c3f1b711.3b982","type":"delay","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"6","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":500,"y":100,"wires":[["39c47589.21ca4a"]],"icon":"font-awesome/fa-hand-stop-o"},{"id":"2d33f88c.5b3218","type":"link out","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Publish","links":["6e0fb1a2.416948"],"x":780,"y":60,"wires":[],"icon":"font-awesome/fa-arrow-down","l":true},{"id":"39c47589.21ca4a","type":"switch","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Values","property":"payload.ipa","propertyType":"msg","rules":[{"t":"null"},{"t":"nnull"}],"checkall":"true","repair":false,"outputs":2,"x":650,"y":100,"wires":[["2d33f88c.5b3218"],["c48649f.4f33938"]],"inputLabels":["Valid"],"outputLabels":["YES","NO"],"icon":"font-awesome/fa-check-square"},{"id":"97508752.1cd3a8","type":"delay","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":320,"y":100,"wires":[["c3f1b711.3b982"]]},{"id":"11627800.6500a","type":"link in","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Retrieve values","links":["7326dc17.928594","97d4ca32.f3eab"],"x":160,"y":140,"wires":[["57ba3d31.c82a94"]],"icon":"font-awesome/fa-arrow-right","l":true},{"id":"57ba3d31.c82a94","type":"delay","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"minutes","rate":"3","nbRateUnits":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":150,"y":100,"wires":[["97508752.1cd3a8","f06e70e4.9be698"]],"icon":"font-awesome/fa-hand-stop-o"},{"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\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 return msg;\n// Also the wait for power delevery to the net could here be checked.\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":60,"wires":[["c3f1b711.3b982"]],"icon":"font-awesome/fa-arrows-h"},{"id":"b7d1e792.f544b","type":"inject","z":"801b0f90.623ea8","g":"d6e3f503.b6b34","name":"PVOutput config & timer","props":[{"p":"payload.ipa","v":"10.10.100.253","vt":"str"},{"p":"payload.PVOid","v":"nnnnn","vt":"str"},{"p":"payload.APIkey","v":"nnnnnnnnnnnnn.......","vt":"str"},{"p":"payload.TTL","v":"","vt":"date"}],"repeat":"","crontab":"*/5 5-22 * * *","once":false,"onceDelay":0.1,"topic":"","payloadType":"str","x":210,"y":240,"wires":[["7326dc17.928594"]],"icon":"font-awesome/fa-pencil-square","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":"576863d4.d2162c","type":"inject","z":"801b0f90.623ea8","d":true,"g":"d6e3f503.b6b34","name":"Timer & config No2","props":[],"repeat":"","crontab":"*/5 5-22 * * *","once":false,"onceDelay":"5","topic":"","payloadType":"str","x":200,"y":280,"wires":[["7326dc17.928594"]]},{"id":"69f5a1ee.df6a48","type":"inject","z":"801b0f90.623ea8","d":true,"g":"d6e3f503.b6b34","name":"Timer & config No3","props":[{"p":"payload.ipa","v":"10.10.100.253","vt":"str"},{"p":"payload.ssid","v":"no3","vt":"str"}],"repeat":"","crontab":"*/5 4-22 * * *","once":true,"onceDelay":"10","topic":"","x":200,"y":320,"wires":[["7326dc17.928594"]]},{"id":"3921663d.c36b9a","type":"inject","z":"801b0f90.623ea8","d":true,"g":"d6e3f503.b6b34","name":"To PVoutput at midnight ","props":[{"p":"payload.ipa","v":"10.10.100.253","vt":"str"},{"p":"payload.ssid","v":"goodwe","vt":"str"},{"p":"payload.PVOid","v":"nnnnn","vt":"str"},{"p":"payload.APIkey","v":"nnnnnnnnnnnnnnn......","vt":"str"}],"repeat":"","crontab":"59 23 * * *","once":false,"onceDelay":0.1,"topic":"","x":210,"y":360,"wires":[["7326dc17.928594"]],"info":"This needed when also sending not only generated power but also consumed power."},{"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 = \"http://pvoutput.org/service/r2/addstatus.jsp\";\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"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 // new status message\n //msg.status.text =Time + \" \" + msg.status;\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 //var msg1 = null;\n //var msg2 = null;\n msg1.payload = stat;\n msg2.payload = stat;\n var msg1 = { payload: stat };\n var msg2 = { payload: stat };\n //msg.status.text = Time + \" \" + msg.status;\n}\nreturn msg;\nreturn (msg1, msg2);","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":500,"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 = \"http://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":220,"y":40,"wires":[]},{"id":"1a1e9c44.bce1f4","type":"function","z":"ff01618d.60809","name":"Prepare values","func":"var PVOsystemid = msg.payload[0].PVOid;\nvar PVOAPIkey = msg.payload[0].APIkey\nvar inverter_reply = msg.payload[1];\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\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 var year = \"20\" + inverter_reply.readInt8(5); // \n var month = inverter_reply.readInt8(6); // \n var day = inverter_reply.readInt8(7); // \n var hour = inverter_reply.readInt8(8); // \n var minutes1 = inverter_reply.readInt8(9); // \n\n if(month.toString().length == 1) { var month = '0'+month; }\n if(day.toString().length == 1) { var day = '0'+day;}\n if(hour.toString().length == 1) { var hour = '0'+hour; }\n //if(minutes1.toString().length == 1) { var minutes1 = '0'+minutes1; }\n var minutes = (minutes1 < 5 ? '0' : '') + minutes1;\n\nvar d = year + month + day;\nvar t = hour + \":\" + minutes;\nvar v1 = parseFloat((inverter_reply.readInt16BE(93) * 100).toFixed(1)); // eDay\nvar v2 = inverter_reply.readInt16BE(61); // production in Watt\nvar v5 = parseFloat((inverter_reply.readInt16BE(87) * 0.1).toFixed(1)); // v5 temperature\nvar v6 = parseFloat((inverter_reply.readInt16BE(41) * 0.1).toFixed(1)); // AC zijde\n\n msg.payload = {\n d,\n t,\n v1,\n v2,\n v5,\n v6,\n PVOsystemid,\n PVOAPIkey\n }\n\n return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":160,"y":80,"wires":[["71cd2d97.8e32d4","106f84dd.f8d73b"]],"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":530,"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":"5edda9f.62c3158","type":"switch","z":"25c26ce6.9d762c","name":"Array [1] well formed?","property":"payload[1]","propertyType":"msg","rules":[{"t":"istype","v":"buffer","vt":"buffer"},{"t":"istype","v":"object","vt":"object"}],"checkall":"false","repair":false,"outputs":2,"x":220,"y":120,"wires":[["e883ef0a.9d7f5"],[]],"info":"When the inverter is offline the PVOutput credentials are still being injected.\n\nThis will check if the payload in the second array field is of the type buffer (contain the inverter values) and not a later injected PVOuput credentials."},{"id":"c48649f.4f33938","type":"function","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"TTL","func":"var timediff = 0\ntimediff = (Date.now() / 1000 ) - (msg.payload.TTL / 1000 );\nif (timediff > 124){\n delete msg.payload\n return msg\n}\n //msg.payload.diff = timediff;\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":140,"wires":[["ca20bfa3.9a4018"]],"icon":"font-awesome/fa-calculator"},{"id":"ca20bfa3.9a4018","type":"switch","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"TTL","property":"payload","propertyType":"msg","rules":[{"t":"nnull"},{"t":"null"}],"checkall":"true","repair":false,"outputs":2,"x":650,"y":140,"wires":[["97d4ca32.f3eab"],["8d4b9241.9ebfb"]],"outputLabels":["TTL valid","TTL invalid"],"icon":"font-awesome/fa-question-circle-o"},{"id":"97d4ca32.f3eab","type":"link out","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Retry","links":["11627800.6500a"],"x":790,"y":100,"wires":[],"icon":"font-awesome/fa-refresh","l":true},{"id":"8d4b9241.9ebfb","type":"link out","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Stop","links":[],"x":790,"y":140,"wires":[],"icon":"font-awesome/fa-chain-broken","l":true},{"id":"7326dc17.928594","type":"link out","z":"801b0f90.623ea8","g":"d6e3f503.b6b34","name":"Begin","links":["11627800.6500a","6e0fb1a2.416948"],"x":410,"y":300,"wires":[],"icon":"font-awesome/fa-arrow-up","l":true},{"id":"a0cff14b.2baee8","type":"function","z":"25c26ce6.9d762c","name":"Timestamp","func":"var inverter_reply = msg.payload[1];\n\nvar message1 = inverter_reply.slice(2); // Remove 'AA55' from start of message\nvar message = message1.slice(0, -2); //Remove two CRC bytes from end of message\n\n\nvar hour = inverter_reply.readInt8(8); // \nvar minute = inverter_reply.readInt8(9); // \n\nif(hour.toString().length == 1) { var hour = '0'+hour; }\n// var minutes = (minutes1 < 5 ? '0' : '') + minutes1;\nif(minute.toString().length == 1) { var minute = '0'+minute; }\n\nmsg.payload = \"Last-time values: \" + hour + \":\" + minute;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":200,"wires":[[]],"icon":"node-red/status.svg"}]