MQTT 在发布消息时与 AWS 断开连接

物联网 MQTT 阿杜伊诺 ESP32 aws
2021-06-15 11:04:23

请看这个 ESP32 的草图。它除了:

  1. 连接到 WiFi
  2. 连接到 AWS MQTT
  3. 订阅/get/accepted主题
  4. 每 5 秒向/get主题发布一条空消息以检索影子文件
#include <SPIFFS.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
#define ETH_PHY_POWER 12
#include <ETH.h>
#include <SSLClient.h>
#include <PubSubClient.h>

#define MQTT_PACKET_SIZE      4096
#define ID "myid"

WiFiClientSecure networkClient;
PubSubClient pubsub;

char *rootCA;
char *privateKey;
char *certificate;

unsigned long old_millis = 0;

bool readFile(const char *path, char **buffer)
{
  File file = SPIFFS.open(path);

  size_t size = file.size();
  *buffer = (char *) malloc(size + 1);

  char *p = *buffer;
  while(file.available()) *p++ = file.read();
  *p = '\0';
  return true;
}

void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Received ");
  Serial.print(length);
  Serial.print(" bytes @ ");
  Serial.println(topic);
  Serial.println((char *) payload);
}

void setup() 
{
  Serial.begin(115200);
  SPIFFS.begin();
  WiFi.mode(WIFI_STA);
  WiFi.begin("myssid", "mypassword");
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.println(".");
    delay(1000);
  }

  Serial.println(WiFi.localIP());

  char filename[64];
  readFile("/AmazonRootCA1.pem", &rootCA);
  networkClient.setCACert(rootCA);

  sprintf(filename, "/%s-cert.pem.crt", ID);
  readFile(filename, &certificate);
  networkClient.setCertificate(certificate);

  sprintf(filename, "/%s-private.pem.key", ID);
  readFile(filename, &privateKey);
  networkClient.setPrivateKey(privateKey); 

  pubsub.setServer("myendpoint-ats.iot.us-east-2.amazonaws.com", 8883);
  pubsub.setBufferSize(MQTT_PACKET_SIZE);
  pubsub.setClient(networkClient);
  pubsub.setCallback(callback);

  old_millis = millis();
}

void loop() 
{
  char topic[64];

  if (pubsub.connected())
  {
    pubsub.loop();

    if (millis() - old_millis > 5000)
    {
      sprintf(topic, "$aws/things/%s/shadow/name/module-1/get", ID);
      pubsub.publish(topic, "");
      Serial.print("Publish to ");
      Serial.println(topic);
      old_millis = millis();
    }
  }
  else
  {
    Serial.print("State ");
    Serial.println(pubsub.state());
    if (pubsub.connect(ID))
    {
      Serial.println("MQTT connected");
      sprintf(topic, "$aws/things/%s/shadow/name/module-1/get/accepted", ID);
      if (pubsub.subscribe(topic)) Serial.print("Subscribed to: ");
      else Serial.print("Error while subscribing to: ");
      Serial.println(topic);
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.println(pubsub.state());
      delay(1000);
    }  
  }
}

这里的输出:

.
.
.
09:52:35.752 -> .
09:52:36.745 -> .
09:52:37.738 -> 192.168.1.41
09:52:37.837 -> State -1
09:52:40.716 -> MQTT connected
09:52:40.716 -> Subscribed to: $aws/things/myid/shadow/name/module-1/get/accepted
09:52:42.834 -> Publish to $aws/things/myid/shadow/name/module-1/get
09:52:42.967 -> State -3
09:52:45.945 -> MQTT connected
09:52:45.945 -> Subscribed to: $aws/things/myid/shadow/name/module-1/get/accepted
09:52:47.831 -> Publish to $aws/things/myid/shadow/name/module-1/get
09:52:47.997 -> State -3
09:52:50.975 -> MQTT connected
09:52:50.975 -> Subscribed to: $aws/things/myid/shadow/name/module-1/get/accepted
09:52:52.828 -> Publish to $aws/things/myid/shadow/name/module-1/get
09:52:52.993 -> State -3

每次发布消息时,MQTT 连接都会丢失。为什么? 我的错误是什么?

1个回答

一些快速的可能性:

  1. 您实际上没有名称为“myid”的东西。
  2. 您尚未授予此客户对您订阅或发布的主题的权利。
  3. 没有具有该名称的命名阴影(尽管我认为这应该会给您一个空的阴影。)。尝试做一个看跌期权(在给予它这样做的权利之后)。

另外,默认阴影是否有效?