Logging MAC commands through MQTT

I am currently setting up a small mqtt consumer for the purpose of monitoring lorawan reception (rssi/snr) and data rates. I have a small device that sends ping messages, and I want to log the rssi/datarate/etc when it’s sending data in different locations (all on the same gateway).
I have the consumer running by consuming mqtt messages. All is peachy so far.

My question is how I can monitor mac commands. I’d like to know what LinkAdrREQ messages are being sent to the device. I see messages like gateway//command/down that seem to be the mac commands? I see a binary phyPayload in there. Is that where the mac command data is? Can I decode those into what chirpstack shows if I open the Live LoraWan Frame viewer?

Ok, I found the resource I need. I was right in thinking the phyPayload is the right field in the
gateway/<gwid>/command/down topic. Using https://github.com/mcci-catena/arduino-lmic/blob/master/doc/LoRaWAN-at-a-glance.pdf you can basically decode the whole lot. The python bitstring package is a huge help too. It allows me to index/slice a binary set of bits/bytes on the bit level.
If you want the first byte (8 bits) of a binary byte array, you can say myarr[:8].
So with this snippet I can reproduce what chirpstack is showing in the live lorawan viewer (almost all numbers are multiples of 8):

from bitstring import BitArray
payload = json.loads(message.payload.decode('ascii'))
phypayload = BitArray(b64decode(payload['phyPayload']))
devaddr = phypayload[8:40].hex
foptslen = phypayload[44:48].uint
if foptslen > 0:
    mac_command = phypayload[64:64+8*foptslen]
    cid = mac_command[:8].uint
    if cid == 3: # LinkADRReq MAC command
        dr = mac_command[8:12].uint
        tx_rate = mac_command[12:16].uint
        chmask = mac_command[16:32].hex
1 Like