MQTT Integration

The MQTT Protocol

The standard communication protocol on the thingable platform! is MQTT (Message Queue Telemetry Transport), a machine to machine communication protocol - M2M, developed by IBM and Eurotech in the 1990s.

In an MQTT communication there are three main actors; publisher, broker and subscriber, in the following figure we have more details of how the flow of information using MQTT is:

From the image we can see that the broker is the central element of this connection where publishers send their data and subscribers receive this data.

The distinction between the following elements should be kept clear:

  • Publisher: it is the element (sensor, computer, software, gateway...) that publishes data for a topic in the broker, this data can be, for example, the reading of a temperature sensor, flow, level or any other information that you want to make available to other subscribers of the topic.

  • Broker: is a server that acts between publishers and subscribers, responsible for managing the connections between the two sides.

  • Subscriber: is the element that consumes information from a specific topic. Example: I have a temperature sensor capable of publishing data on a topic in the broker, I as a consumer connect to the broker and subscribe to the topic that is receiving the information from that sensor. Thus, whenever I have a new data in this topic, I will be informed.

  • Topic: is the way the data is addressed in the MQTT protocol through a hierarchical structure where each information is divided into "/" bars. Topics can be of the publication type (for sending data) or registration type (for receiving data). Following is an example of a standard topic in the thingable! for data publishing:

iot-2/type/sSISC/id/SSISC_POC/evt/data/fmt/json

In this example we have the following information organized hierarchically:

  • type: sSISC, name defined on the platform for the type of a device created on the platform.

  • id: SSISC_POC, name defined on the platform for the individual identification of a device.

  • evt: date, name defined for the event, here the name can be the integrator's choice.

  • fmt: json, data arrival format, can be json or txt.

The topic of enrollment is very similar to the one of publication, the difference is in the exchange of the field evt by cmd. The following is the same example of previous topics, but for enrollment:

iot-2/type/sSISC/id/SSISC_POC/cmd/data/fmt/json

In this example we have the following information organized hierarchically:

  • type: sSISC, name defined on the platform for the type of a device created on the platform.

  • id: SSISC_POC, name defined on the platform for the individual identification of a device.

  • cmd: date, name defined for the event, here the name can be the user's choice.

  • fmt: json, data arrival format, can be json or txt.

A necessary point during the integration of a new device into the thingable! are the access credentials to the broker (user, password and client-ID), so a device needs to know these credentials and the topic of publication.

When we create a new device (Create a Device) we have available the credentials for the device:

Another point that deserves our attention is the type of credentials used in the thingable!, there are two: device credentials and application credentials. Device Type Credentials have simpler definition, focused on the transmission of data from a device to a fixed topic in the broker. Application-type credentials are directed to systems that work with multiple topics at the same time, the main difference is in the client-ID and in the topic.

In device-type credentials, the client-ID specifies the type and ID of the device that will receive this data, while in the application-type credential this information is not specified in the client-ID field but in the topic, so an application can change the topic of publishing/enrollment at runtime. The following are examples explaining these differences:

  • Device topic for publication: iot-2/evt/data/fmt/json

  • Application topic for publishing: iot-2/type/device-type/id/device-id/ evt/data/fmt/json

  • Enrollment device topic: iot-2/cmd/data/fmt/json

  • Application topic for enrollment: iot-2/type/device-type/id/device-id/cmd/date/fmt/json

In the following section we have a practical example of an integration using MQTT protocol: For our tutorial we will use the AirGate 4G device from Novus.

The first step is to create a device on the thingable! platform, the device on the platform is an entity that represents a device in the real world: (Create a Device):

In the image above, the device described as Novus Airgate 4G identified on the platform by the ID AIRGATE_042022 was created and categorized as a device of Type: tipo_generico, created only for this tutorial. After this creation process, the credentials for connecting this device to the broker will be available.

We must also configure the measurement points in the SCADA system through the Schema field within the type created for these tutorials as shown below:

It is possible to see that the schema used has four measurement points: temperature, luminosity, battery_voltage and humidity. The schema used is available at the end of this tutorial. And in this link (Metadata and Schema) is available a tutorial that explains, in detail, how to create a schema that fits your device. Click save, and then yes, when asked if you want to update the database of the devices associated with the type.

In the SCADA Database Manager tool we can check the tags created for these measurement points:

Tag is the medium used by the thingable platform! to identify the measurement points of each device.

The next step is to configure the connection of the physical device to the thingable! broker.

The AirGate 4G is a very versatile gateway manufactured by Novus, with support for MQTT communication, but any other MQTT-compatible device that has the editable topic field can be used by following the steps listed here. In this tutorial we will use the AirGate Modbus/RS485 network connected to a datalogger with four analog sensors, we will not go into the details of the sensors, we will focus only on the integration of Modbus and MQTT protocols.

The first step is to configure the Modbus/RS485 network addresses and registers in the Modbus Poll tab within the Modbus Master menu. In the description of the channels use the same names as the schema keys as shown in figure 7, at the end note the Index number. For more details on the configuration of the channels see the equipment manual provided by Novus, available at this link.

We will now use Airgate's Modbus Transport function, this function allows you to send data from a device connected to the Modbus/RS485 bus to an MQTT broker, FTP server or TCP/IP We will not go into details about the configuration of the Modbus Transport function, as it is already well explained in the equipment manual provided by Novus, available in this link.

The following is the image extracted from the equipment configuration menu. All fields required to configure the MQTT communication are available in the device credentials icon, which has already been shown in Figure 2.

Briefly, the information that needs to be entered is: Server Address (URL field of the device credentials window), Server Port (default port 1883), Username (User field), Password (Password (Client) field), Client ID (Client-lD field).

In the image above it is worth highlighting the Data Format field, this field is specific to the Novus AirGate 4G equipment, the data to be sent in json format can be formatted according to the registers available in this equipment. In other equipment, the data that will constitute the payload can come in different ways, depending on the particularities of the manufacturer and equipment. Taking advantage of the high degree of customization of the Data Format field, we will use a notation that suits our schema.

The completion of the fields will be as follows, taking into account the device created in this tutorial:

Server address: adne61.messaging.internetofthings.ibmcloud.com

Server Port: 1883

Username: use-token-auth

Password: XXXXXXXXXXXX

Cliente ID: d:adne61:teste:AIRGATE_042022

Subscribe Topic: iot-2/cmd/update/fmt/json

Connection Index: 1 (this number must be equal to the Index created in Modbus Poll populated)

Data Format: {"$CHANNEL_DESC": $VALUE,"time": "$DATE"}

Note1: Subscribe Topic and Connection Index will be available when creating an element in the Modbus Channel list (see figure 9).

Note2: The inserted Data Format uses the description of the modbus channel ($CHANNEL_desc), the read values of the registers ($VALUE) and the equipment timestamp ($DATE) to format the MQTT message corresponding to our schema.

These steps are explained in more detail in section 7.20.4 in the official Airgate 4G manual (link).

With the previous steps completed and AirGate being connected to the internet (WiFi, ethernet, 4G...) we already have the necessary infrastructure to receive the data from the device on the platform and thus make it available to the widgets in the applications. In the following figure we can observe the arrival of the data in the events of the device and its subsequent visualization in the dashboard of an example application:

In this link we have a tutorial on how to create an application: How to Create an Application

The following is the source code of the schema used:

{
  "time": {
    "type": "string",
    "ignored": [
      "typeScada"
    ],
    "typeScada": "tsCampo"
  },
  "temperatura": {
    "type": "number",
    "ignored": [
      "typeScada",
      "point",
      "factor",
      "HighLimitValue",
      "HighLimitAlarm",
      "VeryHighValue",
      "VeryHighAlarm",
      "HighValue",
      "HighAlarm",
      "NormalAlarm",
      "LowValue",
      "LowAlarm",
      "VeryLowValue",
      "VeryLowAlarm",
      "LowLimitValue",
      "LowLimitAlarm"
    ],
    "typeScada": "analogIn",
    "point": 1,
    "HighLimitValue": 150,
    "HighLimitAlarm": 0,
    "VeryHighValue": 110,
    "VeryHighAlarm": 0,
    "HighValue": 100,
    "HighAlarm": 0,
    "NormalAlarm": 0,
    "LowValue": 50,
    "LowAlarm": 0,
    "VeryLowValue": 20,
    "VeryLowAlarm": 0,
    "LowLimitValue": 1,
    "LowLimitAlarm": 0
  },
  "luminosidade": {
    "type": "number",
    "ignored": [
      "typeScada",
      "point",
      "factor",
      "HighLimitValue",
      "HighLimitAlarm",
      "VeryHighValue",
      "VeryHighAlarm",
      "HighValue",
      "HighAlarm",
      "NormalAlarm",
      "LowValue",
      "LowAlarm",
      "VeryLowValue",
      "VeryLowAlarm",
      "LowLimitValue",
      "LowLimitAlarm"
    ],
    "typeScada": "analogIn",
    "point": 2,
    "HighLimitValue": 99999,
    "HighLimitAlarm": 0,
    "VeryHighValue": 8000,
    "VeryHighAlarm": 0,
    "HighValue": 6000,
    "HighAlarm": 0,
    "NormalAlarm": 0,
    "LowValue": 4000,
    "LowAlarm": 0,
    "VeryLowValue": 2000,
    "VeryLowAlarm": 0,
    "LowLimitValue": 0,
    "LowLimitAlarm": 0
  },
  "tensao_bateria": {
    "type": "number",
    "ignored": [
      "typeScada",
      "point",
      "factor",
      "HighLimitValue",
      "HighLimitAlarm",
      "VeryHighValue",
      "VeryHighAlarm",
      "HighValue",
      "HighAlarm",
      "NormalAlarm",
      "LowValue",
      "LowAlarm",
      "VeryLowValue",
      "VeryLowAlarm",
      "LowLimitValue",
      "LowLimitAlarm"
    ],
    "typeScada": "analogIn",
    "point": 3,
    "HighLimitValue": 99999,
    "HighLimitAlarm": 0,
    "VeryHighValue": 8000,
    "VeryHighAlarm": 0,
    "HighValue": 6000,
    "HighAlarm": 0,
    "NormalAlarm": 0,
    "LowValue": 4000,
    "LowAlarm": 0,
    "VeryLowValue": 1000,
    "VeryLowAlarm": 0,
    "LowLimitValue": 0,
    "LowLimitAlarm": 0
  },
  "umidade": {
    "type": "number",
    "ignored": [
      "typeScada",
      "point",
      "factor",
      "HighLimitValue",
      "HighLimitAlarm",
      "VeryHighValue",
      "VeryHighAlarm",
      "HighValue",
      "HighAlarm",
      "NormalAlarm",
      "LowValue",
      "LowAlarm",
      "VeryLowValue",
      "VeryLowAlarm",
      "LowLimitValue",
      "LowLimitAlarm"
    ],
    "typeScada": "analogIn",
    "point": 4,
    "HighLimitValue": 99999,
    "HighLimitAlarm": 0,
    "VeryHighValue": 8000,
    "VeryHighAlarm": 0,
    "HighValue": 6000,
    "HighAlarm": 0,
    "NormalAlarm": 0,
    "LowValue": 4000,
    "LowAlarm": 0,
    "VeryLowValue": 2000,
    "VeryLowAlarm": 0,
    "LowLimitValue": 0,
    "LowLimitAlarm": 0
  }
}

Author: Angelo Guimarães

Last updated