Hallo zusammen,
ich habe mir einen Flow zum Auslesen der Pylontech Batterien über die RS232 Console mit anschließender Übertragung nach ioBroker gebastelt.
Die Daten werden im ioBroker unter pylontech.0 unter der Seriennummer abgelegt.
Ich habe 4 Batterien. Aktuell sind im Flow 5 vorgesehen, wovon 4 aktiviert sind.
Der Flow kann aber belibig bis zu 15 erweitert werden.
In der aktuellen Einstellung werden die Daten alle 5 Min abgeholt.
Der Flow benötigt "node-red-node-serialport".
Zum Anschluss wird ein RS232/USB Wandler oder etwas Ähnliches benötigt auch eine Übertragung des Comports mit einem ESP ist möglich.
Das Kabel muss an die erste Batterie an den Konsolenport angeschlossen werden.
Würde mich über Response freuen. Theoretisch kann ich auch einen Adapter daraus bauen.
Die Konsole ist ab Werk auf 1200Baud eingestellt.
Vor dem ersten Zugriff muss die untere V24 mit ihrer Verbindung deaktiviert und die Obere aktiviert werden. Dann einmal den Injekt ausführen.
Sollten danach keine Daten kommen, einmal den init Injekt clicken.
[{"id":"8a67418ecc3cedb7","type":"debug","z":"c8efb1fdd535ecb6","name":"debug 1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1260,"y":400,"wires":[]},{"id":"3f1a6c3e7e5f8e9e","type":"debug","z":"c8efb1fdd535ecb6","name":"debug 2","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1440,"y":460,"wires":[]},{"id":"6e84de1dc0b0e89a","type":"serial request","z":"c8efb1fdd535ecb6","name":"","serial":"4a956651a40d8e44","x":1020,"y":520,"wires":[["8a67418ecc3cedb7","4ec640d7fa3e2470"]]},{"id":"963306c8b42714bd","type":"change","z":"c8efb1fdd535ecb6","name":"bat 1","rules":[{"t":"set","p":"payload","pt":"msg","to":"bat 1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":680,"wires":[["6e84de1dc0b0e89a"]]},{"id":"a30bf3dc65887c3f","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":740,"wires":[["806b43c1963ce85a","2e42141b0c0fd3ab"]]},{"id":"806b43c1963ce85a","type":"change","z":"c8efb1fdd535ecb6","name":"bat 2","rules":[{"t":"set","p":"payload","pt":"msg","to":"bat 2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":740,"wires":[["6e84de1dc0b0e89a"]]},{"id":"3e0e94f84b8388df","type":"change","z":"c8efb1fdd535ecb6","name":"bat 3","rules":[{"t":"set","p":"payload","pt":"msg","to":"bat 3","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":800,"wires":[["6e84de1dc0b0e89a"]]},{"id":"dab2179316524305","type":"change","z":"c8efb1fdd535ecb6","name":"bat 4","rules":[{"t":"set","p":"payload","pt":"msg","to":"bat 4","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":860,"wires":[["6e84de1dc0b0e89a"]]},{"id":"fb3670e4512d05b6","type":"change","z":"c8efb1fdd535ecb6","d":true,"name":"bat 5","rules":[{"t":"set","p":"payload","pt":"msg","to":"bat 5","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":920,"wires":[["6e84de1dc0b0e89a"]]},{"id":"ccc464b0e4c3207c","type":"change","z":"c8efb1fdd535ecb6","name":"soh 1","rules":[{"t":"set","p":"payload","pt":"msg","to":"soh 1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":1020,"wires":[["6e84de1dc0b0e89a"]]},{"id":"2e42141b0c0fd3ab","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":800,"wires":[["3e0e94f84b8388df","6d4cdbe12aa578f7"]]},{"id":"6d4cdbe12aa578f7","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":860,"wires":[["dab2179316524305","fe6a3514e2a5b4f6"]]},{"id":"fe6a3514e2a5b4f6","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":920,"wires":[["fb3670e4512d05b6","edb87fb32e777632"]]},{"id":"edb87fb32e777632","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":1020,"wires":[["ccc464b0e4c3207c","d15ab215db481e94"]]},{"id":"52eb196c22e0a202","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":680,"wires":[["963306c8b42714bd","a30bf3dc65887c3f"]]},{"id":"752d78cddb20a26e","type":"change","z":"c8efb1fdd535ecb6","name":"info 1","rules":[{"t":"set","p":"payload","pt":"msg","to":"info 1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":240,"wires":[["6e84de1dc0b0e89a"]]},{"id":"4ec640d7fa3e2470","type":"function","z":"c8efb1fdd535ecb6","name":"Pylontech toIOB","func":"const baseTopic = 'pylontech.0.';\n\nfunction convert(str) {\n const number = /^(-|\\+)?\\d+$/g;\n const numberP = /^(-|\\+)?\\d+%$/g;\n const numbermAH = /^(-|\\+)?\\d+ mAH$/g;\n const numbermA = /^(-|\\+)?\\d+mA$/g;\n if (number.test(str)) {\n return { payload: parseInt(str, 10) };\n }\n if (numberP.test(str)) {\n return { payload: parseInt(str, 10), unit: '%' };\n }\n if (numbermAH.test(str)) {\n return { payload: parseInt(str, 10), unit: 'mAh' };\n }\n if (numbermA.test(str)) {\n return { payload: parseInt(str, 10), unit: 'mA' };\n }\n return { payload: str };\n}\n\nfunction sendVal(name, topic, val) {\n const r = convert(val);\n const msg = {\n payload: r.payload,\n stateName: name,\n stateReadonly: true,\n stateType: typeof r.payload,\n topic,\n ack: true,\n };\n if (r.unit) {\n msg.stateUnit = r.unit;\n }\n node.status({ fill: 'green', shape: 'ring', text: JSON.stringify(msg) });\n node.send(msg);\n}\n\nfunction processData(filter, mkPath, ignoreKeys) {\n const head = filter.exec(msg.payload);\n if (head) {\n for (let i = 1; i < head.length; i++) {\n head[i] = head[i].trim();\n }\n for (let match; (match = filter.exec(msg.payload)) !== null;) {\n const dat = {};\n for (let i = 1; i < match.length; i++) {\n if (match[i]) {\n dat[head[i]] = match[i].trim();\n }\n }\n const spath = mkPath(dat);\n Object.keys(dat).forEach(key => {\n if (ignoreKeys(dat, key)) {\n sendVal(key, spath + key.replaceAll('.', '').replaceAll(' ', '_').toLocaleLowerCase(), dat[key]);\n }\n });\n }\n }\n}\n\nconst prompt = /(pylon>)(\\S+)\\s(\\d+)/g;\nconst cmd = prompt.exec(msg.payload);\nif (cmd && cmd[2] === 'info') {\n let ok = false;\n const row = /(.+\\S)\\s+:\\s(.*)/gm;\n const data = {};\n for (let match; (match = row.exec(msg.payload)) !== null;) {\n data[match[1]] = match[2];\n }\n if (data.Barcode) {\n ok = true;\n const path = baseTopic + data.Barcode.replaceAll(' ', '_');\n global.set(`pylontech${cmd[3]}`, path);\n Object.keys(data).forEach(key => {\n if (key !== 'Barcode') {\n sendVal(key, `${path}.info.${key.replaceAll(' ', '_').toLocaleLowerCase()}`, data[key]);\n }\n });\n sendVal('Barcode', `${baseTopic}info${cmd[3]}.barcode`, data.Barcode);\n }\n sendVal('Verbunden', `${baseTopic}info${cmd[3]}.connected`, ok);\n} else if (cmd && cmd[2] === 'bat') {\n const path = global.get(`pylontech${cmd[3]}`);\n if (path) {\n processData(\n /^(.{9})(.{9})(.{9})(.{9})(.{13})(.{13})(.{13})(.{13})(.{12})(.{14})(.{1,3})/gm,\n dat => {\n return `${path}.battery${(parseInt(dat.Battery, 10) + 1).toString().padStart(2, '0')}.`;\n },\n (dat, key) => {\n return !['Battery'].includes(key);\n }\n );\n }\n} else if (cmd && cmd[2] === 'soh') {\n const path = global.get(`pylontech${cmd[3]}`);\n if (path) {\n processData(\n /^(.{11})(.{11})(.{11})(.{9})/gm,\n dat => {\n return `${path}.battery${(parseInt(dat.Battery, 10) + 1).toString().padStart(2, '0')}.`;\n },\n (dat, key) => {\n return !['Battery', 'Voltage'].includes(key);\n }\n );\n }\n} else {\n const promptS = /(pylon>)(\\S+)/g;\n const cmd = promptS.exec(msg.payload);\n if (cmd && cmd[2] === 'pwr') {\n processData(\n /^(.{6})(.{7})(.{7})(.{7})(.{7})(.{7})(.{7})(.{7})(.{9})(.{9})(.{9})(.{9})(.{9})(.{21})(.{9})(.{9})?(.{8})?(.{7})?/gm,\n dat => {\n const path = global.get(`pylontech${dat.Power}`);\n return `${path}.power.`;\n },\n (dat, key) => {\n return !(dat['Base.St'] && dat['Base.St'] === 'Absent') && !['Power'].includes(key) && dat[key] && dat[key] !== '-';\n }\n );\n } else if (cmd && cmd[2] === 'log') {\n const row = /(.+\\S)\\s+:\\s(.*)/gm;\n let data = {};\n for (let match; (match = row.exec(msg.payload)) !== null;) {\n data[match[1].trim()] = match[2].trim();\n if (match[1].trim()===\"Info\") {\n node.status({ fill: 'green', shape: 'ring', text: JSON.stringify(data) });\n const path = `${baseTopic}log.${data[\"Index\"]}`;\n Object.keys(data).forEach(key => {\n if (key !== 'Index') {\n sendVal(key, `${path}.${key.replaceAll(' ', '_').toLocaleLowerCase()}`, data[key]);\n }\n });\n data={};\n }\n }\n }\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1260,"y":520,"wires":[["3f1a6c3e7e5f8e9e","ad7fbdde0a611199"]]},{"id":"dada1eb1e02d85c4","type":"change","z":"c8efb1fdd535ecb6","name":"info 2","rules":[{"t":"set","p":"payload","pt":"msg","to":"info 2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":300,"wires":[["6e84de1dc0b0e89a"]]},{"id":"2ce08c297a547c15","type":"change","z":"c8efb1fdd535ecb6","name":"info 3","rules":[{"t":"set","p":"payload","pt":"msg","to":"info 3","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":360,"wires":[["6e84de1dc0b0e89a"]]},{"id":"5972560db0257e0e","type":"change","z":"c8efb1fdd535ecb6","name":"info 4","rules":[{"t":"set","p":"payload","pt":"msg","to":"info 4","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":420,"wires":[["6e84de1dc0b0e89a"]]},{"id":"763851bf660a0908","type":"change","z":"c8efb1fdd535ecb6","d":true,"name":"info 5","rules":[{"t":"set","p":"payload","pt":"msg","to":"info 5","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":480,"wires":[["6e84de1dc0b0e89a"]]},{"id":"50ea64dfbd16eede","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":360,"wires":[["219ecee40d790bac","2ce08c297a547c15"]]},{"id":"219ecee40d790bac","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":420,"wires":[["90c49403c185dd66","5972560db0257e0e"]]},{"id":"90c49403c185dd66","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":480,"wires":[["d52b8181e8fbe7f8","763851bf660a0908"]]},{"id":"d52b8181e8fbe7f8","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":580,"wires":[["52eb196c22e0a202","07e346121af39488"]]},{"id":"fd8f0b0577bbe0f7","type":"inject","z":"c8efb1fdd535ecb6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"300","crontab":"","once":true,"onceDelay":"2","topic":"","payload":"","payloadType":"date","x":350,"y":240,"wires":[["f8eecab391c1e1c6","752d78cddb20a26e"]]},{"id":"6a56d5e5a4b9c9af","type":"change","z":"c8efb1fdd535ecb6","name":"soh 2","rules":[{"t":"set","p":"payload","pt":"msg","to":"soh 2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":1080,"wires":[["6e84de1dc0b0e89a"]]},{"id":"d15ab215db481e94","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":1080,"wires":[["6a56d5e5a4b9c9af","7de93a9b8ccb4b7e"]]},{"id":"7d044e585b21424c","type":"change","z":"c8efb1fdd535ecb6","name":"soh 3","rules":[{"t":"set","p":"payload","pt":"msg","to":"soh 3","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":1140,"wires":[["6e84de1dc0b0e89a"]]},{"id":"7de93a9b8ccb4b7e","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":1140,"wires":[["7d044e585b21424c","918b1ccb36ed0b75"]]},{"id":"a1be957fc5c665c7","type":"change","z":"c8efb1fdd535ecb6","name":"soh 4","rules":[{"t":"set","p":"payload","pt":"msg","to":"soh 4","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":1200,"wires":[["6e84de1dc0b0e89a"]]},{"id":"918b1ccb36ed0b75","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":1200,"wires":[["a1be957fc5c665c7","e4353cc1a4d8cb1d"]]},{"id":"e4353cc1a4d8cb1d","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":1260,"wires":[["d57057a0ca734148","fb3545f07873e002"]]},{"id":"d57057a0ca734148","type":"change","z":"c8efb1fdd535ecb6","d":true,"name":"soh 5","rules":[{"t":"set","p":"payload","pt":"msg","to":"soh 5","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":1260,"wires":[["6e84de1dc0b0e89a"]]},{"id":"ad7fbdde0a611199","type":"ioBroker out","z":"c8efb1fdd535ecb6","name":"","topic":"","ack":"false","autoCreate":"true","stateName":"","role":"","payloadType":"","readonly":"false","stateUnit":"","stateMin":"","stateMax":"","x":1460,"y":500,"wires":[]},{"id":"07e346121af39488","type":"change","z":"c8efb1fdd535ecb6","name":"pwr","rules":[{"t":"set","p":"payload","pt":"msg","to":"pwr","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":580,"wires":[["6e84de1dc0b0e89a"]]},{"id":"f8eecab391c1e1c6","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":300,"wires":[["50ea64dfbd16eede","dada1eb1e02d85c4"]]},{"id":"e87a352e45a92263","type":"inject","z":"c8efb1fdd535ecb6","name":"Set V24","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"300","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"[126,50,48,48,49,52,54,56,50,67,48,48,52,56,53,50,48,70,67,67,51,13]","payloadType":"bin","x":740,"y":60,"wires":[["0b2aaed380713036"]]},{"id":"710ca3ffc929f193","type":"inject","z":"c8efb1fdd535ecb6","name":"Init","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[13,10]","payloadType":"bin","x":750,"y":120,"wires":[["6e84de1dc0b0e89a"]]},{"id":"0b2aaed380713036","type":"serial request","z":"c8efb1fdd535ecb6","d":true,"name":"","serial":"5a8b7bd0fbe83ab7","x":1040,"y":60,"wires":[["c395ddc57f9d7259"]]},{"id":"c395ddc57f9d7259","type":"debug","z":"c8efb1fdd535ecb6","name":"debug 11","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1280,"y":60,"wires":[]},{"id":"b7cac5e8450c2fbf","type":"inject","z":"c8efb1fdd535ecb6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":570,"y":180,"wires":[["cc33e73ade7ee234"]]},{"id":"cc33e73ade7ee234","type":"function","z":"c8efb1fdd535ecb6","name":"set Time","func":"function f2 (val) {\n return val.toString().padStart(2, \"0\")\n}\n\nlet d = new Date()\nmsg.payload = `time ${f2(d.getFullYear()%100)} ${f2(d.getMonth()+1)} ${f2(d.getDate())} ${f2(d.getHours())} ${f2(d.getMinutes())} ${f2(d.getSeconds())}`\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":740,"y":180,"wires":[["6e84de1dc0b0e89a"]]},{"id":"c421bf7a32139ffe","type":"change","z":"c8efb1fdd535ecb6","name":"log","rules":[{"t":"set","p":"payload","pt":"msg","to":"\"log\\n\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":1360,"wires":[["6e84de1dc0b0e89a"]]},{"id":"fb3545f07873e002","type":"delay","z":"c8efb1fdd535ecb6","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":560,"y":1360,"wires":[["c421bf7a32139ffe"]]},{"id":"29b3711f40c93afe","type":"change","z":"c8efb1fdd535ecb6","name":"help","rules":[{"t":"set","p":"payload","pt":"msg","to":"\"pwr\\n\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1210,"y":660,"wires":[["6e84de1dc0b0e89a"]]},{"id":"260891a4b0a2e888","type":"inject","z":"c8efb1fdd535ecb6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":1030,"y":660,"wires":[["29b3711f40c93afe"]]},{"id":"232a266f73d872dc","type":"inject","z":"c8efb1fdd535ecb6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":460,"y":1440,"wires":[["c421bf7a32139ffe"]]},{"id":"4a956651a40d8e44","type":"serial-port","serialport":"/dev/ttyUSB_pylontech","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"$$$$","bin":"false","out":"char","addchar":"\\n","responsetimeout":"1000"},{"id":"5a8b7bd0fbe83ab7","type":"serial-port","d":true,"serialport":"/dev/ttyUSB_pylontech","serialbaud":"1200","databits":"8","parity":"none","stopbits":"1","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"\\n","bin":"false","out":"char","addchar":"","responsetimeout":"10000"}]
last update 28.08.2023
Den Function Block noch einmal einzeln
const baseTopic = 'pylontech.0.';
function convert(str) {
const number = /^(-|\+)?\d+$/g;
const numberP = /^(-|\+)?\d+%$/g;
const numbermAH = /^(-|\+)?\d+ mAH$/g;
const numbermA = /^(-|\+)?\d+mA$/g;
if (number.test(str)) {
return { payload: parseInt(str, 10) };
}
if (numberP.test(str)) {
return { payload: parseInt(str, 10), unit: '%' };
}
if (numbermAH.test(str)) {
return { payload: parseInt(str, 10), unit: 'mAh' };
}
if (numbermA.test(str)) {
return { payload: parseInt(str, 10), unit: 'mA' };
}
return { payload: str };
}
function sendVal(name, topic, val) {
const r = convert(val);
const msg = {
payload: r.payload,
stateName: name,
stateReadonly: true,
stateType: typeof r.payload,
topic,
ack: true,
};
if (r.unit) {
msg.stateUnit = r.unit;
}
node.status({ fill: 'green', shape: 'ring', text: JSON.stringify(msg) });
node.send(msg);
}
function processData(filter, mkPath, ignoreKeys) {
const head = filter.exec(msg.payload);
if (head) {
for (let i = 1; i < head.length; i++) {
head[i] = head[i].trim();
}
for (let match; (match = filter.exec(msg.payload)) !== null;) {
const dat = {};
for (let i = 1; i < match.length; i++) {
if (match[i]) {
dat[head[i]] = match[i].trim();
}
}
const spath = mkPath(dat);
Object.keys(dat).forEach(key => {
if (ignoreKeys(dat, key)) {
sendVal(key, spath + key.replaceAll('.', '').replaceAll(' ', '_').toLocaleLowerCase(), dat[key]);
}
});
}
}
}
const prompt = /(pylon>)(\S+)\s(\d+)/g;
const cmd = prompt.exec(msg.payload);
if (cmd && cmd[2] === 'info') {
let ok = false;
const row = /(.+\S)\s+:\s(.*)/gm;
const data = {};
for (let match; (match = row.exec(msg.payload)) !== null;) {
data[match[1]] = match[2];
}
if (data.Barcode) {
ok = true;
const path = baseTopic + data.Barcode.replaceAll(' ', '_');
global.set(`pylontech${cmd[3]}`, path);
Object.keys(data).forEach(key => {
if (key !== 'Barcode') {
sendVal(key, `${path}.info.${key.replaceAll(' ', '_').toLocaleLowerCase()}`, data[key]);
}
});
sendVal('Barcode', `${baseTopic}info${cmd[3]}.barcode`, data.Barcode);
}
sendVal('Verbunden', `${baseTopic}info${cmd[3]}.connected`, ok);
} else if (cmd && cmd[2] === 'bat') {
const path = global.get(`pylontech${cmd[3]}`);
if (path) {
processData(
/^(.{9})(.{9})(.{9})(.{9})(.{13})(.{13})(.{13})(.{13})(.{12})(.{14})(.{1,3})/gm,
dat => {
return `${path}.battery${(parseInt(dat.Battery, 10) + 1).toString().padStart(2, '0')}.`;
},
(dat, key) => {
return !['Battery'].includes(key);
}
);
}
} else if (cmd && cmd[2] === 'soh') {
const path = global.get(`pylontech${cmd[3]}`);
if (path) {
processData(
/^(.{11})(.{11})(.{11})(.{9})/gm,
dat => {
return `${path}.battery${(parseInt(dat.Battery, 10) + 1).toString().padStart(2, '0')}.`;
},
(dat, key) => {
return !['Battery', 'Voltage'].includes(key);
}
);
}
} else {
const promptS = /(pylon>)(\S+)/g;
const cmd = promptS.exec(msg.payload);
if (cmd && cmd[2] === 'pwr') {
processData(
/^(.{6})(.{7})(.{7})(.{7})(.{7})(.{7})(.{7})(.{7})(.{9})(.{9})(.{9})(.{9})(.{9})(.{21})(.{9})(.{9})?(.{8})?(.{7})?/gm,
dat => {
const path = global.get(`pylontech${dat.Power}`);
return `${path}.power.`;
},
(dat, key) => {
return !(dat['Base.St'] && dat['Base.St'] === 'Absent') && !['Power'].includes(key) && dat[key] && dat[key] !== '-';
}
);
} else if (cmd && cmd[2] === 'log') {
const row = /(.+\S)\s+:\s(.*)/gm;
let data = {};
for (let match; (match = row.exec(msg.payload)) !== null;) {
data[match[1].trim()] = match[2].trim();
if (match[1].trim()==="Info") {
node.status({ fill: 'green', shape: 'ring', text: JSON.stringify(data) });
const path = `${baseTopic}log.${data["Index"]}`;
Object.keys(data).forEach(key => {
if (key !== 'Index') {
sendVal(key, `${path}.${key.replaceAll(' ', '_').toLocaleLowerCase()}`, data[key]);
}
});
data={};
}
}
}
}
last update 28.08.2023