ESP32-CAM如何将大型二进制有效负载发布到AWS IOT ssl mqtt主题,测试了许多库,但均未成功:-

问题描述

我目前正在研究一个ESP32CAM项目,以在AWS IOT主题上发布一些高分辨率(UXGA)相机拍摄的照片。 我已经设法将一些带有属性的简短json负载发布到了不同的AWS IOT证书保护的主题,但是我面临着一个烦人的问题,那就是要对大型负载进行与捕获二进制文件相同的操作。

我浏览了许多站点,论坛,测试了不同的库,例如MQTT,PubSubClient,AsyncMQTTClient ...,但是我没有找到真正有效的解决方案用于大负载 >大约100KB。

例如,对于PubSubClient库,我尝试使用BeginPublish,write,endPublish方案对二进制有效负载进行分段,如下所示:

bool publishBinary(const uint8_t *buffer,size_t len,const char *topicPubName)
{
  Serial.print("publishing binary ["+(String)len+"] ...");
  if (len == 0) {
    // Empty file
    Serial.println("Error : binary payload is empty!");
    return(false);
  }

  if (!client.beginPublish(topicPubName,len,false)) {
    Serial.println("MQTT beginPublish failed.");
    return(false);
  }
  size_t max_transfer_size=80;
  size_t n=0;
  size_t size_send;
  size_t offset=0;

  while ((len-offset)>0) {
    n=(len-offset);
    if (n > max_transfer_size)
      n=max_transfer_size;

    size_send=client.write((const uint8_t *)(buffer+offset),n);
    Serial.printf("%d/%d : %.02f %%\n",offset,(double)((100*offset)/len));
    //Serial.println("n: "+(String)n+" - send: "+(String)size_send);
    if(size_send != n) { 
      // error handling. this is triggered on write fail.
      Serial.println("Error during publishing..."+(String)size_send+" instead of "+(String)n);
      client.endPublish();
      return(false);
    } else {
      offset+=size_send;
    }
  }
  client.endPublish();
  Serial.println("ok");

  return(true);
}

客户端定义为 PubSubClient客户端(net),其中net是具有经过验证的CA_cert,证书和私钥的WiFiClientSecure对象。

MQTT连接运行良好,但是当我尝试发布较大的二进制有效负载时,该函数将缓冲区分段成块,直到最后,但总是会出现类似未知错误代码(0050)的错误或成功发布后,仅一小部分有效负载会发布到目标上。在这种情况下,我的jpeg文件在有效负载到达的S3存储桶上被截断了。

我不得不说,有时候,我设法发布了65K的有效载荷,但是有点运气...:-)

我已经在网上寻找了一些示例,但通常是用于较小的负载。如帖子中所述,我已经测试了PubSubClient中的Publish_P(...),但结果相同,在传输过程中它会中止。

我开始问自己,是否真的可以通过mqtt主题进行操作,还是必须创建一个带有lambda的API网关来处理如此大的有效负载。告诉我我错了:-)

如果您知道一个真正可行的大型有效载荷发布的好的解决方案,我将很高兴与您讨论:-)

谢谢!

解决方法

嘿,我在PubSubClient库和大文件方面也遇到了问题。最后,我发现必须按如下方式更新PubSubClient.h:

//128000 = 128 kB is the maximum size for AWS I think..
#define MQTT_MAX_PACKET_SIZE 100000 

// It takes a long time to transmit the large files 
// maybe even more than 200 seconds...
#define MQTT_KEEPALIVE 200
#define MQTT_SOCKET_TIMEOUT 200
,
#include <PubSubClient.h>
void setup() {
...
  boolean res = mqttClient.setBufferSize(50*1024); // ok for 640*480
  if (res) Serial.println("Buffer resized."); else Serial.println("Buffer resizing failed");
...
}

我正在使用50kB缓冲区,它工作得很好,没有尝试超出此范围,它也应该与100kB一起工作。

按照通常的方式调整缓冲区发布的大小之后。

顺便说一句,setBufferSize函数是最近才添加的IIRC。

,

我遇到了同样的问题,我发现 PubSubClient 的 bufferSize 被定义为 uint16_t

https://github.com/knolleary/pubsubclient/blob/v2.8/src/PubSubClient.h#L92

因此,我们不能将缓冲区大小扩展到 64 kB 以上,也不能发布大型负载。

Michael's comment 可能会对您有所帮助。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...