MQTT (Message Queuing Telemetry Transport) is a publish-subscribe-based messaging protocol that is used on many Internet of Things (IoT) projects. It works on top of the TCP/IP protocol and it is designed for connections with remote locations where a “small code footprint” is required or the network bandwidth is limited. The publish-subscribe messaging pattern requires a message broker.
There is support for MQTT on a large variety of programming languages and platforms. An Arduino or Raspberry Pi module can sent (or publish) I/O to a MQTT broker, and they can also receive (or subscribe) to data.
There are a number of MQTT brokers that can be used. One of the most popular ones is the Mosquitto MQTT broker, and it can be loaded on Windows, OSX and Linux systems. For this blog we will be using the Mosquitto test MQTT server. This Internet based server should not be used for real systems, but it is excellent for small short terms tests.
MQTT Web Sockets
The MQTT server has configurable MQTT and Web Socket ports. For a typical Raspberry Pi or Arduino connection, the default MQTT port 1883 would be used. In many Internet applications only certain ports are open, so for this reason a different MQTT Web Socket is used. This is configurable but ports like 80 or 8080 are typically used.
Javascript Application
There are a number of MQTT javascript libraries that are available. One of the more popular ones is the Paho library that is available at:
https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js
As a first example we will look at creating 2 pages. The first page will publish a value, and the second page will subscribe to the data.
The publish code is:
<html> <head> <title> MQTT Publish Message</title> </head> <script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script> <script> // Define some MQTT variables var mqtt_server = ""; var mqtt_port = ""; var mqtt_destname = ""; function send_mqtt_msg() { // Send an MQTT message mqtt_server = document.getElementById("mqtt_server").value; mqtt_port = Number(document.getElementById("mqtt_port").value); client = new Paho.MQTT.Client(mqtt_server, mqtt_port,""); client.connect({onSuccess:onConnect}); document.getElementById("pubmsg").innerHTML = "Trying to connect... "; } function onConnect() { document.getElementById("pubmsg").innerHTML = "New connection made... "; var mqtt_destname = document.getElementById("mqtt_destname").value; var mqtt_msg = document.getElementById("mqtt_msg").value; message = new Paho.MQTT.Message(mqtt_msg); message.destinationName = mqtt_destname; client.send(message); document.getElementById("pubmsg").innerHTML = "topic:" + mqtt_destname + " = " + mqtt_msg + " ...sent"; } // called when a message arrives </script> <body> <h1>MQTT Publish Test Page</h1> Server Name: <input type="text" id="mqtt_server" value="test.mosquitto.org"><br><br> Websocket: <input type="text" id="mqtt_port" value="8080"><br><br> DestinationName: <input type="text" id="mqtt_destname" value="my_IoT_value1"><br><br> Message: <input type="text" id="mqtt_msg" value="test message"><br><br> <button onclick="send_mqtt_msg()">Publish MQTT Message</button> </body> <hr> <div id=pubmsg></div> </html>
The subscribe code is:
<html> <head> <title> MQTT Subscribe Message</title> </head> <script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script> <script> function sub_mqtt_msg() { // Send an MQTT message var mqtt_server = document.getElementById("mqtt_server").value; var mqtt_port = Number(document.getElementById("mqtt_port").value); client = new Paho.MQTT.Client(mqtt_server, mqtt_port,""); client.onMessageArrived = onMessageArrived; client.onMessageArrived = onMessageArrived; client.connect({onSuccess:onConnect}); document.getElementById("submsg").innerHTML = "Trying to connect... "; } function onConnect() { document.getElementById("submsg").innerHTML = "New connection made... "; var mqtt_destname = document.getElementById("mqtt_destname").value; client.subscribe(mqtt_destname); document.getElementById("submsg").innerHTML = "Subscribing to topic: " + mqtt_destname + " ... "; } function onMessageArrived(message) { var result = message.destinationName + " : " + message.payloadString + " "; document.getElementById("submsg").innerHTML = result; } </script> <body> <h1>MQTT Subscribe Test Page</h1> Server Name: <input type="text" id="mqtt_server" value="test.mosquitto.org"><br><br> Websocket: <input type="text" id="mqtt_port" value="8080"><br><br> DestinationName: <input type="text" id="mqtt_destname" value="my_IoT_value1"><br><br> <button onclick="sub_mqtt_msg()">Subscript to MQTT</button> <hr> <h2>Subscribed Messages:</h2> <div id=submsg></div> </body> </html>
Once you’ve got the basics down it’s possible to make some more advanced web interface pages.
Chart and Gauges
For your IoT projects there are a lot of Dash board options that are available. One of my favorites is Node-Red because it is totally free and standalone.
If you would like to create your own web interface there are a number of good javascript charting and gauge libraries available. For my examples I used Google charts with the Gauge chart . To simulate the inputs I used three of our MQTT Publish pages.
The code for the gauges page is :
<html> <head> <title>IoT - MQTT to JS</title> </head> <script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script> <script src="https://www.gstatic.com/charts/loader.js" type="text/javascript"></script> <script> // MQTT variables var MQTTnames = ["my_IoT_value1","my_IoT_value2","my_IoT_value3"]; var MQTTvalues = [0,0,0]; // Define the Google gauge chart google.charts.load('current', {'packages':['gauge']}); google.charts.setOnLoadCallback(drawChart); function drawChart() { var data = google.visualization.arrayToDataTable([ ['Label', 'Value'], [MQTTnames[0], MQTTvalues[0]], [MQTTnames[1], MQTTvalues[1]], [MQTTnames[2], MQTTvalues[2]], ]); var options = { width: 800, height: 1000, redFrom: 90, redTo: 100, yellowFrom:75, yellowTo: 90, minorTicks: 5 }; var chart = new google.visualization.Gauge(document.getElementById('chart_div')); chart.draw(data, options); setInterval(function() { for (var i=0; i < MQTTnames.length; i++) { data.setValue(i, 1, MQTTvalues[i]); } chart.draw(data, options); }, 1000); } // Create a client instance client = new Paho.MQTT.Client("test.mosquitto.org", 8080,""); client.onMessageArrived = onMessageArrived; // connect the client client.connect({onSuccess:onConnect}); // called when the client connects function onMessageArrived(message) { for (var i=0; i < MQTTnames.length; i++) { if (message.destinationName == MQTTnames[i]) { MQTTvalues[i] = Number(message.payloadString); } } } function onConnect() { // Once a connection has been made, make a subscription and send a message. for (var i=0; i < MQTTnames.length; i++) { client.subscribe(MQTTnames[i]); } } // called when a message arrives </script> <body> <h1 style = 'font-size: xx-large'>IoT - MQTT to JavaScript</h1> <div id="chart_div" style="width: 100%; height: 100%;"></div> </body> </html>
There are many other charting options that could be used. Below is an example using the Google Chart library with bars instead of gauges.
Final Comment
Using Javascript to interact with your IoT projects open up a lot of potential for adding functionality. I found that the Python version of the Paho MQTT library to have better documentation and perhaps some more functions, but at the end of the day I was able to do all the I wanted.
Seek and ye shall find. So I Googled and found this. And I tried it and it WORKED!!! I am eternally grateful because this is exactly what I was wanting to learn how to do. Now to hack it up into something that truly suits my needs.
Thanks a MILLION.
LikeLike
Hey I’m really glad it worked for you. I really appreciate the thanks…and it makes me feel extremely guilty for not thanking the 100s of internet people who’s code has helped me.
LikeLike
I am not able to get the 1st step of publishing and subscribing data.. could you please let me know where would be the problem
LikeLike
Often the MQTT websocket interface is disabled. Check your MQTT broker config settings (mosquitto.conf ) and look for:
listener 9001
protocol websockets
Ensure these lines aren’t commented out.
LikeLike
Your publish / subscribe demo doesn’t work for me either. I am trying using both test.mosquitto.org and broker.hivemq.com brokers, on their websocket ports 8080 and 8000 respectively but no action in either pub or sub browser windows.
LikeLike
How can I use it with a raspberry Pi as a broker and send same type of data from node mcu to the website
LikeLike
Hi, the Raspberry Pi can use a number of MQTT brokers. I’ve used both the Mosquitto broker (https://mosquitto.org/blog/2013/01/mosquitto-debian-repository/) and the NodeRed broker (https://flows.nodered.org/node/node-red-contrib-mqtt-broker).
Arduino has a C# library for MQTT. I found that this pretty easy to use. The only issue I had was that C# is a little ugly managing strings. Unfortunately I haven’t used MQTT with Python on a NodeMCU, but I know that there are some libraries.
Let me know if you need any help.
LikeLike