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?
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.
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.
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)
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With