Develop scalable IoT apps using MQTT

The MQTT protocol is a standard network protocol that is lightweight and flexible which makes it perfect for IoT developers. You can use it to pass messages between client devices, such as IoT sensors, and MQTT brokers, which is a server that receives and routes the messages to other client devices. Read my previous article to learn more about why MQTT is one of the best network protocols for IoT use cases.

In this article, we will look into real world MQTT use cases on IoT edge devices, like the Raspberry Pi. Through just a little bit of code, I’ll show you how to capture data from IoT sensors (DHT11 or DHT22 sensors) connected to the Raspberry Pi and use an MQTT broker to process, store, and forward the data to other devices in the network. There are many use cases for these smart environmental sensors. For example, you could place this Pi with its sensors in a green house and have the Pi control the A/C and irrigation units to keep the plants in an optimal environment.

Setting up a Raspberry Pi

The Raspberry Pi is a very powerful computer in a tiny package. The cheapest option, the Raspberry Pi Zero, is capable of running a fully featured Linux distribution and driving a high definition display. It is the size of two coins (US Quarters) and costs $5. At $10, the Raspberry Pi Zero W comes with integrated WiFi and Bluetooth.

If this is your first Raspberry Pi, the easiest (but most expensive) way to set up is just to buy a desktop kit for around $100 USD. It comes with everything you need for a computer except for the display. The kit typically includes a MicroSD card pre-loaded with Linux for Raspberry Pi. If you do not get a kit, you can purchase a 16GB MicroSD card for $10 online, a MicroSD card reader, and use the Raspberry Pi Imager to load an operating system onto the MicroSD card from your laptop.

Installing an OS on to MicroSD cards

The two popular choices are Raspberry Pi OS and Ubuntu Linux. Both are Debian-based Linux distributions. Most starter kits pre-install the Raspberry Pi OS on their MicroSD cards (it is called NOOBS).

For developers who just want to use the device as a server or IoT device, the Ubuntu Linux is a better choice. It has the latest software packages and libraries, and could be far more efficient without the desktop windows, web browser, Java, games, and learning tools.

You can download Ubuntu Server images for Raspberry Pi from the web, and load it on a MicroSD card. But perhaps a much easier way is just to use the Raspberry Pi Imager, select Ubuntu Server 20.04 TLS from the menu, and write into an empty MicroSD card.

Once the MicroSD card is prepared, you should follow these instructions to put in your WiFi network name and password. This allows the Raspberry Pi device to connect to the network as soon as it boots.

Basically, you can just put the MicroSD card into the Raspberry Pi, connect USB power, then wait for it to come online. You can find the raspberrypi device IP from your WiFi router, and then SSH into it from any computer on your network.

The initial username and password are ubuntu / ubuntu. There is no need to even connect a monitor or keyboard. That’s it for a completely headless setup!

Installing Node.js on your Pi

There are numerous MQTT libraries for Linux on Raspberry Pi. I recommend using Node.js for several reasons.

  • First, Node.js provides an ecosystem of tools and libraries that work with IoT use cases. It is very easy to install software on Node.js. NPM allows you to install modules for MQTT, sensor support, and new runtimes with one line of commands.
  • Second, JavaScript is easy for most developers to grasp. It is a good language for writing IoT applications.
  • Third, Node.js is a high performance runtime. While Node.js applications are written in JavaScript, many computationally heavy or I/O intensive tasks are actually executed by native binaries via the runtime.

To install Node.js on Ubuntu 20.04 or Raspberry Pi OS, SSH into the device and run the following command in the SSH terminal.

$ curl -sL | sudo bash - $ sudo apt install nodejs

You can verify the installation is done correctly by running the following two commands: $ node -v and $ npm -v. Both node and npm are now available.

From here, you can use npm to install additional modules for MQTT communication and IoT accessories.

Using MQTT to subscribe to a message queue

To install the MQTT library on Node.js, run the following command in a SSH console connected to your Raspberry Pi.

$ npm install mqtt --save

Now, you can write a simple JavaScript app to send messages to the mosquitto public test MQTT broker.

const connectOptions = {
    port: 1883,
    host: ,
    rejectUnauthorized: false,
    protocol: 'mqtt'

var mqtt = require('mqtt');
var client  = mqtt.connect(connectOptions);


client.on('connect', function () {
  client.publish('#my_device_id', '{\"mesg\" : \"hello MQTT\"}');

client.on('message', function (topic, message) {
  // message is Buffer

This JavaScript application opens a secure MQTT connection to the mosquitto public test broker, and subscribes to a message queue. It sends a status message when it is connected, and prints out all received messages. The example shows that you can capture data from IoT sensors connected to the Raspberry Pi, structure the data into JSON, and send the JSON message to a MQTT broker to be processed, stored, or forwarded to other devices in the network.

Reading and sending data using the GPIO PINs on the Pi

When IoT accessories, such as sensors, LED lights, motors, are attached to the Raspberry Pi, they typically communicate with the Pi device through the GPIO PINs. From the software, you can read the voltage on each PIN and also set the voltage on each PIN. That allows your software to communicate with external hardware connected to those PINs.

The GPIO package in Node.js enables your application to read and set the PIN status using simple JavaScript. To install it, use the following npm command.

$ npm install gpio

The following command sets PIN 4 to high voltage. If the PIN is connected to an LED light, the light will light up.

var gpio = require("gpio");

var gpio4 = gpio.export(4, {
   direction: gpio.DIRECTION.OUT,
   interval: 200 // Must wait this amount of ms between set() actions

gpio4.set(); // Set to high voltage; Turn on the light
// ...  do something else ...
gpio4.set(0); // Set of low voltage; Turn off the light.

The following command reads the voltage from PIN 4.

var gpio = require("gpio");
var gpio4 = gpio.export(4, {
   direction: gpio.DIRECTION.IN

gpio4.on("change", function(val) {
   // value will report either 1 or 0 (number) when the value changes

With the MQTT and GPIO modules, you can use an MQTT broker to receive and store data from remote sensors, and send commands to those sensors.

Reading and sending sensor data from the Pi to the MQTT broker

There are many IoT sensors that work with the Raspberry Pi. The sensors typically communicate with the Raspberry Pi device through the GPIO PINs on the board.

Let’s use the DHT11 and DHT22 temperature and humidity sensors as examples. Those environmental sensors are useful in a variety of real world applications. For example, you could place one outside of your air-conditioned house in your backyard. It will be able to measure outside temperature and humidity, and compute the heat index on the Raspberry Pi. You can look up the readings on your mobile device before heading out. Another example is to place Raspberry Pi connected environmental sensors inside a green house. The Raspberry Pi device could control the A/C and irrigation units in the green house via WiFi or another devices connected to the GPIO PINs to keep plants at their optimal environment.

The DHT11 and DHT22 are very smaller sensors each have 4 PINs to connect to the Raspberry Pi. Two of the PINs are for power, one for data, and one PIN is not connected or used. You can check out the Step 1 from this “Getting started developing IoT solutions” tutorial to learn how to set up the hardware sensors and connect them to the Pi device. Notice the required resistor to regulate the electric current supplied to the sensor.

The Raspberry Pi sends a high voltage pulse through the data PIN to tell the sensor that it is ready to read temperature and humidity data. The sensor responses by 40 pulses of 0s (low voltage) and 1s (high voltage), which encodes the values of the temperature and humidity. While it is possible to write a program to read the pulses directly from the GPIO PINs and decode the readings from the sensor, there is an easier way.

The node-dht-sensor NPM package provides a simple API to read data from those sensors.

$ npm install node-dht-sensor

The JavaScript code below reads the temperature and humidity data from a DHT11 sensor with its DATA PIN connected to Raspberry Pi’s GPIO 4.

var sensor = require("node-dht-sensor");, 4, function(err, temperature, humidity) {
  if (!err) {
    console.log(`temp: ${temperature}°C, humidity: ${humidity}%`);

Once you have read the temperature and humidity values, you can send them to an MQTT broker, so that other devices and services connected to the broker can see and respond to these readings. For example, a messaging service connected to the hub could monitor the temperature and send alerts to mobile phones when the temperature readings are too high 3 times in a row.

Summary and next steps

In this article, we discussed how the MQTT protocol is used in real world applications. We use a Raspberry Pi device to manage environmental sensors and send the readings in MQTT messages. An MQTT broker listens for those messages. It records, and potentially could dispatch, those environmental readings on the server side. Now it is time to get started with your own MQTT applications!

If you’re ready to put your new-found knowledge of MQTT to use, you might be interested in trying this tutorial, “Build your IoT skills by developing a door monitoring system.”