How to integrate an Arduino device via MQTT on akenza

In this tutorial you will learn how to integrate an Arduino device via MQTT on akenza

MQTT is an OASIS standard messaging protocol for the Internet of Things (IoT) and one of the protocols supported by akenza.

It is designed as an extremely lightweight publish/subscribe messaging protocol that is ideal for connecting remote devices with a small code footprint and minimal network bandwidth. MQTT is used in a wide variety of industries. By using a combination of MQTT and API functionalities, akenza enables you to automatically create Digital Twins for your devices. Akenza runs an open-source MQTT broker from Eclipse Mosquitto.

In order to proceed in this tutorial, you need an Arduino Board capable to connect to the Internet. In our example, we use an Arduino Uno WiFi Rev2. To directly connect your device via MQTT with akenza, you can easily implement it with a Python script. Find out more about MQTT connectivity here.

1. Connect the Arduino device via MQTT on akenza

1.1 Creating a secret

In order to safely communicate with akenza, a secret needs to be generated that has to be provided in the topic structure of the uplink request.

This step has to be performed for all devices with the same connection parameters, which you want to connect. Each device will be uniquely identified by a specific ID accordingly. A secret will be generated after the creation of the MQTT device connector on the Data Flow.

1.1.1 Setting up an MQTT Device Connector on akenza

Go to Data Flow in the menu and select Create Data Flow.

Choose MQTT as a device connector. As Device Type, select Passthrough, in order to receive data in the same format as sent from your MQTT device.

Choose one or multiple Output Connectors of your choice. There are several options to choose from. In this tutorial, we choose the Akenza DB. Find out more about Output Connectors.

1.2 Create an MQTT device on akenza

To create a new MQTT device, select Create Device within the menu of the Asset Inventory. Add a device name and optionally a description, Asset Tags, and Custom Fields. Select Next and choose your created MQTT- Data Flow. Select Proceed.

Generate a random ID for this device by clicking Generate ID. Finish the process by clicking on the button Create Device. Your device will be now displayed on the Asset Inventory Overview.

1.3 Set up the Arduino device

As a next step, the Arduino device has to be now configured to send data to the MQTT Broker of akenza. Go to Asset Inventory and use the filter to search for your device. Open the device detail page by selecting your device. Within API-Configuration, all the required information is available to set up the device as an MQTT- client.

2. Configure the Arduino device

2.1 Set up the WiFi Connection

To have the Arduino Uno Wifi able to connect to WiFi we used the WiFiNINA library, available in the Library Manager of Arduino IDE.

2.1.1 Manage Username and Password

In order to manage Username and Password, we have created an additional header file called arduino_secrets.h

#define SECRET_SSID "<your username>"
#define SECRET_PASS "<your password>"

2.1.2 WiFi connection code

The code to connect Arduino to WiFi is reported as below:

#include <WiFiNINA.h>
#include "arduino_secrets.h"

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;     // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

WiFiClient wifiClient;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // attempt to connect to Wifi network:
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }

  Serial.println("You're connected to the network");
  Serial.println();
}

void loop()
{}

2.2 Set up the MQTT Connection to akenza

For security reasons akenza only supports authenticated connections via MQTT. For this, we have chosen as library PubSubClient to manage our MQTT connection. This enables us to use username and password in our connection string.

#include <PubSubClient.h>

//MQTTClient mqttClient(WiFiClient);

char host[] = "mqtt.akenza.io";
char clientid[] = "Arduino";
char username[] = "<copy from Akenza Device Api configuration>";
char password[] = "<copy from Akenza Device Api configuration>";
char outTopic[] = "<copy from Akenza Device Api configuration>";

PubSubClient client(host, 1883, callback, wifiClient);

void setup() {
  if (client.connect(host, username, password)) {
    Serial.print("Connected to ");
    Serial.println(host);
    Serial.println();
    
    boolean r = client.subscribe(outTopic);
    Serial.print("Subscribed to ");
    Serial.println(outTopic);
    Serial.println();
    } 
    else {
      // connection failed
      // mqttClient.state() will provide more information
      // on why it failed.
      Serial.print("Connection failed: ");
      Serial.println(client.state());
      Serial.println();
  }
}

2.3 Create a JSON message

Akenza accepts messages in JSON format for MQTT connections. To build up a well-formed JSON object, we make use of the ArduinoJson library.

#include <ArduinoJson.h>

void loop()
{
  StaticJsonDocument<256> doc;
  doc["Temperature"] = 22;
  doc["Humidity"] = 68;
  doc["Light"] = 96;

  // Add an array
  JsonArray data = doc.createNestedArray("data");
  data.add(48);
  data.add(2.3);
  
  char out[128];
  int b =serializeJson(doc, out);
  Serial.print("publishing bytes = ");
  Serial.println(b,DEC);
  
  boolean rc = client.publish(outTopic, out);
  
  // The above line prints:
  // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
  delay(5000);
  client.loop();
}

2.4 Final result

Now you have all the elements needed to set up your code on Arduino and stream data via MQTT to akenza.

The final code is reported as below:

#include <SPI.h>
#include <PubSubClient.h>
#include <WiFiNINA.h>
#include <ArduinoJson.h>

#include "arduino_secrets.h"

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;     // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

char host[] = "mqtt.akenza.io";
char clientid[] = "Arduino";
char username[] = "0783ddd64683f579";
char password[] = "bd604gmgit0x7kilc8puok3g2rxsldl2";
char outTopic[] = "/up/bd604gmgit0x7kilc8puok3g2rxsldl2/id/99E77F4ECC728656";

//set interval for sending messages (milliseconds)
const long interval = 8000;
unsigned long previousMillis = 0;

int count = 0;

//receive data
void callback(char* topic, byte* payload, unsigned int length) {

  char str[length+1];
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  int i=0;
  
  for (i=0;i<length;i++) {
    Serial.print((char)payload[i]);
    str[i]=(char)payload[i];
  }

  str[i] = 0; // Null termination
  Serial.println();
  
  StaticJsonDocument <256> doc;
  deserializeJson(doc,payload);

  // deserializeJson(doc,str); can use string instead of payload
  const char* sensor = doc["sensor"];
  long time          = doc["time"];
  float latitude    = doc["data"][0];
  float longitude   = doc["data"][1];

  Serial.println("latitude =");
  Serial.println(latitude,2);
  Serial.println(sensor);
  
}

WiFiClient wifiClient;
PubSubClient client(host, 1883, callback, wifiClient);

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // attempt to connect to Wifi network:
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }

  Serial.println("You're connected to the network");
  Serial.println();

  if (client.connect(host, username, password)) {
    Serial.print("Connected to ");
    Serial.println(host);
    Serial.println();
    
    boolean r = client.subscribe(outTopic);
    Serial.print("Subscribed to ");
    Serial.println(outTopic);
    Serial.println();
    } 
    else {
      // connection failed
      Serial.println("Connection failed ");
      Serial.println(client.state());
      Serial.println();
  }
}

void loop()
{
  StaticJsonDocument<256> doc;
  doc["Temperature"] = 22;
  doc["Humidity"] = 68;
  doc["Light"] = 96;

  // Add an array
  JsonArray data = doc.createNestedArray("data");
  data.add(48);
  data.add(2.3);
  
  char out[128];
  int b =serializeJson(doc, out);
  Serial.print("publishing bytes = ");
  Serial.println(b,DEC);
  
  boolean rc = client.publish(outTopic, out);
  
  // The above line prints:
  // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
  delay(5000);
  client.loop();
}

3. Visualize and manage your data on akenza

Akenza automatically decodes the received JSON and visualizes data received from the Arduino device. Incoming data can be viewed on the Device Detail Page within Message Logs.

Incoming data are visualized on Data Overview as Device Data KPIs and also on the History chart.

Further data processing and visualization options can now be applied to your individual use case. For example:

Last updated