无法使用 SIM800L+ESP32 发送大小大于 1449 个字符的 HTTP POST 负载

Unable to send HTTP POST payload of size greater than 1449 characters with SIM800L+ESP32

所以我在我的 ESP32+SIM800L 设置上通过 HTTP POST 将数据发送到我的 php 托管在 000WebHost 上的脚本。 我正在以 800Hz 的频率记录传感器数据并将其存储在一个字符数组中,例如:a[]=3&a[]=5&a[]=8... 它成为 POST 请求的有效负载数组。

出于某种原因,我只能发送 161 个值,内容长度大约为 1449。

代码有点长所以我在这里减少了它: 我正在使用 TinyGSM 库

//Start GSM:
 SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
 SerialMon.println("Initializing modem...");


modem.init();
  SerialMon.print(F("Connecting to "));
   SerialMon.print(apn);
   if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
      SerialMon.println(" fail");
      delay(10000);
      return;
    }
   SerialMon.println(" success");

   if (modem.isGprsConnected()) {
      SerialMon.println("GPRS connected");
  }

  SerialMon.print("Connecting to ");
  SerialMon.println(server);
  if (!client.connect(server, port)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" success");


// Record Sensor values for one second
//Send the character array to the httpPost function:
if (client.connect(server,port)) {
  Serial.println("connected");
  client.println("POST /upload.php? HTTP/1.1");
  client.println("Host:  epiblastic-reactor.000webhostapp.com");
  client.println("User-Agent: TTGO-TCALL/1.0");
  client.println("Content-Type: application/x-www-form-urlencoded;");
  client.print("Content-Length: ");
  client.println(String(acceldata).length());
  client.println();
  client.println(acceldata);
  

  uint32_t timeout = millis();
  while (client.connected() && millis() - timeout < 10000L) {
    // Print available data
    while (client.available()) {
      char c = client.read();
      SerialMon.print(c);
      timeout = millis();
    }

如果我发送超过 161 个值,串行监视器打印:

#Available: 0 on 1

不断。

出了什么问题? 有人可以帮我吗?

没有什么明显的,您可能想检查您的 TinyGSM 配置并可能启用该库的调试输出。

无论如何。总有一些常见的嫌疑人:

首先,您没有在 ESP32 和调制解调器之间的串口 link 上使用流量控制。这意味着如果您向调制解调器发送更多数据以使其可以发送到 Internet,调制解调器的串行缓冲区可能会溢出。好的解决方案是在两侧启用串行流控制(硬件最好,软件可以)。一个糟糕的解决方案是更慢地发送数据,例如每隔几秒 1400 字节。

其次检查服务器端是否发生任何异常,即服务器关闭连接。

然后你可以检查 - 无论对象 client 是什么(你的代码没有显示它的创建位置) - 它实际上允许你使用大量数据调用 println()

至于您的数据量,通过 HTTP 请求发送 6-7 KiB 的数据并没有什么异常。仅当您希望通过吞吐量较小的 link 每秒发送那么多时才会出现问题 - 显然它没有能力做到这一点。 GPRS 上传速度

以太网的MTU通常为1500,但对于SIM800,我认为它设置为1460字节(您可以使用AT+CIPSEND?查看该值)。 TinyGSM 使用的 TCP/HTTP 客户端似乎不会将超过一个 MTU 的数据分成块,因此用户有责任这样做。

这里是一个关于如何在多个块中发送数据的例子。

代码已从初始输入更新

#define ONE_CHUNK 1024  //you can change it as long as it is <= MTU

int payload_length = acceldata.length(); //assuming your data is already a String object
client.print("Content-Length: ");
client.println(payload_length);
client.println();

if (payload_length < ONE_CHUNK) {  //less than ONE_CHUNK, send it
  client.println(acceldata);
}
else {  // more than ONE_CHUNK, break it into number of chunks
  int chunks = payload_length / ONE_CHUNK;
  for(int i = 0; i < chunks; i++){
    client.print(acceldata.substring(i*ONE_CHUNK, (i*ONE_CHUNK)+ONE_CHUNK));
  }
  int last_chunk = payload_length - chunks * ONE_CHUNK;
  if (last_chunk) {
    client.println(acceldata.substring(payload_length-last_chunk, payload_length - 1)); 
  } 
}