In this document, we explore integrating Norvi IIoT devices with MQTT protocol, publishing data and decoding the data by MQTT broker, and visualization in a DATA cake.
MQTT PROTOCOL #
MQTT (Message Queuing Telemetry Transport) is a lightweight messaging protocol designed for low-bandwidth, high-latency, or unreliable networks. It’s widely used in Internet of Things (IoT) and machine-to-machine (M2M) communication due to its simplicity and efficiency.
Check this link to understand more about the MQTT PROTOCOL.
Here are the components of MQTT,
1. Publisher-Subscriber Model
- MQTT follows a publisher-subscriber model. In this model, there are two main entities, publishers and subscribers.
- Publishers are devices or applications that publish messages on a specific topic.
- Subscribers are devices or applications that receive messages by subscribing to specific topics.
2. Broker
- MQTT communication is facilitated by a broker. The broker is a server responsible for receiving, routing, and delivering messages.
- Publishers and subscribers connect to the broker to send and receive messages.
- The broker is responsible for managing topics, subscribers, and message delivery.
3. Topics
- Messages in MQTT are published to topics. Topics are hierarchical and can be thought of as addresses.
- Subscribers can subscribe to entire topics or specific subtopics using wildcards.
- For example, a topic could be sensors/temperature where sensors are the main topic and temperature is a subtopic.
4. Retained Messages
- MQTT allows for retained messages, which are special messages that are stored by the broker and sent to new subscribers immediately upon subscription.
- This feature is useful for sending status updates or configuration information to new subscribers.
5. Quality of Service (QoS)
- MQTT supports different levels of Quality of Service (QoS) for message delivery:
- QoS 0 (At most once): Messages are delivered at most once, without confirmation.
- QoS 1 (At least once): Messages are guaranteed to be delivered at least once, but duplicates may occur.
- QoS 2 (Exactly once): Messages are guaranteed to be delivered exactly once.
NORVI IIOT with MQTT #
Here we’ll be considering the NORVI ESP32 device as a Publisher and “MQTT.FX” software as the Subscriber. With the NORVI device, we’ll publish the data values of the analog inputs, and store the values in the MQTT Broker and the data visualization platform.
Prerequisites #
- Norvi IIoT device
- MQTT broker
- Subscriber
- Wi-Fi network
- Data visualization platform (e.g., DATACAKE)
Understanding the Test program #
This code connects an ESP32 to a WiFi network and an MQTT broker, reads analog values from an ADS1115 ADC, packages these values into a JSON payload, and publishes the payload to an MQTT topic at regular intervals. It ensures continuous connectivity to the MQTT broker and handles reconnection if the connection drops. Download the example program.
Check the pin configuration of the program according to the NORVI device. Compile and Upload the program.
Include Libraries: The code includes the necessary libraries for WiFi connectivity, MQTT communication, JSON objects, and ADS1115. Find the necessary libraries from here.
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Adafruit_ADS1X15.h>
WiFi Credentials: Defines the WiFi network name (SSID) and password.
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
MQTT Broker Configuration: Sets up the MQTT broker details including server address, port, topic to publish, and authentication credentials.
const char* mqtt_server = "YOUR_MQTT_BROKER_ADDRESS";
const int mqtt_port = "YOUR_MQTT_PORT";
const char* mqtt_topic = "YOUR_MQTT_TOPIC";
const char* mqtt_username = "YOUR_MQTT_USERNAME";
const char* mqtt_password = "YOUR_MQTT_PASSWORD";
WiFi Client, MQTT Client, and ADS1115 Initialization: initializes the WiFi client, MQTT client, and ADS1115 ADC objects.
WiFiClient espClient;
PubSubClient client(espClient);
Adafruit_ADS1115 ads;
WiFi Connection Setup: Connects to the WiFi network using the provided credentials.
void setup_wifi() {
delay(10);
// Connect to WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
MQTT Reconnect Function: Tries to reconnect to the MQTT broker if the connection is lost.
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.println("");
Serial.print("Attempting MQTT connection...");// Attempt to connect
if (client.connect("ESP32Client", mqtt_username, mqtt_password)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
Setup Function: Initializes serial communication, MQTT broker server and port, WiFi connection, I2C communication, and ADS1115 with I2C address 0x48.
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
Wire.begin(16,17);
if (!ads.begin(0x48)) {
Serial.println("Failed to initialize ADS.");
while (1);
}
}
Loop Function: Reconnects to MQTT if disconnected, then reads ADS data, publishes it to the MQTT broker, and creates JSON Payload.
void loop() {
int16_t adc0, adc1, adc2, adc3;
adc0 = ads.readADC_SingleEnded(0); adc1 = ads.readADC_SingleEnded(1);
adc2 = ads.readADC_SingleEnded(2);adc3 = ads.readADC_SingleEnded(3);
Serial.println("");
Serial.print("AIN0: "); Serial.print(adc0);
Serial.print("\nAIN1: "); Serial.print(adc1);
Serial.print("\nAIN2: "); Serial.print(adc2);
Serial.print("\nAIN3: "); Serial.print(adc3);
Serial.println("");
if (!client.connected()) {
reconnect();
}
client.loop();
// Create JSON payload
DynamicJsonDocument doc(256);
doc["Anint1"] = adc0;doc["Anin2"] = adc1;
doc["Anin3"] = adc2;doc["Anin4"] = adc3;
String payload;
serializeJson(doc, payload);
// Publish payload to MQTT topic
client.publish(mqtt_topic, payload.c_str());
delay(5000); // Adjust the delay according to your needs
}
Software Configurations #
Check this link for detailed instructions on how to configure the MQTT broker and the Subscriber.
Results from MQTT conversion using the NORVI device. #
JSON Encoding #
JSON (JavaScript Object Notation) is a lightweight data-interchange format that is easy for humans to read and write and easy for machines to parse and generate. In the provided code, JSON is used to structure the sensor data (both analog and digital) before publishing it to an MQTT broker.
Steps of JSON Encoding in the Code,
- The ArduinoJson library is used to handle JSON encoding. It allows us to create a JSON document and serialize it into a string format.
#include <ArduinoJson.h>
- A DynamicJsonDocument object named doc is created with a capacity of 256 bytes. This object will hold the JSON structure.
DynamicJsonDocument doc(256);
- Each piece of sensor data is added to the doc object as a key-value pair. The keys (e.g., “Analog input1”, “Analog input2”) are strings, and the values (e.g., adc0, adc1) are the sensor readings.
doc["Anin1"] = adc0;
doc["Anin2"] = adc1;
doc["Anin3"] = adc2;
doc["Anin4"] = adc3;
- The serializeJson function converts the JSON document (doc) into a string (payload). This string can then be used to transmit the data over MQTT.
String payload; serializeJson(doc, payload);
- The payload.c_str() function call converts the String object to a C-style string (a null-terminated array of characters). This is required by the publish method of the MQTT client. The JSON string is then published to the specified MQTT topic.
client.publish(mqtt_topic, payload.c_str());
Integration with Data Visualization Platform #
The NORVI Devices can be connected to an IoT platform, allowing users to visualize data collected by the NORVI devices. The platform used in this case is DATACAKE. Here’s how to integrate the NORVI devices with DATACAKE.
1. Access the DATACAKE from this link and navigate the Datacake dashboard. Select the “Add Devices”.
2. For the MQTT integration select the API. This will add the device to the Datacake account.
3. Click on Configuration Scroll down a bit and go to the new panel “MQTT Configuration”. Press on “Add New MQTT Broker”. Fill in the server details and add.
4. Then link the MQTT device on the broker to the device in the DATACAKE by providing the MQTT upline decoder. Subscribe to the topic on the MQTT broker and write a payload decoder.
This decoder function is designed to decode incoming messages from a device and format them into a structure that can be sent to the Datacake API for display or storage.
JSON Parsing: This function starts by converting the incoming payload, presumably in JSON format, into a JavaScript object. It uses JSON.parse() to accomplish this.
function Decoder(topic, payload) {
// Transform incoming payload to JSON
payload = JSON.parse(payload);
Data Extraction: It then extracts analog (ANIN1, ANIN2, ANIN3) and digital (INPUT1, INPUT2, INPUT3, INPUT4) inputs from the payload. Each value is converted to an integer using parseInt(). This assumes that the payload contains these fields as strings representing integer values.
// Extract analog and digital inputs from payload
var ANIN1 = parseInt(payload.Anin1);
var ANIN2 = parseInt(payload.Anin2);
var ANIN3 = parseInt(payload.Anin3);
var ANIN4 = parseInt(payload.Anin4);
Data Forwarding: Finally, it constructs an array of objects where each object represents a data point to be sent to the Datacake Device API.
// Forward Data to Datacake Device API using Serial, Field-Identifier
return [
{
device: "Serial Number", // Serial Number or Device ID
field: "ANIN1",
value: ANIN1
},
{
device: "Serial Number", // Serial Number or Device ID
field: "ANIN2",
value: ANIN2
},
{
device: "Serial Number", // Serial Number or Device ID
field: "ANIN3",
value: ANIN3
},
{
device: "Serial Number", // Serial Number or Device ID
field: "ANIN4",
value: ANIN4
}
];
“Try Decoder Function” allows the decoder function to be tested to verify its functionality before deploying it. By entering sample data and observing the output, you can verify that the decoder is correctly parsing incoming payloads and formatting the data in a way that can be sent to the Datacake API.
5. To create a first database field, click on the “Add Field”. This will open another modal asking for some required input for the fields.
When typing the name for that field, the identifier auto-fills. This identifier is unique and cannot be changed. it’s required for accessing the field from within the payload decoder or API.
6. If the device is already sending data, an indication of incoming data can be seen in the “Last data” column.
7. After the settings in the configuration section, the dashboard can be created. Use the Tab Bar on the Device to navigate into the ”Dashboard” view.