ESP32使用UniversalTelegramBot仅发送首条消息后停止发送问题
问题分析
你的核心问题是WiFiClientSecure连接未正确重置,叠加一处变量作用域错误,导致Telegram消息发送异常:
- Setup函数中重新定义局部变量
previousMillis,覆盖全局变量,造成定时器初始值逻辑混乱; - 每次发送消息后,
WiFiClientSecure的连接未主动关闭,后续请求无法建立有效新连接。
修复步骤
1. 修复变量作用域错误
在setup()中,你定义了局部的unsigned long previousMillis = millis();,这会覆盖全局的previousMillis变量,导致定时器初始值未正确赋值。修改为:
// 去掉unsigned long,直接给全局变量赋值 previousMillis = millis();
2. 重置WiFiClientSecure连接
每次发送消息前后,强制关闭客户端连接,确保下次发送时能建立全新的有效连接。修改loop()中的消息发送逻辑:
if (WiFi.status() == WL_CONNECTED) { // 发送前关闭已有无效连接 if(secured_client.connected()){ secured_client.stop(); } // 重新设置SSL根证书,确保连接安全性 secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT); if(bot.sendMessage(CHAT_ID, "Temp: " + TempState, "")) DEBUG_PRINTLN("Message sent"); else DEBUG_PRINTLN("Message NOT sent"); // 发送后主动关闭连接 secured_client.stop(); }
3. 简化定时器逻辑(可选)
移除冗余的firstTime变量,直接通过全局previousMillis的初始值0触发第一次执行:
// 删除全局变量:bool firstTime = true; // loop中的触发条件改为: if(millis() - previousMillis >= TIMER_INTERVAL*60000UL) { previousMillis = millis(); // 后续执行逻辑 }
完整修改代码
/**************************************************************** * * Sends dummy temperature value string to Telegram account * once ever N minutes * * * HARDWARE: * Adafruit Huzzah ESP32 * * SOFTWARE: * Arduino v 1.8.19 * UniversalTelegramBot v 1.3.0 * ArduinoJson v 6.19.4 * *****************************************************************/ #include <WiFi.h> #include <WiFiClientSecure.h> #include <WiFiMulti.h> #include <UniversalTelegramBot.h> #include <ArduinoJson.h> #include "Credentials.h" WiFiMulti wifiMulti; #define VER "TelegramBotDemo_v2" // Turn on debugging #define MY_DEBUG // ************** Print to serial only when MY_DEBUG is defined ***************** #ifdef MY_DEBUG #define DEBUG_PRINTF(x) Serial.print (x) #define DEBUG_PRINTLNF(x) Serial.println (x) #define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINTDEC(x) Serial.print (x, DEC) #define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINTHEX(x) Serial.print(x,HEX) #else #define DEBUG_PRINTF(x) #define DEBUG_PRINTLNF(x) #define DEBUG_PRINT(x) #define DEBUG_PRINTDEC(x) #define DEBUG_PRINTLN(x) #define DEBUG_PRINTHEX(x) #endif bool wifiFound = false; // Set GPIOs for LED and IO_PIN const int BUILTIN_LED_PIN = 13; //optional const int IO_PIN = 0; float temp = 49.9; bool state; String TempState = "NONE"; unsigned long previousMillis = 0; const long TIMER_INTERVAL = 1; // mins (set to 1 for test otherwise 60) #define LED_ON HIGH #define LED_OFF LOW WiFiClientSecure secured_client; UniversalTelegramBot bot(BOTtoken, secured_client); /********************************************** Round float to places places, return as string ***********************************************/ String rndS(float value, byte places) { //Storage for displaying float converted to char array char valueChar[10]; dtostrf(value, 5, places, valueChar); //convert float to char array String s = (String)valueChar; s.trim(); //remove whitespace return s ; } /************************************ * Connect to wifi and display stats ************************************/ boolean wifiConnect() { DEBUG_PRINTLN(); WiFi.mode(WIFI_STA); uint32_t looptime = millis(); uint8_t loopCount = 0; while (wifiMulti.run() != WL_CONNECTED) { while (millis() - looptime < 500L) yield(); // use this and not delay() looptime = millis(); DEBUG_PRINT("."); if(++loopCount >= 20){ DEBUG_PRINTLN("Timed out waiting for wiFi"); return false; } } DEBUG_PRINTLN(""); DEBUG_PRINT(F("IP address:")); DEBUG_PRINTLN(WiFi.localIP()); DEBUG_PRINT(F("RSSI:")); DEBUG_PRINTLN(WiFi.RSSI()); DEBUG_PRINTLN("WiFi Connected"); DEBUG_PRINTLN(""); return true; } /****************** SETUP ***************************/ void setup() { // Serial port for debugging purposes Serial.begin(115200); Serial.println(VER); // Set RED LED off (LOW) pinMode(BUILTIN_LED_PIN, OUTPUT); digitalWrite(BUILTIN_LED_PIN, LED_OFF); secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org // Connect to Wi-Fi WiFi.mode(WIFI_STA); // add multiple WAPs; it will pick the strongest wifiMulti.addAP(ssid1, pass1); wifiMulti.addAP(ssid2, pass2); wifiMulti.addAP(ssid3, pass3); if(wifiConnect()){ delay(500); wifiFound = true; // not used } else exit(0); WiFi.setSleep(false); // Send startup message (this always works) if(bot.sendMessage(CHAT_ID, "Bot started up", "")) DEBUG_PRINTLN("Startup Message sent"); else DEBUG_PRINTLN("Startup Message NOT sent"); // 修复:给全局变量赋值,而非定义局部变量 previousMillis = millis(); } // END OF SETUP /****************** LOOP ***************************/ void loop() { if(millis() - previousMillis >= TIMER_INTERVAL*60000UL) { previousMillis = millis(); digitalWrite(BUILTIN_LED_PIN, LED_ON); // Flash RED LED delay(200); digitalWrite(BUILTIN_LED_PIN,LED_OFF); TempState = String(rndS(temp,1)); DEBUG_PRINTLN(TempState); if (WiFi.status() == WL_CONNECTED) { // 发送前关闭已有连接,确保建立新连接 if(secured_client.connected()){ secured_client.stop(); } // 重新设置根证书 secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Send dummy string value if(bot.sendMessage(CHAT_ID, "Temp: " + TempState, "")) DEBUG_PRINTLN("Message sent"); else DEBUG_PRINTLN("Message NOT sent"); // 发送后关闭连接 secured_client.stop(); } else DEBUG_PRINTLN("WiFi NOT connected"); } // END interval timer } // END LOOP
修复原理
- 变量作用域修正:确保定时器初始值正确绑定全局变量,避免触发逻辑混乱;
- 连接重置:ESP32的
WiFiClientSecure在发送请求后易处于半开状态,主动关闭后重新建立连接,可避免复用无效连接导致的请求失败; - 证书重设:每次建立连接时重新配置SSL根证书,确保连接的安全性与有效性。
内容的提问来源于stack exchange,提问作者perge
相关产品推荐
相关产品推荐

