Solax X1 Boost MQTT to SMA Modbus Emulator to feed Solar-Log Data Logger

This flow is specific to a Solax X1 MQTT feed, however it could be adapted for any Inverter where an MQTT feed is available. It takes the MQTT data and extracts the elements and pushes them into a Modbus slave with the SMA Modbus register map. Some of the registers contain fixed data as specified by SMA and the Solar-Log recognises these registers and this data during its discovery stage and adds an SMA Modbus inverter to its devices. The Solar-Log then goes into its normal phase and collects the changing data and adds it to its database and repeats this every 15 secs.

Note the Modbus ID is set to 4 in this example, it can be changed but do not go lower than ID 3 or the Solar-Log will fail the discovery. This is to be expected, SMA reserve ID's lower than 3 for their own data loggers.

In the course of developing this flow I discovered that Solar-log trys to read the non existing registers 31253 length 6, this is corrected and the data for registers 30783 Length 2 is sent instead and appears as Grid Volts L1.

This is for a single phase set up, there are 3 phase registers I have ignored but they can be added eg 30785 and 30787 for L2 and L2. There are other 3 phase registers missed too, but the SMA Modbus documentation details these.

You will need to change the Modbus Server IP address to the address of the Node-red computer. Modbus server is set to port 1502 for use on a Raspberry Pi with the Pi's IPtables set to redirect incoming port 502 requests to 1502 due to the Linux block below port 1024 inclusive. The Solar-log searches on port 502 and cannot be changed.

The MQTT feed for the daily yield is only to 0.1 Kwh and the Solar-log can read to 0.01kwh so I ignored the MQTT feed and instead used the

https://flows.nodered.org/node/node-red-contrib-watt2kwh

which coped well with this requirement and results in a more accurate data feed.

Potential Solax MQTT feeds are on Github

https://github.com/search?q=solax%20mqtt&type=repositories

[{"id":"a0f42263502ff357","type":"tab","label":"Solax to SMA Modbus","disabled":false,"info":"","env":[]},{"id":"1c220fbe1dec02cb","type":"modbus-flex-write","z":"a0f42263502ff357","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"server":"49e2ee81576ac7a9","emptyMsgOnFail":true,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":670,"y":180,"wires":[["acee63082c9d2dd6"],[]]},{"id":"b718906678cf1561","type":"function","z":"a0f42263502ff357","name":"Write 30051+ on Unit 1 FC16","func":"msg.payload = { value: msg.payload, 'fc': 16, 'unitid': 4, 'address': 30051 , 'quantity': 4 };\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":180,"wires":[["1c220fbe1dec02cb"]]},{"id":"e1c430ddbd6928ad","type":"inject","z":"a0f42263502ff357","name":"Write multiple 30051+","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"15","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"[0,8001,0,9165]","payloadType":"json","x":190,"y":180,"wires":[["b718906678cf1561"]]},{"id":"acee63082c9d2dd6","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":870,"y":180,"wires":[]},{"id":"79f710dbeb5c3dec","type":"modbus-flex-write","z":"a0f42263502ff357","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"server":"49e2ee81576ac7a9","emptyMsgOnFail":true,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":670,"y":220,"wires":[["960ad3c8445a0ad3"],[]]},{"id":"a161ac11ee7139fb","type":"function","z":"a0f42263502ff357","name":"Write 30057+ on Unit 1 FC16","func":"msg.payload = { value: msg.payload, 'fc': 16, 'unitid': 4, 'address': 30057 , 'quantity': 2 };\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":220,"wires":[["79f710dbeb5c3dec"]]},{"id":"3f16b8c374bba31a","type":"inject","z":"a0f42263502ff357","name":"Write multiple 30057+","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"15","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"[32507,20181]","payloadType":"json","x":190,"y":220,"wires":[["a161ac11ee7139fb"]]},{"id":"960ad3c8445a0ad3","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":870,"y":240,"wires":[]},{"id":"6e7efbfa83712ff1","type":"modbus-server","z":"a0f42263502ff357","name":"SMA Inverter Modbus","logEnabled":false,"hostname":"192.168.1.172","serverPort":"1502","responseDelay":100,"delayUnit":"ms","coilsBufferSize":"100","holdingBufferSize":"20000","inputBufferSize":10000,"discreteBufferSize":10000,"showErrors":true,"x":160,"y":80,"wires":[[],[],[],[],[]]},{"id":"61abaa351f57e75c","type":"inject","z":"a0f42263502ff357","name":"Fault code","props":[{"p":"payload"}],"repeat":"15","crontab":"","once":true,"onceDelay":"0.5","topic":"","payload":"307","payloadType":"num","x":150,"y":260,"wires":[[]]},{"id":"8e801be6b9bb50ee","type":"mqtt in","z":"a0f42263502ff357","name":"Solax X1 Boost","topic":"Solax/state","qos":"0","datatype":"auto-detect","broker":"721f5b24eac30a15","nl":false,"rap":true,"rh":0,"inputs":0,"x":160,"y":300,"wires":[["373b56b3fa9c6cf3","ff386a86010281dd","b45744f1854ce3bf","aa334c776347c3bb","957feb922e827cbc","504544441201f0e2","44ece3ef4cec64cd","dfbdcdd55701164c","94933e3bc6c24d8e","feb5a6dd15c932b0","fe0fc0db96e64b02","6b72c0eb68e35d87","fa6aeea8368deaf4"]]},{"id":"373b56b3fa9c6cf3","type":"debug","z":"a0f42263502ff357","name":"debug 1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":440,"y":260,"wires":[]},{"id":"fa8adac2cc496aed","type":"function","z":"a0f42263502ff357","name":"int16 to int32","func":"function int32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction int32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction dataToBuffer(value) {\n    var mbbuffer = new Uint16Array(1);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setUint16(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    return [uint16Value1];\n}\n\nvar value = msg.payload;\nvar mbbuffer = int32InvToBuffer(value);\n\nvar modbusfx = {\n    payload: {\n        'value': [\n            mbbuffer[0],\n            mbbuffer[1],\n        ],\n        'fc': 16,\n        'unitid': 1,\n        'address': 1002,\n        'quantity': 2\n    }\n}\n\nmsg.payload = modbusfx.payload\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":340,"wires":[["cbc1d0edbe8c31d2"]]},{"id":"cbc1d0edbe8c31d2","type":"modbus-write","z":"a0f42263502ff357","name":"Power Spot","showStatusActivities":true,"showErrors":true,"showWarnings":true,"unitid":"4","dataType":"MHoldingRegisters","adr":"30775","quantity":"2","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":730,"y":340,"wires":[[],["8ba68b96ae1690db"]]},{"id":"8ba68b96ae1690db","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":870,"y":380,"wires":[]},{"id":"c534f5ef70abccc9","type":"watt2kwh","z":"a0f42263502ff357","format":"kwh","maximum":"1","maximumunit":"hours","name":"Daily Yield","x":170,"y":460,"wires":[["fd2f7f041bce616d"]]},{"id":"fd2f7f041bce616d","type":"function","z":"a0f42263502ff357","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,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":460,"wires":[["46896e1fb4f08f94"]]},{"id":"3c4595fb9ecaa040","type":"inject","z":"a0f42263502ff357","name":"reset","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"55 23 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"reset","payloadType":"str","x":170,"y":500,"wires":[["fd2f7f041bce616d"]]},{"id":"895d80e7ac57cf2b","type":"function","z":"a0f42263502ff357","name":"int16 to int32","func":"function int32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction int32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction dataToBuffer(value) {\n    var mbbuffer = new Uint16Array(1);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setUint16(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    return [uint16Value1];\n}\n\nvar value = msg.payload;\nvar mbbuffer = int32InvToBuffer(value);\n\nvar modbusfx = {\n    payload: {\n        'value': [\n            mbbuffer[0],\n            mbbuffer[1],\n        ],\n        'fc': 16,\n        'unitid': 1,\n        'address': 1002,\n        'quantity': 2\n    }\n}\n\nmsg.payload = modbusfx.payload\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":670,"y":460,"wires":[["d4ed77c475ef09d4"]]},{"id":"d4ed77c475ef09d4","type":"modbus-write","z":"a0f42263502ff357","name":"Daily Yield","showStatusActivities":true,"showErrors":false,"showWarnings":true,"unitid":"4","dataType":"MHoldingRegisters","adr":"30529","quantity":"2","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":850,"y":460,"wires":[[],["aa5b8a20c257cd64"]]},{"id":"aa5b8a20c257cd64","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":870,"y":520,"wires":[]},{"id":"46896e1fb4f08f94","type":"calculator","z":"a0f42263502ff357","name":"","inputMsgField":"payload","outputMsgField":"payload","operation":"mult","constant":"1000","round":true,"truncate":false,"decimals":0,"decimals2":0,"x":520,"y":460,"wires":[["895d80e7ac57cf2b","975d0d11916230ca"]]},{"id":"02177f66ca2eb2f0","type":"function","z":"a0f42263502ff357","name":"int16 to int32","func":"function int32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction int32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction dataToBuffer(value) {\n    var mbbuffer = new Uint16Array(1);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setUint16(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    return [uint16Value1];\n}\n\nvar value = msg.payload;\nvar mbbuffer = int32InvToBuffer(value);\n\nvar modbusfx = {\n    payload: {\n        'value': [\n            mbbuffer[0],\n            mbbuffer[1],\n        ],\n        'fc': 16,\n        'unitid': 1,\n        'address': 1002,\n        'quantity': 2\n    }\n}\n\nmsg.payload = modbusfx.payload\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":580,"wires":[["fcc8c82f25b9e9ef"]]},{"id":"fcc8c82f25b9e9ef","type":"modbus-write","z":"a0f42263502ff357","name":"Temperature","showStatusActivities":true,"showErrors":true,"showWarnings":true,"unitid":"4","dataType":"MHoldingRegisters","adr":"30953","quantity":"2","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":690,"y":580,"wires":[[],["2dbae7f95794bb1e"]]},{"id":"2dbae7f95794bb1e","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":870,"y":580,"wires":[]},{"id":"ff386a86010281dd","type":"change","z":"a0f42263502ff357","name":"Internal Temp","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.Temperature","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":220,"y":580,"wires":[["5b017f9f1f1ab1e2"]]},{"id":"5b017f9f1f1ab1e2","type":"calculator","z":"a0f42263502ff357","name":"","inputMsgField":"payload","outputMsgField":"payload","operation":"mult","constant":"10","round":false,"truncate":true,"decimals":0,"decimals2":0,"x":380,"y":580,"wires":[["02177f66ca2eb2f0"]]},{"id":"b45744f1854ce3bf","type":"change","z":"a0f42263502ff357","name":"Grid current","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.GridACurrent","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":150,"y":620,"wires":[["6b6657720a687654"]]},{"id":"6b6657720a687654","type":"function","z":"a0f42263502ff357","name":"int16 to int32","func":"function int32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction int32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction dataToBuffer(value) {\n    var mbbuffer = new Uint16Array(1);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setUint16(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    return [uint16Value1];\n}\n\nvar value = msg.payload;\nvar mbbuffer = int32InvToBuffer(value);\n\nvar modbusfx = {\n    payload: {\n        'value': [\n            mbbuffer[0],\n            mbbuffer[1],\n        ],\n        'fc': 16,\n        'unitid': 1,\n        'address': 1002,\n        'quantity': 2\n    }\n}\n\nmsg.payload = modbusfx.payload\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":640,"wires":[["e6c747a0d7cc2329"]]},{"id":"e6c747a0d7cc2329","type":"modbus-write","z":"a0f42263502ff357","name":"AC Current","showStatusActivities":true,"showErrors":true,"showWarnings":true,"unitid":"4","dataType":"MHoldingRegisters","adr":"30977","quantity":"2","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":590,"y":640,"wires":[[],["807651795ca6f267"]]},{"id":"807651795ca6f267","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":890,"y":640,"wires":[]},{"id":"aa334c776347c3bb","type":"change","z":"a0f42263502ff357","name":"DC Current 1","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.Idc1","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":150,"y":680,"wires":[["dfe88ed1f5e16df6"]]},{"id":"9c47a94e6dc94059","type":"function","z":"a0f42263502ff357","name":"int16 to int32","func":"function int32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction int32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction dataToBuffer(value) {\n    var mbbuffer = new Uint16Array(1);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setUint16(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    return [uint16Value1];\n}\n\nvar value = msg.payload;\nvar mbbuffer = int32InvToBuffer(value);\n\nvar modbusfx = {\n    payload: {\n        'value': [\n            mbbuffer[0],\n            mbbuffer[1],\n        ],\n        'fc': 16,\n        'unitid': 1,\n        'address': 1002,\n        'quantity': 2\n    }\n}\n\nmsg.payload = modbusfx.payload\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":630,"y":700,"wires":[["fbd0ca8f15222bcc"]]},{"id":"fbd0ca8f15222bcc","type":"modbus-write","z":"a0f42263502ff357","name":"DC Current","showStatusActivities":true,"showErrors":true,"showWarnings":true,"unitid":"4","dataType":"MHoldingRegisters","adr":"30769","quantity":"2","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":790,"y":700,"wires":[[],["200b19b98e20966f"]]},{"id":"200b19b98e20966f","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":970,"y":700,"wires":[]},{"id":"504544441201f0e2","type":"change","z":"a0f42263502ff357","name":"DC Voltage 1","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.Vdc1","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":150,"y":760,"wires":[["1d057acc6db74b78"]]},{"id":"ec825a0b98716fbb","type":"function","z":"a0f42263502ff357","name":"int16 to int32","func":"function int32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction int32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction dataToBuffer(value) {\n    var mbbuffer = new Uint16Array(1);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setUint16(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    return [uint16Value1];\n}\n\nvar value = msg.payload;\nvar mbbuffer = int32InvToBuffer(value);\n\nvar modbusfx = {\n    payload: {\n        'value': [\n            mbbuffer[0],\n            mbbuffer[1],\n        ],\n        'fc': 16,\n        'unitid': 1,\n        'address': 1002,\n        'quantity': 2\n    }\n}\n\nmsg.payload = modbusfx.payload\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":800,"wires":[["70fa21ec63922d66"]]},{"id":"70fa21ec63922d66","type":"modbus-write","z":"a0f42263502ff357","name":"DC Voltage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"unitid":"4","dataType":"MHoldingRegisters","adr":"30771","quantity":"2","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":790,"y":760,"wires":[[],["02812ae122f550c1"]]},{"id":"02812ae122f550c1","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":970,"y":760,"wires":[]},{"id":"dfbdcdd55701164c","type":"change","z":"a0f42263502ff357","name":"DC Power 1","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.PowerDc1","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":150,"y":840,"wires":[["2bd329b36505851f"]]},{"id":"3c544d38e722b311","type":"function","z":"a0f42263502ff357","name":"int16 to int32","func":"function int32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction int32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction dataToBuffer(value) {\n    var mbbuffer = new Uint16Array(1);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setUint16(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    return [uint16Value1];\n}\n\nvar value = msg.payload;\nvar mbbuffer = int32InvToBuffer(value);\n\nvar modbusfx = {\n    payload: {\n        'value': [\n            mbbuffer[0],\n            mbbuffer[1],\n        ],\n        'fc': 16,\n        'unitid': 1,\n        'address': 1002,\n        'quantity': 2\n    }\n}\n\nmsg.payload = modbusfx.payload\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":860,"wires":[["b5eba1939ff2a6d1"]]},{"id":"b5eba1939ff2a6d1","type":"modbus-write","z":"a0f42263502ff357","name":"DC Voltage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"unitid":"4","dataType":"MHoldingRegisters","adr":"30773","quantity":"2","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":710,"y":860,"wires":[[],["9c3dbe8b29635cce"]]},{"id":"9c3dbe8b29635cce","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":890,"y":860,"wires":[]},{"id":"957feb922e827cbc","type":"change","z":"a0f42263502ff357","name":"DC Current 2","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.Idc2","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":150,"y":720,"wires":[["dfe88ed1f5e16df6"]]},{"id":"44ece3ef4cec64cd","type":"change","z":"a0f42263502ff357","name":"DC Voltage 2","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.Vdc2","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":150,"y":800,"wires":[["1d057acc6db74b78"]]},{"id":"94933e3bc6c24d8e","type":"change","z":"a0f42263502ff357","name":"DC Power 2","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.PowerDc2","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":150,"y":880,"wires":[["2bd329b36505851f"]]},{"id":"dfe88ed1f5e16df6","type":"join","z":"a0f42263502ff357","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":290,"y":700,"wires":[["56bffcb81d72539e"]]},{"id":"56bffcb81d72539e","type":"calculator","z":"a0f42263502ff357","name":"","inputMsgField":"payload","outputMsgField":"payload","operation":"sum","constant":"","round":false,"truncate":false,"decimals":0,"decimals2":0,"x":410,"y":700,"wires":[["c1b2a4907c58878e"]]},{"id":"1d057acc6db74b78","type":"join","z":"a0f42263502ff357","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":290,"y":780,"wires":[["9a85a8a897aa7d94"]]},{"id":"9a85a8a897aa7d94","type":"calculator","z":"a0f42263502ff357","name":"","inputMsgField":"payload","outputMsgField":"payload","operation":"sum","constant":"","round":true,"truncate":false,"decimals":0,"decimals2":0,"x":410,"y":780,"wires":[["71a6076734d148b0"]]},{"id":"2bd329b36505851f","type":"join","z":"a0f42263502ff357","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":290,"y":860,"wires":[["2dac498d24430f0e"]]},{"id":"2dac498d24430f0e","type":"calculator","z":"a0f42263502ff357","name":"","inputMsgField":"payload","outputMsgField":"payload","operation":"sum","constant":"","round":false,"truncate":false,"decimals":0,"decimals2":0,"x":410,"y":860,"wires":[["3c544d38e722b311"]]},{"id":"c1b2a4907c58878e","type":"calculator","z":"a0f42263502ff357","name":"","inputMsgField":"payload","outputMsgField":"payload","operation":"mult","constant":"1000","round":false,"truncate":true,"decimals":0,"decimals2":0,"x":580,"y":740,"wires":[["9c47a94e6dc94059"]]},{"id":"feb5a6dd15c932b0","type":"change","z":"a0f42263502ff357","name":"AC Volts L1","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.GridAVoltage","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":150,"y":920,"wires":[["b4e4a04cbb614581"]]},{"id":"f8c72f18cc0f5c98","type":"function","z":"a0f42263502ff357","name":"int16 to int32","func":"function int32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction int32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction dataToBuffer(value) {\n    var mbbuffer = new Uint16Array(1);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setUint16(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    return [uint16Value1];\n}\n\nvar value = msg.payload;\nvar mbbuffer = int32InvToBuffer(value);\n\nvar modbusfx = {\n    payload: {\n        'value': [\n            mbbuffer[0],\n            mbbuffer[1],\n        ],\n        'fc': 16,\n        'unitid': 1,\n        'address': 1002,\n        'quantity': 2\n    }\n}\n\nmsg.payload = modbusfx.payload\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":920,"wires":[["b8a13db62c2a77af"]]},{"id":"b8a13db62c2a77af","type":"modbus-write","z":"a0f42263502ff357","name":"AC Volts","showStatusActivities":true,"showErrors":true,"showWarnings":true,"unitid":"4","dataType":"MHoldingRegisters","adr":"31253","quantity":"2","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":700,"y":920,"wires":[[],["3a669c9e1122bddd"]]},{"id":"3a669c9e1122bddd","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":890,"y":920,"wires":[]},{"id":"b4e4a04cbb614581","type":"calculator","z":"a0f42263502ff357","name":"","inputMsgField":"payload","outputMsgField":"payload","operation":"mult","constant":"100","round":false,"truncate":true,"decimals":0,"decimals2":0,"x":360,"y":920,"wires":[["f8c72f18cc0f5c98"]]},{"id":"71a6076734d148b0","type":"calculator","z":"a0f42263502ff357","name":"","inputMsgField":"payload","outputMsgField":"payload","operation":"mult","constant":"100","round":false,"truncate":true,"decimals":0,"decimals2":0,"x":560,"y":800,"wires":[["ec825a0b98716fbb"]]},{"id":"fa6aeea8368deaf4","type":"change","z":"a0f42263502ff357","name":"Yield Today ","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.Yield_Today","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":130,"y":380,"wires":[["4a244135ee99ca1e"]]},{"id":"6c4ee24cae8bc47d","type":"function","z":"a0f42263502ff357","name":"int16 to int32","func":"function int32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction int32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setInt32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32ToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    var uint16Value2 = mbbuffer[1];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction float32InvToBuffer(value) {\n    var mbbuffer = new Uint16Array(2);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setFloat32(0, value, true);\n    var uint16Value1 = mbbuffer[1];\n    var uint16Value2 = mbbuffer[0];\n    return [uint16Value1, uint16Value2];\n}\n\nfunction dataToBuffer(value) {\n    var mbbuffer = new Uint16Array(1);\n    var dataView = new DataView(mbbuffer.buffer);\n    dataView.setUint16(0, value, true);\n    var uint16Value1 = mbbuffer[0];\n    return [uint16Value1];\n}\n\nvar value = msg.payload;\nvar mbbuffer = int32InvToBuffer(value);\n\nvar modbusfx = {\n    payload: {\n        'value': [\n            mbbuffer[0],\n            mbbuffer[1],\n        ],\n        'fc': 16,\n        'unitid': 1,\n        'address': 1002,\n        'quantity': 2\n    }\n}\n\nmsg.payload = modbusfx.payload\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":400,"wires":[["668284bf99e9b041"]]},{"id":"668284bf99e9b041","type":"modbus-write","z":"a0f42263502ff357","name":"Daily Yield","showStatusActivities":true,"showErrors":false,"showWarnings":true,"unitid":"4","dataType":"MHoldingRegisters","adr":"30529","quantity":"2","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":690,"y":400,"wires":[[],[]]},{"id":"f7c2147dc254c83c","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":910,"y":420,"wires":[]},{"id":"975d0d11916230ca","type":"debug","z":"a0f42263502ff357","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":540,"y":520,"wires":[]},{"id":"4a244135ee99ca1e","type":"calculator","z":"a0f42263502ff357","name":"","inputMsgField":"payload","outputMsgField":"payload","operation":"mult","constant":"1000","round":true,"truncate":false,"decimals":0,"decimals2":0,"x":340,"y":400,"wires":[["6c4ee24cae8bc47d"]]},{"id":"7ab0da6bf6524938","type":"change","z":"a0f42263502ff357","name":"Inverter condition","rules":[{"t":"change","p":"payload","pt":"msg","from":"2","fromt":"num","to":"307","tot":"num"},{"t":"change","p":"payload","pt":"msg","from":"0","fromt":"num","to":"303","tot":"num"},{"t":"change","p":"payload","pt":"msg","from":"3","fromt":"str","to":"35","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"4","fromt":"str","to":"455","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":980,"wires":[["a542a2b10d975efd","63133a7b88b92b6d"]]},{"id":"a542a2b10d975efd","type":"debug","z":"a0f42263502ff357","name":"debug 3","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":520,"y":1020,"wires":[]},{"id":"fe0fc0db96e64b02","type":"change","z":"a0f42263502ff357","name":"Condition","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.RunMode","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":140,"y":980,"wires":[["7ab0da6bf6524938"]]},{"id":"e044b66c17622b7b","type":"modbus-response","z":"a0f42263502ff357","name":"","registerShowMax":20,"x":890,"y":980,"wires":[]},{"id":"63133a7b88b92b6d","type":"modbus-write","z":"a0f42263502ff357","name":"30202","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"4","dataType":"HoldingRegister","adr":"30202","quantity":"1","server":"49e2ee81576ac7a9","emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"","x":690,"y":980,"wires":[["e044b66c17622b7b"],[]]},{"id":"6b72c0eb68e35d87","type":"change","z":"a0f42263502ff357","name":"AC Power","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.GridAPower","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":320,"wires":[["fa8adac2cc496aed","c534f5ef70abccc9"]]},{"id":"49e2ee81576ac7a9","type":"modbus-client","name":"SMA Modbus ID4","clienttype":"tcp","bufferCommands":false,"stateLogEnabled":true,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.1.172","tcpPort":"1502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"","unit_id":4,"commandDelay":1,"clientTimeout":500,"reconnectOnTimeout":true,"reconnectTimeout":150,"parallelUnitIdsAllowed":true},{"id":"721f5b24eac30a15","type":"mqtt-broker","name":"LePotato","broker":"192.168.1.52","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]

Flow Info

Created 10 months ago
Rating: not yet rated

Owner

Actions

Rate:

Node Types

Core
  • change (x13)
  • debug (x3)
  • function (x12)
  • inject (x4)
  • join (x3)
  • mqtt in (x1)
  • mqtt-broker (x1)
Other
  • calculator (x9)
  • modbus-client (x1)
  • modbus-flex-write (x2)
  • modbus-response (x12)
  • modbus-server (x1)
  • modbus-write (x10)
  • tab (x1)
  • watt2kwh (x1)

Tags

  • Node-Red
  • Flows
  • Solar-Log
  • Solax
  • SMA
  • Modbus
  • Inverter
  • MQTT
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option