Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paho Python MQTT client connects successfully but on_connect callback is not invoked

Tags:

python

mqtt

paho

I have a simple script on a Raspberry Pi that publishes a sample message every 3 seconds. I have declared the callbacks on_connect, on_publish and on_disconnect. This client connects successfully but on_connect is not called, publishes and on_publish is called, disconnects and on_disconnect is called.

This is my script

import paho.mqtt.client as mqtt
import time

def on_connect(mqttc, userdata, rc):
    print("Connected with result code "+str(rc))
    if rc!=0 :
        mqttc.reconnect()

def on_publish(mqttc, userdata, mid):
    print "Published"

def on_disconnect(mqttc, userdata, rc):
    if rc != 0:
        print("Unexpected disconnection. Reconnecting...")
        mqttc.reconnect()
    else :
        print "Disconnected successfully"

# Setup MQTT
# broker='test.mosquitto.org'
broker = 'iot.eclipse.org'
broker_port=1883

# Create a client instance
mqttc=mqtt.Client(client_id="MyClient")
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_disconnect = on_disconnect

while 1:

    mqttc.connect(broker, broker_port, 60)
    # print "Connected."    # I don't want this message. 
                            # Why isn't the on_connect callback invoked?

    try:
        topic = "this/is/a/test/topic"
        payload = "test_message"
        print "Publishing " + payload + " to topic: " + topic + " ..."
        mqttc.publish(topic, payload, 0)

    except Exception as e:
        print "exception"
        log_file=open("log.txt","w")
        log_file.write(str(time.time())+" "+e.__str__())
        log_file.close()

    mqttc.disconnect()
    print ""
    time.sleep(3)   

Although this minor "bug" doesn't affect the message publishing, which is mainly what I want to achieve, why does it happen and how can I resolve it?

like image 924
evgi9 Avatar asked Apr 05 '16 09:04

evgi9


People also ask

What is callback function in MQTT?

The MQTT client calls a callback method on a separate thread to the main application thread. The client application does not create a thread for the callback, it is created by the MQTT client. The MQTT client synchronizes callback methods. Only one instance of the callback method runs at a time.

How does MQTT broker connect to Python?

To establish a connection to an MQTT broker using the Python client you use the connect method of the client object. The method can be called with 4 parameters. The connect method declaration is shown below with the default parameters. The only parameter you need to provide is the host name.


2 Answers

The reason this isn't working is that you aren't calling any of the loop*() functions. These process network traffic. If you don't use one, there is no guarantee your outgoing messages will be sent and absolutely no incoming messages will be processed.

loop_forever() is a blocking call that processes the network loop - probably not what you want.

loop_start() starts a thread to process the network loop and so returns straight away.

I would do this:

mqttc.connect(broker, broker_port, 60) # Don't forget to handle errors
mqttc.loop_start()

while 1:
    try:
        topic = "this/is/a/test/topic"
        payload = "test_message"
        print "Publishing " + payload + " to topic: " + topic + " ..."
        mqttc.publish(topic, payload, 0)

    except Exception as e:
        print "exception"
        log_file=open("log.txt","w")
        log_file.write(str(time.time())+" "+e.__str__())
        log_file.close()

    print ""
    time.sleep(3)

You do still need to fix your on_connect callback as @Kiran says.

There is no need to disconnect each time - and in fact there is no guarantee your message will have been sent when you do disconnect. You should use the on_publish callback to know when the message is sent.

If you want to do a simple connect-publish-disconnect, then maybe use the paho.mqtt.publish helper module:

import paho.mqtt.publish as publish

while 1:
    try:
        topic = "this/is/a/test/topic"
        payload = "test_message"
        print "Publishing " + payload + " to topic: " + topic + " ..."
        publish.single(topic, payload, 0, host=broker, port=broker_port)

    except Exception as e:
        print "exception"
        log_file=open("log.txt","w")
        log_file.write(str(time.time())+" "+e.__str__())
        log_file.close()

    print ""
    time.sleep(3)
like image 159
ralight Avatar answered Sep 18 '22 09:09

ralight


Your on_connect() method declaration is missing the flags(1) parameter. So it is not getting invoked. Flags parameter contained the response sent by broker. It had to be

def on_connect(mqttc, userdata, flags, rc):

Also, why are you connecting and disconnecting in loop ? Try using the loop_start() and loop_stop() methods which handles auto-reconnections on a connection drop(example).

like image 42
kiranpradeep Avatar answered Sep 18 '22 09:09

kiranpradeep