I've installed Mosquitto and used in the terminal without problem, also installed paho for c++, both mosquitto and paho work well.
Then installed paho for python via pip. Now i'm trying to test it with this code but the on_message and on_connect functions never get called. I'm doing
mosquitto_pub -h localhost -t "test" -m "This is a message"
while the python script runs but it doesn't work. It never gets to the line that prints "on_message!"
import paho.mqtt.client as mqtt
def on_connect(self, mqtt_client, obj, flags, rc):
mqtt_client.subscribe("test")
def on_message(self, mqtt_client, obj, msg):
print "on_message()"
print "Initializing subscriber"
mqtt_client = mqtt.Client()
mqtt_client.on_connect = on_connect
mqtt_client.on_message = on_message
mqtt_client.connect("localhost",1883)
print "Listening"
while True:
mqtt_client.loop()
What am i doing wrong?
The on_message callback gets called only if You are subscribed to a topic.
To do that, You need to call the subscribe method. For example:
print "Initializing subscriber"
mqtt_client = mqtt.Client()
mqtt_client.on_connect = on_connect
mqtt_client.on_message = on_message
mqtt_client.connect("localhost", 1883) # "localhost" or IP or
mqtt_client.subscribe("test") # topic name, same as the "-t" argument in mosquitto_pub
print "Listening"
mqtt_client.loop_forever()
As for the on_connect callback, what caused the issue for me was that I called the connack_string method as it was Client's method, but it is not. Looking at the source code, we see that it is defined directly in the module, not inside a class:
def connack_string(connack_code):
So, I replaced this:
def connect_callback(client, userdata, flags, rc):
print("Connection attempt returned: " + client.connack_string(rc)) # client !!
with this:
def connect_callback(client, userdata, flags, rc):
print("Connection attempt returned: " + mqtt.connack_string(rc)) # mqtt !!
What You can also try is to omit the -h localhost part from the mosquitto_pub command, like this:
mosquitto_pub -t "test" -m "This is a message"
Also, watch for the number of parameters that the on_connect callback receives (4). This is advice to everybody else reading this post. :)
The following is working fine for me.
I have removed the self from the callbacks and swapped the loop for mqtt_client.loop_forever()
import paho.mqtt.client as mqtt
def on_connect(mqtt_client, obj, flags, rc):
mqtt_client.subscribe("test")
def on_message(mqtt_client, obj, msg):
print "on_message()"
print "Initializing subscriber"
mqtt_client = mqtt.Client()
mqtt_client.on_connect = on_connect
mqtt_client.on_message = on_message
mqtt_client.connect("localhost",1883)
print "Listening"
mqtt_client.loop_forever()
This is an old thread but I just hit a similar problem. I had:
def on_message (client, userdata,message):
print("received message", str(message.payload.decode("utf-8")
client.loop_start()
client.subscribe(topic)
client.on_message=on_message
time.sleep(30)
client.loop_stop()
If I changed the time from 30 to 300 then on_message was never executed.
Go figure?
Related
I am sending a number of messages simultaneously from multiple clients from one python script and trying to receive them on another script. The problem I am getting is that the message is received but only from the first client that gets connected and it keeps on looping over it.
What I need to have is that I get messages from each client in the manner they are published.
import paho.mqtt.client as mqtt
import time
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to broker")
global Connected
Connected = True
else:
print("Connection failed")
def on_message(client, userdata, message):
print ("Message received: " + str(message.payload) + " from " + str(client))
Connected = False
client = mqtt.Client()
client.on_connect= on_connect
client.on_message= on_message
client.connect(host)
client.loop_start()
while Connected != True:
time.sleep(0.1)
client.subscribe("test")
print("subscribed")
client.loop_stop()
You are misunderstanding what the client argument in the on_message callback is.
This value is a link to the local instance of the MQTT client that has subscribed to the topic.
MQTT messages do not carry any information about the client that published them, unless you explicitly encode it into the payload. Part of the point of a Pub/Sub protocol like MQTT is to totally decouple the information creator (publisher) from the information consumer (subscriber).
Also you should move the call to client.subscribe("test") to inside the on_connect() callback because as you have it you are trying to resubscribe to the same topic 10 times a second which will achieve absolutely nothing, except to generate unneeded load on the broker.
I'm using this python script to implement a Paho(MQTT) subscriber but i am unable get any responce messages.i am able to subscribe mqtt brokerin command prompt by using mosquitto_sub -t "" -d -h -p 8883 --psk foo --psk-identity bar --insecure --tls-version tlsv1
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe("*********")
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("*********", 8883, 60)
client.loop_forever()
When I run above python script then it does not respond any error or message but keep going with loop , I also run it line by line and when I run client.connect("*********", 8883, 60) then it shows only 0 . please note here without psk and psk-identity we cannot connect to broker.
Thanks
Please check with your topic carefully, sometimes missing of / or # cause this problem.
or
Try This
def on_message(client, userdata, msg):
print("Message Recieved from broker: " + msg.payload.decode())
I have configured MQTT Broker, receiving published messages from another piece of code (not written or accessible by me). I added another topic to the broker configuration and am now trying to publish data to this new topic from a piece of python code. I get the feedback that the message is published by the callback function, but no actual data is received.
Is there anything I am missing?
I am using the following code:
import paho.mqtt.client as mqtt
import time
#=========================================================================
def on_connect(client, userdata, flags, rc) :
print "on_connect()"
#=========================================================================
def on_publish(client, userdata, mid) :
print "on_publish()"
#=========================================================================
def send() :
mqttc = mqtt.Client()
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
#host = "localhost"
host = "127.0.0.1"
port = 1883
keepalive = 60
print "\nConnect to '%s', port '%s', keepalive '%s'" % (host, port, keepalive)
mqttc.connect(host=host, port=port, keepalive=keepalive)
time.sleep(3)
mqttc.loop_start()
time.sleep(3)
topic = "data/MY/TOPIC"
msg = "MY_MESSAGE"
print "Publish to '%s' msg '%s'" % (topic, msg)
mqttc.publish(topic, msg, qos=2)
time.sleep(3)
mqttc.loop_stop()
# end send()
#=========================================================================
if __name__ == "__main__":
send()
# end if
Getting the stdout
Connect to '127.0.0.1', port '1883', keepalive '60'
on_connect()
Publish to 'data/MY/TOPIC' msg 'MY MESSAGE'
on_publish()
I am not sure if the loop() functions are necessary, but if I do not embed the publishing in the loop_start() and loop_stop(), I do not get a on_connect callback.
The loop functions are necessary as these are where all the network traffic is processed.
Manually setting up a connection to the broker to just send a single message like this is not a good idea, it would be better to start the client, leave it running (by calling loop_start() and not calling loop_stop()) in the background and then just call the publish method on the mqttc client object.
If you don't want to keep a instance of the client running then you should use the single message publish helper method provided by the paho python library (https://pypi.python.org/pypi/paho-mqtt/1.1#single):
import paho.mqtt.publish as publish
publish.single("paho/test/single", "payload", hostname="iot.eclipse.org")
I have tested the example program on paho-mqtt, and I know that the function loop_forever() can handles reconnecting. But my question is that, although loop_forever() can reconnect, it cannot re-subscribe. It should be a problem when the server suddenly crashes, in this case, the client is still listening, but when the server is restarted, the client can reconnect, but cannot subscribe message any more. I think maybe I should re-write the loop_forever() function, but I am not sure if I were right, and how to do it.
import sys
try:
import paho.mqtt.client as mqtt
except ImportError:
# This part is only required to run the example from within the examples
# directory when the module itself is not installed.
#
# If you have the module installed, just use "import paho.mqtt.client"
import os
import inspect
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"../src")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
import paho.mqtt.client as mqtt
def on_connect(mqttc, obj, flags, rc):
print("rc: "+str(rc))
def on_message(mqttc, obj, msg):
print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
def on_publish(mqttc, obj, mid):
print("mid: "+str(mid))
def on_subscribe(mqttc, obj, mid, granted_qos):
print("Subscribed: "+str(mid)+" "+str(granted_qos))
def on_log(mqttc, obj, level, string):
print(string)
# If you want to use a specific client id, use
# mqttc = mqtt.Client("client-id")
# but note that the client id must be unique on the broker. Leaving the client
# id parameter empty will generate a random id for you.
mqttc = mqtt.Client()
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
# Uncomment to enable debug messages
#mqttc.on_log = on_log
mqttc.connect("m2m.eclipse.org", 1883, 60)
mqttc.subscribe("$SYS/#", 0)
mqttc.loop_forever()
The easy way to deal with this is to do your subscribing in the on_connect callback, then when you reconnect all the subscriptions will be restored as well.
While instantiating your mqtt client you can set the "clean session" flag to false.
mqttc = mqtt.Client(clean_session=False)
Citation from the mosquitto manual:
Clean session / Durable connections
On connection, a client sets the "clean session" flag, which is sometimes also known as the "clean start" flag. If clean session is set to false, then the connection is treated as durable. This means that when the client disconnects, any subscriptions it has will remain and any subsequent QoS 1 or 2 messages will be stored until it connects again in the future. If clean session is true, then all subscriptions will be removed for the client when it disconnects.
Is there a way to check if the client is still connected to the MQTT broker?
Something like
if client.isConnected(): # for example
# if True then do stuff
Edit: There was instance where my Raspberry Pi stopped receiving from the client although it was still (from the look of it, the code was still showing updated results) running.
Here is the code since I may be doing something wrong:
client = mqtt.Client()
client.connect(address, 1883, 60)
while True:
data = getdata()
client.publish("$ahmed/",data,0)
time.sleep(0.2)
The thing is that I was away, so I am not even sure why it stopped! Only if I restart my broker then it will start receiving again.
You can activate a flag in on_connect and deactivate it in on_disconnect. In this way you can know if the client is connected or not.
import paho.mqtt.client as mqtt
flag_connected = 0
def on_connect(client, userdata, flags, rc):
global flag_connected
flag_connected = 1
def on_disconnect(client, userdata, rc):
global flag_connected
flag_connected = 0
client = mqtt.Client()
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.connect(server,port)
client.loop_forever()
if flag_connected == 1:
# Publish message
else:
# Wait to reconnect
I can't see one in the doc but there are the on_disconnect on_connect callbacks that can be used to set your own state variable
EDIT:
You need to call one of the loop functions to give the client cycles to handle the network operations:
client = mqtt.Client()
client.connect(address, 1883, 60)
while True:
data = getdata()
client.publish("$ahmed/",data,0)
client.loop(timeout=1.0, max_packets=1)
time.sleep(0.2)
You can use will message to do this.
client=mqtt.Client()
client.will_set('will_message_topic',payload=time.time(),qos=2,retain=True)
client.connect(address,1883,60)
client.publish('will_message_topic',payload='I am alive',qos=2,retain=True)
client.loop_start()#this line is important
while 1:#faster than while True
you loop
By leaving a will message, you can use another client to make sure if the client is online or not.
You can also view this article: How to use MQTT in Python (Paho)
A block of code from the article answering your question:
from paho.mqtt import client as mqtt_client
broker = 'broker.io'
port = 8888
client_id = 'client_id '
username = 'username'
password = 'password'
def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
# Set Connecting Client ID
client = mqtt_client.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client
Here is the API available.
You just use client.is_connected() returns True or False.