ESP32:时间戳无法通过 MQTT 发送

物联网 阿杜伊诺 ESP32
2021-06-04 14:16:11

一个星期以来,我一直在我的 ESP32 项目(通过 Arduino IDE 开发)中寻找解决方案:在我的项目中,我执行以下步骤:

  1. 通过 BME280 读取温度
  2. 在 NTP 服务器上询问时间(通过 time.h)
  3. 将数据写入字符串
  4. 通过 mqtt 将字符串发送到 mqtt 代理(通过 PubSubClient)

一切正常,但前提是我不添加这样的时间戳(没有时间戳):

String jsonString="{\"temperature\":"+String(bme.readTemperature())+",\"humidity\":"+String(bme.readHumidity())+",\"pressure\":"+String(bme.readAltitude(SEALEVELPRESSURE_HPA))+",\"deviceID\":\""+deviceID+"\",\"@timestamp\":\"\"}";

但是,如果我添加时间戳,PubSubClient 就不会发送数据。:

String jsonString="{\"temperature\":"+String(bme.readTemperature())+",\"humidity\":"+String(bme.readHumidity())+",\"pressure\":"+String(bme.readAltitude(SEALEVELPRESSURE_HPA))+",\"deviceID\":\""+deviceID+"\",\"@timestamp\":\""+printFormattedTime()+"\"}";

函数printFormattedTime():

String printFormattedTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return String("Failed to obtain time");
  }
  char timeStringBuff[50]; //50 chars should be enough
  strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%B-%d %H:%M:%S", &timeinfo);
  //print like "const char*"
  Serial.println(timeStringBuff);
  
  return String(timeStringBuff);
}

正如我所说:一切正常,直到我添加了返回带有时间格式的字符串的函数。

我还测试了另一个 NTPClient (NTPClient.h) 但没有成功。

任何的想法?

谢谢

1个回答

第一件事——我不相信 String 数据类型。

当我使用它时,我最终会遇到分配错误。内存管理似乎不太好。我不知道它何时重新分配以及何时使用我提供的字符数组。

因此,如果我试图在我的代码中解决这个问题,我会将函数更改为不返回字符串,而是将字符缓冲区地址和大小传递给它,就像传递给 strftime 一样。我不会将重载的“+”运算符与 String 数据类型一起使用,而是使用 strcat 和 strcpy 来构造 json 字符串。

这就是我在我的 Arduino IOT 设备中所做的。

我也是路德分子。我在资源受限的环境中使用 C++ 的经验不太好。我现在搭建的大物联网商用系统都是用C++,但是他们的应用处理器的规模是千兆和千兆。

这里的问题可能是 char 数组的 String 转换没有制作数组的副本。当您从函数返回时,数组(在堆栈上)超出范围,堆栈空间被另一个函数调用重用。您可以阅读 char 到 String 转换的代码,或者您可以切换到仅使用 char 类型,这样您就不会依赖于未知库的未记录功能。