Hi just been getting to know CS v4 very impressed. I’ve used older versions on Gateways.
One thing I wanted was to be able to stash raw logs to a DB. I’m a scripter not a Developer so with the aid of
Ghatgpt
I got it to convert an example form Go to Python.
After many blind alleys I have a POC that might be of use to others. Brian
@bconway
I tried to take the lead from a post a while back and use MQTT but it looks like the protoBuf is different on inbound MQTT to that used for REDIS logging.
One thing for joins the “mType”: key doesn’t get set but I can see it’s join as the “devEui” is set.
2023-03-15 19:05:56 JoinRequest DevEUI: 24e124535b314729
"phyPayload": "AAEAKgDAJOEkKUcxW1Mk4SSsqDqw9Ig=",
"txInfo": {...},
"rxInfo": [..],
"devEui": "24e124535b314729",
"time": "2023-03-15T19:05:56.367195Z"
2023-03-15 19:11:44 UnconfirmedDataUP DevAddr: e0043224
{ "phyPayload": "QCQyBOCAVRIFb92AeHShyiTB"
"txInfo": {...},
"rxInfo": [..],
"mType": "UNCONFIRMED_DATA_UP",
"devAddr": "e0043224",
"time": "2023-03-15T19:06:44.080123Z"
solution
[REDIS]—[xRead up/down stream]—[Publish to MQTT]–[Node-RED]—[InfluxDB]
#########################################################################################
# ChirpStack REDIS logging READ #
# Decode - frame_log.prot UplinkFrameLog() & DownlinkFrameLog() #
# Publish to MQTT eu868/gateway/GUI/logging_UP & logging_Down #
# issue v X.0 #
#########################################################################################
#import json
import redis
import paho.mqtt.client as mqtt #import the client1
import google.protobuf.json_format as json_format
import google.protobuf.message as message
from google.protobuf.json_format import MessageToJson
from chirpstack_api import api
# REDIS
server = "localhost"
port = 6379
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
rdb = redis.Redis(connection_pool=pool)
key = "gw:stream:frame"
lid = "0"
# MQTT
broker_address = "localhost"
client = mqtt.Client("protoBuf") # create new instance
print("connecting to MQTT")
client.connect(broker_address) # connect to broker
while True:
resp = rdb.xread({key: lid}, count=1, block=0)
if len(resp) != 1:
raise ValueError("Exactly one stream response is expected")
for msg in resp[0][1]:
lid = msg[0].decode()
if b"up" in msg[1]:
#print('msg[1][b"up"]',msg[1][b"up"])
b = msg[1][b"up"]
pl = api.frame_log_pb2.UplinkFrameLog()
pl.ParseFromString(b)
#print("=== UP ===")
print(MessageToJson(pl))
client.publish("eu868/gateways/logging_UP",MessageToJson(pl))
if b"down" in msg[1]:
b = msg[1][b"down"]
pl = api.frame_log_pb2.DownlinkFrameLog()
pl.ParseFromString(b)
#print("=== DOWN ===")
print(MessageToJson(pl))
client.publish("eu868/gateways/logging_Down",MessageToJson(pl))
Hi Brian I took my approach from reading the Docs. There is no “Gateway Logging Service” in API the documentation. And [Features/Logging] “Frame logging: ChirpStack provides an option to log all uplink and downlink frames to a Redis stream, which can be consumed by external application(s) for monitoring or logging purposes.”
And the point I started from was: https://github.com/chirpstack/chirpstack/tree/master/examples/frame_log/go/main.go which is connecting to REDIS.
So I’m confused what is the correct way to get access to raw gateway logs?
Thanks, Lawrence
I tried that as that’s what you recommended in a post on the Forum. But get this error google.protobuf.message.DecodeError: Error parsing message. The protoBuf length is quite different between MQTT payload and REDIS read. Any thoughts?
File "/home/chirplns/.local/mqtt_gw_frame_logger.py", line 25, in on_message
pl.ParseFromString(b) google.protobuf.message.DecodeError: Error parsing message
b'\n$@W}\x0b&\x80\x86\x9c\x05\x89\x98\xde8\x18Wm\xd0\xca\r\xfb\xb6\xa7\xd5\xbc\xc1U\xe7\xd1$\x03\x9f\x11\x8c\xdb\xebB"\x12\x08\xa0\x84\x91\x9e\x03\x12\n\x1a\x08\x08\xc8\xd0\x07\x10\x07(\x01*M\n\x1024e124fffef32f55\x10\xe6\xe4\x01\x1a\x0b\x08\x81\xc6\xcc\xa0\x06\x10\x88\xa8\xe8v"\x0b\x08\x93\xcb\xf7\x89\x05\x10\xc0\xe0\xddv0\xb6\xff\xff\xff\xff\xff\xff\xff\xff\x01=33\x13A@\x02H\x01j\x04\xde\xeb\xc8D\x80\x01\x02'
msgLng: 137
b'\n$@W}\x0b&\x80\x86\x9c\x05\x89\x98\xde8\x18Wm\xd0\xca\r\xfb\xb6\xa7\xd5\xbc\xc1U\xe7\xd1$\x03\x9f\x11\x8c\xdb\xebB\x12\x12\x08\xa0\x84\x91\x9e\x03\x12\n\x1a\x08\x08\xc8\xd0\x07\x10\x07(\x01\x1a\x99\x01\n\x1024e124fffef32f55\x10\xe6\xe4\x01\x1a\x0b\x08\x81\xc6\xcc\xa0\x06\x10\x88\xa8\xe8v"\x0b\x08\x93\xcb\xf7\x89\x05\x10\xc0\xe0\xddv0\xb6\xff\xff\xff\xff\xff\xff\xff\xff\x01=33\x13A@\x02H\x01b\x12\t\xcb\xe9j\xc30\xe1I@\x11\x00\x00\x00\x80\x9c(\xd5\xbfj\x04\xde\xeb\xc8Dz\x19\n\x10region_config_id\x12\x05eu868z\x1b\n\x12region_common_name\x12\x05EU868\x80\x01\x02 \x02*\x08260b7d57:\x0b\x08\x81\xc6\xcc\xa0\x06\x10\x88\xa8\xe8v'
msgLng: 239
great work, been meaning to try and get the frames for greater metrics for logging and testing purposes for a while.
did you manage to decode the mqtt gateway topic? Not being familiar with grpc/protobuf and lacking understanding how to use it i usually use the http api integration - but i cannot get the gateway frames this way. there are basically no examples anywhere either 
sorry to tag you @bconway but is this what you do? If so are you able to elaborate on how i would decode the mqtt gateway protobuf. unfortunately i usually use python as well for almost all my scripting.
"github.com/chirpstack/chirpstack/api/go/v4/gw"
"github.com/thingspect/atlas/pkg/decode"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
// gatewayStats parses a gateway Stats payload from a []byte according to the
// spec.
func gatewayStats(body []byte) ([]*decode.Point, error) {
statsMsg := &gw.GatewayStats{}
if err := proto.Unmarshal(body, statsMsg); err != nil {
return nil, err
hey mate,
thanks for replying - i will try decode the mqtt messages with that protobuf you linked (not that i’m 100% sure on exactly what I’m doing with grpc/protobuf as I’ve never used it before).
the difference I found so far was the redis stream and code iiLaw posted provides the gateway frames which is what i was interested in so i can log the other traffic around me and what type of msg they are. I currently do this with a python script by reading the docker logs and picking up the unknown devices.
i did run a modified version of his script which worked fine for a few hours but it seems to of killed the redis db and dropped all the assigned activated device addresses although that could of been something else stupid unrelated i did lol.
i think the reason the other code doesn’t work is because when i changed it to json it is not the same payload - it looks more aligned with the gist you sent (ill check this tomorrow).
this seems to be the address to console that we’re needing to decode
https://example.com/api.InternalService/StreamGatewayFrames