Build a MQTT broker for your IoT projects with Vert.x in a couple of minutes

If you are in IoT, then this is true, that you are familiar with MQTT protocol. It is a common way to connect hardware devices with cloud infrastructure. MQTT relies on brokers to transmit messages, but you can easily build it with Vert.x and not depend on a 3rd party solution.

What is MQTT?

MQTT (that stands for Message Queuing Telemetry Transport) is a lightweight messaging protocol, that is used mainly with smart electronics. It is built on top of TCP/IP and implements publish-subscribe messaging pattern. MQTT protocol has three main actors:

  • Publishers = send messages
  • Subscribers = receive messages
  • Brokers = transfers messages from the publishers to the subscribers

Both publishers and subscribers are defined as clients so they don’t communicate directly with each other, but via the MQTT broker. Anything could be a MQTT client – from smart electronics, based on Arduino-compatible boards to cloud apps. They communicate via MQTT brokers.

Among useful for IoT characteristics of MQTT, there are asynchronous nature of communication, small size of messages, as well an ability to work on unstable networks. By default, MQTT works on the port 1883 (or 8883 – if SSL connection is used).

I recommend you to check this article, if you’re curious about MQTT protocol.

Strategy

IoT devices, that are mounted on smart devices (e.g. cars etc.) use MQTT protocol in order to communicate with cloud services – to send/receive data and to provide monitoring and security. In other words, a cloud application serves as a middleware between mobile clients and hardware. Therefore, client applications (Android, iOS) uses easier REST HTTP API for communicating with cloud, and it is also a question of security – there SHOULD BE NO WAY for direct connection between smartphone and car’s devices.

You could see, that there can be two actors (or Verticles in Vert.x’s terminology; also word ‘actors’ here != actors in Akka; it is just a word): one actor serves as a MQTT broker (you can use external broker, therefore your task would be simplified, but it is a question of security) and the second one is used as a HTTP API. They communicate in some way, also there should be also a data storage (database or blockchain – it is up to you).

Coding

Well, for proof of concept purposes, we would not build a whole infrastructure here. Instead of smart cars emulation we would emulate a simple temperature sensor. For instance, you have an Arduino board, that sends MQTT messages with a current temperature and sensor id.

Initialize a new project with two dependencies:

  • Vert.x Core
  • Vert.x MQTT

Create a new class TempSensorService.java that extends AbstractVerticle:

class TempSensorService extends AbstractVerticle{
	@Override
	public void start() throws Exception(){

	}

	public static void main(String[] args){
		Vertx vertx = Vertx.vertx();
		vertx.deployVerticle(new TempSensorService());
	}
}

Now we are ready to build our MQTT broker:

@Override
public void start() throws Exception{
	super.start();
	var broker = MqttServer.create(vertx);
	// provide endpoint handler
	broker.endpointHandler(endpoint->{
		//create publish handler
		endpoint.publishHandler(message->{
			var payload = message.payload().toString(Charset.defaultCharset());
			var data = new JsonObject(payload);

			//you can add data in DB, but we just STDOUT

			System.out.println(data.encodePrettily());
		});
		endpoint.accept(false);
	}).listen(res->{
		if (result.succeeded()){
			System.out.println("Connection succedded");
		} else {
			System.out.println(result.cause().getLocalizedMessage());
		}
	});
}

Btw, as we concentrate in MQTT only, and I wrote about databases before, we would not do it here. Instead of it, let check how MQTT operates in Vert.x. As with other things in Vert.x, everything is easy:

  1. Obtain an instance of MqttServer
  2. Assign an EndpointHandler – it is used to specify the handler called when a remote client sends a CONNECT message for connecting to the server itself.
  3. Inside the handler, assign a PublishHandler – it is used to handle incoming messages published by the remote client
  4. We can get Message’s payload (as well other data). NB!: By default, Message’s payload is of type Buffer, so we need first to convert it to String
  5. endpoint.accept(false) is used for replying to the remote client with the corresponding CONNACK message
  6. And finally we call listen to start a server.

Now, we can see how it work in practice.

Testing

It is always fun to test IoT project, as you can use some hardware. However, here we just need to prove that everything works. You can use MQTTBox application – it is available for Mac, Linux, Windows and is very easy to use. Something like Postman for MQTT 🙂

After you installed this application, you need to create the Client:

You need to set the address – as we run on localhost, it is localhost:1883/ and the client name – it can be anything. Now run the code. You would see that connection is established (button is green). We are ready to send messages:

Add payload (JSON) with temp in Celsius degrees (for example, 15.0) and id that represents the device’s id. Press Publish and in STDOUT you would see the following output:

{
  "temp" : 15.0,
  "id" : "dev1"
}

Conclusion

In this post I showed you how in just a couple of minutes to create a working MQTT server for your IoT projects. NB! that Vert.x-MQTT has the tech preview status, this means the API can change between versions. Anyway, if you don’t want to rely to 3rd party brokers, you can build it with Vert.x in just several commands!

References

  • Andy Stanford-Clark. MQTT is the leading protocol for connecting IoT devices (2019), IBM Developer, read here
  • Roman Aladev. Testing the MQTT Messaging Broker for IoT – A Guide (2017), read here