You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过SIM800L网络实现ESP32与带SSL/TLS的MQTT Broker连接

问题

我使用集成SIM800L的LilyGo ESP32模块,搭配TinyGSM和PubSubClient库尝试建立带SSL/TLS加密的MQTT Broker连接,但未成功。发现TinyGsmClientSecure没有setCACert方法,无法像普通WiFi客户端那样配置证书。相关代码如下:

主程序代码

#include "config.h"
#define TINY_GSM_MODEM_SIM800
#define TINY_GSM_RX_BUFFER   1024  // Set RX buffer to 1Kb
#include <TinyGsmClient.h>
#include <PubSubClient.h>
#ifdef DUMP_AT_COMMANDS
  #include <StreamDebugger.h>
  StreamDebugger debugger(SerialAT, SerialMon);
  TinyGsm modem(debugger);
#else
  TinyGsm modem(SerialAT);
#endif

TinyGsmClientSecure client(modem);
PubSubClient  mqtt(client);

void setup() 
{
  pinMode(MODEM_PWKEY, OUTPUT);
  pinMode(MODEM_RST, OUTPUT);
  pinMode(MODEM_POWER_ON, OUTPUT);
  digitalWrite(MODEM_PWKEY, LOW);
  digitalWrite(MODEM_RST, HIGH);
  digitalWrite(MODEM_POWER_ON, HIGH);
  SerialMon.begin(115200);
  SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
  SerialMon.println("Initializing modem...");
  modem.restart();
  if(connectToMQTT())
  {
    publishData();
    SerialMon.println("DATA HAS BEEN PUBLISHED");
  }
  else
  {
    SerialMon.println("FAILED TO PUBLISH");
  }
}

void loop() 
{
  while(SerialAT.available())
  {
    SerialMon.println(SerialAT.readString());
  }
  while(SerialMon.available())
  {
    SerialAT.write(SerialMon.read());
  }
}

MQTT连接相关函数

bool connectToMQTT()
{
  modem.gprsConnect("CMNET");
  const char *ca_cert = NULL;
  //client.setCertificate(ca_cert); // 此方法不可用
  // 尝试通过AT命令配置证书
    SerialMon.print(F("Setting SSL certificate... "));
modem.sendAT(GF("+SSLSETCERT=\"" CERT_FILE "\""));
int response = modem.waitResponse(5000);  // Adjust timeout as needed

if (response == 1) {
    SerialMon.println(F("OK"));
} else {
    SerialMon.println(F("Failed"));
    SerialMon.print(F("AT response code: "));
    SerialMon.println(response);
    while (1);
}
  mqtt.setServer("pag.tayrix.com", 30883);
  mqtt.setCallback(mqttCallback);
  SerialMon.println("Connecting to MQTT broker...");
  boolean status = mqtt.connect("GsmClientName", "demo@org.eclipse.packages.c2e", "a2k1jkd");
  if (status == false) 
  {
    SerialMon.println(" fail");
    return false;
  }
  else 
  {
    SerialMon.println(" success");
    return true;
  }
}

void publishData()
{
  const char *topic = "telemetry";
  String kkk=send_json_data();
  mqtt.publish(topic, kkk.c_str());
}

void mqttCallback(char* topic, byte* payload, unsigned int length) 
{
  
}

尝试使用client.setCACert(ca_cert)时,编译器提示该方法不存在,求指导如何通过SIM800L实现SSL/TLS加密的MQTT连接。


解决方案

1. 核心逻辑:SIM800L的SSL处理方式

SIM800L的SSL/TLS加密是在模块内部硬件/固件层面完成的,而非ESP32侧处理,因此TinyGsmClientSecure没有提供setCACert这类客户端侧的证书配置方法,必须通过SIM800L的AT命令直接配置证书。

2. 正确配置证书的两种方式

方式一:直接传入证书字符串

如果模块不支持文件系统存储证书,直接将CA证书内容作为参数发送给模块:

bool connectToMQTT()
{
  // 1. 先建立GPRS连接
  if(!modem.gprsConnect("CMNET")) {
    SerialMon.println("GPRS连接失败");
    return false;
  }
  SerialMon.println("GPRS连接成功");

  // 2. 配置CA证书(替换为你的实际证书内容)
  const char* ca_cert = R"(-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Ad
g06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKI
JFPNlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV
0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8
TBqCAU7CEm9INlkSFFMLGaMD0uNmNI2U9SNiagEhuJw==
-----END CERTIFICATE-----)";

  SerialMon.print(F("配置SSL证书... "));
  // 发送AT命令配置CA证书
  modem.sendAT(GF("+SSLSETCERT=\""), ca_cert, GF("\""));
  int response = modem.waitResponse(10000); // 证书传输需要更长超时
  if (response != 1) {
    SerialMon.println(F("失败"));
    SerialMon.print(F("AT响应码: "));
    SerialMon.println(response);
    return false;
  }
  SerialMon.println(F("成功"));

  // 3. 配置MQTT服务器
  mqtt.setServer("pag.tayrix.com", 30883);
  mqtt.setCallback(mqttCallback);

  // 4. 建立MQTT连接(自动触发SSL握手)
  SerialMon.println("连接MQTT Broker...");
  boolean status = mqtt.connect("GsmClientName", "demo@org.eclipse.packages.c2e", "a2k1jkd");
  if (!status) {
    SerialMon.print("失败,错误码: ");
    SerialMon.println(mqtt.state());
    return false;
  }
  SerialMon.println("成功");
  return true;
}

方式二:使用模块文件系统存储证书

如果你的SIM800L固件支持文件系统(部分版本支持),可以先将证书上传到模块的文件系统(比如/cert/ca.pem),再通过AT命令指定路径:

modem.sendAT(GF("+SSLSETCERT=\"/cert/ca.pem\""));

具体上传方法参考SIM800L的AT命令手册。

3. 关键注意事项

  • 固件版本:确保SIM800L的固件版本支持SSL/TLS,旧版本可能不支持该功能。
  • 证书格式:必须使用PEM格式的证书,内容要完整,包含-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----标记。
  • 超时设置:传输证书时需要更长的超时时间(比如10秒),避免模块未完成处理就判定失败。
  • 调试开启:定义DUMP_AT_COMMANDS宏,打印所有AT命令和响应,方便定位证书配置或连接失败的具体原因。

4. 可选:跳过证书验证(不推荐)

如果测试时暂时无法获取正确的CA证书,可以通过AT命令关闭证书验证(仅用于测试,生产环境禁用):

modem.sendAT(GF("+SSLSECV=0")); // 0表示关闭证书验证,1表示开启
modem.waitResponse();

内容的提问来源于stack exchange,提问作者shaik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 11:08:10