Help on splitting an input array

I have been struggling on how to decipher an input array of hex data with node red, and then show the data separately in the past several days. The data are from two temperature sensors and one accelerometer. The array length varies from sensor to sensor. The data from sensors arrive asynchronously. The sensor data are arranged as follows: sensor id+sensor data+ending sign

For example, the data from temperature sensor one is 210322550A, where 21 is the temperature sensor 1 id, 0322 are 16-bit sensor data, 550A is the ending sign, which is used to indicate the end of data. The data from temperature sensor two is 221223550A, where 22 is the temperature sensor 2 id, 1223 are 16-bit sensor data, 550A is the ending sign again. The data from the acceleromter is 32462311022506550A, where 32 is the acceleromter id, 462311022506 are the 16-bit data for x-axis, y-axis and z-axis respectively, 550A is the ending sign again.

Thank you very much for your help.

Hi
Don't know the answer to your problem straight off but jJust for my interest - what are these sensors? (make/model)?

If the format is always the same then you can easily parse this with a combination of substr and parseInt calls in a function node

But if you have any control of the data format I would strongly suggest you change it to be JSON. That would make this a trivial task.

The temperature sensor is TMP102 and the accelerometer is Lis3dh.

Thanks and could you please elaborate the solution? Sorry I am a starter for Node RED.

The reason we use such format is to improve the data throughput. All the data come from the serial port, which has a limit of 115200 bps. Ideally, we want to minimize the extra characters that we put to the data.

I understand but I suspect your logic is flawed. If you are sending data at this rate, you add "550A" to each message. This is not a lot less that adding 2 curly brackets, 2 quotes, an id and 1 colon to make valid JSON

On the flip side, normalising all these values in node-red (at that rate) might be slower than adding the 3 extra characters to generate valid JSON.
I'm not 100% certain on that but remember - [Premature Optimization Is the Root of All Evil]("Why Premature Optimization Is the Root of All Evil" Amplify Feedback with Continuous Performance)

If you insist on going down this path (I strongly implore you not to) then lookup how to use substr and parseInt - they are standard JavaScript function calls you can use in a function node to split up and parse your string into useful values. But again, I strongly suggest if you have control over the send values, that sending valid JSON would mean you simply pass it through a JSON node to get useable values.

Let me know if you need more help.

Thanks Steve. 550A is necessary for the flexible data length, so that we know when the sensor data ends.

For the temperature data, when three bytes data is transmitted (id+16 bit data), we added two bytes 550A already. We want to avoid adding extra overhead unless there is no easy solution. All the sensor data come through the serial port and the serial port speed of 115200 is the bottleneck currently. If we add 50% extra characters in the transmitter side, then we lower the transmission speed by 50%.

I should be able to write the Javascript codes to handle the receiver part. But I am not sure how to plug Javascript code into Node RED at the moment (A noob in NODE RED). I guess that I should put the Javascript codes into the function node?

Please give me some time to write the Javascript :slight_smile:

Yes - just add javascript code in one of them

What are you planning on doing with the data once its in Node-RED?

Here is a partial solution to get you going....

[{"id":"fee53695.ad6798","type":"inject","z":"df8e9b9d.be8cc8","name":"fake temp sensor data 210322550A","topic":"","payload":"210322550A","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":480,"y":140,"wires":[["86c9cfb1.3a06a"]]},{"id":"1b6c1e78.352b22","type":"inject","z":"df8e9b9d.be8cc8","name":"Fake temperature sensor two 221223550A","topic":"","payload":"221223550A","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":500,"y":300,"wires":[["86c9cfb1.3a06a"]]},{"id":"86c9cfb1.3a06a","type":"function","z":"df8e9b9d.be8cc8","name":"Parse data","func":"/*\nDEMO\ntemperature sensor one is 210322550A, where 21 is the temperature sensor 1 id, 0322 are 16-bit sensor data, 550A is the ending sign, which is used to indicate the end of data. \ntemperature sensor two is 221223550A, where 22 is the temperature sensor 2 id, 1223 are 16-bit sensor data, 550A is the ending sign again. \nThe data from the acceleromter is 32462311022506550A, where 32 is the acceleromter id, \n462311022506 are the 16-bit data for x-axis, y-axis and z-axis respectively, 550A is the ending sign again.\n\n*/\nvar data = msg.payload\nvar id = data.substr(0,2)\nvar sensor = {};\nsensor.id = id;\nswitch (id) {\n    case '21':\n        if(data.length != 10){\n            throw new Error(\"Invalid data - incorrect length\")\n        }\n        if(data.substr(6,4) !== \"550A\"){\n            throw new Error(\"Invalid data - end marker not found\")\n        }\n        sensor.name = \"Sensor 1\";\n        sensor.value = parseInt(data.substr(2,4),16);\n        break;\n    case '22':\n        if(data.length != 10){\n            throw new Error(\"Invalid data - incorrect length\")\n        }\n        if(data.substr(6,4) !== \"550A\"){\n            throw new Error(\"Invalid data - end marker not found\")\n        }\n        sensor.name = \"Sensor 2\";\n        sensor.value = parseInt(data.substr(2,4),16);\n        break;\n    case '32':\n        if(data.length != 18){\n            throw new Error(\"Invalid data - incorrect length\")\n        }\n        if(data.substr(14,4) !== \"550A\"){\n            throw new Error(\"Invalid data - end marker not found\")\n        }\n        sensor.name = \"Accelerometer\";\n        sensor.x = \"todo\"\n        sensor.y = \"todo\"\n        sensor.z = \"todo\"\n        sensor.acc = \"todo\"\n        break;    \n    default:\n        // code\n}\nmsg.payload = sensor;\nreturn msg;","outputs":1,"noerr":0,"x":840,"y":220,"wires":[["b7666bc4.4912a8"]]},{"id":"61f8ea30.59a564","type":"inject","z":"df8e9b9d.be8cc8","name":"Fake accel 32462311022506550A","topic":"","payload":"32462311022506550A","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":480,"y":360,"wires":[["86c9cfb1.3a06a"]]},{"id":"1b4ede39.76e502","type":"inject","z":"df8e9b9d.be8cc8","name":"fake temp sensor bad data 210322550B","topic":"","payload":"210322550B","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":490,"y":180,"wires":[["86c9cfb1.3a06a"]]},{"id":"8bea33c2.010f7","type":"inject","z":"df8e9b9d.be8cc8","name":"fake temp sensor bad data 210322550AXX","topic":"","payload":"210322550AXX","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":500,"y":220,"wires":[["86c9cfb1.3a06a"]]},{"id":"b7666bc4.4912a8","type":"debug","z":"df8e9b9d.be8cc8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1000,"y":220,"wires":[]}]
1 Like

I plan to plot the sensor data in different charts :slight_smile:

Hi Steve, thanks a lot. This solves my problem. :smiley:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.