Get started with MQTT

Prev Next

This tutorial will show you step-by-step how to test the connection of your devices to Servitly using the MQTT standard protocol.
To publish data through the MQTT protocol, you can download the Eclipse PAHO library, which is available in several programming languages. Check out the PAHO download page for more details.
You can download the source code (Java) of the sample project used in this tutorial here.

DPS Account creation

  1. Create a new account on https://lab.servitly-sandbox.com/

  2. When done, log in and select the "My Home" location.

  3. Press the (+) button to create new Equipment

  • Name: The mnemonic name of the equipment you are creating.

  • Serial Number: The equipment’s unique serial number (e.g., SN-12345).

  • Thing Definition: Select Generic-Device which is the default definition for testing that includes a predefined set of metrics, commands, configuration parameters, and event/alert definitions.

  • GPS Position: The coordinates where the device is installed (Optional). By default, it’s inherited from the location if specified.

MQTT Connector Configuration

Once saved, go to the equipment Connection tab to configure how the Equipment will connect to the cloud. Provide the following information:

  • Type: Servitly Thing Connector.

  • MQTT Broker URL: mqtt.servitly-sandbox.com:8883.

  • Username: Choose a unique username to identify the MQTT connection.
    It’s the root part of the MQTT topics <USERNAME>/<ASSET_ID>/<METRIC_PATH>.

  • Password: At least 8 characters long with at least one lowercase letter, one uppercase letter, and one number.

  • Asset Id: The equipment identifier, which will be used as the MQTT sub-topic (usually it is equivalent to the Serial Number or the MAC address of the gateway).

  • Path: The optional path which can be used to manage multiple devices mapped under the same gateway.

Now you are ready to open an MQTT connection and start sending data to Servitly.

MQTT Client

To publish data through the MQTT channel, the following information is needed:

  • MQTT Broker URL: The MQTT broker connection URL.

  • Username: The username used to open the MQTT connection.

  • Password: The username and password used to authenticate the MQTT connection.

  • Asset Id: The device identifier used within the publishing topic.

  • Metric Path: The path mapping the metrics you want to publish.
    If you are using the "Generic Device" Thing Definition, you must use "measures".

For more details about how to configure the connection properties, enter the device dashboard page and click on the Edit button (top right), and then enter the Connection tab.
Please note that the publishing topic must have this structure <USERNAME>/<ASSET-ID>/<METRIC_PATH>. For this test, you can use measures as the metric path.
Here is the PublishSample Java class that connects to the Servitly MQTT broker and publishes a message by using the PAHO MqttClient synchronous API.

Remember to replace the variables (<***>) with your connection properties.

package com.servitly.samples.mqtt;

import java.util.Random;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * This sample class uses the PAHO client to publish a message to the MQTT broker.
 */
public class PublishSample {

 private static final String BROKER_URL = "ssl://mqtt.servitly-sandbox.com:8883";

 private static final String USERNAME = "<USERNAME>";
 private static final String PASSWORD = "<PASSWORD>";
 private static final String ASSET_ID = "<ASSET_ID>";

 private static final String METRIC_PATH = "measures";

 public static void main(String[] args) {
    try {

       // create the Servitly payload
       ObjectNode payload = JsonNodeFactory.instance.objectNode();
       payload.put("ts", System.currentTimeMillis());
       ObjectNode data = JsonNodeFactory.instance.objectNode();
       Random random = new Random();
       data.put("measure1", 42 + random.nextInt(10));
       data.put("measure2", 24 + random.nextInt(10));
       payload.set("data", data);

       // create the MQTT Client
       MqttClient mqttClient = new MqttClient(BROKER_URL, USERNAME + "_PUB");
       MqttConnectOptions connOpts = new MqttConnectOptions();
       connOpts.setCleanSession(true);
       connOpts.setUserName(USERNAME);
       connOpts.setPassword(PASSWORD.toCharArray());

       // open MQTT connection
       System.out.println("Connecting to MQTT broker: " + BROKER_URL);
       mqttClient.connect(connOpts);
       System.out.println("Connected");

       // publish message
       String topic = String.format("%s/%s/%s", USERNAME, ASSET_ID, METRIC_PATH);
       System.out.println("==> Publishing message to " + topic);
       System.out.println(payload.toPrettyString());
       MqttMessage message = new MqttMessage(payload.toString().getBytes());
       message.setQos(1);
       mqttClient.publish(topic, message);
       System.out.println("Message published");

       // disconnect client
       mqttClient.disconnect();
       mqttClient.close();
       System.out.println("Client disconnected");
    } catch (MqttException me) {
       System.out.println("Reason: " + me.getReasonCode());
       System.out.println("Message: " + me.getMessage());
       System.out.println("Cause: " + me.getCause());
       me.printStackTrace();
    }
 }
}

Let’s see how it works.

MQTT connection parameters

private static final String BROKER_URL = "ssl://mqtt.servitly-sandbox.com:8883";

// fields to replace
private static final String USERNAME = "<USERNAME>";
private static final String PASSWORD = "<PASSWORD>";
private static final String ASSET_ID = "<ASSET_ID>";

Here, we are defining the parameters needed for the connection; the same ones you have configured during the product registration within Servitly.

MQTT connection certificate

All the Servitly endpoints are exposed over TLS 1.2, so before the MQTT connection is established, the client has to validate the certificate presented by the broker.
Depending on the capabilities of your device, you can either rely on a public CA or provision the CA certificate yourself.

  • Using a public CA: The Servitly broker certificate is issued by a public Certificate Authority, whose root certificate is already included in the trust store shipped with most operating systems and runtimes.
    This is the recommended method, but you must ensure that the trust store on your device is kept updated (e.g., OS update).

  • Downloading and using the CA certificate: Devices based on limited hardware, or runtimes that do not provide a trust store, cannot rely on the certificates embedded in the operating system.
    In this case, the CA certificate must be downloaded from the Servitly endpoint and loaded into the MQTT client. You can set a custom SSLSocketFactory to your MQTT Client.

For more details about certificates, refer to the SSL Certificates article.

Create the MQTT message payload

Here, we are preparing the MQTT payload that contains the measures being sent to Servitly.

ObjectNode payload = JsonNodeFactory.instance.objectNode();
payload.put("ts", System.currentTimeMillis());
ObjectNode data = JsonNodeFactory.instance.objectNode();
Random random = new Random();
data.put("measure1", 42 + random.nextInt(10));
data.put("measure2", 24 + random.nextInt(10));
payload.set("data", data);

A generic payload has the following format:

{
  "ts": 1605179226000,
  "data":{
    "measure1": 42,
    "measure2": 24
  }
}

Publish the MQTT message

Here, we are creating the MQTT client that will connect to Servitly and send the message that we have previously created.

// create the MQTT Client
MqttClient mqttClient = new MqttClient(BROKER_URL, USERNAME + "_PUB");
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
connOpts.setUserName(USERNAME);
connOpts.setPassword(PASSWORD.toCharArray());

// open MQTT connection
System.out.println("Connecting to MQTT broker: " + BROKER_URL);
mqttClient.connect(connOpts);
System.out.println("Connected");

// publish message
String topic = String.format("%s/%s/%s", USERNAME, ASSET_ID, METRIC_PATH);
System.out.println("==> Publishing message to " + topic);
System.out.println(payload.toPrettyString());
MqttMessage message = new MqttMessage(payload.toString().getBytes());
message.setQos(1);
mqttClient.publish(topic, message);
System.out.println("Message published");

If everything works correctly, the result will be the Connection Status changed to ONLINE, and then a new measure is received.

Dealing with configuration parameters

The Generic-Device thing-definition exposes two metrics and a configuration parameter:

METRIC

MAPPING PATH

MAPPING NAME

Measure 1

measures

measure1

Measure 2

measures

measure2

Parameter 1

measures

parameter1

Parameter1 can be updated directly within the dashboard, using the corresponding configuration parameter in the Overview tab.
To receive data from Servitly for the Parameter 1 parameter, the MQTT client has to subscribe to the following topic:

<USERNAME>/<ASSET-ID>/command

Within the Java sample, you can find the SubscribeSample class, which, once running, remains active for 20 seconds, while MQTT messages are logged to the console.
Here is the source code fragment responsible for listening on topics.

mqttClient.subscribe(topic, new IMqttMessageListener() {

 @Override
 public void messageArrived(String topic, MqttMessage message) throws Exception {
    JsonNode payload = JSON_MAPPER.readTree(message.getPayload());
    System.out.println("<== Incoming message from " + topic);
    System.out.println(payload.toPrettyString());
 }

});

Technical restrictions

  • The communication between the gateway and Servitly is TCP/IP based and encrypted with TLS 1.2.

  • The MQTT broker is exposed on port 8883.

  • To open the connection, this information is mandatory:

    • username and password: credentials defined within the Connection tab of the equipment registered within Servitly.

    • asset-id: the ID of the asset opening the connection, usually the serial number, or the MAC address can be used.

  • The MQTT topics must always start with the <USERNAME>/<ASSET_ID>/ path.

  • The MQTT topics must always end with the metric mapping path.

  • The Servitly Lab tenant allows 200 measures per hour per equipment; measures exceeding such a limit will be discarded until the end of the hour.

  • The certificates of Servitly are periodically updated (see the SSL Certificates article).