Encode/decode i'm confuse

Hi everyone,

I’ll start by saying that I’m not expert with LoRa and also with coding, but I’m trying to do something.
I’ve been trying to figure out how to send my encoded data for a few days and then decode it on the server side.

I’m using the RadioLib library.
Didactically, I want to send 2 constant data, that hypothetically represent humidity and temperature (positive integers at the moment).

On the device side, I use this part of code as a teaching example.

uint8_t payload[4];
int16_t tmp;
int16_t hum;

tmp = 0x01;  //1 value
tmp = htons(tmp);
memcpy(&payload[0], &tmp, sizeof(tmp));

hum = 0x00  //0 value;
hum = htons(hum);
memcpy(&payload[2], &hum, sizeof(hum));

state = node.uplink(payload, sizeof(payload), 10, false, &eventUp);

LoRa server side I use this below

function decodeUplink(input) {
   var float = 0, tmp, hum;
   tmp = (input.bytes[0] << 8 | input.bytes[1])/100;
   hum = (input.bytes[2] << 8 | input.bytes[3])/100;
   return {
     date: {
       temperatures: tmp,
       humidity: hum,
     warnings: [],
     errors: []

and as output I have this part, as I expect.

"frm_payload": "AAEAAA==",
"decoded_payload": {
	"humidity": 0,
	"temperatures": 0.01

the LoRa server in question is TTN.

I send the same data 10 times, and 10 times I find both frm_payload and hum and temp as expected.
I try to move the exact same decodeUplink code to ChirpStack, but something go wrong.
First of all the payload changes constantly and then the values for hum and temp are also inconsistent.

Where am I wrong? because I’m definitely doing something wrong.
Can anyone help me understand?


  • source code from device side is the same;
  • I’m using a 4.6 chirpstack installed locally on one my system;
  • as gateway, I use a Pi4 with RAK, and for my test I only change network server reference.

thnaks, Davide

You may have better luck including what you areactually seeing on the ChirpStack side. But since I’m guessing, hopefully you’re looking at the data (decrypted) event field and not the frm_payload (encrypted) frame field.


thanks for your time and sorry for not to be clear.
When i referr to chirpstack uplink payload, i refer to what i have sign with red arrow on image.
When i send constant data that value change and following that also temp and hum change with not coerent value.
Is correct to use the same code for decoding on TTN and ChirpStack? or something have to be changed? for what I understand, payload is “bytes” in “input” object.

If other info will be necessary to better unterstand my question/problem, do not esitate to ask me.

thanks, Davide


Ignoring the JavaScript values entirely for now, your TTN payload base64-decodes as this, which sounds like it is expected:

$ echo AAEAAA==|base64 -D|hexdump -C
00000000  00 01 00 00                                       |....|

And the ChirpStack one you just posted (data) looks like this:

$ echo Bevl1w==|base64 -D|hexdump -C
00000000  05 eb e5 d7                                       |....|

Do you have the ability to debug on the device and verify what payloads are being assembled and sent?


I’m sorry for the late response, but trying to retrieve data for your request, now magically everything is working as expected.

I have made no change on device source code and also no change on decode code. I don’t know why, but now, both TTN and ChirpStark work perfectly.
I get results consistent with what I expected, both as values of the two constants, and as the same value of the payload.

Sincerly I don’t understand why it didn’t work before…

I will try to continue my project and in case of other problems, I will come back to you :slight_smile:

I tested both gateway software “ChirpStack Gateway OS” and “pi+rak software” and everything seems to be fine.

Thank you for your time.

1 Like


I claimed victory too soon.
After a few restart/wipe and chirpstack/ttn change, no change on code, ttn is ok but chirpstack is ko.


Isn’t this strange? It is virtually impossible to get the wrong values from the device, given that there is MIC.

Could it be that you are receiving uplinks from different device functions, perhaps characterized by different FPort numbers?


at the moment i’m excluding the payload decode.
I’m trying to understand why payload value (on chirpstack) change when payload value at the source is a constant value.
that don’t happen on ttn.
nothing change during that test on end device code
I have an heltec wifi lora 32 V3 devboard no other lora device in power on.

this is the source code for uplink

void my_uplink() {
    int state_4;
    LoRaWANEvent_t eventUp;
    uint8_t payload[1];
    payload[0] = 0x00;

    state_4 = node.uplink(payload, sizeof(payload), 10, false, &eventUp);

    Serial.printf("payload: [%2d] - size\n", sizeof(payload));
    for (int i = 0; i < sizeof(payload); i++) {
        Serial.printf("payload: [%2d] - [%4d] - [%02x]\n", i, payload[i], payload[i]);

    if(state_4 == RADIOLIB_ERR_NONE) {
    } else if(state_4 == RADIOLIB_ERR_UPLINK_UNAVAILABLE) {
        Serial.printf("[LoRaWAN] - uplink [%6d] - [RADIOLIB_ERR_UPLINK_UNAVAILABLE] User requested to start uplink while still inside RX window.\n", state_4);
    } else {
        Serial.printf("[LoRaWAN] - uplink [%6d] - failed\n", state_4);

this is the output on serial monitor consolle

15:14:33:221 -> ESP-ROM:esp32s3-20210327
15:14:33:222 -> Build:Mar 27 2021
15:14:33:222 -> rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
15:14:33:222 -> SPIWP:0xee
15:14:33:222 -> mode:DIO, clock div:1
15:14:33:222 -> load:0x3fce3808,len:0x44c
15:14:33:222 -> load:0x403c9700,len:0xbe4
15:14:33:222 -> load:0x403cc700,len:0x2a68
15:14:33:222 -> entry 0x403c98d4

15:14:34:047 -> [ SX1262] Initializing ... success!
15:14:34:099 -> [LoRaWAN] Attempting over-the-air activation ... success!
15:14:39:653 -> success!
15:14:39:654 -> 
15:14:39:654 -> AHT10
15:14:39:814 -> [LoRaWAN] Sending uplink packet ... and wait downlink
15:14:39:992 -> ---------------------
15:14:39:994 -> payload: [ 1] - size
15:14:39:996 -> payload: [ 0] - [   0] - [00]
15:14:39:999 -> ---------------------
15:14:40:001 -> [LoRaWAN] Event information: [    UPLINK]
15:14:41:099 -> [LoRaWAN]       - downlink - received!
15:14:41:103 -> [LoRaWAN]       - downlink - data [    0]: <MAC commands only>
15:14:41:107 -> [LoRaWAN] Event information: [  DOWNLINK]
15:14:41:111 -> 
15:15:41:110 -> AHT10
15:15:41:273 -> [LoRaWAN] Sending uplink packet ... and wait downlink
15:15:41:410 -> ---------------------
15:15:41:414 -> payload: [ 1] - size
15:15:41:415 -> payload: [ 0] - [   0] - [00]
15:15:41:416 -> ---------------------
15:15:41:417 -> [LoRaWAN] Event information: [    UPLINK]
15:15:42:464 -> [LoRaWAN]       - downlink - received!
15:15:42:467 -> [LoRaWAN]       - downlink - data [    0]: <MAC commands only>
15:15:42:472 -> [LoRaWAN] Event information: [  DOWNLINK]
15:15:42:475 ->

and here chirpstack output
I do a wipe, after that end device join network and send data for first run one minute late send data for second run.
orginal payload is always “00” but on chirpstack the first is “ac” and then “fa”

same action sequence, but now my gateway referr ttn.
I do not attach serial console output. is the same with different time.
no change on end device code.
only a wipe send through the serial to force a join to ttn network.
do not look the temp and humidity part, just the hexadecimal code which remains coherent at “00” as expected

Are you using LoRaWAN 1.1? If you’re using LoRaWAN 1.1, did you check whether you got both the NwkKey and AppKey entered correctly in Chirpstack? I’ve never used LoRaWAN 1.1 before, but it looks like AppKey is used to derive AppSKey, which is used to only encrypt/decrypt the application payload. So if you got the AppKey wrong, the encryption/decryption of data would not work correctly.

Yes, I am using version 1.1 rev A, but even using, for example, version 1.0.3, the result does not change.

I’m not very expert but I follow your reflection and from what I understand I agree with the encrypt/decrypt function following the exchange of keys.

If I understand correctly, this happens during the join phase of an end device to the Lorawan network. Once the device has joined, the identities are defined and the keys exchanged. I imagine there may be subsequent phases of “re-verification” of identity, but I expect this to be “almost” transparent to the dialogue.

The thing that puzzles me is that even variations in shared and certified keys should lead to having the same payload value, otherwise the payload decode phase would be impossible.

At the moment I have no idea where to investigate, also because at a certain point in the tests this thing worked on both ChirpStack and TTN in the same way.

At this point I’m sure I’m missing something.


Agreed this is puzzling. Can you find an example where your firmware debugging/serial log shows a different payload output than what ChirpStack decodes for you? I don’t think I saw it above.

I’ve taken plenty of devices across different LoRaWAN networks without any unexpected behavior in payloads, so I’m inclined to think your device is doing something weird here.

1 Like


I attach 3 images taken from above, where you can see what you are asking, I hope I have understood well, if so let me know and I will try to provide you with everything that may be useful to you.

1 image, where there is the firmware code where I build (fixed), send to network and write to the console, the payload;
2 image where you can see an extract of the vscode/platformio console with the printout of the size and payload content;
3 image where you can see the payload (data) on the chirpstack side, which varies, despite being fixed on the firmware side.

Can these images be useful to you? Let me know.
Thanks, Davide

image 1

iamge 2

image 3


I found the cause of the problem.
The appKey in the chirpstack had inadvertently been set to all “0”, the device was joined to the network, but the decoding of the payload was incorrect due to the appSkey.

thanks for the suggestions, Davide

1 Like

Well, congratulations!

Unlike LoRaWAN 1.0, AppKey does not seem to be linked to MIC in any way for LoRaWAN 1.1. MIC is also computed after encryption and before decryption. So a mistake to in the LoRaWAN 1.1 AppKey appears as an inability to correctly transfer data, rather than MIC errors.