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?

Your DNS resolution and IP connectivity confirm that plain TCP on port 1883 is reachable, and the HiveMQ public broker (broker.hivemq.com) does NOT require TLS or authentication on port 1883. So your connection string tcp://broker.hivemq.com:1883 is correct.

Can I ask you to attempt connecting to the broker’s IP (35.157.114.127), rather then first resolving DNS?

Kind regards,
Finn