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