I am new to using MQTT and I would like to run two Python programs simultaneously: one to publish messages to a topic and the other to print out the messages as they are published to the topic. However, the callback function to print out the message isn't working for me.
These are the two programs I have:
Publish messages:
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Connected! Result code: " + str(rc))
client = mqtt.Client(client_id="clientID")
client.on_connect = on_connect
client.username_pw_set(username="username", password="password")
client.loop_start()
client.connect("node02.myqtthub.com", 1883)
while True:
client.publish("my/topic", "test")
Subscribe to and print messages:
import paho.mqtt.client as mqtt
def on_message(client, userdata, msg):
print(msg.payload.decode())
def on_connect(client, userdata, flags, rc):
print("Connected! Result code: " + str(rc))
client.subscribe("my/topic")
client = mqtt.Client(client_id="clientID")
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(username="username", password="password")
client.connect("node02.myqtthub.com", 1883)
client.loop_forever()
Could someone help me fix this issue?
Both programs are using client_id="clientID"; the mqtt spec states
If the ClientId represents a Client already connected to the Server then the Server MUST disconnect the existing Client [MQTT-3.1.4-2].
So whichever app connects second will cause the first to be disconnected. To fix this change the client id in one of the apps.
Note: This is a comment on something obviously wrong. When asking a question please state what you see happening (any output, errors, what you have tried etc) because there may be another problem.
Related
i've been trying to make this example running for many hours. I was building an example so my friend can learn some python but i've end up frustrated on my own.
My python knowledge is quite limited. Something is causing the program thread to finish no matter how much I try delaying the execution with time.sleep (i've removed that part of the code).
Expect result: sender container should be started after the receiver one. So the receiver is subscribed to the broker and waiting for messages.
Given result: receiver container starts and then dies.
Thanks in advance.
I have a docker compose as follows:
services:
mqtt_broker:
image: eclipse-mosquitto
volumes:
- "./mosquitto.conf:/mosquitto/config/mosquitto.conf"
client_send:
build:
context: ./client_send/
environment:
BROKER_HOST: mqtt_broker
depends_on:
- client_receive
client_receive:
build:
context: ./client_receive/
environment:
BROKER_HOST: mqtt_broker
depends_on:
- mqtt_broker
Then I have client code for each of these clients:
Receiver:
import os
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("[receiver] Connected with result code " + str(rc))
client.subscribe("sample_topic")
def on_message(client, userdata, msg):
print("[receiver] got a message: " + str(msg.payload.decode()))
client.loop_stop()
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(os.environ["BROKER_HOST"], 1883, 60)
client.loop_start()
Sender:
import os
import paho.mqtt.client as mqtt
def run():
print("[sender] will send a message")
client.publish("sample_topic", "message from sender")
client.loop_stop()
def on_connect(client, userdata, flags, rc):
print("[sender] Connected with result code " + str(rc))
run()
client = mqtt.Client()
client.on_connect = on_connect
client.connect(os.environ["BROKER_HOST"], 1883, 60)
client.loop_start()
I was using loop_forever without too much success bcoz print() calls were not logging anything since the main thread was blocked so I couldn't see if my code was working.
EDIT: previous paragraph is just not correct. loop_forever will work taking this into account: Python app does not print anything when running detached in docker
Finally got it working as suggested by #Brits (see comments) just by running exit or disconnecting the client (works using exit too)
I also keep the depends_on so the docker-compose.yml was not changed
This is the receiver:
import os
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("[receiver] Connected with result code " + str(rc))
client.subscribe("sample_topic")
def on_message(client, userdata, msg):
print("[receiver] got a message: " + str(msg.payload.decode()))
client.disconnect()
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(os.environ["BROKER_HOST"], 1883, 60)
client.loop_forever()
As a side note, if the main thread is blocked you will never be able to see the output of the program even if you got the message back from the sender. If you don't disconnect the client it might actually work if your application does not rely on console output. Soo freeing the main thread allows for the system to release the output logs to docker.
It's my first time trying to connect to a mqtt broker and it's not really going great. I've been trying to get data from the broker but am unable to figure out how to connect. I've been handed a username, password, port and encrypted port aswell as "Topics. When trying to connect the "client.connect"-line responds with "0". I changed the username and password and I still get the same result so there is something wrong with my configuration. Any help would be much appreciated!
I'm running python 3.6.5
import paho.mqtt.client as mqtt
import time
username="temp"
password="temp"
# The callback for when the client receives a CONNACK response from the server.
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("extapi/data/esm")
# The callback for when a PUBLISH message is received from the server.
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.username_pw_set(username, password)
client.connect("example.io", 1883, 60)
This is my code
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc): # The callback for when the client connects to the broker
print("Connected with result code {0}".format(str(rc))) # Print result of connection attempt
def on_message(client, userdata, message): # The callback for when a PUBLISH message is received from the server.
print("message received " ,str(message.payload.decode("utf-8")))
print("message topic=",message.topic)
print("message qos=",message.qos)
print("message retain flag=",message.retain)
#creating client instance
client = mqtt.Client(client_id="random_id_name")
print("client created ......")
client.on_connect = on_connect # Define callback function for successful connection
client.on_message = on_message # Define callback function for receipt of a message
#connecting to broker/server
hostname = "hostname_I_am_trying_to_connect" #give the host/server/broker name
portnumber = **random_port_number_as_integer_value** #give the port number
client.username_pw_set("username", "password") #give the username and password for the broker/server/host
client.connect(host= hostname ,port= portnumber)
print("client connected to- ",hostname," on port_number:",portnumber)
client.subscribe("login")
print("subscribed to the topic")
client.publish("login","some_message")
print("message published")
client.loop_forever() # Start networking daemon
Here I am expecting to receive some_message/unique_id from the broker , i.e. 1234/1234_qyehfj_1234_jfjfj.
Instead, I am receiving some random numbers. See the screenshot:
What is the problem here? Is the problem in my code or something wrong with the broker I am sending messages to?
If something is wrong with the code please let me know how to fix this.
I solved the problem last night. So here I am going to explain what happened.
I subscribed to the wrong topic, that's why I was receiving everything that other people may or may not have published on that particular topic.
In the future, if anyone is facing the same problem, double-check if you are subscribed to the right topic.
I want to test the mosquitto MQTT Python client ports.
import json
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
"""Called when connected to MQTT broker."""
client.subscribe("hermes/intent/#")
client.subscribe("hermes/nlu/intentNotRecognized")
print("Connected. Waiting for intents.")
def on_disconnect(client, userdata, flags, rc):
"""Called when disconnected from MQTT broker."""
client.reconnect()
def on_message(client, userdata, msg):
"""Called each time a message is received on a subscribed topic."""
nlu_payload = json.loads(msg.payload)
if msg.topic == "hermes/nlu/intentNotRecognized":
sentence = "Unrecognized command!"
print("Recognition failure")
else:
# Intent
print("Got intent:", nlu_payload["intent"]["intentName"])
# Speak the text from the intent
sentence = nlu_payload["input"]
site_id = nlu_payload["siteId"]
client.publish("hermes/tts/say", json.dumps({"text": sentence, "siteId": site_id}))
# Create MQTT client and connect to broker
client = mqtt.Client()
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message
client.connect("localhost", 1883)
client.loop_forever()
I run it with the command
$ python script.py`
Connected. Waiting for intents.
Does mosquitto send a POST request? or do I have to start a request with mosquitto? How should I create a request so that I get
Got intent: SetTimer
MQTT is not HTTP, POST is a HTTP verb that has no meaning in a MQTT context.
MQTT is a pub/sub protocol, where as HTTP is a request/response protocol.
The code you have posted only subscribes to 2 topics, it doesn't publish anything (until it receives a message). So unless you have another application that will publish a message to 1 of the 2 topics the python code has subscribed to it will just sit there and wait for a message.
You can use the mosquitto command line tools to send a message if needed. e.g.
mosquitto_pub -t hermes/intent/foo -m '{"intent": { "intentName": "SetTimer"}}'
I have written a code that can do both publishing and subscribing in the same python file. My aim is to be able to send endlessly color temperature to a lamp and receive back its state (ON/OFF or online/offline).
However, when I run the code, I can send messages to the lamp but I don't receive anything (note that publisher and subscriber worked well separately)
import paho.mqtt.client as mqtt
import sys
import time
topic = "testtopic/3"
topic_casa = "testtopic/1"
def on_connect(client, userdata, flags, rc):
print("Connection to the broker. Result : "+str(rc))
client.subscribe(topic_casa, qos=1)
client.publish(topic, light.circadianLight())
def on_message(client, userdata, msg):
Message = str(msg.payload)
print("[MSG RECEBIDA] Topico: "+msg.topic+" / Mensagem: "+Message)
def on_publish(client,userdata,result):
client.publish(topic, light.circadianLight())
time.sleep(10)
def on_disconnect(client, userdata, rc):
if rc != 0:
print("Unexpected disconnection.")
try:
print("[STATUS] Inicializando MQTT...")
#inicializa MQTT:
client = mqtt.Client()
client.username_pw_set(username, password)
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
client.on_publish = on_publish #with this callback we won't be able to
#receive messages
client.connect(Broker, PortaBroker, KeepAliveBroker)
client.loop_forever()
except KeyboardInterrupt:
print ("\nCtrl+C pressionado, encerrando aplicacao e saindo...")
sys.exit(0)
The problem is two fold, first that you are calling time.sleep(10) in the on_publish() callback.
This is blocking the MQTT client network loop so it will not send/receive any messages for 10 seconds every time you publish a message.
You should not be doing any blocking or long running tasks in any of the MQTT client callbacks.
The other problem is that without the sleep the client will spend all it's time publishing messages (because everytime it finishes publishing a message it trigger the on_publish() callback which kicks off another publish. It will never get round to handing the incoming messages.
If you want to publish messages at a regular interval then you need to start a separate thread to do it, not try to do it in the callbacks.