Your First MQTT Lua Program

Your First MQTT Lua Program

Lua MQTT

The combination of Lua scripting language with MQTT offers an interesting avenue for those seeking to simplify and fast-track MQTT programming. With its lightweight syntax and flexibility, Lua simplifies complex programming tasks, which becomes particularly evident when dealing with MQTT's authentication and security features.

This tutorial will guide you through crafting MQTT client code using Lua and deploying it in RTOS systems and High-Level-Operating-System (HLOS) environments.

What is MQTT?

MQTT, or Message Queuing Telemetry Transport, is a lightweight communication protocol that operates on a publish-subscribe model, enabling devices to send (publish) messages. Other devices can then receive these messages by subscribing to the same topic.

MQTT is a streamlined way for devices to talk to each other. Think of it like a message board: one device posts a message under a specific topic, and any other device interested in that topic gets the message. A central manager, called a broker, handles all the messages and topics, ensuring each device gets the information it wants. This setup makes adding or removing devices easy without disrupting the whole system.

How to Use the MQTT Lua Client

This tutorial introduces you to the Barracuda App Servers MQTT client, which is implemented in Lua and provides a Lua programming API. The Barracuda App Server (BAS) C library can be tailored and compiled to fit a variety of setups, from monolithic firmware to a standalone runtime. In this tutorial, however, we'll focus on two ready-to-use (pre-compiled) environments: one designed for Real-Time Operating Systems (RTOS) and another for high-level operating systems such as Windows, Mac, (embedded) Linux, and QNX.

If you're not familiar with Lua yet, you can get a quick start by checking out an online interactive Lua tutorial.

Establishing a Connection to the MQTT Broker

To establish a connection to an MQTT broker, you can use the following Lua code snippet:

-- Define a function to handle MQTT connection status
local function onstatus(type,code,status)
   if "mqtt" == type and "connect" == code and 0 == status.reasoncode then
      print"Connected to broker"
      return true -- Accept connection
   end
    -- If the connection is not successful, print a message
   print("Disconnect or connect failed",type,code)
   return false -- Deny reconnect
end

-- Connect to the public HiveMQ broker
local mqtt=require("mqttc").create("broker.emqx.io",onstatus)

In the above code, the onstatus callback function is defined to monitor the status of the MQTT connection. If the connection to the broker is successful, it prints "Connected to broker" to the console and allows the connection. Otherwise, it prints an error message and denies the connection. The above example is similar to the one provided in the MQTT Lua API documentation.

The last code line above loads the MQTT library and then connects to the public broker broker.emqx.io using the MQTT library function create(). While finding a variety of public online MQTT test brokers is relatively straightforward, it's important to be aware of their limitations. Public brokers lack essential security features, making them unsuitable for production or deployment scenarios. Using a public broker could expose your data to unauthorized access. For this reason, you should only use public brokers for testing and development purposes.

Publishing Messages to a Topic

To send a message to a specific topic, you can use the publish method of the MQTT client. Here's how to do it in Lua:

-- Publish a temperature reading of 25.5 to the topic "sensors/1/temperature"
mqtt:publish("sensors/1/temperature","25.5")

Subscribing to Topics and Receiving Messages

To listen to messages from a specific topic or a set of topics, use the subscribe method like this:

-- Subscribe to a wildcard topic related to temperature sensors
mqtt:subscribe("sensors/+/temperature", {
   -- Anonymous function that runs when a message arrives on a matching topic
   onpub=function(topic,payload)
      print("Received message:", topic, payload)
   end
})

The above code subscribes to the topic "sensors/+/temperature." The plus sign (+) acts as a wildcard, matching any topic in the "sensors" namespace followed by "temperature." When a message arrives, an anonymous callback function triggers, printing the topic and payload to the console.

An "anonymous function" is a function without a name, directly passed as an argument to another function -- in this case, mqtt:subscribe().

Disconnecting from the MQTT Broker

Finally, if you need to sever the connection with the MQTT broker, you can use the disconnect method:

mqtt:disconnect()

The above simple command disconnects your client from the MQTT broker, effectively halting any further message publishing or reception.

Click to Run the Complete MQTT Example on the Lua Tutorial Server

Click the link above to upload the full Lua example to the tutorial server. Once it's uploaded, you can run the code by pressing the 'Run' button. This example subscribes to messages on the topic sensors/+/temperature while publishing messages to sensors/1/temperature. When the code runs successfully, you should see the following output:

Connected to broker
Received message: sensors/1/temperature 25.5

The above output you see is generated because the example has been enhanced to establish a TLS-encrypted connection while also verifying the trustworthiness of the broker. This secure connection and trust verification are enabled by specifying a Lua options table, with the secure flag set to true.

-- Connect using TLS
local mqtt = require("mqttc").create("broker.emqx.io", onstatus, {secure=true})

Verify Broker Trustworthiness

To better understand how the broker's trustworthiness is checked, let's go ahead and change the broker name "broker.emqx.io" with the broker's IP address. You can find the IP address by running the following in a command window:

ping broker.emqx.io

Once you've got the IP, insert it into the example code on the tutorial server. Your connection code would now look something like:

local mqtt=require("mqttc").create("54.146.113.169", onstatus, {secure=true})

The above message, which is printed by the onstatus callback function, indicates that the trust verification failed, causing the MQTT client to terminate the connection. Note that the mechanics of trust verification are complex and not covered in detail in this tutorial. For an introduction to certificates and trust verification, refer to the article, Certificate Management for Embedded Devices.

A Word on Security

While TLS adds a layer of security, remember that public brokers do not require client authentication. This leaves your communications open to eavesdropping or misleading commands. If security is a priority, it's advisable to use a broker that requires username and password authentication at the very least.

For a more secure MQTT solution, consider the tutorial How to Connect to AWS IoT Core using MQTT. This advanced tutorial covers mutual TLS authentication (mTLS), which uses digital certificates to securely authenticate both parties, not just the broker as we do in this example.

Managing Network Instability with Automatic Connection Mode

When developing IoT applications, handling network instability is a crucial challenge. Fortunately, the Lua MQTT client includes an Automatic Connection Mode feature that can be particularly useful in such scenarios. When running the MQTT client on a High-Level-Operating-System or a microcontroller with sufficient onboard memory, like the ESP32-S3, you can take full advantage of this feature. Here's how it works:

In Automatic Connection Mode, the MQTT client will attempt to automatically reconnect to the broker if it detects the network connection has dropped. More importantly, during this period of disconnection, the client will queue up any messages your application attempts to publish. These messages are stored in the device's RAM and sent to the broker after restoring the network connection.

This way, your application can continue functioning and publishing messages even during network outages. This automatic queuing and reconnection process occurs in the background, requiring no additional coding on your part, thus simplifying the network logic in your IoT applications.

To enable Automatic Connection Mode in your MQTT client, always return true in the onstatus callback function. Consult the MQTT library's documentation for details.

Introducing MQTT Sparkplug

While MQTT caters to a diverse audience, MQTT Sparkplug specializes in industrial automation and control systems. Think of Sparkplug as an "advanced version" of MQTT. It doesn't just queue messages; it standardizes how data is exchanged between industrial machinery, edge gateways, and backend systems. This ensures seamless communication and interoperability. The MQTT Lua library offers an optional Lua MQTT Sparkplug extension, making it easier to develop MQTT Sparkplug-compliant applications. See the Lua MQTT Sparkplug Tutorial if you are interested in learning more.

Getting Started with MQTT and Lua

To begin, you'll need the MQTT Lua library, available for download on GitHub. This library is designed to work with the Barracuda App Server (BAS) runtime engine. BAS can be compiled into different setups: as firmware or as a standalone runtime for various platforms, including Linux and Windows.

Download Ready-to-Run Solutions:

If you'd prefer to skip the C code compilation and jump straight into Lua development, there are convenient, ready-to-use solutions available:

  • Mako Server: Tailored for high-level operating systems, Mako Server is ideal for deploying on embedded Linux and QNX systems.

  • Xedge32: Designed specifically for the ESP32 processor, Xedge32 is a full-fledged RTOS development environment. The ESP32 Lua Example's GitHub Repo provides many examples, including rapid image publishing from an ESP32 camera board and a webpage for subscribing to these images. There's also a weather station example that pulls data from a BME280 chip and publishes it.

Additional MQTT Tutorials:

Discover More:

No matter what your background or project goals, we're here to help you find the perfect solution! Are you a maker looking for the right tools? A startup trying to get off the ground? A large business seeking new software solutions? We've got you covered.

If you have any questions or just aren't sure which product is right for you, don't hesitate to reach out. Our team is dedicated to helping you overcome your hardware/software challenges and find the best solution for your needs. Let us know how we can help - we'd love to lend a hand!


OPC-UA

OPC-UA Client & Server

An easy to use OPC UA stack that enables bridging of OPC-UA enabled industrial products with cloud services, IT, and HTML5 user interfaces.

Edge Controller

Edge Controller

Use our user programmable Edge-Controller as a tool to accelerate development of the next generation industrial edge products and to facilitate rapid IoT and IIoT development.

On-Premises IoT

On-Premises IoT Platform

Learn how to use the Barracuda App Server as your On-Premises IoT Foundation.

Embedded Web Server

Barracuda Embedded Web Server

The compact Web Server C library is included in the Barracuda App Server protocol suite but can also be used standalone.

WebSocket Server

Microcontroller Friendly

The tiny Minnow Server enables modern web server user interfaces to be used as the graphical front end for tiny microcontrollers. Make sure to check out the reference design and the Minnow Server design guide.

WebDAV Server

Network File System

Why use FTP when you can use your device as a secure network drive.

HTTP Client

Secure HTTP Client Library

PikeHTTP is a compact and secure HTTP client C library that greatly simplifies the design of HTTP/REST style apps in C or C++.

WebSocket Client

Microcontroller Friendly

The embedded WebSocket C library lets developers design tiny and secure IoT applications based on the WebSocket protocol.

SMTP Client

Secure Embedded SMTP Library

Send alarms and other notifications from any microcontroller powered product.

Crypto Library

RayCrypto C Library

The RayCrypto engine is an extremely small and fast embedded crypto library designed specifically for embedded resource-constrained devices.

Embedded PKI Service

Automatic SSL Certificate Management for Devices

Real Time Logic's SharkTrust™ service is an automatic Public Key Infrastructure (PKI) solution for products containing an Embedded Web Server.

Modbus

Modbus TCP client

The Modbus client enables bridging of Modbus enabled industrial products with modern IoT devices and HTML5 powered HMIs.

Posted in Whitepapers