#include <Arduino.h>
// Hardware pin definitions
#define SIM7600_RX_PIN 25
#define SIM7600_TX_PIN 26
#define PWRKEY_PIN 4
// MQTT configuration
const char* broker = "broker.hivemq.com";
const int brokerPort = 1883;
const char* mqttClientID = "MethaneMonitor_12345";
const char* mqttTopic = "methane/node1/data";
//APN options
const char* MTN_APN[] = {
"web.gprs.mtnnigeria.net",
"internet.ng",
"web.gprs.mtnnigeria.net"
};
// Sample methane data
String methaneData = "{\"time\":\"2025-01-16 15:30:45\",\"nodes\":[{\"id\":1,\"chip\":\"AUTO_1\",\"online\":true,\"ppm\":{\"min\":384.4,\"avg\":387.7,\"max\":398.4}},{\"id\":2,\"chip\":\"AUTO_2\",\"online\":false,\"ppm\":{\"min\":382.3,\"avg\":382.8,\"max\":384.3}}]}";
// Global variables
HardwareSerial sim7600(2);
bool networkConnected = false;
bool mqttConnected = false;
// Function declarations
String sendATCommand(String command, unsigned long timeout);
void powerOnSim7600();
bool setupNetwork(const char* apn);
bool mqttConnect(const char* clientID, const char* broker, int port);
bool mqttPublish(const char* topic, const char* payload);
void testConnectivity();
bool resetMQTTService();
void setup() {
Serial.begin(115200);
sim7600.begin(115200, SERIAL_8N1, SIM7600_RX_PIN, SIM7600_TX_PIN);
delay(3000);
Serial.println("=== Complete SIM7600 MQTT Setup ===");
Serial.println("Methane Monitoring System");
Serial.println("=====================================");
// Step 1: Power on SIM7600
Serial.println("\n1. Powering on SIM7600...");
powerOnSim7600();
delay(10000); // Wait for complete boot
// Step 2: Test basic communication
Serial.println("\n2. Testing SIM7600 communication...");
if (sendATCommand("AT", 3000).indexOf("OK") == -1) {
Serial.println("ERROR: SIM7600 not responding!");
Serial.println("Check power supply and serial connections");
return;
}
Serial.println("SIM7600 communication OK");
// Step 3: Check SIM card
Serial.println("\n3. Checking SIM card status...");
String simStatus = sendATCommand("AT+CPIN?", 5000);
if (simStatus.indexOf("READY") == -1) {
Serial.println("ERROR: SIM card not ready!");
Serial.println("SIM Response: " + simStatus);
return;
}
Serial.println("SIM card ready");
// Step 4: Setup cellular network
Serial.println("\n4. Setting up cellular network...");
for (int i = 0; i < 3; i++) {
Serial.println("Trying APN " + String(i+1) + ": " + String(MTN_APN[i]));
if (setupNetwork(MTN_APN[i])) {
networkConnected = true;
Serial.println("Network connected with APN: " + String(MTN_APN[i]));
break;
}
Serial.println("APN " + String(i+1) + " failed, trying next...");
delay(5000);
}
if (!networkConnected) {
Serial.println("ERROR: Failed to connect to cellular network!");
Serial.println("Check SIM card data plan and coverage");
return;
}
// Step 5: Test connectivity
Serial.println("\n5. Testing network connectivity...");
testConnectivity();
delay(5000);
Serial.println("\n5.5. Testing DNS and internet access...");
String googleDNS = sendATCommand("AT+CDNSGIP=\"google.com\"", 10000);
Serial.println("Google DNS test: " + googleDNS);
String hivemqDNS = sendATCommand("AT+CDNSGIP=\"broker.hivemq.com\"", 10000);
Serial.println("HiveMQ DNS test: " + hivemqDNS);
if (hivemqDNS.indexOf("ERROR") != -1) {
Serial.println("DNS ISSUE: Cannot resolve broker.hivemq.com");
Serial.println("MTN may be blocking this domain");
} else {
Serial.println("DNS resolution successful for HiveMQ");
}
// Step 6: Connect to MQTT broker
Serial.println("\n6. Resetting and connecting to MQTT broker...");
if (!resetMQTTService()) {
Serial.println("ERROR: Cannot reset MQTT service!");
return;
}
if (mqttConnect(mqttClientID, broker, brokerPort)) {
mqttConnected = true;
Serial.println("MQTT connected successfully!");
} else {
Serial.println("ERROR: MQTT connection failed after reset!");
return;
}
// Step 7: Publish methane data
Serial.println("\n7. Publishing methane sensor data...");
if (mqttPublish(mqttTopic, methaneData.c_str())) {
Serial.println("SUCCESS! Methane data published to MQTT broker");
Serial.println("Topic: " + String(mqttTopic));
Serial.println("Data size: " + String(methaneData.length()) + " bytes");
Serial.println("\nCheck your MQTT dashboard for the message!");
} else {
Serial.println("ERROR: Failed to publish methane data");
}
Serial.println("\n=== Setup Complete ===");
}
void powerOnSim7600() {
Serial.println("Executing SIM7600 power-on sequence...");
pinMode(PWRKEY_PIN, OUTPUT);
digitalWrite(PWRKEY_PIN, LOW);
delay(1000);
digitalWrite(PWRKEY_PIN, HIGH);
delay(2000);
Serial.println("Power-on sequence complete");
}
String sendATCommand(String command, unsigned long timeout) {
// Clear input buffer
while (sim7600.available()) {
sim7600.read();
}
// Send command
sim7600.println(command);
String response = "";
unsigned long startTime = millis();
// Read response
while (millis() - startTime < timeout) {
while (sim7600.available()) {
char c = sim7600.read();
response += c;
}
delay(10);
}
response.trim();
return response;
}
bool setupNetwork(const char* apn) {
Serial.println("Starting 4G network setup with APN: " + String(apn));
// Wait for network registration
Serial.println("Waiting for network registration...");
int retries = 30;
bool registered = false;
while (retries--) {
String regResponse = sendATCommand("AT+CREG?", 3000);
if (regResponse.indexOf("+CREG: 0,1") != -1 || regResponse.indexOf("+CREG: 0,5") != -1) {
Serial.println("Registered to cellular network");
registered = true;
break;
}
Serial.println("Registration attempt " + String(30-retries) + "/30...");
delay(2000);
}
if (!registered) {
Serial.println("Network registration timeout");
return false;
}
// Set APN
String apnCmd = String("AT+CGDCONT=1,\"IP\",\"") + apn + "\"";
if (sendATCommand(apnCmd, 5000).indexOf("OK") == -1) {
Serial.println("Failed to set APN");
return false;
}
Serial.println("APN configured: " + String(apn));
// Set authentication for MTN
String authCmd = "AT+CGAUTH=1,1,\"web\",\"web\"";
sendATCommand(authCmd, 3000);
// Attach to packet service
Serial.println("Attaching to data service...");
for (int i = 0; i < 3; i++) {
if (sendATCommand("AT+CGATT=1", 15000).indexOf("OK") != -1) {
Serial.println("Attached to packet service");
break;
}
if (i == 2) {
Serial.println("Failed to attach to packet service");
return false;
}
delay(5000);
}
// Activate PDP context
Serial.println("Activating data context...");
for (int i = 0; i < 3; i++) {
if (sendATCommand("AT+CGACT=1,1", 20000).indexOf("OK") != -1) {
Serial.println("Data context activated");
break;
}
if (i == 2) {
Serial.println("Failed to activate data context");
return false;
}
delay(5000);
}
// Get and display IP address
delay(5000);
String ipResponse = sendATCommand("AT+CGPADDR=1", 5000);
if (ipResponse.indexOf(".") == -1) {
Serial.println("No IP address assigned");
return false;
}
// Extract IP address
int start = ipResponse.indexOf("\"") + 1;
int end = ipResponse.indexOf("\"", start);
if (start > 0 && end > start) {
String ip = ipResponse.substring(start, end);
Serial.println("IP Address: " + ip);
}
Serial.println("4G network setup complete");
return true;
}
void testConnectivity() {
Serial.println("Testing network connectivity...");
// Test 1: Check attachment status
String attachStatus = sendATCommand("AT+CGATT?", 3000);
Serial.println("Attachment status: " + attachStatus);
// Test 2: Check signal quality
String signalQuality = sendATCommand("AT+CSQ", 3000);
Serial.println("Signal quality: " + signalQuality);
// Test 3: Check operator
String operator_info = sendATCommand("AT+COPS?", 5000);
Serial.println("Network operator: " + operator_info);
// Test 4: Ping test (basic connectivity)
String pingResult = sendATCommand("AT+CGPADDR=1", 3000);
if (pingResult.indexOf(".") != -1) {
Serial.println("Network connectivity confirmed");
} else {
Serial.println("Network connectivity issue");
}
}
bool resetMQTTService() {
Serial.println("Resetting MQTT service...");
// Force stop all MQTT operations
sendATCommand("AT+CMQTTDISC=0,1", 2000);
sendATCommand("AT+CMQTTREL=0", 2000);
sendATCommand("AT+CMQTTSTOP", 3000);
delay(3000);
// Reset network stack to clean MQTT state
Serial.println("Resetting network stack...");
sendATCommand("AT+CGATT=0", 5000); // Detach
delay(3000);
sendATCommand("AT+CGATT=1", 10000); // Re-attach
delay(5000);
// Test if MQTT can start cleanly
if (sendATCommand("AT+CMQTTSTART", 5000).indexOf("OK") != -1) {
Serial.println("MQTT service reset successful");
sendATCommand("AT+CMQTTSTOP", 2000); // Stop it again for clean connect
delay(2000);
return true;
}
Serial.println("MQTT service still corrupted");
return false;
}
bool mqttConnect(const char* clientID, const char* broker, int port) {
Serial.println("Connecting to MQTT broker: " + String(broker) + ":" + String(port));
// Clean any previous MQTT state
sendATCommand("AT+CMQTTSTOP", 3000);
delay(2000);
// Start MQTT service
if (sendATCommand("AT+CMQTTSTART", 5000).indexOf("OK") == -1) {
Serial.println("Failed to start MQTT service");
return false;
}
Serial.println("MQTT service started");
// Set client ID
String accqCmd = String("AT+CMQTTACCQ=0,\"") + clientID + "\",1";
if (sendATCommand(accqCmd, 5000).indexOf("OK") == -1) {
Serial.println("Failed to set MQTT client ID");
return false;
}
Serial.println("MQTT client ID set: " + String(clientID));
// Connect to broker
String connectCmd = String("AT+CMQTTCONNECT=0,\"tcp://") + broker + ":" + port + "\",60,1";
// Clear buffer before connection
while (sim7600.available()) {
sim7600.read();
}
sim7600.println(connectCmd);
// Wait for connection response
String response = "";
unsigned long startTime = millis();
while (millis() - startTime < 15000) { // 15 second timeout
while (sim7600.available()) {
char c = sim7600.read();
response += c;
}
if (response.indexOf("+CMQTTCONNECT: 0,0") != -1) {
Serial.println("MQTT broker connected");
delay(2000); // Wait for connection stability
return true;
} else if (response.indexOf("+CMQTTCONNECT: 0,") != -1) {
Serial.println("MQTT connection failed: " + response);
return false;
}
delay(100);
}
Serial.println("MQTT connection timeout");
return false;
}
bool mqttPublish(const char* topic, const char* payload) {
Serial.println("Publishing MQTT message...");
Serial.println("Topic: " + String(topic));
Serial.println("Payload size: " + String(strlen(payload)) + " bytes");
// Set topic
int topicLen = strlen(topic);
String topicCmd = String("AT+CMQTTTOPIC=0,") + topicLen;
if (sendATCommand(topicCmd, 3000).indexOf(">") == -1) {
Serial.println("Failed to initiate topic setting");
return false;
}
sim7600.print(topic);
delay(300);
String topicResponse = sendATCommand("", 3000);
if (topicResponse.indexOf("OK") == -1) {
Serial.println("Topic setting failed");
return false;
}
Serial.println("Topic set successfully");
// Set payload
int payloadLen = strlen(payload);
String payloadCmd = String("AT+CMQTTPAYLOAD=0,") + payloadLen;
if (sendATCommand(payloadCmd, 3000).indexOf(">") == -1) {
Serial.println("Failed to initiate payload setting");
return false;
}
sim7600.print(payload);
delay(500);
String payloadResponse = sendATCommand("", 3000);
if (payloadResponse.indexOf("OK") == -1) {
Serial.println("Payload setting failed");
return false;
}
Serial.println("Payload set successfully");
// Publish message
String publishResult = sendATCommand("AT+CMQTTPUB=0,1,60", 8000);
if (publishResult.indexOf("+CMQTTPUB: 0,0") != -1 || publishResult.indexOf("OK") != -1) {
Serial.println("MQTT message published successfully!");
return true;
} else {
Serial.println("MQTT publish failed: " + publishResult);
return false;
}
}
void loop() {
// Monitor SIM7600 responses
if (sim7600.available()) {
Serial.print((char)sim7600.read());
}
// Status check every 30 seconds
static unsigned long lastStatusCheck = 0;
if (millis() - lastStatusCheck > 30000) {
lastStatusCheck = millis();
if (networkConnected && mqttConnected) {
Serial.println("\nStatus: Network | MQTT | System operational");
}
}
delay(100);
}
Methane Monitoring System
=====================================
1. Powering on SIM7600...
Executing SIM7600 power-on sequence...
Power-on sequence complete
2. Testing SIM7600 communication...
SIM7600 communication OK
3. Checking SIM card status...
SIM card ready
4. Setting up cellular network...
Trying APN 1: web.gprs.mtnnigeria.net
Starting 4G network setup with APN: web.gprs.mtnnigeria.net
Waiting for network registration...
Registered to cellular network
APN configured: web.gprs.mtnnigeria.net
Attaching to data service...
Attached to packet service
Activating data context...
Data context activated
4G network setup complete
Network connected with APN: web.gprs.mtnnigeria.net
5. Testing network connectivity...
Testing network connectivity...
Attachment status: AT+CGATT?
+CGATT: 1
OK
Signal quality: AT+CSQ
+CSQ: 16,99
OK
Network operator: AT+COPS?
+COPS: 0,0,"MTN Nigeria",7
OK
Network connectivity confirmed
5.5. Testing DNS and internet access...
Google DNS test: AT+CDNSGIP="google.com"
+CDNSGIP: 1,"google.com","142.250.178.174"
OK
HiveMQ DNS test: AT+CDNSGIP="broker.hivemq.com"
+CDNSGIP: 1,"broker.hivemq.com","3.67.130.24"
OK
DNS resolution successful for HiveMQ
6. Resetting and connecting to MQTT broker...
Resetting MQTT service...
Resetting network stack...
MQTT service reset successful
Connecting to MQTT broker: broker.hivemq.com:1883
MQTT service started
MQTT client ID set: MethaneMonitor_12345
MQTT connection failed: AT+CMQTTCONNECT=0,"tcp://broker.hivemq.com:1883",60,1
OK
+CMQTTCONNECT: 0,26
ERROR: MQTT connection failed after reset!
Hello Everyone,
I’m working on a Methane Monitoring System using the SIM7600 module, and I’m running into issues with connecting to an MQTT broker. Above is the sequence of steps and logs from my setup:
The SIM7600 successfully registers on the network, attaches to data service, resolves DNS, and even confirms connectivity. However, whenever I try to connect to HiveMQ broker (broker.hivemq.com:1883) with the AT+CMQTTCONNECT command, the connection fails with:
+CMQTTCONNECT: 0,26
From my understanding, error code 26 indicates a network connection failure, but since I can resolve DNS and have internet connectivity, I’m not sure why the MQTT session itself isn’t being established.
Is there something I might be missing in the AT command sequence?
Do I need to configure any special TLS/SSL parameters for HiveMQ public broker, or should a plain TCP connection on port 1883 work?