Ssl implimentation using at commands in "EC200U" ( using esp32 c3 mini and EC200U )

I am using ESP32 c3 mini1 and EC200U and task is sending hello through mqtt with help of AT commands and in that i am using ssl implimentation in that i am facing issue of +QMTOPEN: 0,5

i am using isrgroot.pem ( lets encrypt certificate )

code -

/**

  • ESP32-C3 MQTTS EC200U Example (SPIFFS Version - Merged)
  • This version uses the user’s robust loop and AT command functions,
  • combined with all the necessary SSL fixes.
  • *** FINAL FIX APPLIED ***
  • This version now FORCE-DELETES all old/conflicting certificates from
  • the modem’s UFS on boot to prevent SSL stack confusion.
  • It includes fixes for:
    1. Correct command order: Config SSL/MQTT before activating network.
    1. Force-deletes ALL old certs from modem on boot.
    1. Uses the full “UFS:” path for the certificate.
    1. Uses “seclevel 1” (Server auth only).
    1. Forces “sslversion 3” (TLS 1.2 only).
    1. Forces a specific modern cipher suite (0XC02F).
    1. Enables SNI (“sni”, 1).
    1. Ignores modem’s local time (“ignorelocaltime”, 1).
    1. Links MQTT to the correct PDP context (“pdpcid”, 1).
    1. Waits for the correct URCs (e.g., “+QMTOPEN: 0,0”).
    1. Removes the failing “clientid” command.
  • PLATFORMIO SPIFFS PREPARATION:
    1. Create a ‘data’ folder in your project’s root.
    1. Place ‘isrgroot.pem’ inside the ‘data’ folder.
    1. Run ‘pio run -t uploadfs’ to upload the file to the ESP32’s SPIFFS.
  • HARDWARE CONNECTIONS (ESP32-C3 ↔ EC200U):
    • ESP32 3.3V → EC200U VCC
    • ESP32 GND → EC200U GND
    • ESP32 TXD1 (19) → EC200U Main RX
    • ESP32 RXD1 (18) → EC200U Main TX
      */

#include <Arduino.h> // Required for PlatformIO
#include <HardwareSerial.h> // Include for HardwareSerial communication
#include <string.h> // Include for strlen
#include “SPIFFS.h” // Include SPIFFS library

// — User Configuration —
// Modem communication pins and baud rate
#define MODEM_RX 18
#define MODEM_TX 19
#define MODEM_BAUD 115200
#define MStat 2 // Status LED

// APN Configuration
#define APN “www”

// MQTT Broker Details
#define MQTT_SERVER “mqtts.lets.balwaan.com
#define MQTT_PORT 8883
#define MQTT_USERNAME “lets-balwaan-mqtts”
#define MQTT_PASSWORD “Balwaanletsmqtts”
#define MQTT_CLIENT_ID “esp32-c3-device-01” // MUST be unique
#define MQTT_TOPIC “balwaan/test”

// Certificate file paths
#define CERT_FILENAME_ON_SPIFFS “/isrgroot.pem” // Path on ESP32
#define CERT_FILENAME_ON_MODEM “isrgroot.pem” // Filename on Modem
#define CERT_FULLPATH_ON_MODEM “UFS:isrgroot.pem” // Full path on Modem
#define SSL_CONTEXT_ID 0 // We’ll use SSL context 0

// Create a HardwareSerial instance for the modem
HardwareSerial modem(1);

// Global flag to track MQTT connection status
bool mqttConnected = false;

// — Utility Functions —

// Sends an AT command and waits for a specific expected response
String sendATCommand(String command, int timeout, String expectedResponse) {
while (modem.available()) modem.read();
if (command != “”) modem.println(command);

String response = “”;
long startTime = millis();

Serial.print(">>> “);
Serial.println(command);
Serial.print(”<<< ");

while (millis() - startTime < timeout) {
if (modem.available()) {
char c = (char)modem.read();
response += c;
Serial.print(c);

  if (expectedResponse != "" && response.indexOf(expectedResponse) != -1)
    return response;
  if (response.indexOf("ERROR") != -1)
    return response;
}

}
Serial.println();
if (expectedResponse == “” && response.indexOf(“ERROR”) == -1) return “OK”;
return response;
}

bool waitForActivation(uint32_t timeout = 30000) {
Serial.println(“\n[INFO] Waiting for PDP Context Activation (30s timeout)…”);
long startTime = millis();
while (millis() - startTime < timeout) {
String response = sendATCommand(“AT+QIACT?”, 2000, “+QIACT: 1,1,1”);
if (response.indexOf(“+QIACT: 1,1,1”) != -1) {
Serial.println(“[INFO] PDP Context is active.”);
return true;
}
Serial.println(“[INFO] Waiting… (PDP context not active yet)”);
delay(2000);
}
Serial.println(“[ERROR] PDP Context activation timed out!”);
return false;
}

// Check file on modem
bool checkFileOnModem(const char* filename) {
Serial.println(“\n[INFO] Checking for file on modem…”);
String response = sendATCommand(“AT+QFLST”, 5000, “OK”);
if (response.indexOf(filename) != -1) {
Serial.println(“[INFO] File found in modem file list.”);
return true;
}
Serial.println(“[INFO] File not found in modem file list.”);
return false;
}

// Upload certificate from SPIFFS to modem
bool uploadFileToModem(const char* spiffsFilename, const char* modemFilename) {
Serial.println(“\n[INFO] Uploading file from SPIFFS to modem…”);

File file = SPIFFS.open(spiffsFilename, “r”);
if (!file) {
Serial.print("[ERROR] Failed to open file: ");
Serial.println(spiffsFilename);
return false;
}

size_t fileSize = file.size();
Serial.print("[INFO] File size: ");
Serial.println(fileSize);

String cmd = “AT+QFUPL=“” + String(modemFilename) + “”,” + String(fileSize) + “,100”;

if (sendATCommand(cmd, 5000, “CONNECT”).indexOf(“CONNECT”) == -1) {
Serial.println(“!! Cert upload failed: No CONNECT”);
file.close();
return false;
}

Serial.println(“[INFO] Sending file…”);
uint8_t buffer[256];
size_t bytesSent = 0;
while (bytesSent < fileSize) {
size_t bytesToRead = file.read(buffer, sizeof(buffer));
if (bytesToRead == 0) break;
modem.write(buffer, bytesToRead);
bytesSent += bytesToRead;
Serial.print(“.”);
}

file.close();
if (sendATCommand(“”, 10000, “OK”).indexOf(“OK”) != -1) {
Serial.println(“\n>> Cert Uploaded Successfully”);
delay(1000);
return true;
}
Serial.println(“!! Cert upload failed”);
return false;
}

// Initialize modem and network
bool initAndCheckNetwork() {
if (sendATCommand(“AT”, 2000, “OK”).indexOf(“OK”) == -1) {
Serial.println(“[ERROR] Modem not ready.”);
return false;
}

sendATCommand(“ATE0”, 500, “OK”);
sendATCommand(“AT+CFUN=1”, 10000, “OK”);
if (sendATCommand(“AT+CPIN?”, 5000, “READY”).indexOf(“READY”) == -1) return false;
if (sendATCommand(“AT+CSQ”, 1000, “+CSQ:”).indexOf(“+CSQ:”) == -1) return false;

String reg = sendATCommand(“AT+CREG?”, 2000, “OK”);
if (reg.indexOf(“+CREG: 0,1”) == -1 && reg.indexOf(“+CREG: 0,5”) == -1) return false;

if (sendATCommand(“AT+CGATT=1”, 1000, “OK”).indexOf(“OK”) == -1) return false;
return true;
}

bool configureSSL() {
sendATCommand(“AT+QFDEL=“” CERT_FULLPATH_ON_MODEM “””, 5000, “”);
if (!checkFileOnModem(CERT_FILENAME_ON_MODEM))
if (!uploadFileToModem(CERT_FILENAME_ON_SPIFFS, CERT_FILENAME_ON_MODEM))
return false;

if (sendATCommand(“AT+QSSLCFG=“sslversion”,0,3”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“ciphersuite”,0,0XC02F”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“seclevel”,0,1”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“cacert”,0,“” CERT_FULLPATH_ON_MODEM “””, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“ignorelocaltime”,0,1”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“sni”,0,1”, 1000, “OK”).indexOf(“OK”) == -1) return false;

return true;
}

bool configureMQTT() {
if (sendATCommand(“AT+QMTCFG=“pdpcid”,0,1”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QMTCFG=“ssl”,0,1,0”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QMTCFG=“version”,0,4”, 1000, “OK”).indexOf(“OK”) == -1) return false;
return true;
}

bool activateNetwork() {
sendATCommand(“AT+QIDEACT=1”, 5000, “”);
String apnCmd = “AT+QICSGP=1,1,“” APN “”,“”,“”,0”;
if (sendATCommand(apnCmd, 5000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QIACT=1”, 30000, “OK”).indexOf(“OK”) == -1) return false;
return waitForActivation();
}

bool connectModemAndMQTT() {
if (!initAndCheckNetwork()) return false;
if (!configureSSL()) return false;
if (!configureMQTT()) return false;
if (!activateNetwork()) return false;

String open = “AT+QMTOPEN=0,“” MQTT_SERVER “”,” + String(MQTT_PORT);
if (sendATCommand(open, 15000, “+QMTOPEN: 0,0”).indexOf(“+QMTOPEN: 0,0”) == -1)
return false;

String conn = “AT+QMTCONN=0,“” MQTT_CLIENT_ID “”,“” MQTT_USERNAME “”,“” MQTT_PASSWORD “””;
if (sendATCommand(conn, 15000, “+QMTCONN: 0,0,0”).indexOf(“+QMTCONN: 0,0,0”) == -1)
return false;

return true;
}

bool mqttPublish(const char* payload) {
static int msgId = 1;

String cmd = “AT+QMTPUB=0,” + String(msgId++) + “,0,0,“” MQTT_TOPIC “””;
if (sendATCommand(cmd, 3000, “>”).indexOf(“>”) == -1) return false;

modem.print(payload);
modem.write(0x1A);

String expect = “+QMTPUB: 0,” + String(msgId - 1) + “,0”;
if (sendATCommand(“”, 5000, expect).indexOf(expect) != -1) return true;

return false;
}

void setup() {
Serial.begin(115200);
pinMode(MStat, OUTPUT);
modem.begin(MODEM_BAUD, SERIAL_8N1, MODEM_RX, MODEM_TX);

if (!SPIFFS.begin(true)) while(1);

mqttConnected = connectModemAndMQTT();
}

void loop() {
static unsigned long last = 0;
if (!mqttConnected) mqttConnected = connectModemAndMQTT();
if (mqttConnected && millis() - last > 10000) {
last = millis();
if (!mqttPublish(“hello”)) mqttConnected = false;
}
}
}

OUTPUT-

ESP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5810,len:0x438
load:0x403cc710,len:0x90c
load:0x403ce710,len:0x2624
entry 0x403cc710
— EC200U MQTTS Publisher Start (Merged Code) —
[INFO] SPIFFS Mounted.

AT
<<<
OK
[INFO] Modem: OK.
ATE0
<<<
OK>>> AT+CFUN=1
<<<
OK[INFO] Checking SIM and Network…>>> AT+CPIN?
<<<
+CPIN: READY>>> AT+CSQ
<<<
+CSQ:>>> AT+CREG?
<<<
+CREG: 0,1

OK>>> AT+CGATT=1
<<<
OK
[INFO] SIM/Network Checks OK.

[INFO] Forcing deletion of old certificate file(s)…

AT+QFDEL=“UFS:isrgroot.pem”
<<<
OK

AT+QFDEL=“UFS:ca.crt”
<<<
+CME ERROR>>> AT+QFDEL=“UFS:client.crt”
<<<
+CME ERROR>>> AT+QFDEL=“UFS:client.key”
<<<
+CME ERROR>>> AT+QFDEL=“UFS:isrg.pem”
<<<
+CME ERROR>>> AT+QFDEL=“UFS:isrgrootx1.pem”
<<<
+CME ERROR[INFO] Old file cleanup complete.

[INFO] Checking/Uploading Certificate…

[INFO] Checking for file on modem…

AT+QFLST
<<<
+QFLST: “UFS:boot”,15004
+QFLST: “UFS:firm”,243616
+QFLST: “UFS:gnss_data”,4636
+QFLST: “UFS:gnss_loca”,47
+QFLST: “UFS:gnss_time”,21

OK[INFO] File not found in modem file list.
[INFO] Certificate not found on modem, uploading…

[INFO] Uploading file from SPIFFS to modem…
[INFO] File found on SPIFFS. Size: 1939

AT+QFUPL=“isrgroot.pem”,1939,100
<<<
CONNECT[INFO] Modem is ready. Sending file data…

[INFO] File data sent.

<<< +QFUPL: 1939,4f64

OK>> Cert Uploaded Successfully: isrgroot.pem

[INFO] Configuring SSL Context…

AT+QSSLCFG=“sslversion”,0,3
<<<
OK>>> AT+QSSLCFG=“ciphersuite”,0,0XC02F
<<<
OK>>> AT+QSSLCFG=“seclevel”,0,1
<<<
OK>>> AT+QSSLCFG=“cacert”,0,“UFS:isrgroot.pem”
<<<
OK>>> AT+QSSLCFG=“ignorelocaltime”,0,1
<<<
OK>>> AT+QSSLCFG=“sni”,0,1
<<<
OK[INFO] SSL Context Configured.

[INFO] Configuring MQTT for SSL…

AT+QMTCFG=“pdpcid”,0,1
<<<
OK>>> AT+QMTCFG=“ssl”,0,1,0
<<<
OK>>> AT+QMTCFG=“version”,0,4
<<<
OK[INFO] MQTT Configured for SSL.
[INFO] Deactivating old PDP context (AT+QIDEACT=1)…>>> AT+QIDEACT=1
<<<
OK

Done.
[INFO] Setting APN…>>> AT+QICSGP=1,1,“www”,“”,“”,0
<<<
OK
[INFO] APN Set.
[INFO] Connecting to GPRS/LTE…>>> AT+QIACT=1
<<<
OK
[INFO] Connected to GPRS/LTE.

[INFO] Waiting for PDP Context Activation (30s timeout)…

AT+QIACT?
<<<
+QIACT: 1,1,1[INFO] PDP Context is active.
[INFO] Connecting to MQTT Broker…>>> AT+QMTOPEN=0,“mqtts.lets.balwaan.com”,8883
<<<
OK

+QMTOPEN: 0,5

[ERROR] Failed to open network connection. Check SSL config.

[FATAL] Initial connection failed. Loop will attempt reconnect.

[WARN] Attempting full modem and MQTT reconnect…

AT
<<<
OK
[INFO] Modem: OK.
ATE0
<<<
OK>>> AT+CFUN=1
repeatative

again and again giving me the +QMTOPEN: 0,5 this error

Hi @vnksharma13 !
Unfortunately your code is unreadable due to wrong formatting.
Please edit your post, delete the code and paste in your code again using pre-formatted text!

#include <Arduino.h> // Required for PlatformIO
#include <HardwareSerial.h> // Include for HardwareSerial communication
#include <string.h> // Include for strlen
#include “SPIFFS.h” // Include SPIFFS library

// — User Configuration —
// Modem communication pins and baud rate
#define MODEM_RX 18
#define MODEM_TX 19
#define MODEM_BAUD 115200
#define MStat 2 // Status LED

// APN Configuration
#define APN “www”

// MQTT Broker Details
#define MQTT_SERVER “mqtts.lets.balwaan.com”
#define MQTT_PORT 8883
#define MQTT_USERNAME “lets-balwaan-mqtts”
#define MQTT_PASSWORD “Balwaanletsmqtts”
#define MQTT_CLIENT_ID “esp32-c3-device-01” // MUST be unique
#define MQTT_TOPIC “balwaan/test”

// Certificate file paths
#define CERT_FILENAME_ON_SPIFFS “/isrgroot.pem” // Path on ESP32
#define CERT_FILENAME_ON_MODEM “isrgroot.pem” // Filename on Modem
#define CERT_FULLPATH_ON_MODEM “UFS:isrgroot.pem” // Full path on Modem
#define SSL_CONTEXT_ID 0 // We’ll use SSL context 0

// Create a HardwareSerial instance for the modem
HardwareSerial modem(1);

// Global flag to track MQTT connection status
bool mqttConnected = false;

// — Utility Functions —

// Sends an AT command and waits for a specific expected response
String sendATCommand(String command, int timeout, String expectedResponse) {
while (modem.available()) modem.read();
if (command != “”) modem.println(command);

String response = “”;
long startTime = millis();

Serial.print(">>> “);
Serial.println(command);
Serial.print(”<<< ");

while (millis() - startTime < timeout) {
if (modem.available()) {
char c = (char)modem.read();
response += c;
Serial.print(c);

  if (expectedResponse != "" && response.indexOf(expectedResponse) != -1)
    return response;
  if (response.indexOf("ERROR") != -1)
    return response;
}
}
Serial.println();
if (expectedResponse == “” && response.indexOf(“ERROR”) == -1) return “OK”;
return response;
}

bool waitForActivation(uint32_t timeout = 30000) {
Serial.println(“\n[INFO] Waiting for PDP Context Activation (30s timeout)…”);
long startTime = millis();
while (millis() - startTime < timeout) {
String response = sendATCommand(“AT+QIACT?”, 2000, “+QIACT: 1,1,1”);
if (response.indexOf(“+QIACT: 1,1,1”) != -1) {
Serial.println(“[INFO] PDP Context is active.”);
return true;
}
Serial.println(“[INFO] Waiting… (PDP context not active yet)”);
delay(2000);
}
Serial.println(“[ERROR] PDP Context activation timed out!”);
return false;
}

// Check file on modem
bool checkFileOnModem(const char* filename) {
Serial.println(“\n[INFO] Checking for file on modem…”);
String response = sendATCommand(“AT+QFLST”, 5000, “OK”);
if (response.indexOf(filename) != -1) {
Serial.println(“[INFO] File found in modem file list.”);
return true;
}
Serial.println(“[INFO] File not found in modem file list.”);
return false;
}

// Upload certificate from SPIFFS to modem
bool uploadFileToModem(const char* spiffsFilename, const char* modemFilename) {
Serial.println(“\n[INFO] Uploading file from SPIFFS to modem…”);

File file = SPIFFS.open(spiffsFilename, “r”);
if (!file) {
Serial.print("[ERROR] Failed to open file: ");
Serial.println(spiffsFilename);
return false;
}

size_t fileSize = file.size();
Serial.print("[INFO] File size: ");
Serial.println(fileSize);

String cmd = “AT+QFUPL=“” + String(modemFilename) + “”,” + String(fileSize) + “,100”;

if (sendATCommand(cmd, 5000, “CONNECT”).indexOf(“CONNECT”) == -1) {
Serial.println(“!! Cert upload failed: No CONNECT”);
file.close();
return false;
}

Serial.println(“[INFO] Sending file…”);
uint8_t buffer[256];
size_t bytesSent = 0;
while (bytesSent < fileSize) {
size_t bytesToRead = file.read(buffer, sizeof(buffer));
if (bytesToRead == 0) break;
modem.write(buffer, bytesToRead);
bytesSent += bytesToRead;
Serial.print(“.”);
}

file.close();
if (sendATCommand(“”, 10000, “OK”).indexOf(“OK”) != -1) {
Serial.println(“\n>> Cert Uploaded Successfully”);
delay(1000);
return true;
}
Serial.println(“!! Cert upload failed”);
return false;
}

// Initialize modem and network
bool initAndCheckNetwork() {
if (sendATCommand(“AT”, 2000, “OK”).indexOf(“OK”) == -1) {
Serial.println(“[ERROR] Modem not ready.”);
return false;
}

sendATCommand(“ATE0”, 500, “OK”);
sendATCommand(“AT+CFUN=1”, 10000, “OK”);
if (sendATCommand(“AT+CPIN?”, 5000, “READY”).indexOf(“READY”) == -1) return false;
if (sendATCommand(“AT+CSQ”, 1000, “+CSQ:”).indexOf(“+CSQ:”) == -1) return false;

String reg = sendATCommand(“AT+CREG?”, 2000, “OK”);
if (reg.indexOf(“+CREG: 0,1”) == -1 && reg.indexOf(“+CREG: 0,5”) == -1) return false;

if (sendATCommand(“AT+CGATT=1”, 1000, “OK”).indexOf(“OK”) == -1) return false;
return true;
}

bool configureSSL() {
sendATCommand(“AT+QFDEL=“” CERT_FULLPATH_ON_MODEM “””, 5000, “”);
if (!checkFileOnModem(CERT_FILENAME_ON_MODEM))
if (!uploadFileToModem(CERT_FILENAME_ON_SPIFFS, CERT_FILENAME_ON_MODEM))
return false;

if (sendATCommand(“AT+QSSLCFG=“sslversion”,0,3”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“ciphersuite”,0,0XC02F”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“seclevel”,0,1”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“cacert”,0,“” CERT_FULLPATH_ON_MODEM “””, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“ignorelocaltime”,0,1”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QSSLCFG=“sni”,0,1”, 1000, “OK”).indexOf(“OK”) == -1) return false;

return true;
}

bool configureMQTT() {
if (sendATCommand(“AT+QMTCFG=“pdpcid”,0,1”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QMTCFG=“ssl”,0,1,0”, 1000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QMTCFG=“version”,0,4”, 1000, “OK”).indexOf(“OK”) == -1) return false;
return true;
}

bool activateNetwork() {
sendATCommand(“AT+QIDEACT=1”, 5000, “”);
String apnCmd = “AT+QICSGP=1,1,“” APN “”,“”,“”,0”;
if (sendATCommand(apnCmd, 5000, “OK”).indexOf(“OK”) == -1) return false;
if (sendATCommand(“AT+QIACT=1”, 30000, “OK”).indexOf(“OK”) == -1) return false;
return waitForActivation();
}

bool connectModemAndMQTT() {
if (!initAndCheckNetwork()) return false;
if (!configureSSL()) return false;
if (!configureMQTT()) return false;
if (!activateNetwork()) return false;

String open = “AT+QMTOPEN=0,“” MQTT_SERVER “”,” + String(MQTT_PORT);
if (sendATCommand(open, 15000, “+QMTOPEN: 0,0”).indexOf(“+QMTOPEN: 0,0”) == -1)
return false;

String conn = “AT+QMTCONN=0,“” MQTT_CLIENT_ID “”,“” MQTT_USERNAME “”,“” MQTT_PASSWORD “””;
if (sendATCommand(conn, 15000, “+QMTCONN: 0,0,0”).indexOf(“+QMTCONN: 0,0,0”) == -1)
return false;

return true;
}

bool mqttPublish(const char* payload) {
static int msgId = 1;

String cmd = “AT+QMTPUB=0,” + String(msgId++) + “,0,0,“” MQTT_TOPIC “””;
if (sendATCommand(cmd, 3000, “>”).indexOf(“>”) == -1) return false;

modem.print(payload);
modem.write(0x1A);

String expect = “+QMTPUB: 0,” + String(msgId - 1) + “,0”;
if (sendATCommand(“”, 5000, expect).indexOf(expect) != -1) return true;

return false;
}

void setup() {
Serial.begin(115200);
pinMode(MStat, OUTPUT);
modem.begin(MODEM_BAUD, SERIAL_8N1, MODEM_RX, MODEM_TX);

if (!SPIFFS.begin(true)) while(1);

mqttConnected = connectModemAndMQTT();
}

void loop() {
static unsigned long last = 0;
if (!mqttConnected) mqttConnected = connectModemAndMQTT();
if (mqttConnected && millis() - last > 10000) {
last = millis();
if (!mqttPublish(“hello”)) mqttConnected = false;
}
}
}