MQTT over websocket in python - python

is there any support in python to subscribe on mqtt broker with port 8080
import sys
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)
mqttc = mqtt.Client()
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
mqttc.connect("test.mosquitto.org", 8080, 60)
mqttc.subscribe("test/iot", 0)
mqttc.loop_forever()
i can not connect with this code. Mosquitto has websocket support at port 8080 but this paho library does not work for it. any solution for python?
i am using python 2.7 on windows 10.

The Paho MQTT module introduced websocket support some days ago. I don't think it is released yet, but you can install from the master under Linux branch using
pip install git+git://github.com/eclipse/paho.mqtt.python.git
Also works under windows. (Thanks for info from the comments)
You can use the websockets as transport by connecting with
mqttc = mqtt.Client(transport="websockets")
UPDATE:
If you try to use the websocket protocol with the python client because you also need to connect a browser client (for example MQTT.js) then you can also configure mosquitto to listen to websockets and the normal mqtt protocol.
Simply create a configuration file for example in
/etc/mosquitto/mosquitto.conf
with the following contents:
listener 1883
protocol mqtt
listener 9001
protocol websockets
Then you can then run mosquitto with
mosquitto -c /etc/mosquitto/mosquitto.conf
You should see similar output:
1469015320: mosquitto version 1.4.8 (build date 2016-05-3112:07:40+0200) starting
1469015320: Config loaded from /etc/mosquitto/mosquitto1.conf.
1469015320: Opening ipv4 listen socket on port 1883.
1469015320: Opening ipv6 listen socket on port 1883.
1469015320: Opening websockets listen socket on port 9001.
Your python client then connects to port 1883 and the browser client to 9001
You can use what-mqtt browser client to test the websocket listener. Just point it to ws://localhost:9001

Between Feb and now the paho.mqtt.python codebase has been fixed. Just add transport='websockets' as Fl0v0 suggested, it simply works. Below is the full code which subscribes to everything or everything under $SYS/. The code tested is on the master branch with commit hash e56f913 on June 3 of 2016.
#!/usr/bin/python
import sys
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)
mqttc = mqtt.Client(transport='websockets')
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
mqttc.connect("test.mosquitto.org", 8080, 60)
mqttc.subscribe("#", 0)
#mqttc.subscribe("$SYS/#", 0)
mqttc.loop_forever()
Update: The code above does not work on Windows 7 with python 2.7.6 that I tested with, by invoking from one version of Cygwin (not the cygwin python though). None of the topic "#" or "$SYS/#" gives any published message back.
Instead, pub or sub to solid topics works as the example follows. Patch paho.mqtt.python examples/pub-single.py and examples/sub-simple.py. Then run sub-simple.py in one terminal. Run pub-single.py in another terminal, twice. The subscriber terminal will print out two messages published by the publisher.
Patch to examples/pub-single.py:
-publish.single("paho/test/single", "boo", hostname="test.mosquitto.org")
+publish.single("/HelloWorld", "boo", hostname="test.mosquitto.org",
+ port=8080, transport='websockets')
Patch to examples/sub-simple.py:
-topics = ['#']
+topics = ['/HelloWorld']
-m = subscribe.simple(topics, hostname="iot.eclipse.org", retained=False, msg_count=2)
+m = subscribe.simple(topics, hostname="test.mosquitto.org",
+ retained=False, msg_count=2,
+ port=8080, transport='websockets')

No, the Python version of the Paho library does not support MQTT over Websockets.
In fact I believe the only native client side (not in a browser) MQTT library that supports MQTT over Websockets is the NodeJS module (https://www.npmjs.com/package/mqtt)

Related

Trying to use mosquitto broker with TLS using paho python

python code
import time
broker = "test.mosquitto.org"
port=8884
conn_flag= False
def on_connect(client, userdata, flags, rc):
global conn_flag
conn_flag=True
print("connected",conn_flag)
conn_flag=True
def on_log(client, userdata, level, buf):
print("buffer", buf)
def on_disconnect(client, userdata, rc):
print("client disconnected ok")
client1= paho.Client("control")
client1.on_log=on_log
client1.tls_set('C:\etc\mosquitto\certs\mosquitto.org.crt')
client1.on_connect = on_connect
client1.on_disconnect = on_disconnect
client1.connect(broker,port)
while not conn_flag:
time.sleep(1)
print("waiting", conn_flag)
client1.loop()
time.sleep(3)
print("publishing")
client1.publish("house/bulb", "Test")
time.sleep(2)
client1.loop()
time.sleep(2)
client1.disconnect()
I am using the mosquitto.org.crt (PEM format) file gave by test.mosquitto.org, currently can't get to connect on port 8884, conn_flag is always false what should I do?
As per http://test.mosquitto.org the ports are:
8883 : MQTT, encrypted, unauthenticated
8884 : MQTT, encrypted, client certificate required
In your code client1.tls_set('C:\etc\mosquitto\certs\mosquitto.org.crt') you are setting the ca_cert - the params being:
tls_set(ca_certs=None, certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLS, ciphers=None)
This would be sufficient to connect to port 8883 (and your code connects to that port successfully for me). A connection to port 8883 will be encrypted and the client can confirm the identify of the server; however the client does not have to provide a client certificate (to identify itself).
To connect to port 8884 you have to provide a client certificate (used to authenticate the client) - i.e. the certfile and keyfile arguments. An appropriate certificate can be requested here.

How to test the python paho mqtt with mosquitto?

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"}}'

Two MQTT server pub/sub with python

I've been trying to find answers or info about this question but without results yet. The idea is to publish the same topic into two different MQTT servers with python. I mean, something like this:
import paho.mqtt.client as paho
import datetime, time
mqttc = paho.Client()
host1 = "broker.hivemq.com" # the address of 1st mqtt broker
host2 = "192.168.1.200" # the address of 2nd mqtt broker
topic= "testingTopic"
port = 1883
def on_connect(mosq, obj, rc):
print("on_connect() "+str(rc))
mqttc.on_connect = on_connect
print("Connecting to " + host)
mqttc.connect(host1, port, 60)
mqttc.connect(host2, port, 60)
while 1:
# publish some data at a regular interval
now = datetime.datetime.now()
mqttc.publish(topic, now.strftime('%H:%M:%S')) #Publishing to MQTT1
mqttc.publish(topic, now.strftime('%H:%M:%S')) #Publishing to MQTT2
time.sleep(1)
So, the question is about the while statment... how can I do to publish the same topic into MQTT1 and MQTT2?
As you can see, I want to have to posibility to publish that payload in MQTT broker that is running in internet, but if I lose internet connection, then I can pub/sub to MQTT broker in my LAN.
You can't just connect the same client to 2 different brokers. You need 2 separate instances of the of the client that you connect to the separate brokers.
...
mqttc1 = paho.Client()
mqttc2 = paho.Client()
...
mqttc1.connect(host1, port, 60)
mqttc2.connect(host2, port, 60)
...
mqttc1.publish(topic, now.strftime('%H:%M:%S')) #Publishing to MQTT1
mqttc2.publish(topic, now.strftime('%H:%M:%S')) #Publishing to MQTT2

MQTT Client not receiving messages

I'm using the following code from MQTT Paho project to subscribe to messages from my mqtt broker. I tested the connection using mosquitto_sub and I receive the messages there. However, when I run the following code it doesn't receive any messages and no output is printed. I checked the topic and host.
import paho.mqtt.client as mqtt
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, 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("test")
# 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.connect("localhost", 1883, 60)
client.loop_forever()
The following error is logged by the broker:
Invalid protocol "MQTT" in CONNECT from ::1.
Socket read error on client (null), disconnecting.
EDIT Thanks to #hardillb for pointing out the outdated MQTT version.
Everything worked after I did the following:
sudo apt-get purge mosquitto
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt-get update
sudo apt-get install mosquitto
This is most likely because you are using an old version of mosquitto and the python is expecting a newer build that supports MQTT 3.1.1
Try changing the code as shown:
import paho.mqtt.client as mqtt
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, 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("test")
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
# Change made HERE
client = mqtt.Client(protocol=MQTTv31)
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost", 1883, 60)
client.loop_forever()
You should also upgrade your broker as soon as possible, that version is incredibly out of date and has a number of known issues, the current version is 1.4.10

Can't connect to Mosquitto server using paho.mqtt.client although mosquitto_pub works fine

I have a remote server running mosquitto. I can connect to this server and exchange messages using mosquitto_pub and mosquitto_sub. If i try the same using some python with paho.mqtt.client I get no connection. My script keeps running but the on_connection hook is never called.. The same scripts however work flawlessly with my local mosquitto server.
What could possibly be the reason for the connection problems? How can I get some more feedback on what's happening? Any suggestions?
EDIT: I added a minimal code example
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Yeeha")
client.subscribe("botgrid/init", qos=2)
def on_message(client, userdata, msg):
print(msg.payload)
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost")
print("Waiting for connection...")
client.loop_forever()
EDIT 2: While playing around, I noted that replacing "localhost" with "test.mosquitto.org" resulted in OSError: [Errno 101] Network is unreachable although I have no problems connecting to it via mosquitto_sub
Does this code produce the same problem? This is probably the equivalent to the code at the point that it is failing.
import socket
sock = socket.create_connection(("test.mosquitto.org", 1883))

Categories

Resources