如何通过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
相关产品推荐
相关产品推荐

