SIM7600 MQTT Connection Failure

#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?