Understanding Fcnt

Hello,

I am confused about the Fcnt value I get upon decoding LoRaWAN packets. I was wondering if someone could enlighten me in understanding them. The Fcnt value in the FHDR is D82E (Big Endian) however I’m not too sure how this value is so large. Upon putting new firmware on a mbed board I presumed it would reset. The counter in TTN resets each time I flash the device with a new program a number like 55342 seems far too large to be my frame count.
_

Summary

80a0fed8827c2ed804a9bd1fcea21bc18cafcb6aa84c87e1df69b0bdc8ae9185

Below are the values I get back from parsing
( FHDR = DevAddr[4] | FCtrl[1] | FCnt[2] | FOpts[0…15] )
DevAddr = 82D8FEA0 (Big Endian)
FCtrl = 7C
FCnt = D82E (Big Endian)
FOpts = 04A9BD1FCEA21BC18CAFCB6A

Message Type = Confirmed Data Up
Direction = up
FCnt = 55342
FCtrl.ACK = true
FCtrl.ADR = false

_

That’s not a TTN DevAddr. Where did you get this packet? Are you sure it’s a full LoRaWAN packet as received by a gateway?

The decoder you’re using will boldly assume it’s a valid LoRaWAN 1.0.x packet when it does not know the secret keys to validate the MIC. Also, the decoder shows that the packet includes MAC commands in FOpts, 04A9BD1FCEA21BC18CAFCB6A, which I don’t think is valid. 04 would indicate a DutyCycleAns which is an acknowledgement without any payload. The next byte, A9 is not a valid MAC command.

Probably more precisely: whenever the device performs a new OTAA Join.

I got this packet from a LoRa node that I set to receive rx on the same frequency as a LoRaWAN node On 868.3 with the same sf and coding rate and IQ. My lorawan node (not the receiver) is on ttn so it is concerning that this is the case of the devaddr I will have to look into it.

When it does capture my node the address is follows
4060151268010f914c747216e62f86ca026bd885f81654c3f14e4db48087d92e4cb23

6015126 being the Device address, correct?

I can enter the secrets to decode but I wanted to to capture packet in its entirety and and monitor frame count. The purpose would be to replay a packet with high frame count before mentioned here.
https://www.thethingsnetwork.org/forum/t/turning-off-frame-counting-for-security-research/22694/3

That’s 3.5 bytes, not 4.

The DevAddr of that last packet would be 60151268 (4 bytes, LSB), hence 68121560 (MSB), which does not start with 0x26 or 0x27 which TTN addresses should.

Any chance that in the log you’re not printing leading zeroes for values of 0x0F and lower? Like, any chance the packet actually starts with one of:

40 60 01 51 26 80 01 00 …
40 60 15 01 26 80 01 00 …

That would decode to DevAddr 0x26510160 or 0x26011560, and FCnt 0x0001. In your device’s memory this is probably not an issue, assuming you’re just keeping an array of bytes there, and are not using some hexadecimal string representation when you want to replay it.

Strange,

In the code buffer size is defined to 48 which I assumed may be asking for buffer overflow, this may be an issue. Maybe as the original ping-pong program was made by Semtech to capture regular LoRa packets between two devices slave and master not mac lorawan packets going to net serv ? . I don’t get how it would not note leading zeros is it the way the array works?

You are correct I am looping through buffer as an array and printing result. When printing the packet to debug in my program I’m am using a %x hex identifier.

In the buffer it’s really just bits, zeroes and ones, which do not have any notion of leading zeroes. The memory contents (or LoRa radio transmission) of binary 0b00001101 can be printed to be read by humans in many ways:

  • decimal: 13
  • hexadecimal: 0xD, 0x0D, Dhex, 0Dhex, D16, 0D16, or some lowercase version of that
  • ASCII: new line (carriage return)
  • Roman: XIII
  • and so on.

So, when printing a single byte, both hexadecimal 0xD and 0x0D refer to the very same bit value in memory. But remember that 1 byte of 8 bits needs at most two characters to be printed as hexadecimal, like 0x00, 0x01, …, 0x0F, 0x10, …, 0xFD, 0xFE through 0xFF. So when not printing delimiters between the bytes, you need leading zeroes to enforce each byte to print as exactly two characters, to tell where each byte starts and ends.

By the way: beware not to use that value of 48 as the length of the message, but to use the actual received length that the LoRa module gives you, as otherwise you will not know how many bytes were in a packet. Within a LoRaWAN message there is no indication of its total length. Instead, the LoRa module tells the software how many bytes were received and the LoRaWAN standard specifies that a full LoRaWAN uplink message starts with a specific header, and ends with a 4 byte MIC. So a decoder implicitly knows where the application payload starts and ends.

For fprintf you could try “%02x” to enforce 2 characters for each byte, showing a leading zero whenever needed. Or print a space between each byte.

1 Like

Thank you for clarification and suggestions.

Thanks for help Arjan after editing my code I got the correct output today.

Summary
Assuming hex-encoded packet
40601501268002000f8b0953374db4b50a0d6976b13edb1b8ff27294068a8fc97fb8d431c01a

Message Type = Data
  PHYPayload = 40601501268002000F8B0953374DB4B50A0D6976B13EDB1B8FF27294068A8FC97FB8D431C01A

( PHYPayload = MHDR[1] | MACPayload[..] | MIC[4] )
        MHDR = 40
  MACPayload = 601501268002000F8B0953374DB4B50A0D6976B13EDB1B8FF27294068A8FC97FB8
         MIC = D431C01A

( MACPayload = FHDR | FPort | FRMPayload )
        FHDR = 60150126800200
       FPort = 0F
  FRMPayload = 8B0953374DB4B50A0D6976B13EDB1B8FF27294068A8FC97FB8

      ( FHDR = DevAddr[4] | FCtrl[1] | FCnt[2] | FOpts[0..15] )
     DevAddr = 26011560 (Big Endian)
       FCtrl = 80
        FCnt = 0002 (Big Endian)
       FOpts = 

Message Type = Unconfirmed Data Up
   Direction = up
        FCnt = 2
   FCtrl.ACK = false
   FCtrl.ADR = true
1 Like

Nice. I guess you know, but just in case: without decoding the full LoRaWAN packet, you could easily check the first byte to only consider uplinks, and then compare bytes 1 through 4 with some known DevAddr.

Very much untested:

// LSB; for TTN should end with 0x26 or 0x27
const uint8_t devaddr[4] = { 0x60, 0x15, 0x01, 0x26 }; 
 
// Byte 0: MHDR; bits 7..5 in MHDR: message type
uint8_t mtype = buffer[0] >> 5;

// Bytes 6..7: FCnt (LSB; only 2 bytes, even for 32 bits counter)
uint16_t fcnt = buffer[6] | buffer[7] << 8;

if (mtype == 0b010 || mtype == 0b100) {
  // Bytes 1..4: DevAddr (LSB)
  if (memcmp(buffer + 1, devaddr, 4) == 0) {
    // Found an uplink for the given DevAddr
    ...
  }
}

That looks like a good idea to filter target packets thanks, some further ideas I have for my project are switching the single channel frequency every 15 seconds to scan other channels.

At the moment though I am having an issue repeating a received frame using SX1272Lib in mbed, In the API Radio.Send (Sends the buffer of size. Prepares the packet to be sent and sets the radio in transmission.) . Each time I try to send it I receive a TxTimeout.

typically outputs like this.

Summary
OnRxTimeout
OnRxDone -25

RX Recieved Packet

4060150126c04b000f9a3a2f0cd02177fc5ad4637d7a2f8fda97f9bec8dabf23f84a0fd9e7daf9

TX Radio.Send

OnTxTimeout

The output I am expecting is OnTxDone but am not sure why it times out each time. If sent just after a Uplink on the same frequency I assumed it would transmit.

If you are interested my code is below. (line 119-136)
https://pastebin.com/YPVxtuuU

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