Debugging LoRaWAN packets

If you write software using LoRaWAN network at some point you may want to get more details about packets exchanged between your node and network. With uplinks and application downlinks should be simpler. They are being sent basically by you, so you can should now what is in payload and create proper payload formatter and browse data directly in TTN console. But what with MAC commands?

MAC commands can be sent by gateway/network server and they control node behavior. To have access to them you need to have LoRaWAN gateway under your control (you need just to have access to TTN console for this gateway). Then you can track MAC commands sent to devices.

All messages in LoRaWAN are encrypted on network level. Easiest way to get packet decrypted and also gather info what given packet means is to use lora-packet decryptor. This is tool written in node.js (GitHub page). To install:

npm install lora-packet

Now, you need network and application session key. Go to application console in TTN, select end device you want to debug and in section titled Session information you will find NwSKey and AppSKey.

If you hover over text fields there will show icon to copy key to clipboard. Then, you need payload itself. Go to gateway, find interesting you packet and there will be raw_payload field. You need its content. Then execute command line tool (I use npx since package lora-packet was installed not by root):

npx lora-packet-decode --nwkkey  933A411E0E63F32C22169EFA8464C1AA  --appkey  85BA526B915D37172B544DA8035DDED0 --base64 "YPjnCyaGAAADQP8AAQZ24oGT"
decoding from Base64:  YPjnCyaGAAADQP8AAQZ24oGT
Decoded packet
--------------
Message Type = Data
            PHYPayload = 60F8E70B268600000340FF00010676E28193

          ( PHYPayload = MHDR[1] | MACPayload[..] | MIC[4] )
                  MHDR = 60
            MACPayload = F8E70B268600000340FF000106
                   MIC = 76E28193 (OK)

          ( MACPayload = FHDR | FPort | FRMPayload )
                  FHDR = F8E70B268600000340FF000106
                 FPort = 
            FRMPayload = 

                ( FHDR = DevAddr[4] | FCtrl[1] | FCnt[2] | FOpts[0..15] )
               DevAddr = 260BE7F8 (Big Endian)
                 FCtrl = 86
                  FCnt = 0000 (Big Endian)
                 FOpts = 0340FF000106

          Message Type = Unconfirmed Data Down
             Direction = down
                  FCnt = 0
             FCtrl.ACK = false
             FCtrl.ADR = true
        FCtrl.FPending = false

TTN console shows you payload encoded as base64. In case you have packet in HEX, just use --hex instead of --base64.

This tool can be used for other packets in TTN network, you just need to know network and application session keys.