Search code examples
mqttpython-3.7paho

Python paho MQTT, client.on_publish not called even though message is sent to broker


Ok so this is one of those "what-am-I-missing-here?" kind of questions.

My callback registered for the client.on_publish event is never called even though messages are successfully published to the broker (no log messages are printed from the callback and it doesn't stop on a break point in VS Code). The message in particular that I'm interested in is published from the on_msg callback, I have tried to publish it outside of any callbacks but it makes no difference, the message is received by the broker but the on_publish callback never triggers.

When debugging I can see that at the time of publishing there is a function registered for the on_publish callback (the client._on_publish property is set)

Python version 3.7.4

OS Windows 10

Code that initializes the client:

import paho.mqtt.client as mqtt

#configure mqtt client
client = mqtt.Client(config['MQTT']['client_id'])
client.on_connect = on_connect
client.on_message = on_msg
client.on_disconnect = on_disconnect
client.on_publish = on_publish

try:
    client.connect(config["MQTT"]["host"], int(config["MQTT"]["port"]))
except Exception as e:
    log.error("Failed to connect to MQTT broker", exc_info=True)

client.loop_start()

My callbacks for on_msg and on_publish:

def on_msg(client, userdata, msg):
    global status_msg_id

    log.debug("on_msg")
    payload = json.loads(msg.payload)
    if payload['id'] == config["MISC"]["session_id"]:
        if payload['result'] == 0:
            log.debug("payload content=ok")
            status_msg_id = client.publish(
                topic = config["MQTT"]["pub_status"],
                payload = json.dumps({'status':'ok'}),
                qos = 2)
        else:
            log.debug("payload content=error")
            client.publish(
                topic = config["MQTT"]["pub_status"],
                payload = json.dumps({'status':'error'}),
                qos = 2)
        log.debug("msg id (mid) of status msg: {}".format(status_msg_id))

def on_publish(client, userdata, mid, granted_qos):
    log.debug("on_publish, mid {}".format(mid))
    # we never get here :(

So, why isn't the on_publish function called, what am I missing?


Solution

  • The signature for the on_publish callback is wrong.

    From the docs:

    on_publish()

    on_publish(client, userdata, mid)

    It should be:

    def on_publish(client, userdata, mid):
        log.debug("on_publish, mid {}".format(mid))