Import gateway stats from the MQTT payloads

Viewed 22

I have a self-hosted chirpstak (4.6.0). When I log in and go to the dashboard of a gateway, I can see these kind of stats

I'd like to intergrate those values in my platform, but I don't know which is the best/recommended way to do so.

I see on my MQTT broker messages with stats for the gateway, using topics like

  • eu868/gateway/fcc23dfffe2ead35/state/conn
  • eu868/gateway/fcc23dfffe2ead35/event/stats
  • eu868/gateway/fcc23dfffe2ead35/event/up

which seems exactly what I want, but the payloads are binary data (protobuf).

I tried downloading the protobuf specs from https://github.com/brocaar/chirpstack-api/tree/master/protobuf and to compile them myself, but I was not able to get a proper python script that decodes the MQTT messages, I had a lot of exceptions becuase modules were missing.

Then I realized the python packages has already a compiled version, so I installed it and tried to use that instead:

from chirpstack_api.gw.gw_pb2 import GatewayStats

GatewayStats.ParseFromString(bin_payload)

where bin_payload is the body of the MQTT message of event/stats topics. But it also raises this exception

TypeError: descriptor 'ParseFromString' for 'google._upb._message.Message' objects doesn't apply to a 'bytes' object

So, how can I use the MQTT messages in order to extract:

  • number of received packages
  • number or sent packages
  • current status (online, offline) etc

Thanks

1 Answers

Ok, I've had 0 experience with protobuf so, I didn't really know what I was doing. After reading tutorials about protobuf I realized what I was doing wrong.

The ParseFromString method is not a class method that generates a new message object, but it operates on a Message object and populates it with values from the string. That means, that this works:

from google.protobuf import json_format
from chirpstack_api.gw.gw_pb2 import GatewayStats

obj = GatewayStats()
obj.ParseFromString(bin_payload)
payload = json_format.MessageToDict(obj)

And with this code, I get this:

{
    "time": "2026-07-23T14:53:26Z",
    "rxPacketsReceived": 2,
    "gatewayId": "0016c001f184d28a"
}

What I didn't expect is that the GatewayStat for a different gateway has different values. For example, another gateway send me this state

{
    "time": "2026-07-23T14:53:24Z",
    "location": {
        "latitude": <redacted>,
        "longitude": <redacted>,
        "altitude": 8.0,
        "source": "GPS"
    },
    "gatewayId": "0016c001f184da8d"

how come that here I get location (and what does altitude == 8.0 mean? 8 meters above sea level?) and why the other gateway sends the number of received packages? Is it normal, that the stats messages do not always contain all the information every time?