Getting uplink metadata using Node-RED "ttn device" or "ttn message" nodes

I am building an application in node-red for my SODAQ tracker device.
So far I succeeded in sending a twitter message with my device location.
I want to extend the twitter message with RSSI and ID of the LoRaWan which is receiving my device messages.
I can not find the right settings for the ttn device / ttn message in node-red to accomplish this. I am not sure if this is the right way to do this. Can somebody put me on the right track to make this happen.
The purpose of my application is testing the coverage of the network in the Eindhoven region with a mobile device.

1 Like

Which version of the library are you using? The MQTT format changed for production (v2), so using some staging (v1) version might not expose the meta data?

To see what version is installed:

cd $HOME/.node-red
npm list node-red-contrib-ttn

Today, the current version is 2.0.1.

:warning: Meanwhile, in 2019, the support and maintenance for this SDK has been discontinued, it is not recommended to use the SDK for new projects.

(Also, see https://ttnmapper.org.)

Hi Arjan,

I’m using the 2.0.1 version of node-red-contrib-ttn
I don’t know what to fill in for ‘event’ or ‘field’ in the ttn-device or ttn-message to get the meta data value out the input node block for e.g. the RSSI.
for tty-device the only thing that works as event is “activations”
But maybe I’m completely wrong and missing the point.
Just started with TTN two weeks ago and with the device and gate-way already running not too bad I would say. Only the SW knowledge is lacking.

For me, a ttn message node with just a configuration for the app, gets me an object that includes metadata, which includes gateways. Simply connecting a ttn message node with a debug node, and setting the latter to log complete msg object gives me all the details in the debug panel.

By the way: using a standard Node-RED mqtt input node is much easier, I feel…

For ttn device nodes the TTN Node-RED Quick Start links to “and other device events”, which I guess translates to:

  • down/scheduled
  • down/sent
  • down/acks
  • up/errors
  • down/errors
  • activations/errors

I’ve tested a few from the list. Indeed, for example down/scheduled, down/sent and down/errors work for me, but wildcards such as # or down/+ are not allowed, and just errors shows no results even when down/errors gets an event:

To test down/errors: in TTN Console go to the device and schedule a downlink of type “fields”, entering something like {"foo": "bar"} without providing an encoder payload function. When the downlink is to be sent (after an uplink was received) this will throw “Downlink Payload not valid: fields supplied, but no Encoder function set”. To get rid of that error, just schedule another downlink of type “bytes” and enter something like 00.

1 Like

Finally… Beware that you might need to upgrade Node-RED. The “App” field should be a dropdown, and it needs to show a pencil icon to the right. Older versions might show just a text field, but it does not suffice to just enter some text in the “App” field.


:warning: The above screenshots are no longer valid for later releases of the TTN’s Node-RED library. Read on!

1 Like

A post was merged into an existing topic: Node-RED data in v2

Thanks Arjan, I now have meta data in node-red. Next step is making a function that combines the specific metadata and pay load fields to a twitter message.
Thanks for the other info too. I will have a look into ttnmapper.org and will register my SODAQ device and fill in some blank spots.

1 Like

Solution:

“ttn message” (node block)
“function” block with return “msg.metadata”
“debug” block with for instance “msg.frequency”

This show the ‘frequency’ meta data in the debug window

1/30/2017, 10:33:55 PMnode: df2f9ca1.3092d
msg.frequency : number
868.1

3 Likes

useful tip. thank you

Note that you’d get multiple gateways in your meta data if the node’s packets were received by multiple.

You can also use the function block to return the data just as you want it. Like:

// Just a helper variable to use below
var gateways = msg.metadata.gateways;

return {
  // Assuming the TTN Payload Functions decode some bytes from the node
  // into a "location" in the output:
  mylocation: msg.payload_fields.location,

  // Some fields from the metadata
  freq: msg.metadata.frequency,
  cr: msg.metadata.cr,
  dr: msg.metadata.dr,

  // Combine RSSI and SNR of all gateways into two arrays:
  rssi: gateways.map(gw => gw.rssi),
  snr: gateways.map(gw => gw.snr),

  // ...or: get an array with an object for each gateway:
  gateways: gateways.map(gw => {
    return {
      location: {
          lat: gw.latitude,
          lng: gw.longitude
      },
      rssi: gw.rssi,
      snr: gw.snr
    }
  })
};

When printing “complete msg object” in a debug node, you’d then get something like:

{
  "mylocation": {
    "lat": -33.8688,
    "lng": 151.2092
  },
  "freq": 868.1,
  "rssi": [-36, -45],
  "snr": [9, 9],
  "gateways": [
    {
      "id": "eui-b827ebffff5fe05c",
      "location": {
        "lat": 52.12345,
        "lng": 4.12345
      },
      "rssi": -36,
      "snr": 9
    },
    {
      "id": "eui-5ccf7ff42f1970ec",
      "location": {
        "lat": 52.54321,
        "lng": 4.54321
      },
      "rssi": -45,
      "snr": 9
    }
  ]
}

Or to get a msg.payload for a Node-RED Twitter input:

var gateways = msg.metadata.gateways;

msg.payload = "Received by "
  + gateways.length
  + " gateway(s), with RSSIs "
  + gateways.map(gw => gw.rssi).join(", ")
  + " and SNRs "
  + gateways.map(gw => gw.snr).join(", ")
  ;

return msg;

…to get

Received by 2 gateway(s), with RSSIs -38, -44 and SNRs 9, 9
2 Likes

Works great, see below !
Thanks for making the story complete.

brandevoort IoT ‏@brandevoort_eu 24s25 seconds ago
More
Received by 1 gateway(s), with RSSIs -49 and SNRs 7.8

Nice. If you want to get rid of the plural thing when not needed, then:

// Just some helpers
var gateways = msg.metadata.gateways;
var count = gateways.length;
var s = count === 1 ? "" : "s";
var rssi = gateways.map(gw => gw.rssi).join(", ");
var snr = gateways.map(gw => gw.snr).join(", ");

msg.payload = 
  "Received by " + count + " gateway" + s +
  ", with RSSI" + s + " " + rssi +
  " and SNR" + s + " " + snr;

…or with template literals:

msg.payload =
  `Received by ${count} gateway${s}, with RSSI${s} ${rssi} and SNR${s} ${snr}`;
1 Like

This is gold-plating but good for learning :slight_smile:

I end up with the following twitter message :

brandevoort IoT ‏@brandevoort_eu 34s34 seconds ago

Object position : 51.4571686 , 5.6171753
Gateway ID : eui-b827ebfffe517647
RSSI=-48 SNR=9.8

I still have to catch a second gateway to see what it looks like in “plural” mode

Hi @arjanvanb and @mvbakel,

I have been reading through this post and the node-red quick start as well.

I finally made the flow as shown below.

But when I inject the time stamp, it shows :slight_smile:

22/08/2017, 19:40:32node: function
msg : Object
object
_msgid: "8cd2f01e.744d4"
topic: ""
payload: 1494689048489

Can you please let me know what I am doing wrong.

Regards,
Sid
My flow is :

[{“id”:“f2a8dc4b.63b01”,“type”:“ttn message”,“z”:“ba1baf4e.520de”,“name”:"",“app”:“9a11302e.19f89”,“dev_id”:“sidsfirstdevice”,“field”:"",“x”:256,“y”:212,“wires”:[[“9f122e7e.f7cfc”]]},{“id”:“a86ec9a1.145318”,“type”:“debug”,“z”:“ba1baf4e.520de”,“name”:“device”,“active”:true,“console”:“false”,“complete”:“true”,“x”:511,“y”:124,“wires”:[]},{“id”:“d53d0a4b.c61a18”,“type”:“ttn send”,“z”:“ba1baf4e.520de”,“name”:"",“app”:“9a11302e.19f89”,“dev_id”:“sidsfirstdevice”,“port”:“1”,“x”:550,“y”:386,“wires”:[]},{“id”:“b62e1981.26e528”,“type”:“ttn device”,“z”:“ba1baf4e.520de”,“name”:"",“app”:“9a11302e.19f89”,“dev_id”:“sidsfirstdevice”,“event”:“activations”,“x”:249,“y”:124,“wires”:[[“a86ec9a1.145318”]]},{“id”:“9f122e7e.f7cfc”,“type”:“debug”,“z”:“ba1baf4e.520de”,“name”:“message”,“active”:true,“console”:“false”,“complete”:“true”,“x”:507,“y”:218,“wires”:[]},{“id”:“f3454569.753e38”,“type”:“debug”,“z”:“ba1baf4e.520de”,“name”:“function”,“active”:true,“console”:“false”,“complete”:“true”,“x”:551,“y”:303,“wires”:[]},{“id”:“4549c7c1.fa3508”,“type”:“inject”,“z”:“ba1baf4e.520de”,“name”:"",“topic”:"",“payload”:"",“payloadType”:“date”,“repeat”:"",“crontab”:"",“once”:false,“x”:188,“y”:324,“wires”:[[“d53d0a4b.c61a18”,“f3454569.753e38”]]},{“id”:“9a11302e.19f89”,“type”:“ttn app”,“z”:“ba1baf4e.520de”,“appId”:“sidsfirstapplication”,“region”:“se”,“accessKey”:“ttn-account-v2.R7yqoOfazcI7IWHgMCVmeOM8tXI9mC7QwcE6H2VYCtg”}]

I am loging the messages from my ttn node running the cayenneLPP sketch to a local file on my desktop computer using NodeRed. This works using the following NodeRed flow:
grafik
I would like to have the timestamp out of the metadate which i obtained with the following code in the function node:

return {
//Some fields from the metadata
time: msg.metadata.time };

to be logged with the payload. How can I convert the time metadata to be a payload type and combine it so that I get one line log entries with timestamp first followed by the payload. Everything I tried was not successful…
Can somebody give me a hint?

Have you looked at the split and join nodes? (example)

Yes, thanks, but SPLIT only works on the payload part of the message and my extracted time from metadata is not payload… I do not see how split and join would help eafter looking at the example but I am a nodered newbie

deleted…

see The LIBRARY basement part 4