Trouble connecting to AWS IOT Thing using A-7670AS Modem and MQTT with ESP32

Hello all,

I am working on a project that requires me to talk to my AWS Thing instance from my ESP32. I am using a lilygo board that should have all the hardware I need, and I have a fresh SIM card from Hologram that I have activated and that I can see usage on.

The code should connect to LTE, then connect to AWS, and then publish some data. The project aims to publish GPS data routinely so that it can be plotted on a map. The current issue is that the mqtt_connect() call always returns false, and I can never connect to my topic. I can connect to LTE, but I can't get past AWS. I have created a new Thing and generated new certs which didn't help. Below is my code and the console output:

/**
 * @file      MqttsBuiltlnAWS.ino
 * @author    Lewis He (lewishe@outlook.com)
 * @license   MIT
 * @copyright Copyright (c) 2023  Shenzhen Xin Yuan Electronic Technology Co., Ltd
 * @date      2023-11-28
 * @note
 * * * Example is suitable for A7670X/A7608X/SIM7672 series
 * * Connect MQTT Broker as https://aws.amazon.com/campaigns/IoT
 * * Example uses a forked TinyGSM <https://github.com/lewisxhe/TinyGSM>, which will not compile successfully using the mainline TinyGSM.
 * *!!!! When using ESP to connect to AWS, the AWS IOT HUB policy must be set to all devices, otherwise the connection cannot be made.
 * *!!!! When using ESP to connect to AWS, the AWS IOT HUB policy must be set to all devices, otherwise the connection cannot be made.
 * *!!!! When using ESP to connect to AWS, the AWS IOT HUB policy must be set to all devices, otherwise the connection cannot be made.
 * *!!!! When using ESP to connect to AWS, the AWS IOT HUB policy must be set to all devices, otherwise the connection cannot be made.
 * *Youtube : https://youtu.be/am-rTDzm4lQ
 * */
#define TINY_GSM_RX_BUFFER 1024  // Set RX buffer to 1Kb
#define TINY_GSM_USE_GPRS true
// See all AT commands, if wanted
#define DUMP_AT_COMMANDS

#include "utilities.h"
#include <TinyGsmClient.h>
#include "certs/AWSClientCertificate.h"
#include "certs/AWSClientPrivateKey.h"
#include "certs/AmazonRootCA.h"
#include <PubSubClient.h>

#ifdef DUMP_AT_COMMANDS  // if enabled it requires the streamDebugger lib
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif

// MQTT details
const char *broker = "a3jw4mm4a8k9f8-ats.iot.us-east-2.amazonaws.com";
const uint16_t broker_port = 8883;
const char *clien_id = "iot24_zami_GPSTracker";  // Was "ZaneTest" then proj5

const char *subscribe_topic = "zami_gps/data";
const char *publish_topic = "zami_gps/data";

// Current connection index, range 0~1
const uint8_t mqtt_client_id = 0;
uint32_t check_connect_millis = 0;

void mqtt_callback(const char *topic, const uint8_t *payload, uint32_t len) {
  Serial.println();
  Serial.println("======mqtt_callback======");
  Serial.print("Topic:");
  Serial.println(topic);
  Serial.println("Payload:");
  for (int i = 0; i < len; ++i) {
    Serial.print(payload[i], HEX);
    Serial.print(",");
  }
  Serial.println();
  Serial.println("=========================");
}

bool mqtt_connect() {
  Serial.print("Connecting to ");
  Serial.print(broker);

  bool ret = modem.mqtt_connect(mqtt_client_id, broker, broker_port, clien_id);
  if (!ret) {
    Serial.println("Failed!");
    return false;
  }
  Serial.println("successed.");

  if (modem.mqtt_connected()) {
    Serial.println("MQTT has connected!");
  } else {
    return false;
  }
  // Set MQTT processing callback
  modem.mqtt_set_callback(mqtt_callback);
  // Subscribe to topic
  modem.mqtt_subscribe(mqtt_client_id, subscribe_topic);

  return true;
}


void setup() {
  Serial.begin(115200);  // Set console baud rate

  Serial.println("Start Sketch");

  SerialAT.begin(115200, SERIAL_8N1, MODEM_RX_PIN, MODEM_TX_PIN);

#ifdef BOARD_POWERON_PIN
  pinMode(BOARD_POWERON_PIN, OUTPUT);
  digitalWrite(BOARD_POWERON_PIN, HIGH);
#endif

  // Set modem reset pin ,reset modem
  pinMode(MODEM_RESET_PIN, OUTPUT);
  digitalWrite(MODEM_RESET_PIN, !MODEM_RESET_LEVEL);
  delay(100);
  digitalWrite(MODEM_RESET_PIN, MODEM_RESET_LEVEL);
  delay(2600);
  digitalWrite(MODEM_RESET_PIN, !MODEM_RESET_LEVEL);

  pinMode(BOARD_PWRKEY_PIN, OUTPUT);
  digitalWrite(BOARD_PWRKEY_PIN, LOW);
  delay(100);
  digitalWrite(BOARD_PWRKEY_PIN, HIGH);
  delay(100);
  digitalWrite(BOARD_PWRKEY_PIN, LOW);

  // Check if the modem is online
  Serial.println("Start modem...");

  int retry = 0;
  while (!modem.testAT(1000)) {
    Serial.println(".");
    if (retry++ > 10) {
      digitalWrite(BOARD_PWRKEY_PIN, LOW);
      delay(100);
      digitalWrite(BOARD_PWRKEY_PIN, HIGH);
      delay(1000);
      digitalWrite(BOARD_PWRKEY_PIN, LOW);
      retry = 0;
    }
  }
  Serial.println();

  // Check if SIM card is online
  SimStatus sim = SIM_ERROR;
  while (sim != SIM_READY) {
    sim = modem.getSimStatus();
    switch (sim) {
      case SIM_READY:
        Serial.println("SIM card online");
        break;
      case SIM_LOCKED:
        Serial.println("The SIM card is locked. Please unlock the SIM card first.");
        // const char *SIMCARD_PIN_CODE = "123456";
        // modem.simUnlock(SIMCARD_PIN_CODE);
        break;
      default:
        break;
    }
    delay(1000);
  }

  //SIM7672G Can't set network mode
#ifndef TINY_GSM_MODEM_SIM7672
  if (!modem.setNetworkMode(MODEM_NETWORK_AUTO)) {
    Serial.println("Set network mode failed!");
  }
  String mode = modem.getNetworkModes();
  Serial.print("Current network mode : ");
  Serial.println(mode);
#endif

  while (!modem.gprsConnect("hologram", "", "")) {
    Serial.println("connecting to apn...");
    delay(1000);
  }

  // Check network registration status and network signal status
  int16_t sq;
  Serial.print("Wait for the modem to register with the network.");
  RegStatus status = REG_NO_RESULT;
  while (status == REG_NO_RESULT || status == REG_SEARCHING || status == REG_UNREGISTERED) {
    status = modem.getRegistrationStatus();
    switch (status) {
      case REG_UNREGISTERED:
      case REG_SEARCHING:
        sq = modem.getSignalQuality();
        Serial.printf("[%lu] Signal Quality:%d", millis() / 1000, sq);
        delay(1000);
        break;
      case REG_DENIED:
        Serial.println("Network registration was rejected, please check if the APN is correct");
        return;
      case REG_OK_HOME:
        Serial.println("Online registration successful");
        break;
      case REG_OK_ROAMING:
        Serial.println("Network registration successful, currently in roaming mode");
        break;
      default:
        Serial.printf("Registration Status:%d\n", status);
        delay(1000);
        break;
    }
  }
  Serial.println();


  Serial.printf("Registration Status:%d\n", status);
  delay(1000);

  String ueInfo;
  if (modem.getSystemInformation(ueInfo)) {
    Serial.print("Inquiring UE system information:");
    Serial.println(ueInfo);
  }

  // while (!modem.enableNetwork()) {
  //     Serial.println("Enable network failed - retrying...");
  //     delay(1000);
  // }
  // Serial.println("Network Opened!");

  delay(5000);

  String ipAddress = modem.getLocalIP();
  Serial.print("Network IP:");
  Serial.println(ipAddress);

  // Initialize MQTT, use SSL
  if (modem.mqtt_begin(true))
    Serial.println("Began MQTT Client");

  // Set Amazon Certificate
  modem.mqtt_set_certificate(AmazonRootCA, AWSClientCertificate, AWSClientPrivateKey);

  // Connecting to AWS IOT Core
  if (!mqtt_connect()) {
    return;  // Don't run connect() too many times because it sucks up data
  }

  while (1) {
    // Check the connection every ten seconds
    if (millis() > check_connect_millis) {
      check_connect_millis = millis() + 10000UL;
      if (!modem.mqtt_connected()) {
        mqtt_connect();
      } else {
        // If connected, send information once every ten seconds
        String payload = "RunTime:" + String(millis() / 1000);
        modem.mqtt_publish(0, publish_topic, payload.c_str());
      }
    }
    // MQTT handling
    modem.mqtt_handle();
    delay(5);
  }
}

void loop() {
  // Debug AT
  if (SerialAT.available()) {
    Serial.write(SerialAT.read());
  }
  if (Serial.available()) {
    SerialAT.write(Serial.read());
  }
  delay(1);
}

And the console output I am reading with AT commands being shown

=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2024.04.27 18:38:03 =~=~=~=~=~=~=~=~=~=~=~=
ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13964
load:0x40080400,len:3600
entry 0x400805f0
Start Sketch
Start modem...
AT
AT
AT
AT
.
AT
AT
AT
AT
.
AT
AT
AT
AT
.
AT
AT
AT
AT
.
AT
AT
AT
AT
.
AT
AT
AT
AT
.
AT
AT
AT
AT
.
AT
AT
AT
AT
.
AT
AT
AT
AT

+CPIN: READY
.
AT

*ATREADY: 1
AT
OK

AT+CPIN?
AT
OK
AT
OK
AT
OK
AT
OK
AT
OK
AT
OK
AT
OK
AT+CPIN?
+CPIN: READY

OK
SIM card online
AT+CNMP=2

SMS DONE
AT+CNMP=2
OK
AT+CNMP?
AT+CNMP?
+CNMP: 2

OK
Current network mode : AUTO
AT+NETCLOSE
AT+NETCLOSE
+NETCLOSE: 2

ERROR
AT+CGDCONT=1,"IP","hologram","0.0.0.0",0,0
AT+CGDCONT=1,"IP","hologram","0.0.0.0",0,0
OK
AT+CIPMODE=0
AT+CIPMODE=0
OK
AT+CIPSENDMODE=0
AT+CIPSENDMODE=0
OK
AT+CIPCCFG=10,0,0,0,1,0,75000
AT+CIPCCFG=10,0,0,0,1,0,75000
OK
AT+CIPTIMEOUT=75000,15000,15000
AT+CIPTIMEOUT=75000,15000,15000
OK
AT+CGACT=1,1
AT+CGACT=1,1
+CME ERROR: unknown error

+CGEV: EPS PDN ACT 1

PB DONE
connecting to apn...
AT+NETCLOSE
AT+NETCLOSE
+NETCLOSE: 2

ERROR
AT+CGDCONT=1,"IP","hologram","0.0.0.0",0,0
AT+CGDCONT=1,"IP","hologram","0.0.0.0",0,0
OK
AT+CIPMODE=0
AT+CIPMODE=0
OK
AT+CIPSENDMODE=0
AT+CIPSENDMODE=0
OK
AT+CIPCCFG=10,0,0,0,1,0,75000
AT+CIPCCFG=10,0,0,0,1,0,75000
OK
AT+CIPTIMEOUT=75000,15000,15000
AT+CIPTIMEOUT=75000,15000,15000
OK
AT+CGACT=1,1
AT+CGACT=1,1
OK
AT+NETOPEN
AT+NETOPEN
OK

+NETOPEN: 0Wait for the modem to register with the network.AT+CGREG?

AT+CGREG?
+CGREG: 0,5

OK
Network registration successful, currently in roaming mode

Registration Status:5
AT+CPSI?
AT+CPSI?
+CPSI: LTE,Online,310-260,0xA181,30298981,372,EUTRAN-BAND4,2350,3,0,15,37,37,4

OK
Inquiring UE system information:LTE,Online,310-260,0xA181,30298981,372,EUTRAN-BAND4,2350,3,0,15,37,37,4
AT+IPADDR
AT+IPADDR
+IPADDR: 100.76.10.133

OK
Network IP:100.76.10.133
AT+CMQTTSTART
AT+CMQTTSTART
OK

+CMQTTSTART: 0
Began MQTT Client
Connecting to a3jw4mm4a8k9f8-ats.iot.us-east-2.amazonaws.comAT+CCERTDOWN="ca_cert.pem",1199
AT+CCERTDOWN="ca_cert.pem",1199
>
-----BEGIN ROOT CERTIFICATE-----
<secret ca_cert>
-----END ROOT CERTIFICATE-----

OK
AT+CSSLCFG="cacert",0,"ca_cert.pem"
AT+CSSLCFG="cacert",0,"ca_cert.pem"
OK
AT+CCERTDOWN="cert.pem",1221
AT+CCERTDOWN="cert.pem",1221
>
-----BEGIN CERTIFICATE-----
<secret cert>
-----END CERTIFICATE-----

OK
AT+CSSLCFG="clientcert",0,"cert.pem"
AT+CSSLCFG="clientcert",0,"cert.pem"
OK
AT+CCERTDOWN="key_cert.pem",1676
AT+CCERTDOWN="key_cert.pem",1676
>
-----BEGIN RSA PRIVATE KEY-----
<secret private key>
-----END RSA PRIVATE KEY-----

OK
AT+CSSLCFG="clientkey",0,"key_cert.pem"
AT+CSSLCFG="clientkey",0,"key_cert.pem"
OK
AT+CSSLCFG="sslversion",0,4
AT+CSSLCFG="sslversion",0,4
OK
AT+CMQTTSSLCFG=0,0
AT+CMQTTSSLCFG=0,0
OK
AT+CSSLCFG="authmode",0,2
AT+CSSLCFG="authmode",0,2
OK
AT+CMQTTREL=0
AT+CMQTTREL=0
+CMQTTREL: 0,20

ERROR
AT+CMQTTACCQ=0,"iot24_zami_GPSTracker",1
AT+CMQTTACCQ=0,"iot24_zami_GPSTracker",1
OK
AT+CMQTTCONNECT=0,"tcp://a3jw4mm4a8k9f8-ats.iot.us-east-2.amazonaws.com:8883",60,1
AT+CMQTTCONNECT=0,"tcp://a3jw4mm4a8k9f8-ats.iot.us-east-2.amazonaws.com:8883",60,1
+CMQTTCONNECT: 0,34

ERROR
Failed!

I am seeking advice for using LTE to communicate with AWS using MQTT. I will be extremely active on this topic, so please don't hesitate to ask questions.

Firstly, test if your ESP32 board can reach the Internet via LTE. You can do so by programming ESP32 to making HTTP request to a web server

If your ESP32 can connect to the Internet, try follow the ESP32 AWS IoT Core via WiFi tutorial

If both works well, you can combine them

where have you defined MODEM_RX_PIN etc

Hello, I have a similar problem, I posted in Post.
Could you solve it?
I was seeing if it is a bug in the PubSubClient library that does not support the AT transport (custom transport) that does not activate the SNI. Therefore, I would have to look for another alternative or use AT modem commands, but I am still not sure about the AT transport issue.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.