Uplink-PayLoadFormatter

Hello everyone, I have an Arduino MKR1310 in TTN.
I measure the temperature and humidity with a DHT22 sensor. The measured values are visible in TTN, but in a hexadecimal code, I want to transform this code to ascii, I can do that by writing an uplink - PayLoadformatter. What is the correct code to write ? Thanks for your help.

What does you encoder look like?

Then read https://www.thethingsnetwork.org/docs/devices/bytes/ and search on the forum, lots of information.

Then please show us your code and where you are battling. As from your post we can see what you have done or tried.

var LED_STATES = [‘off’, ‘on’]

function decodeUplink(input) {
var data = {};
data.ledState = LED_STATES[input.bytes[0]];
return {
data: data,
};
}

function encodeDownlink(input) {
var i = LED_STATES.indexOf(input.data.ledState);
if (i === -1) {
return {
errors: [‘unknown led state’],
};
}
return {
bytes: [i],
fPort: 1,
};
}

I recieve in TTN this message in HEX format : 31392E313037372E3130

It is in Ascii 19.1077.10

temp = 19.10 degrees clecius
hum = 77.10 %

Can you please also use the post formatting tool </> post all code, text any thing you can copy and past?

This is the code in the Arduino MKR 1310

#include "arduino_secrets.h"
#include <MKRWAN.h>
#include <Arduino_JSON.h>
#include "DHT.h"
LoRaModem modem;
String appEui = SECRET_APPEUI;
String appKey = SECRET_APPKEY;

#define DHTPIN 9
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
//make the upload
unsigned long previousMillis = 0;
const long interval = 60 * 1000; //  = 60 sec
void setup() {
  Serial.begin(115200);
 if (!modem.begin(EU868)) {
    Serial.println("Error");
    while (1) {}
  };
  Serial.print("Module version is: ");
  Serial.println(modem.version());
  Serial.print("Device EUI is: ");
  Serial.println(modem.deviceEUI());
  //Connecten to LoRa
  int connected = modem.joinOTAA(appEui, appKey);
  if (!connected) {
    Serial.println("Not possible to connect with LoRa");
    while (1) {}
  }
  dht.begin();
}
void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time you send the sensors value
    previousMillis = currentMillis;    
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    //maak de uplink gereed
    String msg = String(t) + String(h);
    Serial.print("Sending: " + msg + " - ");
    for (unsigned int i = 0; i < msg.length(); i++) {
      Serial.print(msg[i] >> 4, HEX);
      Serial.print(msg[i] & 0xF, HEX);
      Serial.print(" ");
    }
    Serial.println();
    //Send the uplink
    int err;
    modem.beginPacket();
    modem.print(msg);
    err = modem.endPacket(false);
    if (err > 0) {
      Serial.println("Values are correct sendet!");
    } else {
      Serial.println("Error :(");
    }
    if (!modem.available()) {
      Serial.println( downlink not received on the moment.");
      return;
    }
     
    char rcv[64];
    int i = 0;
    while (modem.available()) {
      rcv[i++] = (char)modem.read();
    }
    Serial.println();
   
    JSONVar myObject = JSON.parse(rcv);
    if (JSON.typeof(myObject) == "ongedifineerd") {
        return;
    }
    }
  }

Event details in TTN

{
  "name": "as.up.data.forward",
  "time": "2023-01-02T15:03:55.346183438Z",
  "identifiers": [
    {
      "device_ids": {
        "device_id": "eui-a8610a333729800c",
        "application_ids": {
          "application_id": "ruchesdalhem"
        },
        "dev_eui": "A8610A333729800C",
        "join_eui": "A8610A333729800C",
        "dev_addr": "260B2FFA"
      }
    }
  ],
  "data": {
    "@type": "type.googleapis.com/ttn.lorawan.v3.ApplicationUp",
    "end_device_ids": {
      "device_id": "eui-a8610a333729800c",
      "application_ids": {
        "application_id": "ruchesdalhem"
      },
      "dev_eui": "A8610A333729800C",
      "join_eui": "A8610A333729800C",
      "dev_addr": "260B2FFA"
    },
    "correlation_ids": [
      "as:up:01GNSG5D6EPPZBN657R0DCYG07",
      "gs:conn:01GNSAEZFNCT4EP5RGCN419YN4",
      "gs:up:host:01GNSAEZFXJS3KQV646DT849KA",
      "gs:uplink:01GNSG5CZWZXCY1G8AXQDWN1CY",
      "ns:uplink:01GNSG5CZX355T2YYS29FEK4D9",
      "rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01GNSG5CZXMN52JHGQD31SZXQJ",
      "rpc:/ttn.lorawan.v3.NsAs/HandleUplink:01GNSG5D6DAB63GHM29K6YZ5C5"
    ],
    "received_at": "2023-01-02T15:03:55.341566433Z",
    "uplink_message": {
      "session_key_id": "AYVy0jKz8KduW+ZoptkIdA==",
      "f_port": 2,
      "f_cnt": 52,
      "frm_payload": "MTguNTA4MC4wMA==",
      "decoded_payload": {
        "ledState": null
      },
      "rx_metadata": [
        {
          "gateway_ids": {
            "gateway_id": "xxxxxxxxxxxxxxxxxxxxxx",
            "eui": "xxxxxxxxxxxxxxxxxxxxxxxx"
          },
          "time": "2023-01-02T15:03:55.059505939Z",
          "timestamp": 1681398731,
          "rssi": -57,
          "channel_rssi": -57,
          "snr": 10,
          "location": {
            "latitude": 50.7087743609399,
            "longitude": 5.72002100934697,
            "altitude": 90,
            "source": "SOURCE_REGISTRY"
          },
          "uplink_token": "CiIKIAoUZXVpLTU4YTBjYmZmZmU4MDIwMzUSCFigy//+gCA1EMu34KEGGgsI2+TLnQYQvrmWPyD4obLZ960B",
          "received_at": "2023-01-02T15:03:55.075752611Z"
        }
      ],
      "settings": {
        "data_rate": {
          "lora": {
            "bandwidth": 125000,
            "spreading_factor": 7,
            "coding_rate": "4/5"
          }
        },
        "frequency": "868300000",
        "timestamp": 1681398731,
        "time": "2023-01-02T15:03:55.059505939Z"
      },
      "received_at": "2023-01-02T15:03:55.133831683Z",
      "consumed_airtime": "0.061696s",
      "locations": {
        "user": {
          "latitude": 50.70877164318449,
          "longitude": 5.7199931147988545,
          "altitude": 90,
          "source": "SOURCE_REGISTRY"
        }
      },
      "version_ids": {
        "brand_id": "arduino",
        "model_id": "mkr-wan-1310",
        "hardware_version": "1.0",
        "firmware_version": "1.2.3",
        "band_id": "EU_863_870"
      },
      "network_ids": {
        "net_id": "000013",
        "tenant_id": "ttn",
        "cluster_id": "eu1",
        "cluster_address": "eu1.cloud.thethings.network"
      }
    }
  },
  "correlation_ids": [
    "as:up:01GNSG5D6EPPZBN657R0DCYG07",
    "gs:conn:01GNSAEZFNCT4EP5RGCN419YN4",
    "gs:up:host:01GNSAEZFXJS3KQV646DT849KA",
    "gs:uplink:01GNSG5CZWZXCY1G8AXQDWN1CY",
    "ns:uplink:01GNSG5CZX355T2YYS29FEK4D9",
    "rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01GNSG5CZXMN52JHGQD31SZXQJ",
    "rpc:/ttn.lorawan.v3.NsAs/HandleUplink:01GNSG5D6DAB63GHM29K6YZ5C5"
  ],
  "origin": "ip-10-100-5-128.eu-west-1.compute.internal",
  "context": {
    "tenant-id": "CgN0dG4="
  },
  "visibility": {
    "rights": [
      "RIGHT_APPLICATION_TRAFFIC_READ"
    ]
  },
  "unique_id": "01GNSG5D6JCA45GGJ0EPQ5JMNW"
}

Payload formatter

// This is used with the LoRa LED/ON off basic sketch
// Please refer to https://create.arduino.cc/editor/FT-CONTENT/043f42fb-2b04-4cfb-a277-b1a3dd5366c2/preview

var LED_STATES = ['off', 'on']

function decodeUplink(input) {
  var data = {};
  data.ledState = LED_STATES[input.bytes[0]];
  return {
    data: data,
  };
}

function encodeDownlink(input) {
  var i = LED_STATES.indexOf(input.data.ledState);
  if (i === -1) {
    return {
      errors: ['unknown led state'],
    };
  }
  return {
    bytes: [i],
    fPort: 1,
  };
}

function decodeDownlink(input) {
  return {
    data: {
      ledState: LED_STATES[input.bytes[0]]
    }
  }
}

ASCII, as you will have read in the link provided, is very inefficient and a mess to decode. Please for your battery lifetimes and the communities benefit, migrate to sending binary data - the link explains it all.

So 10 bytes in ASCII or 4 bytes as two 16 bit integers …

Hello Johan, I found the right code. Thank you for helping me!

function Decoder(bytes, port) {
 //source: https://flows.nodered.org/flow/845bb5b8cf788939dd261f472c289f77
 var result = ""; 
 for (var i = 0; i < bytes.length; i++) { 
   result += String.fromCharCode(parseInt(bytes[i])); 
 } 
 return { payload: result, };
}

@jan_vanbogget, whilst you are free to do as you please within the limits of the Fair Use Policy, you may find those answering here, all volunteers, won’t be so enthusiastic to help you if you wish to ignore community guidelines & preferences.

1 Like

Sending ASCII over LoRaWAN is not a good idea, please read the documentation.

10 bytes for your ASCII, you consume at SF7 61.7mS
4 bytes you consume at SF7 51.5mS

A increase of 19,8%, so you are decreasing your battery usage by nearly 20%, consuming 20% more valuable air time and under FUP from 24 to 20 messages per hour, not a practice I will follow.

1 Like

And of course the situation gets a lot worse if the node is some ditance from the Gateway and higher spreading factors are needed.

Especially when its easy enough to significantly cut the size of an ‘ASCII’ payload.

Thanks for the helpful tip!

I don’t understand Nick McCloud’s explanation at all.
Doesn’t matter, the information I got from the others is a useful piece of information…

There are three people saying the same thing. But if you’d read the Working with Bytes page that Johan had linked to, you’d already know this.

Simple, this is a community, if you don’t want to abide by the communities advice, guidelines & preferences, don’t expect much help with your next issue.

Getting temperature & humidity readings from a hive is just scratching the surface of what you can do - like weight of hive, bee counting and much much more. You’d be concerned if someone popped up and started asking basic questions about bee keeping and didn’t appear to take proper note of them. So it’s not unreasonable that we express such concerns - just like beekeeping there is a lot of detail to get right with LoRaWAN and just like beekeeping, a large community prepared to help people do it properly.

Its really simple.

There have been several attampts to persuade you that the impact on the service that someone else is paying for, can be reduced, with absolutly no loss of information, sent or received, within TTN for your application.

But you dont seem intersted.

I have set up a TTN sensor, that sends the same information as you are sending, but with a 60% reduction in the size of the payload, and it appears very nicley in the TTN console. Why is this not a good idea ?

Here are a few more post to read

Try it and if you don’t win post what you tried.

Dear, i understand your story only share. That’s because English isn’t my language, but I also don’t understand what my question has to do with honey bees. I’m just a hobbyist who got a small project up and running to transfer the temperature and humidity to LoRa. No more and no less. Don’t worry, I’m leaving this forum from me, you won’t be bothered anymore, and especially think about your heartbeat. You will not receive an answer from me and leave me alone. Thank you

I never said honey bees! But don’t you think your avatar picture doesn’t tell us what you are interested in?

You are very welcome to use the TTN community LoRaWAN network that is paid for by The Things Industries, so no need to leave, just please consider the community.

I could help you change the sketch to use Cayenne.

Cayenna is a kinf of standard payload format that is much more efficient than ASCII, and there is already a uplink payload decoder for that, so you don’t have to write your own. Temperature and humidity are already supported as standard data types in Cayenne, so that should work out easily.

Just let me know if you’re interested.
If you have a github repo, tell me the URL and I can make a clone with the required changes.