How can i parse my c structure data in node red

Hello There,
I have c structure
typedef struct {
float temp;
float status;
unsigned char tdata;
} data;
data mydata;
value of my structure variable fill by the below parameters.
mydata.tdata = 0x55;
mydata.temp = 28.95;
mydata.status = 0;

and the data store in memory is
9A99E7410000000055000000
in this data 9a99e741 is a float value of the temp variable,
00000000 is the value of the status variable,
55000000 is the value of the tdata variable which is an unsigned char

If I want to pars my data on the node-red side how can I pars this
please guide me.

How are you getting that into node red?

Have a look at the excellent node https://flows.nodered.org/node/node-red-contrib-buffer-parser (from @Steve-Mcl )

1 Like

As @janvda says, you can use the buffer-parser node...

image

image

3 Likes

Buffer method is best I can think of, it you know C, the buffer method should be straight forward.

The reason I asked how it gets from C to node-red is that if it could be converted to JSON as it leaves the C s/w it would be much easier to pick up in node red. Also this would be more rugged a solution as if he s/w were moved to a different architecture or even C compiler version the details of the structure might change.

True.

Typical data structures in C are type structures that are added to rather than changed to support backward compatibility, but that is not required nor consistently done. It is more of an acknowledged design methodology that many C programmers choose to adopt. The same is true of JSON file content, for example, lets say one day you decide to add a new node type that requires a new data set to function, the parent structure of the flows file might still just define a 'type' value that is new, but the child structure(s) maybe radically different from other node types.

My point, and I say this for those that may read this in the future, having been a C developer for many years if not decades, is that mapping C structures, as they may now exist, the buffer method is the straight forward, you have a one to one relationship per structure 'part' to buffer method defined elements.

We do this all the time, for example using C based DLLs in Windows, in a different high level language, say VB .NET, you have to rely on the static nature of structures to do the mapping, if such changes, your mapping has to adapt. To avoid this, we come back to always adding structures, not changing structures, to again, maintain backward compatibility.

This is why many of the Windows OS core API has routines named 'IamACall' and 'IamACallEx', of course Microsoft never explains this, but if you look at the difference between the two calls, the 'Ex' call is the newer routine, and has an extended or enhanced data structure different or larger than the original API call but clearly related to the original API call.

Hello everyone,
Thanks for the reply the solution is very useful but still, I am confused that how can I parse my data from my json payload,
my payload is {"data":"0A003A0012504858553038200F4E6D380000E4410000000000000000000000000000000001000000","devaddr":"0190A703"}
here I agave to parse my data through buffer parser and
store my parse data in db with device address.
please guide me ...


here I am attached my flow file flows (3).json (4.3 KB)

What is the C typedef structures? Can you show that here? If we know the typedef and structures declarations we should be able to breakup the 'data' value into understandable elements, and use the buffer item qualifications to match the C data structure information as noted above.

Hello,
My C structure is
typedef struct {
uint32_t UID0;
uint32_t UID1;
uint32_t UID2;
uint32_t EpochTime;
float Temprature;
uint8_t key[16];
uint8_t LockStatus;
uint8_t TempratureAlart;
} Payload;
and the paulod json which I got in nodered using mqtt is
{"data":"0A003A001250485855303820D8236E380000E4410000000000000000000000000000000001000000","devaddr":"0190A703"}"

the data of 0A003A001250485855303820D8236E380000E4410000000000000000000000000000000001000000 is in c structure is
uid: array[3]

0: 3801098

1: 1481134098

2: 540553301

epochTime: 946742232

Temprature: 28.5

Key: ""

LockStatus: 1

tempratureAlart: 0

but to store in db i also require devaddr value
Thanks
swapnil

So when you configure the buffer elements, you are basically parsing the 'data', you tried to setup a flow doing the buffer parsing right?

Adding the devaddr is easy once we have a JavaScript object that represents the 'data' values.

I looks like you have your buffer parser setup, but I do have 2 questions, how is the temperature valve encoded and is the epoch value right?

epochTime: 946684803
Temprature: 1105461248

Do these values above make sense? An epoch valve for me, for today, now... is much higher value. For example... 1602338222532.

Ok, I am trying to figure out how to get the buffer-parser right. I have not used this node before, but I am familiar with C.

I found two errors in your buffer parser,

  1. Change the input property from msg.payload to msg.payload.data. This will allow the parser to see the correct object property 'data' as needed.

  2. The temperature type definition is wrong, it is not int32 (le). It should be "float (le)" not what it is now. This on my test flow, returned 28.5, which per the C output is correct for the 'data' value you used.

To add the devaddr to the output msg.payload, can be done a few ways. Below is a flow that shows one way to do it.

[{"id":"5db3fd69.1c77a4","type":"inject","z":"f9c8a450.82cf78","name":"OTTA 26002088","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"devaddr\":\"26002088\",\"data\":\"0A003A001250485855303820D8236E380000E4410000000000000000000000000000000001000000\"}","payloadType":"json","x":200,"y":120,"wires":[["2210c9e2.4b1c96"]]},{"id":"b4fd5c1b.c3776","type":"debug","z":"f9c8a450.82cf78","name":"Message (msg)","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1080,"y":120,"wires":[]},{"id":"e279784e.6490f8","type":"change","z":"f9c8a450.82cf78","name":"Restore Device Address","rules":[{"t":"set","p":"payload.devaddr","pt":"msg","to":"devaddr","tot":"msg"},{"t":"delete","p":"devaddr","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":850,"y":120,"wires":[["b4fd5c1b.c3776"]]},{"id":"42813884.cf9f98","type":"buffer-parser","z":"f9c8a450.82cf78","name":"","data":"payload.data","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint32le","name":"uid0","offset":0,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32le","name":"uid1","offset":4,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"int32le","name":"uid2","offset":8,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"int32le","name":"epochTime","offset":12,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"floatle","name":"Temprature","offset":16,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"ascii","name":"Key","offset":20,"length":16,"offsetbit":0,"scale":1,"mask":""},{"type":"uint8","name":"LockStatus","offset":36,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint8","name":"tempratureAlart","offset":37,"length":1,"offsetbit":0,"scale":1,"mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"output","multipleResult":false,"setTopic":true,"x":630,"y":160,"wires":[["e279784e.6490f8"]]},{"id":"2210c9e2.4b1c96","type":"change","z":"f9c8a450.82cf78","name":"Save Device Address","rules":[{"t":"set","p":"devaddr","pt":"msg","to":"payload.devaddr","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":120,"wires":[["42813884.cf9f98"]]}]

The next step is what to do with the data? If you want send an alert via email or to your cell phone? you can learn about how do use the NR nodes that allow this...


If you wanted to save it to a database? You could do something like...

"INSERT INTO <table> (uid0,uid1,uid2,epochTime,Temprature,Key,LockStatus,tempratureAlart,devaddr) VALUES (msg.payload.uid0,msg.payload.uid1,msg.payload.uid2,msg.payload.epochTime,msg.payload.Temprature,msg.payload.Key,LockStatus,msg.payload.tempratureAlart,msg.payload.devaddr);"

Where is the name of the table in your DB. The insert query may need some changes depending on which SQL server you are using. And assuming your name the table columns the same as the payload property names is done.

For more on SQL and NR...

Hello There,
Thanks for reply.
i have new way to solve this, please guide me. it's valid method or not
here is my flow
flows (4).json (2.2 KB)
Thanks
swapnil

Looks fine to me, as long as it works the way you want, so be it. :slight_smile:

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