Getting raw data from TTN Uplink node

I am getting a full frame [51B] of raw bytes from a device connected to TTN. For that purpose, an Uplink TTN node is connected to TTN in Node-Red screen. If I pass the results directly to the debug node, I can see the contents of bytes buffer in the Node-Red debug window. My aim is to get access to that buffer, as I would like to manipulate with this buffer in a certain way (that's why I do not want to use Cayennellp Decoder node for this). But if I insert a Function node between Uplink and Debug nodes, I am not able to access appropriate payload fields from Uplink output message. I don't have a lot of practice writing functions in Node-Red, so that's probably my problem. Any hints, how to access this buffer of 51 bytes?
Any help will be appreciated.
Zbig

Perhaps this would help? ...

1 Like

Hi Steve,
Thank you for the hint, but I would prefer to see a piece of code that "gets" an array of bytes from the Uplink node for a hand-written function. I'd rather avoid one more node inserted into the flow, the more so that the content of the byte stream can be quite "non-standard".
Thanks,
Zbig

Many people struggle with byteswapping and data conversion (search this forum and you will see the deluge of requests for help) & generating a single object with 1 or more values, some int, some uint, some want booleans, some float, some int64. Then there are those who need multiple values or objects from the raw byte data, that node does all the heavy lifting without any additional dependencies (uses the nodejs buffer that is built in to the underlying nodejs that runs node-red)

Feel free to use it or not.

And the node I pointed you to accepts a dynamic specification for exactly that reason.

Search this forum or the net for buffer and readint16be or readint16le there are many questions and a few answers.

Steve,

All what I really need is a pece of working code that allows to access buffer of bytes in the Node-Red. Manipulating with this is another story. I tried something like this:

var b0 = msg.payload.buffer[0];

It doesn't generate an error but seems not to work at all. On the other hand, I can see all that bytes in a buffer in the debug window.

What do you do with b0 ? Do you add it to the msg and return the msg?

This is just a sample showing how I try to access this buffer of bytes. In fact, the code is a little bit more complex. In a short, the code in Function node looks as follows:

var newp = {'tempC': 3, tempF: ""}; // The <<3>> is just to help observing whether the code works or not
var b0 = msg.payload.buffer[0]; // buffer[0] contains <<49>>
newp['tempC'] = b0;

var newMsg = {payload: newp};
return newMsg;

Of course, it is simplified to just processing with one byte from the buffer (the final processing will be more complex), but even this seems not to work, i e, in the debug window the 'tempC' has still value of <<3>>.

Hi - firstly wrap code in three back ticks
```
var why = "cos it looks much better and doesnt get chewed up by forum formatting";
```

so - try this and show us the debug nodes (set to show "complete message") results with properties expanded...

if(Buffer.isBuffer(msg.payload.buffer) == false){
  node.warn("msg.payload.buffer is not a Buffer");
  return null; //halt flow
}
if(msg.payload.buffer.length < 1){
  node.warn("msg.payload.buffer does not have enough bytes");
  return null; //halt flow
}
msg.buffer = msg.payload.buffer; //first, keep a ref to buffer - for later debug analysis
node.warn(["This is msg.payload.buffer", msg.payload.buffer]); //check debug window - is byte zero correct? 

var newp = {};//create new empty object
newp.tempC = msg.payload.buffer[0]; //get first byte
msg.payload = newp;//now replace payload with new payload
return msg;

Hi Steve,

OK, I will try it in late evening and let you know,

Hi Steve,

I copied your code into function node and here are results:

8.05.2020, 12:16:05[node: ee9b8483.0b7228](http://localhost:1880/)function : (warn)
"msg.payload.buffer is not a buffer"

I also added another debug node with option to show the whole content of message:

8.05.2020, 12:16:05[node: ddb8241e.1d7ab8](http://localhost:1880/)msg : Object
*object*
app_id: "agricheck-test-jas"
dev_id: "lora-agri-evl"
hardware_serial: "60C5A8FFFE766873"
port: 1
counter: 9989
payload_raw: *buffer[11]*
metadata: *object*
payload: *buffer[11]*
_msgid: "9b3db419.29f378

As you can see, the function node returned null with the warning message, that "buffer' is not a buffer. At the same time, the another debug node shows the complete object and you can see the 'buffer' (and even its content, after expanding it). And if the debug node is configured to show msg.payload, the 'buffer' is displayed and its content.
All of this is confusing (and a little bit frustrating...).
Zbig

Hi, i edited your post (I couldnt read it) - please put code between 3 backticks on new lines

```
Like this
```

There is your problem - as we suspected.

you are making the popular mistake of not using the tools provided.

your buffer is NOT in msg.payload

Use the "Copy Path" button in the debug panel to get EXACT path to data...
image

EDIT ...

i didnt see the payload was also a buffer.

Send me a screen shot of your flow & your flow (relevant part of if). (between backticks)

i have another theory.

Since this happens....

if(Buffer.isBuffer(msg.payload.buffer) == false){
  node.warn("msg.payload.buffer is not a Buffer");
  return null; //halt flow
}

I suspect your payload ISNT a nodejs buffer but something like a Buffer.

Try this please....

node.warn(["typeof msg.payload.buffer", typeof msg.payload.buffer]);
node.warn(["msg.payload.buffer.constructor.name", msg.payload.buffer.constructor.name]);

if(Buffer.isBuffer(msg.payload.buffer) == false){
  msg.oldPayloadBuffer = msg.payload.buffer; //keep a copy - for later debug analysis
  node.warn("msg.payload.buffer is not a Buffer");
  msg.payload.buffer = Buffer.from(msg.payload.buffer);
}

node.warn(["typeof msg.payload.buffer", typeof msg.payload.buffer]);

if(msg.payload.buffer.length < 1){
  node.warn("msg.payload.buffer does not have enough bytes");
  return null; //halt flow
}
msg.buffer = msg.payload.buffer; //first, keep a ref to buffer - for later debug analysis
node.warn(["This is msg.payload.buffer", msg.payload.buffer]); //check debug window - is byte zero correct? 

var newp = {};//create new empty object
newp.tempC = msg.payload.buffer[0]; //get first byte
msg.payload = newp;//now replace payload with new payload
return msg;

Some proof that it works...

Your "buffer" is probably NOT a nodejs buffer

the test flow...

[{"id":"689990b8.38751","type":"inject","z":"c70ba4a4.e7fb58","name":"","topic":"","payload":"[47,48,42,43,44,45,46,47,48,49,50]","payloadType":"bin","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1610,"y":740,"wires":[["58700641.4be6c8"]]},{"id":"1121484c.f108f8","type":"function","z":"c70ba4a4.e7fb58","name":"get [0]","func":"if(!msg.payload.buffer){\n    node.warn(\"msg.payload.buffer is empty\");\n    return null;\n}\n\nnode.warn([\"msg.payload.buffer.constructor.name\", msg.payload.buffer.constructor.name]);\n\nif(Buffer.isBuffer(msg.payload.buffer) == false){\n  node.warn(\"msg.payload.buffer is not a Buffer\");\n  return null;\n}\n\nif(msg.payload.buffer.length < 1){\n  node.warn(\"msg.payload.buffer does not have enough bytes\");\n  return null; //halt flow\n}\n\nmsg.buffer = msg.payload.buffer; //first, keep a ref to buffer - for later debug analysis\nnode.warn([\"This is msg.payload.buffer\", msg.payload.buffer]); //check debug window - is byte zero correct? \n\nvar newp = {};//create new empty object\nnewp.tempC = msg.payload.buffer[0]; //get first byte\nmsg.payload = newp;//now replace payload with new payload\nreturn msg;","outputs":1,"noerr":0,"x":1690,"y":820,"wires":[["473c288a.648a18"]]},{"id":"473c288a.648a18","type":"debug","z":"c70ba4a4.e7fb58","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1730,"y":860,"wires":[]},{"id":"58700641.4be6c8","type":"function","z":"c70ba4a4.e7fb58","name":"put buffer into payload.buffer","func":"msg.payload = {\n    buffer: msg.payload\n}\nreturn msg","outputs":1,"noerr":0,"x":1740,"y":780,"wires":[["1121484c.f108f8"]]}]

Hi Steve,

Thanks a lot for your patience and suggestions. I will use your code sample in the evening (again) and let you know results. There is a problem with screen dumps, because I run Node-Red on Raspberry Pi 4. I couldn't install TTN nodes on Win7, there are problems with the installation script and I gave up after several attempts. Therefore, I am using e-mail to "swap" output of debug window between RPi and Win7. I tried to use "Copy path" option, but it doesn't seem to work. The same for screen dump - I cannot copy / paste Node-red screen :frowning:
Zbig

You know if the RPi is on same network as your PC, you can just open node-red in the browser on your PC right?

Get the IP of your RPi then navigate to http://rasp-ip-address:1880 then you can screenshot the browser & paste directly into your reply here.

I strongly recommend greenshot or sharex to make nice and easy desktop screen snips with annotations/comments/arrows/boxes

Hi Steve,
I prepaded a reply to your suggestions, but when I tried to send it, I got a warning:

"Sorry, new users can only put 2 links in a post."

And the only link was the uploaded image with my simple flow. This warning was issued even I removed this link from my message. Any suggestions? :frowning:

Best,
Zbig

dont put links to external pictures in a post.

Just copy your image from the image editor into the clipboard and paste it directly into the reply. (or if you dont know what I mean then drag an image into the reply)

That's exactly what I did.
Here's the picture with the flow (again)

That is an screenshot of a flow (not a flow).

What is it?

Where are the debug output pictures showing the result of the node.warn calls?

I still cannot paste the content of debug window into message - still getting the same warning... :confused: