Let’s take a look at MQTT and see how you can use MQTT with Rust in your next IoT project using the rumqttc crate.
Why do you want to buy IoT devices? In most cases, you want to have more control over your home. Maybe you want to monitor things or even control them remotely.
Of course, you can rely on the apps provided by the manufacturers. But as a programmer, this is not your only option. Maybe, you want to receive a message when the washing machine is running, or you want to receive an alert when the appliance consumes too much power. In these cases, you can take a look at MQTT.
In this article, we will create a small MQTT client in Rust that listens to an MQTT broker and writes messages. So let’s start.
So first, what is MQTT? MQTT is a lightweight, publish-subscribe, machine-to-machine (M2M) network protocol. It is optimized for low bandwidth and high latency.
But how does it work? MQTT works according to the publish-subscribe pattern. message senders named publisherscannot specify the receiver directly, which is called customersbut instead classify the published messages into classes called Subject, This happens without knowledge of how many subscribers have subscribed to topics. But how does this system actually work?
To make MQTT communication possible, we need a broker and multiple clients. The broker acts as an intermediary. The client can send messages to any topic on the broker. At the same time, other clients can listen for new messages on the topic. Once these basics are clear, we can move to the code.
For this small project we will be using Rust. Rust is a well performing and reliable language. Performance is comparable to C++ when memory-safety and thread-safety are guaranteed through its rich type system and proprietary model. Both features are helpful in this particular case of a lightweight program running in the background for a long time.
For this article, we use Rust crate (=library)
rumqttc, This is a complete implementation of the MQTT client in Rust.
First, we need to create a new Rust project.
cargo new mqtt-rust-demo
After switching to new project we add
rumqttc For us
rumqttc = "0.17.0"
After installing the library, we can start with the code.
The first thing we do is create a variable with our connection data. this is done through
let mut mqttoptions = MqttOptions::new("NAME", "YOUR BROKER", 1883);
First of all, we need to specify the name of the client. It is important to give a unique name to the client as no two clients can have the same name at the broker. After that, the broker’s address and port will follow as the next parameters. You can connect to a broker over the internet or your local network. In addition, you can set options. In our case, the client will send a ‘still active’ message every five seconds.
let (mut client, mut connection) = Client::new(mqttoptions, 10);
Thus we create a synchronous client. We fill it with our options. We get back the client object and the event loop. The latter will be important later. First, let’s say we want to subscribe to the topic
Also, we specify the QoS level. Quality of Service (QoS) is a key feature of the MQTT protocol. There are 3 different levels of QoS: at most once (0), at least once (1) and exactly once (2).
- QoS 0 – at most once simply sends messages (as fire and forget) to the broker. This level should only be used in very reliable networks
- QoS 1 – at least once Sends messages to the broker. At the same time, the sender stores the message locally until the broker sends back an acknowledgment message (PUBACK message). Sender repeats the message when no acknowledgment message is returned after some time.
- QoS 2 – exactly once Sends messages to the broker (which is not surprising). Like QoS 1, it waits until it receives an acknowledgment message (
PUBREC) Back. Until then, the sender sends the same published message with a duplicate flag. When the acknowledgment message is received by the sender, it responds with a
PUBRELMessage to broker. Meanwhile, the sender stores
PUBRECmessage. when the broker receives
PUBRELmessage, it can safely discard all data temporarily stored for this message. At the same time, the broker sends a
PUBCOMPMessage to sender. Now the sender can delete all temporal data.
In this subject, we send some messages. So we do a new thing. In this task, we publish a message on a topic with a number.
thread::spawn(move || for i in 0..10
client.publish("demo/mqtt", QoS::AtLeastOnce, false, vec![i; i as usize]).unwrap();
Next, we come to our event loop object. We wrap it in an infinite loop, because it should always be listening for messages from the topic.
This is done with the command
connection.iter().enumerate(), Next, we output the message.
for (_i, message) in connection.iter().enumerate()
println!("Message= :?", message);
This article gives only a small introduction to the vast and interesting topic of MQTT. But let’s take a look at what you’ve learned – you have a basic understanding of the structure of MQTT and have created a small program in Rust that can send and receive messages. That’s a great start!
here it is code for this article
This article can also be found on my blog: