繁体   English   中英

esp8266 通过 MQTT 发送大型 JSON 文档的问题

[英]Problem with esp8266 sending large JSON Document via MQTT

我开发了一个从传感器读取数据的小应用程序,将它们存储在我的 wemos D1 mini (esp8266) 的 SPIFFS memory 中,然后创建一个 JSON 文档并通过 MQTT 将其发送到我的主题。 问题是,只要我发送带有 10 object 的 JSON 文档,一切都很好,但是当我将文档的大小增加到 10 object 时,没有任何效果。 最终我需要发送一个 JSON 文档,里面有 100 个 object。

我已经做了什么?

  1. 我正在使用 PubSubClient 并且我已经将 MAX_PACKET_SIZE 设置为正确的值

  2. 使用 arduinojson 助手,我发现了我的 JSON 文档的大小(8192 字节)

  3. 我尝试使用 mqtt.fx 来测试问题是 esp8266 还是 mqtt 代理。 使用 mqtt.fx 我可以发送一个包含 100 个对象的 JSON 文档

  4. 一旦我增加 JSON 文档的大小,我的 arduino IDE 的串行监视器就会出现 wdt 错误。

    Arduino IDE 串行监视器 WDT 错误图像

  5. 我在互联网上搜索 wdt 错误,但我不知道它们是什么以及如何解决我的问题

  6. 最后一件事我已经尝试在串行监视器上显示我存储数据的 SPIFFS 中的 file.txt,我可以存储然后读取 100 object

所以最后我认为这是一个 esp8266 问题,而不是 PubSubClient 或 MQTT。 我对吗? 你们这里有没有人曾经遇到过这个问题或者我可以运行其他一些测试?

我在互联网上搜索 wdt 错误,但我不知道它们是什么以及如何解决我的问题

WDT 代表看门狗定时器。 https://os.mbed.com/cookbook/WatchDog-Timer#:~:text=A%20watchdog%20timer%20(WDT)%20is,a%20software%20or%20hardware%20fault

看门狗定时器 (WDT) 是一个硬件定时器,如果主程序忽略定期服务它,它会自动生成系统复位。 它通常用于自动重置由于软件或硬件故障而挂起的嵌入式设备。 一些系统也可能将其称为计算机正常运行 (COP) 计时器。 包括 mbed 处理器在内的许多微控制器都有看门狗定时器硬件。

让我们用一个例子来描绘一幅更好的画面。 假设您设置了一个时间为 10 秒的 WDT。 然后 WDT 从 10 秒开始倒计时。 如果它达到 0,处理器将重置。 “进给” WDT 会将倒计时重置为原始值,在这种情况下为 10 秒。 因此,如果 WDT 已倒计时到 4 秒,而您喂它,它会将倒计时重置回 10 并再次开始倒计时。

你们这里有没有人曾经遇到过这个问题或者我可以运行其他一些测试?

在我看来,发送更大的 JSON object 所需的时间比 WDT 设置的时间更长。 一种可能性是将 JSON object 分成多个部分,并以较小的块而不是一个大块的形式发送。 这样,WDT“馈送”之间的时间就减少了。 我不知道这是否可能让你改变。 但这至少应该让您更好地了解正在发生的事情。

好的,最后问题是发送一个大的 JsonDocument 触发了 WDT,我发现解决这个问题的唯一方法是,正如建议的那样,创建一个包含所有 100 个 object 的主文件,然后调用 function 来拆分它将文件分成 10 个较小的文件,然后通过 HTTP 请求或 Mosquitto 通过 Internet 发送每个文件。

假设您已经在 spiffs memory 中创建了主文件,那么:

这是拆分主文件:

void WritePacks() {
  
  sourceFile = LittleFS.open("/file.txt", "r");
  if (!sourceFile) {
    Serial.println(F("Error: file.txt open failed"));
  } else {
    Serial.println("File open w/ success");
    for (byte idx = 0; idx < outputCount; idx++) {
      String aLine;
      aLine.reserve(capacity);
      if (sourceFile.available() == 0) break;
      destinationFile = LittleFS.open(outputFileNames[idx], "w");
      if (!destinationFile) {
        Serial.print(F("can't open destination "));
        Serial.println(outputFileNames[idx]);
        break;
      } else {
        int lineCount = 0;
        while (sourceFile.available() && (lineCount <= 10)) {
          aLine = sourceFile.readStringUntil('\n');
          destinationFile.println(aLine); // double check if the '\n' is in the String or not (--> print or println accordingly)
          lineCount++;
        }
        outputIndex = idx;
        Serial.println(outputIndex);
        destinationFile.close();
      }
    } // end for
    sourceFile.close();
  }
}//end WritePacks

这要发布:

//------ HTTP Publish ------
void httpPublish(){

  const char * outputFileNames[] = {"/out1.txt", "/out2.txt", "/out3.txt", "/out4.txt", "/out5.txt", "/out6.txt", "/out7.txt", "/out8.txt", "/out9.txt", "/out10.txt"};
  const byte outputCount = sizeof outputFileNames / sizeof outputFileNames[0];
  byte outputIndex = 0;
  
  File sourceFile;
  File destinationFile;
  
  //Serial.println(capacity);
  

  for (byte idx = 0; idx < outputCount; idx++) {

      DynamicJsonDocument doc(capacity);
      DynamicJsonDocument globalDoc(capacity);
      StaticJsonDocument <1024> localDoc;
      String aLine;
      aLine.reserve(capacity);
      
      destinationFile = LittleFS.open(outputFileNames[idx], "r");
      if (!destinationFile) {
        Serial.print(F("can't open destination "));
        Serial.println(outputFileNames[idx]);
        break;
      } else {
        Serial.print("Reading: ");
        Serial.println(outputFileNames[idx]);
        //int lineCount = 0;
        while (destinationFile.available()) {
          aLine = destinationFile.readStringUntil('\n');
          DeserializationError error = deserializeJson(localDoc, aLine);
          if (!error) globalDoc.add(localDoc);  
          else{ Serial.println("Error Writing All files");}
        }//while

        JsonObject Info = doc.createNestedObject("Info");
        Info["Battery"] = battery;
        Info["ID"] = id;
        Info["Latitudine"] = latitudine;
        Info["Longitudine"] = longitudine;
    
        
        JsonArray Data = doc.createNestedArray("Data"); 
        Data.add(globalDoc);
    
        HTTPClient http;
        //Send request
        http.begin("yourURL");
        char buffer[capacity];
        size_t n = serializeJson(doc, buffer);
        
        http.POST(buffer);
        Serial.println(buffer);
        http.end();
        destinationFile.close();
      }
    }// end for   
}//end httpPublish

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM