Introduction: Secure MQTT With SIMCOM SIM7500 Guide on NORVI GSM Series

About: ESP32 & STM32 based Industrial Controllers

NORVI devices are industrial IoT controllers that use the SIMCOM SIM7500 module for secure cellular connectivity via SSL MQTT communication. This guide outlines the process of setting up NORVI devices with the SIM7500 modem, including configuring the modem, connecting to the network, and establishing an SSL-secured MQTT session using AT commands.

Click here to view the web guide

NORVI GSM Series

MQTT Protocol

Click here for a guide on the MQTT protocol

Supplies

SSL MQTT Communication


SSL (Secure Sockets Layer) safeguards data in transit from being intercepted or altered by unauthorized entities. It creates an encrypted connection between a client (such as the SIM7500 modem) and a server (like an MQTT broker), ensuring that any information exchanged remains confidential and protected from eavesdropping or tampering. This encryption technology is essential for maintaining the security of data during transmission over networks, especially in IoT communications where sensitive data is involved.

To configure SSL on NORVI SIM7500 devices for secure MQTT communication, follow these steps:

1. Insert the SIM card into the NORVI GSM series SIM7500 device.

2. Power on the NORVI device.

3. Open the serial monitor in your development environment.

4. Send AT commands to the SIM7500 module to enable SSL for MQTT communication.

5. Ensure the device and MQTT broker certificates are up-to-date for secure connections.

NORVI SIM7500 Devices (Click here to check SIM7500 Devices)


Setting Up NORVI GSM series SIM7500 to MQTT SSL


Here we’ll be considering the NORVI GSM series SIM7500 device as a Publisher and “MQTT.FX” software as the Subscriber. With the NORVI device, we’ll be storing the I/O values in the MQTT Subscriber and the data visualization platform. 

Key features of NORVI devices with the SIM7500 module,

  1. Industrial-grade design: Suitable for harsh environments.
  2. Versatile I/O options: Digital and analog inputs/outputs for various sensors and actuators.
  3. Cellular connectivity: LTE support via the SIM7500 module for remote monitoring and control.
  4. SSL/TLS security: Secure data transmission using SSL/TLS over MQTT.


Prerequisites

Before you begin, ensure you have the following,

  1. NORVI Device with an integrated SIM7500 module
  2. MQTT broker details (hostname, port, username, password)
  3. MQTT.fx software for testing and monitoring
  4. Arduino IDE and necessary libraries for programming the NORVI device.
  5. Data visualization platform (e.g., DATACAKE)
  6. SSL Certificates: ( CA certificate, client certificate, and client key).

Required Libraries 

  1. Arduino.h
  2. Wire.h
  3. WiFi.h
  4. ArduinoJson.h
  5. Datacake.h

Sensitive Information Handling

  1. Secret.h: This file should contain the MQTT username and password, which should be kept secure.

SSL Certificate Setup

To establish an SSL-encrypted connection, include the SSL certificates in the code.

  1. Root CA Certificate: The certificate authority that issued the broker’s certificate.
  2. Client Certificate: Your device’s certificate.
  3. Client Key: The private key corresponding to the client certificate.


Hardware Setup


1. Pin Connections

  1. MODEM_TX (TX Pin)
  2. MODEM_RX (RX Pin)
  3. GSM_RESET (Reset Pin)
  4. Digital Input Pins (D0, D1, D2, D3)

Step 1: Test Program

Click here to get the code (Github) SIM7500_Connecting_to_Datacake_with_MQTT_Broker_TLS_Secured

This code configures a NORVI device with the SIM7500 modem for SSL-secured MQTT communication over a cellular network. It initializes the modem, connects to GPRS, and uploads an SSL certificate. The code sets up MQTT communication by using specific AT commands to establish a secure connection with an MQTT broker. The `mqttCallback` function handles incoming MQTT messages and checks if they match the device’s serial number. Periodic data is sent to the broker, and connection status is monitored, reconnecting if necessary. The code also supports publishing sensor data in JSON format.


sim75000 mqtt (ssl).txt

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Show hidden characters
#include
#include
#include // Include the WiFi library for MAC address
#include
#include "Secret.h" // Include the file to get the username and pasasword of MQTT server
#include"datacake.h"
String gsm_send_serial(String command, int delay);
#define SerialMon Serial
#define SerialAT Serial1
#define GSM_PIN ""
//#define D0 36
//#define D1 35
//#define D2 32
//#define D3 33
//#define R0 4
// Your GPRS credentials, if any
const char apn[] = "dialogbb";
const char gprsUser[] = "";
const char gprsPass[] = "";
// MQTT details
String broker = "mqtt.datacake.co";
String MQTTport = "8883";
#define uS_TO_S_FACTOR 1000000ULL // Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP 60 // Time ESP32 will go to sleep (in seconds)
#define UART_BAUD 115200
#define MODEM_TX 32
#define MODEM_RX 33
#define GSM_RESET 21
#define MAC_ADDRESS_SIZE 18 // Assuming MAC address is in format "XX:XX:XX:XX:XX:XX"
byte mac[6];
String str_macAddress;
unsigned long prevMillis = 0;
const unsigned long interval = 60000; // Interval for sending messages
// Device-specific details
const char* deviceSerial = "34865D461830"; // Replace with your device serial
void Init(void); // Function prototype for network and GPRS initialization
void connectToGPRS(void); // Function prototype for GPRS connection
void connectToMQTT(void); // Function prototype for MQTT connection
bool isNetworkConnected(); // Function prototype to check if network is connected
bool isGPRSConnected(); // Function prototype to check if GPRS is connected
void mqttCallback(char* topic, byte* payload, unsigned int len) {
SerialMon.print("Message arrived [");
SerialMon.print(topic);
SerialMon.print("]: ");
SerialMon.write(payload, len);
SerialMon.println();
// Extract serial number from the topic
String topicStr = String(topic);
int firstSlash = topicStr.indexOf('/');
int lastSlash = topicStr.lastIndexOf('/');
String MAC_ID = topicStr.substring(firstSlash + 1, lastSlash);
SerialMon.print("MAC ID: ");
SerialMon.println(MAC_ID);
if (MAC_ID == deviceSerial) {
// Decode the received message
StaticJsonDocument<200> doc;
DeserializationError error = deserializeJson(doc, payload, len);
if (error) {
SerialMon.print("deserializeJson() failed: ");
SerialMon.println(error.c_str());
return;
}
// Extract the payload
bool state = doc["state"];
// if(state == 0){
// digitalWrite(R0,LOW);
// }else if(state == 1){
// digitalWrite(R0,HIGH);
// }
} else {
SerialMon.println("Received message for a different serial number");
}
}
void setup() {
// Set console baud rate
Serial.begin(115200);
delay(10);
SerialAT.begin(UART_BAUD, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(2000);
pinMode(GSM_RESET, OUTPUT);
digitalWrite(GSM_RESET, HIGH); // RS-485
delay(2000);
// pinMode(D0, INPUT);
// pinMode(D1, INPUT);
// pinMode(D2, INPUT);
// pinMode(D3, INPUT);
// pinMode(R0, OUTPUT);
Init();
connectToGPRS();
connectToMQTT();
}
void loop() {
if (millis() - prevMillis >= interval) {
prevMillis = millis();
// bool IN1 = digitalRead(D0);
// bool IN2 = digitalRead(D1);
// bool IN3 = digitalRead(D2);
// bool IN4 = digitalRead(D3);
// Create JSON object
// StaticJsonDocument<200> doc;
// doc["D0"] = IN1 ? 1 : 0;
// doc["D1"] = IN2 ? 1 : 0;
// doc["D2"] = IN3 ? 1 : 0;
// doc["D3"] = IN4 ? 1 : 0;
int DI0 = 1;
// int DI1 = IN2 ? 1 : 0;
// int DI2 = IN3 ? 1 : 0;
// int DI3 = IN4 ? 1 : 0;
// Construct the command string with the certificate length
// String command5 = "AT+CCERTDOWN=\"server_cert.pem\"," + String(cert_length);
// gsm_send_serial(command5, 2000);
gsm_send_serial("AT+CCERTDOWN=\"server_cert.pem\",1806", 2000);
delay(2000);
// String command4 = mqtt_ca_cert + "\x1A";
gsm_send_serial(mqtt_ca_cert, 2000);
delay(2000);
gsm_send_serial("AT+CCERTLIST", 2000);
delay(1000);
gsm_send_serial("AT+CSSLCFG=\"sslversion\",0,4", 2000);
gsm_send_serial(" AT+CSSLCFG=\"authmode\",0,1", 2000);
gsm_send_serial("AT+CSSLCFG=\"ignorelocaltime\",0,1", 2000);
gsm_send_serial("AT+CSSLCFG=\"cacert\",0,\"server_cert.pem\"", 2000);
gsm_send_serial("AT+CSSLCFG=\"ciphersuites\",0,0xFFFF", 2000);
gsm_send_serial("AT+CSSLCFG=\"enableSNI\",0,1", 2000);
gsm_send_serial("AT+CMQTTREL=0", 2000);
gsm_send_serial("AT+CSSLCFG?", 2000);
gsm_send_serial("AT+CCHADDR", 2000);
gsm_send_serial("AT+CMQTTSTOP", 2000);
gsm_send_serial("AT+CMQTTSTART", 2000);
delay(2000);
//gsm_send_serial(" AT+CSSLCFG=\"cacert\",1,\"datacake_ca.pem \"", 1000);
gsm_send_serial("AT+CMQTTACCQ=0,\"PE\",1", 2000);
delay(2000);
gsm_send_serial("AT+CMQTTSSLCFG=0,0", 2000);
gsm_send_serial("AT+CMQTTCFG=\"checkUTF8\",0,0", 2000);
gsm_send_serial("AT+CSSLCFG=0", 2000);
gsm_send_serial("AT+CMQTTWILLTOPIC=0,1", 5000);
gsm_send_serial("p\x1A", 5000);
gsm_send_serial("AT+CMQTTWILLMSG=0,1,1", 5000);
gsm_send_serial("q\x1A", 5000);
delay(2000);
String command = "AT+CMQTTCONNECT=0,\"tcp://mqtt.datacake.co:8883\",60,1,\"" + username + "\",\"" + password + "\"";
gsm_send_serial(command,1500);
delay(2000);
// String downlinkTopic = "NORVI/+/OUTPUT";
// gsm_send_serial("AT+CMQTTSUB=0,14,1", 1000);
// gsm_send_serial(downlinkTopic + "\x1A", 1000);
// delay(2000);
}
bool isNetworkConnected() {
String response = gsm_send_serial("AT+CREG?", 3000);
return (response.indexOf("+CREG: 0,1") != -1 || response.indexOf("+CREG: 0,5") != -1);
}
bool isGPRSConnected() {
String response = gsm_send_serial("AT+CGATT?", 3000);
return (response.indexOf("+CGATT: 1") != -1);
}
String gsm_send_serial(String command, int delay) {
String buff_resp = "";
Serial.println("Send ->: " + command);
SerialAT.println(command);
long wtimer = millis();
while (wtimer + delay > millis()) {
while (SerialAT.available()) {
buff_resp += SerialAT.readString();
}
}
Serial.println(buff_resp);
return buff_resp;
}
view raw sim75000 mqtt (ssl).txt hosted with ❤ by GitHub

Step 2: Enter the User Credentials Information


We also included a step to enter the user credentials for the SSL certificate. This requires providing the necessary authentication details, such as the client certificate, private key, and CA certificate, to establish a secure connection. These credentials are essential for the device to verify its identity and securely communicate with the MQTT broker over SSL. This step is a key difference from the SIM7500_MQTT setup used with Datacake, which does not require SSL.


Step 3: Steps to Configure MQTT.FX

Click here to guide the steps of configure in MQTT.fx

  1. Check this link for detailed instructions on how to configure the MQTT broker and the Subscriber.

Download MQTT.FX client & install it .

Open the MQTT.FX and click the setting icon.

Click + to create a profile

Enter the connection profile & general information.


Step 4: Enter the Connection Profile & General Information

Step 5: Enter the User Credentials Information

  1. After completing the above steps, click Apply > OK to save. 
  2. Then, select the name of the file just created in the profile box and click Connect.
  3. If the round icon in the top-right corner is green, the connection to IoT Hub is successful, and publishing and subscribing operations can be performed.
  4. Select the Subscribe tab in the client, scan and select the topic name, and click Subscribe to subscribe to the topic.


Step 6: MQTT Subscriber Dashboard

  1. The subscribing result can be seen in the bottom right corner.


Step 7: Integration With Data Visualization Platform

  1. Access the DATACAKE from this link and navigate the Datacake dashboard. Select the “Add Devices.

Step 8: Add API Device

Step 9: Dashboard of the Added Devices

Step 10: Add MQTT Broker Configuration

Step 11: Add MQTT Broker

Step 12: MQTT Broker Connected Successfully

Step 13: Data Logs

Step 14: MQTT Device Dashboard View in Datacake