No data in message

The problem is that i get a payload from the device but it is not readable in my API.
my message is ok:

The MQTT is:

import binascii
import paho.mqtt.client as mqtt
import json
import pybase64
import requests

# Call back functions
APPEUI = "70B3D5E75xxxxxxxxx"
APPID = "xxxxxxxxxxxx"
PSW = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# gives connection message
def on_connect(mqttc, mosq, obj, rc):
    print("Connected with result code:" + str(rc))
    # subscribe for all devices of user
    mqttc.subscribe('+/devices/+/up')


# gives message from device
def on_message(mqttc, obj, msg):
    global app, deveui, counter
    try:
        x = json.loads(msg.payload.decode('utf-8'))
        # metadata
        app = x["app_id"]
        device = x["dev_id"]
        deveui = x["hardware_serial"]
        port = x["port"]
        confirmed = x["confirmed"]
        counter = x["counter"]
        global payload_fields
        payload_fields = x["payload_raw"]
        datetime = x["metadata"]["time"]
        frequency = x["metadata"]["frequency"]
        modulation = x["metadata"]["modulation"]
        data_rate = x["metadata"]["data_rate"]
        air_time = x["metadata"]["airtime"]
        coding_rate = x["metadata"]["coding_rate"]
        gateways = x["metadata"]["gateways"]

        for gw in gateways:
            global rssi, snr
            gateway_id = gw["gtw_id"]
            timestamp = gw["timestamp"]
            time = gw["time"]
            channel = gw["channel"]
            rssi = gw["rssi"]
            snr = gw["snr"]

    except Exception as e:
        print(e)
        pass

    #decoding the payload_field
    def decoder():
        global byte
        payload_r = (pybase64.b64decode(payload_fields + "="))  # decoding the Payload_r to Byte-Ascii string
        payload_h = binascii.hexlify(payload_r)  # Bin to b'hex
        node_data = (payload_h.decode("utf-8)"))  # b'hex to pretty
        byte = payload_r
        print(byte)
    decoder()
("here comes the code cracker and after that comes" )

def on_publish(mosq, obj, mid):
    print("mid: " + str(mid))

def on_subscribe(mosq, obj, mid, granted_qos):
    print("Subscribed: " + str(mid) + " " + str(granted_qos))

def on_log(mqttc, obj, level, buf):
    print("message:" + str(buf))
    print("userdata:" + str(obj))

mqttc = mqtt.Client()
# Assign event callbacks
mqttc.on_connect = on_connect
mqttc.on_message = on_message
mqttc.on_log = on_log

mqttc.username_pw_set(APPID, PSW)
mqttc.connect("eu.thethings.network", 1883, 60)

# and listen to server
run = True
while run:
    mqttc.loop()

It’s not clear from your opening paragraph what the problem is.

Does this receive the uplink messages OK?

If it does, which bit of the code is causing issue?

I’m with @descartes here as for: what’s the problem? But maybe it’s below:

That doesn’t look right. See also A Python program to listen to your devices with MQTT which uses:

…and:

(Where hopefully payload_plain is not plain text.)

See also What to do with the raw payload via MQTT?

(And please see also How do I format my forum post? [HowTo])

Additionally, MQTT has been seen recently to time out on the JavaScript decoder on occasion so you may not get any payload_fields.

And Python isn’t overly helpful in what it returns when you try to access an entry that doesn’t exist:

# Technique 1, use get()
missing1 = theJSON.get(“missing1”)
# But if it’s missing, it has a value of NoneType which can’t be readily printed
try:
print("missing1 = " + missing1)
except:
pass
# so we can add an if missing, use this value situation
missing1 = theJSON.get(“missing1”, “”)
print("missing1 = " + missing1)

# Technique 2, check if the field is there
if ‘missing2’ in theJSON:
missing2 = theJSON[“missing2”]
else:
missing2 = “Couldn’t find it at all”
print("missing2 = " + missing2)

# BUT that’s a bit of a pain as you may as well do
missing2 = theJSON.get(“missing2”, “Couldn’t find it at all”)
print("missing2 = " + missing2)
# unless you want to do other processing when a field is missing
# or you are heading off handling a list (see below) at the pass

# Technique 3, use an error handler
try:
missing1 = theJSON[“missing1”]
missing2 = theJSON[“missing2”]
except KeyError:
print(“Something is missing but I’m not sure what”)
# so you either have to wrap each dictionary lookup in a try / error handler
# or just not do it this way

And just to add an extra level of annoyance, # is a heading so Python comments have to be turned in to pre-formatted text.

1 Like

The API receives the uplink as it should.
The problem is in the on_message function . I do have other devices running on the same setup with the same json load.
But with this setup i get nothing in this part, where i actually should get the data from TTN:

def on_message(mqttc, obj, msg):
    global app, deveui, counter
    try:
        x = json.loads(msg.payload.decode('utf-8'))
        # metadata
        app = x["app_id"]
        device = x["dev_id"]
        deveui = x["hardware_serial"]
        port = x["port"]
        confirmed = x["confirmed"]
        counter = x["counter"]
        global payload_fields
        payload_fields = x["payload_raw"]
        datetime = x["metadata"]["time"]
        frequency = x["metadata"]["frequency"]
        modulation = x["metadata"]["modulation"]
        data_rate = x["metadata"]["data_rate"]
        air_time = x["metadata"]["airtime"]
        coding_rate = x["metadata"]["coding_rate"]
        gateways = x["metadata"]["gateways"]

        for gw in gateways:
            global rssi, snr
            gateway_id = gw["gtw_id"]
            timestamp = gw["timestamp"]
            time = gw["time"]
            channel = gw["channel"]
            rssi = gw["rssi"]
            snr = gw["snr"]

    except Exception as e:
        print(e)
        pass

How do you know?

Can you dump x and also msg.payload and msg.payload.decode and post here.

There was an error, json do not accept empty attributes,despite exceptions.
After removing all unnessersary attributes in message the problem was solved.