Introduction: MQTT With SIMCOM SIM7500 Guide on NORVI GSM Series

About: ESP32 & STM32 based Industrial Controllers

NORVI devices are robust IoT industrial controllers, and when combined with the SIMCOM SIM7500 LTE module, they enable secure cellular communication with cloud platforms via MQTT. This guide explains the setup, essential AT commands, and code for using the SIM7500 module to connect NORVI devices to an MQTT broker.

Click here to view the web guide

For Understanding MQTT -MQTT PROTOCOL


Understanding NORVI Controllers with the SIM7500 Module


NORVI devices are flexible industrial IoT solutions that simplify the integration of sensors, actuators, and communication modules. Adding the SIM7500 module boosts their capabilities by enabling cellular connectivity, making them ideal for remote monitoring and data collection in areas without Wi-Fi or wired networks.

NORVI GSM Series

Supplies

Setting Up NORVI GSM series SIM7500 to MQTT


In this setup, the NORVI GSM series SIM7500 device serves as an MQTT publisher, while the MQTT.fx software acts as the subscriber. The NORVI device collects I/O data and transmits it to the MQTT subscriber and a data visualization platform for remote monitoring and analysis.


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.


1. 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)


2. Required Libraries 


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


3. Sensitive Information Handling


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


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: Understanding the Test Program

This code sets up a NORVI GSM device with the SIM7500 module to connect to an MQTT broker. It initializes the GSM modem, connects to GPRS, and subscribes to MQTT topics while publishing sensor data in JSON format. The code handles incoming MQTT messages, allowing the device to respond to commands based on the received payload. Key functions include establishing network connections, sending commands to the GSM module, and processing MQTT messages. Additionally, it manages input states and periodically sends updates over MQTT.


gistfile SIM7500 MQTT.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
String gsm_send_serial(String command, int delay);
#define TINY_GSM_MODEM_SIM7600
#define SerialMon Serial
#define SerialAT Serial1
#define GSM_PIN ""
// Your GPRS credentials, if any
const char apn[] = "dialogbb";
const char gprsUser[] = "";
const char gprsPass[] = "";
// MQTT details
String broker = "mqtt.sensoper.net";
String MQTTport="1881";
#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 23
#define MODEM_RX 18
#define GSM_RESET 34
#define D0 36
#define D1 35
#define D2 32
#define D3 33
#define R0 4
#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 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 );
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;
String jsonString;
//char jsonBuffer[512];
serializeJson(doc, jsonString);
WiFi.macAddress(mac);
str_macAddress = (String(mac[0] >> 4, HEX) + String(mac[0] & 0x0F, HEX)) +
(String(mac[1] >> 4, HEX) + String(mac[1] & 0x0F, HEX)) +
(String(mac[2] >> 4, HEX) + String(mac[2] & 0x0F, HEX)) +
(String(mac[3] >> 4, HEX) + String(mac[3] & 0x0F, HEX)) +
(String(mac[4] >> 4, HEX) + String(mac[4] & 0x0F, HEX)) +
(String(mac[5] >> 4, HEX) + String(mac[5] & 0x0F, HEX));
str_macAddress.toUpperCase();
String Digital_input = "NORVI/INPUTS/" + str_macAddress;
SerialMon.print("Published: ");
SerialMon.println(jsonString);
// Send a periodic "ping" message to verify MQTT connection
String payload=(String)(millis()/1000L);
String response = gsm_send_serial("AT+CMQTTTOPIC=0," + String(Digital_input.length()), 1000);
response = gsm_send_serial(Digital_input, 1000);
response = gsm_send_serial("AT+CMQTTPAYLOAD=0," + String(jsonString.length()), 1000);
response = gsm_send_serial(jsonString + "\x1A", 1000);
response = gsm_send_serial("AT+CMQTTPUB=0,1,60", 1000);
// Check if the publish command was successful
if (response.indexOf("ERROR") != -1) {
Serial.println("MQTT publish failed. Reconnecting...");
connectToMQTT();
if (!isGPRSConnected()) {
Serial.println("GPRS connection lost. Reconnecting...");
connectToGPRS();
connectToMQTT();
}
if (!isNetworkConnected()) {
Serial.println("Network connection lost. Reconnecting...");
Init();
connectToGPRS();
connectToMQTT();
}
}
}
// Handle incoming MQTT messages
handleIncomingMessages();
}
void handleIncomingMessages() {
while (SerialAT.available()) {
String response = SerialAT.readStringUntil('\n');
response.trim();
if (response.startsWith("+CMQTTRXTOPIC")) {
// Extract topic length
int topicLength = response.substring(response.indexOf(",") + 1).toInt();
SerialMon.print("Topic Length: ");
SerialMon.println(topicLength);
// Read the topic
String topic = SerialAT.readStringUntil('\n');
topic.trim();
SerialMon.print("Topic: ");
SerialMon.println(topic);
// Confirm receipt of payload length
response = SerialAT.readStringUntil('\n');
response.trim();
if (response.startsWith("+CMQTTRXPAYLOAD")) {
int payloadLength = response.substring(response.indexOf(",") + 1).toInt();
SerialMon.print("Payload Length: ");
SerialMon.println(payloadLength);
// Read the payload
String payload = SerialAT.readStringUntil('\n');
payload.trim();
SerialMon.print("Payload: ");
SerialMon.println(payload);
// Ensure arrays are large enough to hold the topic and payload
char topicArr[topicLength + 1];
char payloadArr[payloadLength + 1];
topic.toCharArray(topicArr, topicLength + 1);
payload.toCharArray(payloadArr, payloadLength + 1);
mqttCallback(topicArr, (byte*)payloadArr, payloadLength);
}
}
}
}
void Init(void){ // Connecting with the newtwork and GPRS
delay(5000);
gsm_send_serial("AT+CFUN=1", 10000);
gsm_send_serial("AT+CPIN?", 10000);
gsm_send_serial("AT+CSQ", 1000);
gsm_send_serial("AT+CREG?", 1000);
gsm_send_serial("AT+COPS?", 1000);
gsm_send_serial("AT+CGATT?", 1000);
gsm_send_serial("AT+CPSI?", 500);
gsm_send_serial("AT+CGDCONT=1,\"IP\",\"dialogbb\"", 1000);
gsm_send_serial("AT+CGACT=1,1", 1000);
gsm_send_serial("AT+CGATT?", 1000);
gsm_send_serial("AT+CGPADDR=1", 500);
gsm_send_serial("AT+NETOPEN", 500);
gsm_send_serial("AT+NETSTATE", 500);
}
void connectToGPRS(void) {
gsm_send_serial("AT+CGATT=1", 1000);
gsm_send_serial("AT+CGDCONT=1,\"IP\",\"dialogbb\"", 1000);
gsm_send_serial("AT+CGACT=1,1", 1000);
gsm_send_serial("AT+CGPADDR=1", 500);
gsm_send_serial("AT+NETOPEN", 500);
gsm_send_serial("AT+NETSTATE", 500);
}
void connectToMQTT(void){
gsm_send_serial("AT+CMQTTSTART", 1000);
gsm_send_serial("AT+CMQTTACCQ=0,\"client test0\",0", 1000);
gsm_send_serial("AT+CMQTTWILLTOPIC=0,2", 1000);
gsm_send_serial("01\x1A", 1000);
gsm_send_serial("AT+CMQTTWILLMSG=0,6,1", 1000);
gsm_send_serial("qwerty\x1A", 1000);
String command = "AT+CMQTTCONNECT=0,\"tcp://mqtt.sensoper.net:1881\",60,1,\"" + username + "\",\"" + password + "\"";
gsm_send_serial(command, 10000);
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;
}

Step 2: MQTT Broker Configeration

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

  1. Download MQTT.fx client and install it.
  2. Open the MQTT.fx and click the Settings icon.
  3. Click + to create a profile.
  4. Enter the Connection Profile and General information.





Step 3: Enter the User Credentials Information

  1. After completing the above steps, click Apply > OK to save. 


Step 4: Select the Subscribe Tab

  1. Then, select the name of the file just created in the profile box and click Connect.
  2. 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.


Step 5: Full Guide and Additional Information

Click here to get the code

Understanding the Test program

Software Configurations

Github explanation of sim7600 module with at commands ( You can apply for sim7500) -MQTT Connection with SIM7600 Using AT Commands

Setting Up the MQTT Broke

  1. MQTT Broker Configuration
  2. Steps to Configure in MQTT.fx

Step 6: MQTT Broker Configuration

Step 7: 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.


Step 8: Connected to the Broker

  1. Select the Subscribe tab in the client, scan and select the topic name, and click Subscribe to subscribe to the topic.


Step 9: MQTT Subscriber Dashboard

Step 10: Captured Data From the MQTT Broker

Step 11: Integration With Data Visualization Platform

  1. Datacake dashboard.

Step 12: Add API Device

Step 13: The Dashboard of the Added Device.

Step 14: Add MQTT Broker Configuration.

Step 15: Add MQTT Broker

Step 16: MQTT Broker Connected Successfully.

Step 17: Data Logs

Step 18: MQTT Device Dashboard View in Datacake