Sending Struct Function to Node-Red via serial

Hi, does anyone may help me? I have a struct like this (Arduino)

struct attribute((packed)) SENSOR_DATA {
uint16_t sessionid;
uint8_t idmeter[5];
uint16_t standmeter[5];
boolean state[5];
boolean indicator;
} sensorData;

I want to send sessionid, idmeter, standmeter, state, and indicator as a single variable that collected in an array.
This is how I create my flows, but the result wasn't as I expected

my function code :

msg.payload = String.fromCharCode(msg.payload);
return msg;

I expected to receive :
{sessionid : .... (left it blank to be filled by text input UI) ;
idmeter :... ;
....}

Is it possible?
Thanks before!

You will need to read and parse the buffer byte by byte and assign the values to equivalent JavaScript types. The field names aren't sent within the binary data.

Other option could be: https://flows.nodered.org/node/node-red-contrib-buffer-parser

I have not used buffer-parser myself but my understanding is that it's designed for this kind of task.

2 Likes

To do it manually you process the buffer (msg.payload) by using Buffer methods readXxx, documented here: https://nodejs.org/api/buffer.html

A crude way would go something like this (out of memory):

let buf = msg.payload:

let data = {};
let offset = 0;

data.sessionid = buf.readUInt16LE(offset);
offset += 2; // move offset 2 bytes

data.idmeter = [];
data.idmeter[0] = buf.readUInt8(offset);
offset++;
data.idmeter[1] = buf.readUInt8(offset);
offset++;

// and so forth

Wow, thank you so much for the help. Going to try your suggestion now.
May I post another question if some troubles happened again?

Thanks before!

Sure, this is what the forum mostly is for I suppose. I might not respond but likely someone else will.

Please let us know if this solved the issue after trying so it might help others as well.

1 Like

If you have control of the Arduino code then change it to send a JSON string, that will make your life much easier.
[Edit] Once into node-red you just have to feed it through a JSON node to convert it to a javascript object.

1 Like

I second @Colin here. It's super simple using the ArduinoJson library. I somehow missed the Arduino part. Of course sending in binary is more efficient and uses less data if that is desired.

Hi, first of all I wanna thank you guys @ristomatti and @Colin
I've just updated my work. I tried using ArduinoJSON library according to Colin's suggestion.

I wrote my Arduino code this way

#include <ArduinoJson.h>

void setup() {
  // Initialize Serial port
  Serial.begin(9600);
  while (!Serial) continue;
  StaticJsonDocument<200> doc;
  
  // Sessionnid name with null value
  JsonObject& doc = jsonBuffer.createObject();
  doc["sessionid"] = (char*)0; // or (char*)NULL if you prefer

  // Add an idmeter array.
  JsonArray idmeter = doc.createNestedArray("idmeter");

  // Generate the minified JSON and send it to the Serial port.
  //
  serializeJson(doc, Serial);
  // to print :
  // {"sessionid":" ","idmeter":[ ]}

  // Start a new line
  Serial.println();

  // Generate the prettified JSON and send it to the Serial port.
  serializeJsonPretty(doc, Serial);
}

void loop() {
  // not used in this example
}

And my Node-Red flows

[{"id":"ff0d843c.5e05b8","type":"tab","label":"laman oprek","disabled":false,"info":""},{"id":"81e6b612.bd4468","type":"debug","z":"ff0d843c.5e05b8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"jsonata","x":700,"y":280,"wires":[]},{"id":"86336189.e237d","type":"serial in","z":"ff0d843c.5e05b8","name":"","serial":"4bff77f8.029b88","x":310,"y":280,"wires":[["25087f18.702cb","31fe5d6.317b0a2"]]},{"id":"25087f18.702cb","type":"ui_text","z":"ff0d843c.5e05b8","group":"119a7de4.6ebb92","order":1,"width":0,"height":0,"name":"","label":"","format":"{{msg.payload}}","layout":"row-spread","x":490,"y":200,"wires":[]},{"id":"31fe5d6.317b0a2","type":"json","z":"ff0d843c.5e05b8","name":"","property":"payload","action":"str","pretty":false,"x":500,"y":280,"wires":[["81e6b612.bd4468"]]},{"id":"4bff77f8.029b88","type":"serial-port","z":"","serialport":"COM3","serialbaud":"19200","databits":"8","parity":"none","stopbits":"1","waitfor":"","newline":"\\n","bin":"false","out":"char","addchar":"false","responsetimeout":""},{"id":"119a7de4.6ebb92","type":"ui_group","z":"","name":"test","tab":"e2d4c61b.53b908","order":1,"disp":true,"width":"23","collapse":false},{"id":"e2d4c61b.53b908","type":"ui_tab","z":"","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]

The problem is that I wish the sent JSON wasn't seperated like in this picture. And, I begin from Arduino with 9600 baud rate, but it shows nothing when I set the baud rate on Node-Red serial node 9600. I have to set it at 19200, then it shows like in the picture above.

Can someone help me?

Thank youu!

I'm sorry, my mistakes. I should have change the split input

It works now, but still. The problem is with the baud rate. I don't understand why I set 9600 baudrate on Arduino but it won't work if I set 9600 on Node-Red.

And also, my problem was
does anyone know how can I fill the empty/null value on JSON data?
Thanks before!!!

The debug node is showing a string, so presumably that is direct from the serial node. If you feed it through a JSON node that will convert it to a javascript object, then you can do what you like with the data values. Should the values not be sent by the Arduino though?

1 Like

The baud rate issue seems really odd. You should be able to use faster speeds on the Arduino end also. I think 57600 or 115200 should be still OK and with luck might resolve your issue (and be faster in the process). Based on a quick glance I see no problem in your serial in node configuration...

If you connect to your Arduino using a serial console (from Arduino IDE for example), which baud rate does it seem to communicate then? Although I've yet to encounter an Arduino that wouldn't obay the baud rate set in the code.

1 Like

Ah, I see. Gonna try it. Thanks..
Answering your question, unfortunately no, I wished to fill the sessionid and idmeter value from the Node-Red, while other variables sent by the Arduino.

So if I convert it to JavaScript object I can fill the sessionid and idmeter value from the Node-Red?

Thanks again

Ah, okay I'll try using 115200. Thankss

I'm using the serial monitor from Arduino IDE with 19200 of baudrate, and the JSON data displayed. But, when I changed to 9600, it shows some strange signs. I don't get it.

Dear Collin,

I've tried to feed through JSON node to convert to javascript object. But it shows an error message :

"Unexpected token { in JSON at position 33"

or am I doing it wrong?

Thanks before

I am sorry again. How careless am I, I changed the property to become JSONata.

Thanks, Collin

That last entry in the debug is not valid JSON.

Try copy and paste into an online json validator.

Basically multiple objects should either be properties of another object or array entries.

Edit.
Looks like you need your com to split in newline.

Oh dear, yes I've just realized it. I made a mistake on my Arduino code I guess
Gonna check it now. Thanks @Steve-Mcl

By the way, I don't understand how to split the com. Can you explain the detail?
Thanks

Is this a valid JSON now? I made some changes

Here is my flows :

[{"id":"ff0d843c.5e05b8","type":"tab","label":"laman oprek","disabled":false,"info":""},{"id":"81e6b612.bd4468","type":"debug","z":"ff0d843c.5e05b8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"jsonata","x":740,"y":260,"wires":[]},{"id":"86336189.e237d","type":"serial in","z":"ff0d843c.5e05b8","name":"","serial":"4bff77f8.029b88","x":170,"y":280,"wires":[["25087f18.702cb","31fe5d6.317b0a2"]]},{"id":"25087f18.702cb","type":"ui_text","z":"ff0d843c.5e05b8","group":"119a7de4.6ebb92","order":1,"width":0,"height":0,"name":"","label":"","format":"{{msg.payload}}","layout":"row-spread","x":490,"y":200,"wires":[]},{"id":"31fe5d6.317b0a2","type":"json","z":"ff0d843c.5e05b8","name":"","property":"JSONata","action":"obj","pretty":true,"x":350,"y":280,"wires":[["f514a3f0.6b85d"]]},{"id":"f514a3f0.6b85d","type":"ui_text_input","z":"ff0d843c.5e05b8","name":"","label":"","tooltip":"","group":"119a7de4.6ebb92","order":1,"width":0,"height":0,"passthru":true,"mode":"text","delay":"3000","topic":"","x":460,"y":400,"wires":[["21b8eff3.8f3e7"]]},{"id":"21b8eff3.8f3e7","type":"json","z":"ff0d843c.5e05b8","name":"","property":"payload","action":"obj","pretty":false,"x":600,"y":320,"wires":[["81e6b612.bd4468"]]},{"id":"4bff77f8.029b88","type":"serial-port","z":"","serialport":"COM3","serialbaud":"19200","databits":"8","parity":"none","stopbits":"1","waitfor":"","newline":"1000","bin":"false","out":"interbyte","addchar":"false","responsetimeout":""},{"id":"119a7de4.6ebb92","type":"ui_group","z":"","name":"Received from Arduino","tab":"e2d4c61b.53b908","order":1,"disp":true,"width":"23","collapse":false},{"id":"e2d4c61b.53b908","type":"ui_tab","z":"","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]

and the result :

Look good. It's no longer a string but an actual object. (debug says object & you can expand the properties)

1 Like

Okay, thank you so much Steve. I made a mistake on setting the json node property. Silly me