Convert Bytes to integer

I have a battery controller that sends UDP packets with the stats on the battery. Using the UDP node I was able to capture the packet but I'm not exactly sure how I would go about converting the Bytes to integers.

Documentation on the packet contents linked below:
https://www.dropbox.com/s/50juimg5axhftsg/UDP-Docs.pdf?dl=0

As the data structure is quite simple a good option is using the node-red-contrib-binary node.

Testing flow

[{"id":"3ef3d95f.231a96","type":"inject","z":"1640e766.742789","name":"Go","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":200,"wires":[["bfc1660d.a162d8"]]},{"id":"bfc1660d.a162d8","type":"function","z":"1640e766.742789","name":"Dataset Buffer","func":"msg.payload =  Buffer.from([0xa2, 0x5c, 0x01, 0x80, 0x02, 0x10, 0x02, 0x10, 0x02, 0x15, 0x95, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x10, 0x02, 0x10, 0x03, 0x01, 0x11, 0x50]);\nreturn msg;","outputs":1,"noerr":0,"x":340,"y":200,"wires":[["2d23bf58.f55db","85f126fb.3e4578"]]},{"id":"2d23bf58.f55db","type":"binary","z":"1640e766.742789","name":"","pattern":"b8 => header, l32 => msg_id, l32 => family_id, l32 => timestamp, b8 => rtr, b8 => priority, b8 => identifier, b8 => len","x":540,"y":200,"wires":[["d5b0fe8e.cf2c4"]]},{"id":"d5b0fe8e.cf2c4","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":690,"y":200,"wires":[]},{"id":"85f126fb.3e4578","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":550,"y":280,"wires":[]}]

You will feed the capture data to the binary node (remove the function node from the testing flow).

@Andrei thanks for giving me a direction, I added the node and connected it to the UDP node, but the output seems to be missing that data. Do I need to modify the pattern on the binary node?

I assumed the data is structured as below (8 fields). If not it will be necessary to change the pattern in the binary node.

Edit: Only now i read the full document. There is indeed a misunderstanding on my side. I will provide another testing flow shortly.

The pattern should be more like below. You will get in the output of the binary node an array of 8 bytes inside msg.payload.data. If I understood correctly these 8 bytes have to be interpreted differently based on the value of msg.payload.msg_id. If this is correct you will need to add additional logic to the flow to further decode those 8 first data bytes.

b64a => data, b32 => msg_id, b32 => family_id, b32 => timestamp, b8 => rtr, b8 => priority, b8 => identifier, b8 => len

Adding a second level of decoding the flow will looks like below (missing to decode the 8 bytes though).

[{"id":"1640e766.742789","type":"tab","label":"node-red-contrib-binary","disabled":false,"info":""},{"id":"3ef3d95f.231a96","type":"inject","z":"1640e766.742789","name":"Go","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":200,"wires":[["bfc1660d.a162d8"]]},{"id":"bfc1660d.a162d8","type":"function","z":"1640e766.742789","name":"Dataset Buffer","func":"msg.payload =  Buffer.from([0xa2, 0x5c, 0x01, 0x80, 0x02, 0x10, 0x02, 0x10, 0x8f, 0x06, 0x00, 0x00, 0x10, 0x02, 0x10, 0x02, 0x10, 0x10, 0x02, 0x10, 0x03, 0x01, 0x11, 0x50]);\nreturn msg;","outputs":1,"noerr":0,"x":340,"y":200,"wires":[["2d23bf58.f55db"]]},{"id":"2d23bf58.f55db","type":"binary","z":"1640e766.742789","name":"","pattern":"b64a => data, l16 => id1,  l16 => id2,b16 => family_id, b32 => timestamp, b8 => rtr, b8 => priority, b8 => identifier, b8 => len","x":540,"y":200,"wires":[["c3c48a3e.60d398","30b187ce.57f6e8"]]},{"id":"d5b0fe8e.cf2c4","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":930,"y":160,"wires":[]},{"id":"c3c48a3e.60d398","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":650,"y":380,"wires":[]},{"id":"30b187ce.57f6e8","type":"switch","z":"1640e766.742789","name":"","property":"payload.id1","propertyType":"msg","rules":[{"t":"eq","v":"0x68f","vt":"num"},{"t":"eq","v":"0x652","vt":"num"},{"t":"eq","v":"0x651","vt":"num"},{"t":"eq","v":"0x650","vt":"num"},{"t":"eq","v":"0x150","vt":"num"}],"checkall":"true","repair":false,"outputs":5,"x":730,"y":200,"wires":[["d5b0fe8e.cf2c4"],["55899ae4.daa184"],["add64986.963e88"],["f608e01c.b8961"],["f29d4f52.94f8e"]]},{"id":"55899ae4.daa184","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":930,"y":200,"wires":[]},{"id":"add64986.963e88","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":930,"y":240,"wires":[]},{"id":"f608e01c.b8961","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":930,"y":280,"wires":[]},{"id":"f29d4f52.94f8e","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":930,"y":320,"wires":[]}]

1 Like

I see what is happening now, the UDP packet itself is a wrapper for another set of bytes, I see in the switch how you're splitting up the messages, so now all I have to do is add another binary node behind the switch to decode the bytes of each message?

For example message 0x652 is the max/min allowed battery temps (which on the controller are set to 55 and 5 respectively), so once I decode the screenshot below I should end up with an array of [55,5], right?

Right, the data is wrapped in a structure (CAN ?). I also thought you would need a second binary node but having a close look on the data this may not be needed. It is easy to decode the 8 bytes with just basic math or sometimes just using the byte value without any change. Below flow will decode the SOC (state of Charge) that is contained in a msg of type 0x650. In such case it will just display the value byte[0].

Note: I corrected the endianness of previous flow. Use flow below as reference:

[{"id":"1640e766.742789","type":"tab","label":"node-red-contrib-binary","disabled":false,"info":""},{"id":"3ef3d95f.231a96","type":"inject","z":"1640e766.742789","name":"Go","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":200,"wires":[["bfc1660d.a162d8"]]},{"id":"bfc1660d.a162d8","type":"function","z":"1640e766.742789","name":"Dataset Buffer","func":"msg.payload =  Buffer.from([0x9b, 0x5c, 0x01, 0x80, 0x02, 0x10, 0x02, 0x10, 0x50, 0x06, 0x00, 0x00, 0x10, 0x02, 0x10, 0x02, 0x10, 0x10, 0x02, 0x10, 0x03, 0x01, 0x11, 0x50]);\nreturn msg;","outputs":1,"noerr":0,"x":340,"y":200,"wires":[["2d23bf58.f55db"]]},{"id":"2d23bf58.f55db","type":"binary","z":"1640e766.742789","name":"","pattern":"l64a => data, l16 => id1,  l16 => id2,b16 => family_id, b32 => timestamp, b8 => rtr, b8 => priority, b8 => identifier, b8 => len","x":540,"y":200,"wires":[["c3c48a3e.60d398","30b187ce.57f6e8"]]},{"id":"d5b0fe8e.cf2c4","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":930,"y":160,"wires":[]},{"id":"c3c48a3e.60d398","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":610,"y":380,"wires":[]},{"id":"30b187ce.57f6e8","type":"switch","z":"1640e766.742789","name":"","property":"payload.id1","propertyType":"msg","rules":[{"t":"eq","v":"0x68f","vt":"num"},{"t":"eq","v":"0x652","vt":"num"},{"t":"eq","v":"0x651","vt":"num"},{"t":"eq","v":"0x650","vt":"num"},{"t":"eq","v":"0x150","vt":"num"}],"checkall":"true","repair":false,"outputs":5,"x":730,"y":200,"wires":[["d5b0fe8e.cf2c4"],["55899ae4.daa184"],["add64986.963e88"],["f608e01c.b8961"],["f29d4f52.94f8e"]]},{"id":"55899ae4.daa184","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":930,"y":200,"wires":[]},{"id":"add64986.963e88","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":930,"y":240,"wires":[]},{"id":"f608e01c.b8961","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data[0]","targetType":"msg","x":940,"y":280,"wires":[]},{"id":"f29d4f52.94f8e","type":"debug","z":"1640e766.742789","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.data","targetType":"msg","x":930,"y":320,"wires":[]}]

Ok so that makes perfect sense on message 0x650 since it's a 1 byte message, according to the docs take the number and divide by 2 which should give you the SOC and it looks to match exactly to the controller. I also noticed that on message 0x652 [4] and [6] corresponds to the values on the controller (after doing some math).

However, (forgive me here, I'm a novice to the whole byte conversion) on a message like 0x150 which is 8 bytes, according what I just mentioned above and the docs [0] should be the amperage going through the pack, which doesn't seem to be correct when looking at the screenshot below (should be in the 200 range).

So either I'm doing something wrong or my logic on how to extract the data out of the bytes is incorrect.

Perhaps this particular value is formed by the least significant part of byte 0 + most significant part of byte 1 ?

You will need to test this assumption with several measuments.

44 = 0010 1100
255 = 1111 1111

207 = 1100 1111

Got it, that makes sense now. After a bit of Googling looking for a method (JS is not my strongest) I was able to come up if a function to convert the data.

(The battery is charging hence why it's negative)

@Andrei thank you very much for the help

2 Likes

I have the same battery controller and was attempting to parse the same UDP packet and came to the forum for advice and found your thread!!! Did you ever finish parsing all the different messages? If so any chance I could get a copy of your flow?

Thanks!

Sorry I missed your reply.

Here's the flow. It's a bit messy but it'll get you what you need. If you want to get all incoming packets just remove the message limiter, I added a limiter because it was bogging down node when I tried to edit that flow.

Let me know how it works out for you.

[{"id":"3f2452.f6cc8bae","type":"tab","label":"Battery Dashboard","disabled":false,"info":""},{"id":"67f65e3a.33148","type":"ui_gauge","z":"3f2452.f6cc8bae","name":"SOC","group":"d430f344.48b8d","order":7,"width":0,"height":0,"gtype":"donut","title":"Charge Level","label":"%","format":"{{value}}","min":0,"max":"100","colors":["#c10000","#ff8000","#00b700"],"seg1":"25","seg2":"60","x":1235.5,"y":194,"wires":[]},{"id":"922054fc.807308","type":"ui_gauge","z":"3f2452.f6cc8bae","name":"","group":"14078cbe.6d0373","order":3,"width":"6","height":"3","gtype":"donut","title":"Battery Power","label":"kWh","format":"{{value / 1000 | number:2}}","min":"0","max":"12000","colors":["#00b500","#ff8000","#ca3838"],"seg1":"6000","seg2":"8000","x":1266.5,"y":338.00001525878906,"wires":[]},{"id":"9b6774dd.c6a228","type":"ui_gauge","z":"3f2452.f6cc8bae","name":"","group":"e8c963b3.9ec38","order":1,"width":0,"height":0,"gtype":"gage","title":"Battery Voltage","label":"V","format":"{{value}}","min":"36","max":"50.4","colors":["#c10000","#ff8000","#00b500"],"seg1":"38","seg2":"43.2","x":1420.5,"y":488.0000104904175,"wires":[]},{"id":"2039ae53.dcdc32","type":"ui_gauge","z":"3f2452.f6cc8bae","name":"","group":"aa20a6d4.8551b8","order":1,"width":0,"height":0,"gtype":"gage","title":"Battery Temp","label":"C","format":"{{value}}","min":0,"max":"60","colors":["#00b500","#ff8000","#ca3838"],"seg1":"15","seg2":"45","x":1409.5,"y":521.0000104904175,"wires":[]},{"id":"c08ab6f7.e7d8f8","type":"ui_text","z":"3f2452.f6cc8bae","group":"14078cbe.6d0373","order":1,"width":0,"height":0,"name":"Battery State","label":"Battery State","format":"{{msg.payload}}","layout":"row-spread","x":1252.5728759765625,"y":559.708384513855,"wires":[]},{"id":"133d0e2a.317822","type":"binary","z":"3f2452.f6cc8bae","name":"","pattern":"l64a => data, l16 => id1,  l16 => id2,b16 => family_id, b32 => timestamp, b8 => rtr, b8 => priority, b8 => identifier, b8 => len","x":230,"y":240,"wires":[["5a2078e9.33ebf8","2bce82ba.37f9ee"]]},{"id":"5a2078e9.33ebf8","type":"switch","z":"3f2452.f6cc8bae","name":"","property":"payload.id1","propertyType":"msg","rules":[{"t":"eq","v":"0x651","vt":"num"},{"t":"eq","v":"0x650","vt":"num"},{"t":"eq","v":"0x150","vt":"num"},{"t":"eq","v":"0x68F","vt":"str"},{"t":"eq","v":"0x652","vt":"str"}],"checkall":"true","repair":false,"outputs":5,"x":490,"y":260,"wires":[["ff095083.4420f"],["a72f94fb.d11018"],["49a3f8ef.28d9a8"],["259ab6d8.20b61a"],["ae7442a8.1586c"]]},{"id":"84ec979c.5e9ee8","type":"debug","z":"3f2452.f6cc8bae","name":"lowCellV, highCellV, avgCellV","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1304.9999389648438,"y":127.00003051757812,"wires":[]},{"id":"c0b6dc3d.34013","type":"debug","z":"3f2452.f6cc8bae","name":"SOC","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1235.9999389648438,"y":161,"wires":[]},{"id":"fe2c0574.eead88","type":"udp in","z":"3f2452.f6cc8bae","name":"","iface":"","port":"6650","ipv":"udp4","multicast":"false","group":"","datatype":"buffer","x":100.017333984375,"y":99.01039123535156,"wires":[["9e05b9b5.ffa9a8","7ca6575d.ef73d8"]]},{"id":"49a3f8ef.28d9a8","type":"function","z":"3f2452.f6cc8bae","name":"Convert","func":"var amps = [msg.payload.data[0],msg.payload.data[1]];\nvar ampsBuff = new Buffer(amps);\namps = ampsBuff.readInt16LE(0)\nglobal.set('globalAmps', amps);\n\nvar volts = [msg.payload.data[2],msg.payload.data[3]];\nvar voltsBuff = new Buffer(volts);\nvolts = voltsBuff.readInt16LE(0) / 10\nglobal.set('globalVolts', volts);\n\nvar amph = [msg.payload.data[4],msg.payload.data[5]];\nvar amphBuff = new Buffer(amph);\namph = (amphBuff.readInt16LE(0) / 10) * -1\nglobal.set('globalAmph', amph);\n\nvar maxTemp = msg.payload.data[6]\nglobal.set('globalMaxTemp', maxTemp);\n\nvar minTemp = msg.payload.data[7]\nglobal.set('globalMinTemp', minTemp);\n\nif (ampsBuff.readInt16LE(0) < 0) {\n    packState = \"CHARGING\"\n} else if (ampsBuff.readInt16LE(0) > 0) {\n    packState = \"DISCHARGING\"\n} else {\n    packState = \"IDLE\"\n}\nglobal.set('globalPackState', packState);\n\nkWatts = volts * amps\nglobal.set('globalkWatts', kWatts);\n\nvar msg1 = { payload:kWatts };\nvar msg2 = { payload:volts };\nvar msg3 = { payload:amph};\nvar msg4 = { payload:maxTemp };\nvar msg5 = { payload:minTemp };\nvar msg6 = { payload:packState };\nvar msg7 = { payload:amps };\n\nreturn [ msg1, msg2, msg3, msg4, msg5, msg6, msg7 ];","outputs":7,"noerr":0,"x":888.576416015625,"y":332.56251525878906,"wires":[["f765d881.dd97b8","922054fc.807308","959dfbd0.98e0c8"],["1a5e8085.d672ff"],[],["6d21dda1.340ce4"],[],["c08ab6f7.e7d8f8"],["59e4e87a.ff6908","2d431bd5.53fb84"]]},{"id":"f765d881.dd97b8","type":"debug","z":"3f2452.f6cc8bae","name":"A, V, AH, MaxT, MinT","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1287.5763969421387,"y":305.0069637298584,"wires":[]},{"id":"8b4f086b.879fa8","type":"function","z":"3f2452.f6cc8bae","name":"Convert","func":"global.set('globalSOC', msg.payload.data[0] / 2);\nmsg.payload = global.get('globalSOC');\n\nreturn  msg","outputs":1,"noerr":0,"x":881.5797729492188,"y":197.68060302734375,"wires":[["c0b6dc3d.34013","67f65e3a.33148","96e48ddf.77abb","5c78422a.c2ccac"]]},{"id":"f22cf11c.1a129","type":"function","z":"3f2452.f6cc8bae","name":"Convert","func":"var avgCellVolts = [msg.payload.data[4],msg.payload.data[5]];\nvar avgCellVoltsBuff = new Buffer(avgCellVolts);\nglobal.set('globalAvgCellVolts', avgCellVoltsBuff.readInt16LE(0) / 1000);\n\nvar lowCellVolts = [msg.payload.data[0],msg.payload.data[1]];\nvar lowCellVoltsBuff = new Buffer(lowCellVolts);\nglobal.set('globalLowCellVolts', lowCellVoltsBuff.readInt16LE(0) / 1000);\n\nvar highCellVolts = [msg.payload.data[2],msg.payload.data[3]];\nvar highCellVoltsBuff = new Buffer(highCellVolts);\nglobal.set('globalHighCellVolts', highCellVoltsBuff.readInt16LE(0) / 1000);\n\nvar msg1 = {topic:\"Avg Cell\",   payload:global.get('globalAvgCellVolts')};\nvar msg2 = {topic:\"Low Cell\",   payload:global.get('globalLowCellVolts')};\nvar msg3 = {topic:\"High Cell\",  payload:global.get('globalHighCellVolts')};\nvar msg4 = {payload:\"High: <font color=Lime >\" + msg3.payload + \n                    \"</font> Avg: <font color=Lime >\" +  msg1.payload + \n                    \"</font> Low: <font color=Lime >\" + msg2.payload + \"</font>\"\n    };\nreturn [msg1, msg2, msg3, msg4];","outputs":5,"noerr":0,"x":880,"y":140,"wires":[["84ec979c.5e9ee8","15282e2d.aac1c2"],[],["8b31d624.a81828"],["763fdbeb.7ccc84"],[]]},{"id":"96e48ddf.77abb","type":"ui_chart","z":"3f2452.f6cc8bae","name":"SOC","group":"d430f344.48b8d","order":10,"width":0,"height":0,"label":"","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":"1","removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":1236.5,"y":228,"wires":[[]]},{"id":"59e4e87a.ff6908","type":"ui_text","z":"3f2452.f6cc8bae","group":"14078cbe.6d0373","order":2,"width":0,"height":0,"name":"Amps","label":"Current","format":"{{msg.payload}}A","layout":"row-spread","x":1231.5,"y":593,"wires":[]},{"id":"5a13bd2a.cd6a74","type":"function","z":"3f2452.f6cc8bae","name":"Convert","func":"var moduleNumber = msg.payload.data[0]\n\nvar cell1Volts = ((msg.payload.data[2]) + 200) / 100\nvar cell2Volts = ((msg.payload.data[3]) + 200) / 100\nvar cell3Volts = ((msg.payload.data[4]) + 200) / 100\nvar cell4Volts = ((msg.payload.data[5]) + 200) / 100\nvar cell5Volts = ((msg.payload.data[6]) + 200) / 100\nvar cell6Volts = ((msg.payload.data[7]) + 200) / 100\n\nmsg.totalModules = msg.payload.data[1]\n\n\nvar msg1 = { label: \"Module \" + moduleNumber + \" Cell 1\" , payload:cell1Volts };\nvar msg2 = { label: \"Module \" + moduleNumber + \" Cell 2\" , payload:cell2Volts };\nvar msg3 = { label: \"Module \" + moduleNumber + \" Cell 3\" , payload:cell3Volts };\nvar msg4 = { label: \"Module \" + moduleNumber + \" Cell 4\" , payload:cell4Volts };\nvar msg5 = { label: \"Module \" + moduleNumber + \" Cell 5\" , payload:cell5Volts };\nvar msg6 = { label: \"Module \" + moduleNumber + \" Cell 6\" , payload:cell5Volts };\n\nglobal.set('globalModule', {\n                            Module:moduleNumber, \n                            Cell1:cell1Volts,\n                            Cell2:cell2Volts,\n                            Cell3:cell3Volts,\n                            Cell4:cell4Volts,\n                            Cell5:cell5Volts,\n                            Cell6:cell6Volts\n    }\n)\n\nreturn [msg1, msg2, msg3, msg4, msg5, msg6];","outputs":6,"noerr":0,"x":889,"y":450,"wires":[["d50b95ae.247688","9b322c28.b953f"],["d50b95ae.247688","9b322c28.b953f"],["d50b95ae.247688","9b322c28.b953f"],["d50b95ae.247688","9b322c28.b953f"],["d50b95ae.247688","9b322c28.b953f"],["d50b95ae.247688","9b322c28.b953f"]]},{"id":"d50b95ae.247688","type":"ui_chart","z":"3f2452.f6cc8bae","name":"Cell Voltages","group":"57d0640f.9d725c","order":2,"width":"7","height":"6","label":"","chartType":"bar","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"3.0","ymax":"4.2","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":true,"colors":["#00ff00","#00ff00","#00ff00","#00ff00","#00ff00","#008000","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":1248.5,"y":660,"wires":[[]]},{"id":"9b322c28.b953f","type":"debug","z":"3f2452.f6cc8bae","name":"Mod#, CellVolts, TotalMod#","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1298.5,"y":627,"wires":[]},{"id":"259ab6d8.20b61a","type":"delay","z":"3f2452.f6cc8bae","name":"","pauseType":"rate","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":710,"y":400,"wires":[["5a13bd2a.cd6a74"]]},{"id":"ff095083.4420f","type":"delay","z":"3f2452.f6cc8bae","name":"","pauseType":"rate","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":702.5,"y":175,"wires":[["f22cf11c.1a129"]]},{"id":"a72f94fb.d11018","type":"delay","z":"3f2452.f6cc8bae","name":"","pauseType":"rate","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":699.5,"y":209,"wires":[["8b4f086b.879fa8"]]},{"id":"1a5e8085.d672ff","type":"delay","z":"3f2452.f6cc8bae","name":"","pauseType":"rate","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":1255,"y":487,"wires":[["9b6774dd.c6a228"]]},{"id":"6d21dda1.340ce4","type":"delay","z":"3f2452.f6cc8bae","name":"","pauseType":"rate","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":1255,"y":520,"wires":[["2039ae53.dcdc32"]]},{"id":"2bce82ba.37f9ee","type":"msg-speed","z":"3f2452.f6cc8bae","name":"","frequency":"sec","estimation":false,"ignore":false,"x":250,"y":340,"wires":[["62b94649.49bb08","c8273444.919e38"],[]]},{"id":"62b94649.49bb08","type":"ui_text","z":"3f2452.f6cc8bae","group":"d430f344.48b8d","order":11,"width":0,"height":0,"name":"","label":"UDP Packets Processed","format":"{{msg.payload}} / Second","layout":"row-spread","x":230,"y":420,"wires":[]},{"id":"18b30e4d.cb77a2","type":"ui_text","z":"3f2452.f6cc8bae","group":"d430f344.48b8d","order":12,"width":0,"height":0,"name":"","label":"UDP Packets Received","format":"{{msg.payload}} / Second","layout":"row-spread","x":523,"y":60,"wires":[]},{"id":"9e05b9b5.ffa9a8","type":"Message Counter","z":"3f2452.f6cc8bae","name":"","units":"seconds","interval":1,"alignToClock":true,"generator":"internal","x":298,"y":60,"wires":[["18b30e4d.cb77a2"],[]]},{"id":"9be7a03b.06c1d","type":"ui_button","z":"3f2452.f6cc8bae","name":"","group":"d430f344.48b8d","order":1,"width":"6","height":"1","passthru":false,"label":"Clear Dashboards","tooltip":"","color":"","bgcolor":"","icon":"clear","payload":"[]","payloadType":"json","topic":"","x":865.5,"y":521,"wires":[["67f65e3a.33148","96e48ddf.77abb","c08ab6f7.e7d8f8","59e4e87a.ff6908","d50b95ae.247688","9b6774dd.c6a228","2039ae53.dcdc32","c8b7d843.4f4908"]]},{"id":"7ca6575d.ef73d8","type":"delay","z":"3f2452.f6cc8bae","name":"","pauseType":"rate","timeout":"10","timeoutUnits":"seconds","rate":"20","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":180,"y":160,"wires":[["133d0e2a.317822"]]},{"id":"959dfbd0.98e0c8","type":"function","z":"3f2452.f6cc8bae","name":"prepare","func":"var last = context.get('last') || 'under'\nvar threshold = 0\nvar undermessage = {topic:'Charging',payload:null}\nvar overmessage = {topic:'Discharging',payload:null}\nvar unsentmessage = null\n\nif(msg.payload > threshold){\n    if(last == 'under'){\n        undermessage.payload = threshold\n        overmessage.payload = threshold\n        unsentmessage = msg\n    }\n    else{\n        overmessage.payload = msg.payload\n    }\n    last = 'over'\n}\nelse{\n    if(last == 'over'){\n        overmessage.payload = threshold\n        undermessage.payload = threshold\n        unsentmessage = msg\n    }\n    else{\n        undermessage.payload = msg.payload\n    }\n    last = 'under'\n}\ncontext.set('last',last)\n\nreturn [[overmessage,undermessage],unsentmessage]","outputs":2,"noerr":0,"x":1244,"y":372,"wires":[["c8b7d843.4f4908"],["4bf1c42e.6ba06c"]]},{"id":"c8b7d843.4f4908","type":"ui_chart","z":"3f2452.f6cc8bae","name":"Battery Power","group":"14078cbe.6d0373","order":4,"width":0,"height":0,"label":"","chartType":"line","legend":"true","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":"5","removeOlderPoints":"","removeOlderUnit":"60","cutout":0,"useOneColor":false,"colors":["#ff0000","#00ec00","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":1460,"y":366,"wires":[[]]},{"id":"4bf1c42e.6ba06c","type":"delay","z":"3f2452.f6cc8bae","name":"","pauseType":"delay","timeout":"20","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1250,"y":443,"wires":[["959dfbd0.98e0c8"]]},{"id":"763fdbeb.7ccc84","type":"ui_text","z":"3f2452.f6cc8bae","group":"57d0640f.9d725c","order":1,"width":0,"height":0,"name":"Avg/Low/High Cells","label":"","format":"{{msg.payload}}","layout":"row-center","x":1270,"y":94,"wires":[]},{"id":"2d431bd5.53fb84","type":"link out","z":"3f2452.f6cc8bae","name":"Time Remaining TX","links":["9b5ef2e2.80e47"],"x":1635,"y":380,"wires":[]},{"id":"c8273444.919e38","type":"function","z":"3f2452.f6cc8bae","name":"Set Global","func":"global.set('globalPacketsRX', msg.payload);","outputs":1,"noerr":0,"x":470,"y":340,"wires":[[]]},{"id":"384ce0a1.a16f","type":"inject","z":"3f2452.f6cc8bae","name":"","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":390,"y":480,"wires":[["c8273444.919e38"]]},{"id":"f1336902.851ec8","type":"function","z":"3f2452.f6cc8bae","name":"Convert","func":"var LowVCut = [msg.payload.data[6],msg.payload.data[7]];\nvar LowVCutBuff = Buffer(LowVCut);\nglobal.set('globalLowVCut', LowVCutBuff.readInt16LE(0)/10);\n\nvar HighVCut = [msg.payload.data[4],msg.payload.data[5]];\nvar HighVCutBuff = Buffer(HighVCut);\nglobal.set('globalHighVCut', HighVCutBuff.readInt16LE(0)/10);\n\n//node.status({text:(global.get('globalLowVCut')+.02) + \" < \" + global.get('globalLowCellVolts')});","outputs":1,"noerr":0,"x":890,"y":560,"wires":[["478b01da.77b34"]]},{"id":"478b01da.77b34","type":"debug","z":"3f2452.f6cc8bae","name":"High/Low Cell Volt Cutoff","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1290,"y":700,"wires":[]},{"id":"ae7442a8.1586c","type":"delay","z":"3f2452.f6cc8bae","name":"","pauseType":"rate","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":690,"y":560,"wires":[["f1336902.851ec8"]]},{"id":"8b31d624.a81828","type":"link out","z":"3f2452.f6cc8bae","name":"High Cell TX","links":["bb227778.079258"],"x":1195,"y":20,"wires":[]},{"id":"15282e2d.aac1c2","type":"link out","z":"3f2452.f6cc8bae","name":"AvgCell TX","links":["2b85036b.725dec"],"x":1195,"y":60,"wires":[]},{"id":"5c78422a.c2ccac","type":"link out","z":"3f2452.f6cc8bae","name":"SOC TX","links":["c4c46af3.d59978"],"x":975,"y":220,"wires":[]},{"id":"d430f344.48b8d","type":"ui_group","z":"","name":"Controls","tab":"e39ed875.179ed8","order":1,"disp":true,"width":"6","collapse":true},{"id":"14078cbe.6d0373","type":"ui_group","z":"","name":"Input / Output","tab":"e39ed875.179ed8","order":2,"disp":true,"width":"6","collapse":true},{"id":"e8c963b3.9ec38","type":"ui_group","z":"","name":"Voltages","tab":"e39ed875.179ed8","order":4,"disp":true,"width":"6","collapse":true},{"id":"aa20a6d4.8551b8","type":"ui_group","z":"","name":"Enviromental","tab":"e39ed875.179ed8","order":3,"disp":true,"width":"6","collapse":true},{"id":"57d0640f.9d725c","type":"ui_group","z":"","name":"Cell Voltages","tab":"e39ed875.179ed8","order":5,"disp":true,"width":"7","collapse":true},{"id":"e39ed875.179ed8","type":"ui_tab","z":"","name":"Dashboard","icon":"dashboard","order":1}]
1 Like

I had missed your reply until now. Thanks so much for posting. I had figured out most of it but had never done the individual cell voltages so you made that very easy thank you!

I'm working on Sigineer inverter now. There is an snmp module that will allow communication with it.

I really need to enable email alerts on replies. anyways, you don't actually need to buy that module the serial port on the remote returns RS232 data you can parse with node. Here's the baud settings and what to send in order to control the inverter and get data.