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

ESP8266+Arduino调用Telegram API时响应截断问题排查

ESP8266通过SoftwareSerial连接Arduino Uno向Telegram API发送请求时响应截断问题

我用SoftwareSerial将ESP8266与Arduino Uno连接,向Telegram API发送GET请求,AT指令打印信息正常,但服务器返回的响应始终存在截断情况。

原代码

#include <SoftwareSerial.h>
 
SoftwareSerial mySerial(8, 9);
 
#define WIFI_SERIAL mySerial


String command(const char *toSend, unsigned com_delay, unsigned milliseconds) {
  String result;
  Serial.print("Sending: ");
  Serial.println(toSend);
  WIFI_SERIAL.println(toSend);
  unsigned long startTime = millis();
  Serial.print("Received: ");
  delay(com_delay);
  while (millis() - startTime - com_delay < milliseconds) {
    if (WIFI_SERIAL.available()) {
      delay(1);
      char c = WIFI_SERIAL.read();
      Serial.write(c);
      result += c;  // append to the result string
    }
  }
  Serial.println();  // new line after timeout.
  return result;
}

void setup()
{
  Serial.begin(9600);
  while (!Serial);

  Serial.print("Serial init OK\n");
  WIFI_SERIAL.begin(9600);
  char concom[] = "AT+CWJAP_DEF=\"---\",\"---\"";
  char sendcom[] = "AT+CIPSTART=\"TCP\",\"api.telegram.org\",443";
  char api[] = "GET /botxxxxxxxxxxxxxxxxxxxx/ HTTP/1.1\nHost: api.telegram.org\nAccept: application/json\nCache-Control: no-cache\n\n";
  
  //command("AT+CWMODE=1", 10000, 100);
  
  
  command(concom, 7000, 500);
  command(sendcom, 10000, 500);
  command("AT+CIPSEND=139", 3000, 500);
  Serial.println("+"+command(api, 40000, 15000));
}


 
void loop()
{
  while(WIFI_SERIAL.available())
  {
      char line = WIFI_SERIAL.read();        // read one char at a time
      delay(1);                      // prevent freezing
      Serial.print(line);
      // if (line == '\0') continue;    // terminate the `while` when end of the data
  }
}

服务器返回内容

Serial init OK
00:02:08.438 -> Sending: AT+CWJAP_DEF="---","---"
00:02:08.469 -> Received: T+CWJAP_DEF="---","----"

00:02:15.526 -> busy s...
00:02:15.531 -> 
00:02:15.531 -> Recv 1
00:02:15.959 -> Sending: AT+CIPSTART="TCP","api.telegram.org",443
00:02:16.026 -> Received: 
00:02:26.021 -> Sending: AT+CIPSEND=139
00:02:26.082 -> Received: AT+CIPSTART="TCP","api.telegram.org",443

00:02:29.090 -> CONNECT
00:02:29.090 -> 
00:02:29.090 -> OK
00:02:29.090 -> AT+CI
00:02:29.551 -> Sending: GET /botxxxxxxxxxxxxxx/ HTTP/1.1
00:02:29.613 -> Host: api.telegram.org
00:02:29.646 -> Accept: application/json
00:02:29.679 -> Cache-Control: no-cache
00:02:29.679 -> 
00:02:29.679 -> 
00:02:29.779 -> Received: 
00:03:09.792 -> +
00:03:09.853 -> 
00:03:09.853 -> busy s...
00:03:09.853 -> 
00:03:09.853 -> Recv 139 bytes
00:03:09.853 -> 
00:03:09.853 -> SEND OK
00:03:09.858 -> 
00:03:09.858 -> +IPD,595:HTTP/1.1 4 // <---- HERE IS INCOMPLETED ANSWER

问题原因与解决方法

核心问题点

  1. HTTPS连接错误:Telegram API的443端口是HTTPS服务,原代码用TCP连接,属于明文请求,服务器返回的响应会异常,甚至被截断。
  2. SoftwareSerial性能限制:软串口是模拟实现的,9600波特率下缓存有限,处理595字节的响应时容易丢包,加上代码中delay(1)的额外阻塞,导致无法及时读取所有数据。
  3. 超时逻辑不合理:command函数中先执行固定时长的delay(com_delay),这段时间内ESP8266返回的数据可能因缓存溢出丢失。
  4. 请求长度计算错误:AT+CIPSEND=139的长度参数可能与实际HTTP请求长度不符,导致发送不完整或响应异常。

修正后的代码

#include <SoftwareSerial.h>
 
SoftwareSerial mySerial(8, 9);
 
#define WIFI_SERIAL mySerial

String command(const char *toSend, unsigned long timeoutMs) {
  String result;
  Serial.print("Sending: ");
  Serial.println(toSend);
  WIFI_SERIAL.println(toSend);
  
  unsigned long startTime = millis();
  Serial.print("Received: ");
  
  // 实时读取串口数据,直到超时
  while (millis() - startTime < timeoutMs) {
    while (WIFI_SERIAL.available()) {
      char c = WIFI_SERIAL.read();
      Serial.write(c);
      result += c;
    }
  }
  Serial.println();
  return result;
}

void setup()
{
  Serial.begin(115200); // 提高硬件串口波特率,加快调试输出
  while (!Serial);

  Serial.println("Serial init OK");
  WIFI_SERIAL.begin(115200); // 提高软串口波特率,减少传输延迟
  char concom[] = "AT+CWJAP_DEF=\"你的WiFi名称\",\"你的WiFi密码\"";
  // 改用SSL连接HTTPS服务
  char sendcom[] = "AT+CIPSTART=\"SSL\",\"api.telegram.org\",443";
  // 构造标准HTTP请求,用\r\n换行符符合协议规范
  String apiRequest = "GET /botxxxxxxxxxxxxxxxxxxxx/getMe HTTP/1.1\r\nHost: api.telegram.org\r\nAccept: application/json\r\nCache-Control: no-cache\r\n\r\n";
  
  // 连接WiFi,超时10秒
  command(concom, 10000);
  // 建立SSL连接,超时10秒
  command(sendcom, 10000);
  
  // 自动计算请求长度,避免手动输入错误
  String sendLenCmd = "AT+CIPSEND=" + String(apiRequest.length());
  command(sendLenCmd.c_str(), 3000);
  
  // 发送API请求,超时20秒
  Serial.println("+"+command(apiRequest.c_str(), 20000));
}

void loop()
{
  // 实时读取ESP8266返回的剩余数据
  while(WIFI_SERIAL.available())
  {
      char c = WIFI_SERIAL.read();
      Serial.print(c);
  }
}

额外优化建议

  • 如果软串口仍存在丢包问题,建议改用Arduino Uno的硬件串口(引脚0/1)连接ESP8266,注意上传代码时需断开ESP8266的TX/RX引脚,避免串口冲突。
  • 可以开启ESP8266的AT指令长响应模式,使用AT+CIPRECVMODE=1设置为被动接收,通过AT+CIPRECVDATA主动读取响应数据,减少软串口的实时压力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 07:38:20