ESP32 MQTT onMessage Callback never called

Hello Guys

I use an ESP32 and connect it to AWS IOT.
After connecting to Wifi and IOT I publish an empty message to the topic "$aws/things/chicken-door/shadow/name/door/get"
AWS IOT has some logic. So the empty message to this topic triggers a new message to the topic "$aws/things/chicken-door/shadow/name/door/get/accepted" containing a json document of the things state (they call it shadow).

Until here everything works fine. I see the empty message in the "get topic" and I see the json file in the "get/accepted topic".

But unfortunately the message is never received by the ESP32. the onMessage callback function is never called.

Here is my code:


#include "secrets.h"
#include <WiFiClientSecure.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include "WiFi.h"

// Topics
#define AWS_IOT_PUBLISH_TOPIC   "$aws/things/chicken-door/shadow/name/door/get"
#define AWS_IOT_SUBSCRIBE_TOPIC "$aws/things/chicken-door/shadow/name/door/get/accepted"

int msgReceived = 0;
String rcvdPayload;
char sndPayloadOff[512];
char sndPayloadOn[512];

WiFiClientSecure net = WiFiClientSecure();
MQTTClient client;

void connectAWS()
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.println("");
  Serial.println("###################### Starting Execution ########################");
  Serial.println("Connecting to Wi-Fi");

  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }

  // Configure WiFiClientSecure to use the AWS IoT device credentials
  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);

  // Connect to the MQTT broker on the AWS endpoint
  client.begin(AWS_IOT_ENDPOINT, 8883, net);

  // Create a message handler
  client.onMessage(messageHandler);

  Serial.println("Connecting to AWS IOT");

  while (!client.connect(THINGNAME)) {
    Serial.print(".");
    delay(100);
  }

  if(!client.connected()){
    Serial.println("AWS IoT Timeout!");
    return;
  }

  // Subscribe to a topic
  client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);

  Serial.println("AWS IoT Connected!");
}

void messageHandler(String &topic, String &payload) {
  msgReceived = 1;
  rcvdPayload = payload;
  Serial.println("something received");
}

void setup() {
  Serial.begin(115200);
  
  connectAWS();
  
  Serial.println("Get shadow");
  client.publish(AWS_IOT_PUBLISH_TOPIC, "");
  
  Serial.println("##############################################");
}

void loop() {
   if(msgReceived == 1)
    {
//      This code will run whenever a message is received on the SUBSCRIBE_TOPIC_NAME Topic
        delay(100);
        msgReceived = 0;
        Serial.print("Received Message:");
        Serial.println(rcvdPayload);
      Serial.println("##############################################");
    }
  client.loop();
}

Thanks in advance for looking into this.

What MQTT client are you using? Most people use PubSubClient, it works well with ESP and has examples to show usage with callback.

I am currently using this client: GitHub - 256dpi/arduino-mqtt: MQTT library for Arduino as it was recomended by AWS.

So you suggest to use the PubSubClient instead?

I have basically rebuilt the solution based on an example of the PubSubClient library.. (example used: ESP-MQTT-AWS-IoT-Core/PubSubClient.ino at master · debsahu/ESP-MQTT-AWS-IoT-Core · GitHub)
They are not useing the shadow logic (i.e if I publish to /get, IoT will publish to /get/accepted)

What I have noticed in the meantime is that if I subscribe directly to the topic I am publishing in, the subscription works (pub and sub to i.e /update/accepted). Only when another process (in my case AWS IOT) is publishing to the topic i don't get the message (even though i see the message when debugging in the aws console). Very strange.

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <time.h>
#define emptyString String()

#include "secrets.h"

const int MQTT_PORT = 8883;
const char AWS_IOT_UPDATE[] = "$aws/things/chicken-door/shadow/name/door/update";
const char AWS_IOT_UPDATE_DELTA[] = "$aws/things/chicken-door/shadow/name/door/update/delta";
const char AWS_IOT_GET_SHADOW[] = "$aws/things/chicken-door/shadow/name/door/get";
const char AWS_IOT_SHADOW_ACCEPTED[] = "$aws/things/chicken-door/shadow/name/door/get/accepted";

WiFiClientSecure net;
PubSubClient client(net);

unsigned long lastMillis = 0;

void messageReceived(char *topic, byte *payload, unsigned int length)
{
  if (strcmp(topic,AWS_IOT_SHADOW_ACCEPTED)==0){
    Serial.printf("Received Message from topic : %s", AWS_IOT_SHADOW_ACCEPTED);
  }
  if (strcmp(topic,AWS_IOT_UPDATE_DELTA)==0){
    Serial.printf("Received Message from topic : %s", AWS_IOT_SHADOW_ACCEPTED);
  }
  Serial.print("Received [");
  Serial.print(topic);
  Serial.print("]: ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void pubSubErr(int8_t MQTTErr)
{
  if (MQTTErr == MQTT_CONNECTION_TIMEOUT)
    Serial.print("Connection tiemout");
  else if (MQTTErr == MQTT_CONNECTION_LOST)
    Serial.print("Connection lost");
  else if (MQTTErr == MQTT_CONNECT_FAILED)
    Serial.print("Connect failed");
  else if (MQTTErr == MQTT_DISCONNECTED)
    Serial.print("Disconnected");
  else if (MQTTErr == MQTT_CONNECTED)
    Serial.print("Connected");
  else if (MQTTErr == MQTT_CONNECT_BAD_PROTOCOL)
    Serial.print("Connect bad protocol");
  else if (MQTTErr == MQTT_CONNECT_BAD_CLIENT_ID)
    Serial.print("Connect bad Client-ID");
  else if (MQTTErr == MQTT_CONNECT_UNAVAILABLE)
    Serial.print("Connect unavailable");
  else if (MQTTErr == MQTT_CONNECT_BAD_CREDENTIALS)
    Serial.print("Connect bad credentials");
  else if (MQTTErr == MQTT_CONNECT_UNAUTHORIZED)
    Serial.print("Connect unauthorized");
}

void connectToMqtt(bool nonBlocking = false)
{
  Serial.print("MQTT connecting ");
  while (!client.connected())
  {
    if (client.connect(THINGNAME))
    {
      if (!client.subscribe(AWS_IOT_SHADOW_ACCEPTED))
        pubSubErr(client.state());
      if (!client.subscribe(AWS_IOT_UPDATE_DELTA))
        pubSubErr(client.state());
      Serial.println("connected!");
    }
    else
    {
      Serial.print("failed, reason -> ");
      pubSubErr(client.state());
      if (!nonBlocking)
      {
        Serial.println(" < try again in 5 seconds");
        delay(5000);
      }
      else
      {
        Serial.println(" <");
      }
    }
    if (nonBlocking)
      break;
  }
}

void connectToWiFi(String init_str)
{
  if (init_str != emptyString)
    Serial.print(init_str);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(1000);
  }
  if (init_str != emptyString)
    Serial.println("ok!");
}

void checkWiFiThenMQTT(void)
{
  connectToWiFi("Checking WiFi");
  connectToMqtt();
}

unsigned long previousMillis = 0;
const long interval = 5000;

void checkWiFiThenMQTTNonBlocking(void)
{
  connectToWiFi(emptyString);
  if (millis() - previousMillis >= interval && !client.connected()) {
    previousMillis = millis();
    connectToMqtt(true);
  }
}

void checkWiFiThenReboot(void)
{
  connectToWiFi("Checking WiFi");
  Serial.print("Rebooting");
  ESP.restart();
}

void sendData(String value)
{
  DynamicJsonDocument jsonBuffer(JSON_OBJECT_SIZE(3) + 100);
  JsonObject root = jsonBuffer.to<JsonObject>();
  JsonObject state = root.createNestedObject("state");
  JsonObject state_reported = state.createNestedObject("reported");
  state_reported["value"] = value;
  Serial.printf("Sending  [%s]: ", AWS_IOT_UPDATE);
  serializeJson(root, Serial);
  Serial.println();
  char shadow[measureJson(root) + 1];
  serializeJson(root, shadow, sizeof(shadow));
  if (!client.publish(AWS_IOT_UPDATE, shadow, false))
    pubSubErr(client.state());
}

void getShadow(void)
{
  Serial.printf("Requesting Shadow [%s]: ", AWS_IOT_GET_SHADOW);
  if (!client.publish(AWS_IOT_GET_SHADOW, "", false))
    pubSubErr(client.state());
}

void setup()
{
  Serial.begin(115200);
  delay(5000);
  Serial.println();
  Serial.println();
#ifdef ESP32
  WiFi.setHostname(THINGNAME);
#else
  WiFi.hostname(THINGNAME);
#endif
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  connectToWiFi(String("Attempting to connect to SSID: ") + String(WIFI_SSID));

  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);

  client.setServer(AWS_IOT_ENDPOINT, MQTT_PORT);
  client.setCallback(messageReceived);

  connectToMqtt();
  getShadow();
}

void loop()
{
  if (!client.connected())
  {
    checkWiFiThenMQTT();
  }
  else
  {
    client.loop();
    if (millis() - lastMillis > 5000)
    {
      lastMillis = millis();
      sendData("closed");
    }
  }
}

I do not use AWS but instead of subscribing to AWS_IOT_SHADOW_ACCEPTED and AWS_IOT_UPDATE_DELTA what do you get in the serial monitor if you subscribe to just "$aws/things/chicken-door/shadow/name/door/#". The # will match anything that is returned so may help.

Is this the example you followed on aws?

That is exactly the tutorial i followed at first. Now i implemented the solution based on PubSubClient. For this i used this as a base: ESP-MQTT-AWS-IoT-Core/PubSubClient.ino at master · debsahu/ESP-MQTT-AWS-IoT-Core · GitHub

If I subscribe to /# I still get only the messages I publish in the loop (via sendData()). Eventhough on AWS I see everything else.

I also tested with MQTT Explorer using the same credentials I use on the ESP32 (cert and key). Everything works as expected there. Therefor I would think the issue has to be in the implementation on the ESP32...

Any ideas?

Does the example sketch work without alteration (apart from adding secret.h details) or does this also fail?
From your description it does seem there is some problem with the certificate/secure connection on the ESP and AWS is rejecting/ignoring it.
The example sketch implement pubSubErr() that may help in determining the cause of the connection issue, what do you see in the Serial monitor?

The example sketch works (sending and subscribing to the same topic).

I did log if the wifi connection fails. And it looks like the wifi connection is lost everytime i send data to a topic that I am not explicitly subsribed to.
COM output:

Attempting to connect to SSID: dehei.local...ok!
MQTT connecting connected!
Requesting Shadow [$aws/things/chicken-door/shadow/name/door/get]: Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Checking WiFiok!
MQTT connecting connected!
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Connection lostChecking WiFiok!
MQTT connecting connected!
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Connection lostChecking WiFiok!
MQTT connecting connected!
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Connection lostChecking WiFiok!
MQTT connecting connected!
Checking WiFiok!
MQTT connecting connected!
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Checking WiFiok!
MQTT connecting connected!
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Connection lostChecking WiFiok!
MQTT connecting connected!
Checking WiFiok!
MQTT connecting connected!
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Connection lostChecking WiFiok!
MQTT connecting connected!
Checking WiFiok!
MQTT connecting connected!
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Sending test to $aws/things/chicken-door/shadow/name/door/get/accepted: 
Connection lostChecking WiFiok!

The current code:

#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <time.h>
#define emptyString String()

#include "secrets.h"

const int MQTT_PORT = 8883;
const char AWS_IOT_UPDATE[] = "$aws/things/chicken-door/shadow/name/door/update";
const char AWS_IOT_UPDATE_DELTA[] = "$aws/things/chicken-door/shadow/name/door/update/delta";
const char AWS_IOT_GET_SHADOW[] = "$aws/things/chicken-door/shadow/name/door/get";
const char AWS_IOT_SHADOW_ACCEPTED[] = "$aws/things/chicken-door/shadow/name/door/get/accepted";

WiFiClientSecure net;
PubSubClient client(net);

unsigned long lastMillis = 0;

void messageReceived(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Received [");
  Serial.print(topic);
  Serial.print("]: ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void pubSubErr(int8_t MQTTErr)
{
  if (MQTTErr == MQTT_CONNECTION_TIMEOUT)
    Serial.print("Connection tiemout");
  else if (MQTTErr == MQTT_CONNECTION_LOST)
    Serial.print("Connection lost");
  else if (MQTTErr == MQTT_CONNECT_FAILED)
    Serial.print("Connect failed");
  else if (MQTTErr == MQTT_DISCONNECTED)
    Serial.print("Disconnected");
  else if (MQTTErr == MQTT_CONNECTED)
    Serial.print("Connected");
  else if (MQTTErr == MQTT_CONNECT_BAD_PROTOCOL)
    Serial.print("Connect bad protocol");
  else if (MQTTErr == MQTT_CONNECT_BAD_CLIENT_ID)
    Serial.print("Connect bad Client-ID");
  else if (MQTTErr == MQTT_CONNECT_UNAVAILABLE)
    Serial.print("Connect unavailable");
  else if (MQTTErr == MQTT_CONNECT_BAD_CREDENTIALS)
    Serial.print("Connect bad credentials");
  else if (MQTTErr == MQTT_CONNECT_UNAUTHORIZED)
    Serial.print("Connect unauthorized");
}

void connectToMqtt(bool nonBlocking = false)
{
  Serial.print("MQTT connecting ");
  while (!client.connected())
  {
    if (client.connect(THINGNAME))
    {
//      if (!client.subscribe(AWS_IOT_SHADOW_ACCEPTED))
//        pubSubErr(client.state());
//      if (!client.subscribe(AWS_IOT_UPDATE_DELTA))
//        pubSubErr(client.state());
      if (!client.subscribe("$aws/things/chicken-door/shadow/name/door/#"))
        pubSubErr(client.state());
      Serial.println("connected!");
    }
    else
    {
      Serial.print("failed, reason -> ");
      pubSubErr(client.state());
      if (!nonBlocking)
      {
        Serial.println(" < try again in 5 seconds");
        delay(5000);
      }
      else
      {
        Serial.println(" <");
      }
    }
    if (nonBlocking)
      break;
  }
}

void connectToWiFi(String init_str)
{
  if (init_str != emptyString)
    Serial.print(init_str);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(1000);
  }
  if (init_str != emptyString)
    Serial.println("ok!");
}

void checkWiFiThenMQTT(void)
{
  connectToWiFi("Checking WiFi");
  connectToMqtt();
}

unsigned long previousMillis = 0;
const long interval = 5000;

void checkWiFiThenMQTTNonBlocking(void)
{
  connectToWiFi(emptyString);
  if (millis() - previousMillis >= interval && !client.connected()) {
    previousMillis = millis();
    connectToMqtt(true);
  }
}

void checkWiFiThenReboot(void)
{
  connectToWiFi("Checking WiFi");
  Serial.print("Rebooting");
  ESP.restart();
}

void sendData(String value) 
{
  DynamicJsonDocument jsonBuffer(JSON_OBJECT_SIZE(3) + 100);
  JsonObject root = jsonBuffer.to<JsonObject>();
  JsonObject state = root.createNestedObject("state");
  JsonObject state_reported = state.createNestedObject("reported");
  state_reported["value"] = value;
  Serial.printf("Sending test to %s: ", AWS_IOT_SHADOW_ACCEPTED);
  //serializeJson(root, Serial);
  Serial.println();
  char shadow[measureJson(root) + 1];
  serializeJson(root, shadow, sizeof(shadow));
  if (!client.publish(AWS_IOT_SHADOW_ACCEPTED, "test", false))
    pubSubErr(client.state());
}

void getShadow(void)
{
  Serial.printf("Requesting Shadow [%s]: ", AWS_IOT_GET_SHADOW);
  if (!client.publish(AWS_IOT_GET_SHADOW, "", false))
    pubSubErr(client.state());
}

void setup()
{
  Serial.begin(115200);
  delay(5000);
  Serial.println();
  Serial.println();

  WiFi.setHostname(THINGNAME);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  connectToWiFi(String("Attempting to connect to SSID: ") + String(WIFI_SSID));

  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);

  client.setServer(AWS_IOT_ENDPOINT, MQTT_PORT);
  client.setCallback(messageReceived);

  connectToMqtt();
  getShadow();
}

void loop()
{
  if (!client.connected())
  {
    checkWiFiThenMQTT();
  }
  else
  {
    client.loop();
    if (millis() - lastMillis > 5000)
    {
      lastMillis = millis();
      sendData("closed");
    }
  }
}
"
type or paste code here

I tested the credentials by using them in the desktop tool "MQTT Explorer". There I can publish to the topics and also receive the updates in the get/accepted topic

1 Like

Trying to compare the working example and your code and the main thing that stands out is the differences in sendData()
The example packs the message into a JSON object that it published to "$aws/things/" THINGNAME "/shadow/update".
I don't know if AWS expects the data in JSON format or if this is just for the end device that subscribes to the topic.
Your code does not put the message into a JSON object (and I suspect you don't need to) and publishes the message to "$aws/things/chicken-door/shadow/name/door/get/accepted" but I suspect it should be published to "$aws/things/chicken-door/shadow/name/door/update"

1 Like

AWS does not expect json. I tested iz with MQTT Broker. Everything works as expected there.

I think the problem is, that the esp is loosing/terminating the connection after sending.

Did you try altering sendData() to publish to $aws/things/chicken-door/shadow/name/door/update instead of $aws/things/chicken-door/shadow/name/door/get/accepted

What happens if you publish to $aws/things/chicken-door/shadow/name/door/get/accepted using MQTT Broker. Does this cause AWS to terminate the connection?

1 Like

you are right!

when i send "test" to the door/update topic i get the following output:

Attempting to connect to SSID: dehei.local...ok!
MQTT connecting connected!
Requesting Shadow [$aws/things/chicken-door/shadow/name/door/get]: Sending test to $aws/things/chicken-door/shadow/name/door/update: 
Sending test to $aws/things/chicken-door/shadow/name/door/update: 
Received [$aws/things/chicken-door/shadow/name/door/update]: test
Received [$aws/things/chicken-door/shadow/name/door/update/rejected]: {"code":400,"message":"Payload contains invalid json"}
Sending test to $aws/things/chicken-door/shadow/name/door/update: 
Received [$aws/things/chicken-door/shadow/name/door/update]: test
Received [$aws/things/chicken-door/shadow/name/door/update/rejected]: {"code":400,"message":"Payload contains invalid json"}

So the payload is received but not accepted by AWS IOT.. Therefor I get an error message in the /update/rejected topic

I changed to code to send a valid json.. then I get the follwing ouput:

Attempting to connect to SSID: dehei.local...ok!
MQTT connecting connected!
Requesting Shadow [$aws/things/chicken-door/shadow/name/door/get]: {"state":{"reported":{"value":"closed"}}}
Sending {"state":{"reported":{"value":"closed"}}} to $aws/things/chicken-door/shadow/name/door/update: Received [$aws/things/chicken-door/shadow/name/door/get]: 
Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"closed"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"closed"}},"metadata":{"reported":{"value":{"timestamp":1638433784}}},"version":139,"timestamp":1638433784}
{"state":{"reported":{"value":"closed"}}}
Sending {"state":{"reported":{"value":"closed"}}} to $aws/things/chicken-door/shadow/name/door/update: Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"closed"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"closed"}},"metadata":{"reported":{"value":{"timestamp":1638433789}}},"version":140,"timestamp":1638433789}
{"state":{"reported":{"value":"closed"}}}

This is great. The only thing that is still not working is to get the current state in the setup function.

When testing this in mqtt broker it works. But as we see in the ouptut I never receive a message on any topic after requesting the shadow:

Requesting Shadow [$aws/things/chicken-door/shadow/name/door/get]: {"state":{"reported":{"value":"closed"}}}
Sending [......]

I added a delay between the subscritions and the shadow request but still no luck:

  connectToMqtt();
  delay(2000);
  getShadow();

Matching the sketch file to the JSON output list you show above and you do seem to be getting door state in Setup when getShadow() is called...
Requesting Shadow [$aws/things/chicken-door/shadow/name/door/get]: {"state":{"reported":{"value":"closed"}}}
But I cannot figure out where this (the bold bit) is coming from, it cannot be messageReceived() as this would start with Received [ if it did.

EDIT:
I still don't know where it arrives in the sketch but this outlines what and where the response is comming from for the /get.

I found the line that prints the bold bit. It is part of the sendData function. So has nothing to do with the request:

serializeJson(root, Serial);

I commented this line out and also alternate between state "open" and "close" to see if I get updates in the "update/delta".

void loop()
{
  if (!client.connected())
  {
    checkWiFiThenMQTT();
  }
  else
  {
    client.loop();
    if (millis() - lastMillis > 5000)
    {
      lastMillis = millis();
      sendData("closed");
      delay(2000);
      sendData("open");
    }
  }
}

I get the following output:

Attempting to connect to SSID: dehei.local...ok!
MQTT connecting connected!
Requesting Shadow [$aws/things/chicken-door/shadow/name/door/get]: 
Sending {"state":{"reported":{"value":"closed"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Sending {"state":{"reported":{"value":"open"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"closed"}},"metadata":{"reported":{"value":{"timestamp":1638440442}}},"version":628,"timestamp":1638440442}
Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"open"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"open"}},"metadata":{"reported":{"value":{"timestamp":1638440444}}},"version":629,"timestamp":1638440444}
Sending {"state":{"reported":{"value":"closed"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Sending {"state":{"reported":{"value":"open"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"closed"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"closed"}},"metadata":{"reported":{"value":{"timestamp":1638440447}}},"version":630,"timestamp":1638440447}
Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"open"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"open"}},"metadata":{"reported":{"value":{"timestamp":1638440449}}},"version":631,"timestamp":1638440449}
Sending {"state":{"reported":{"value":"closed"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Sending {"state":{"reported":{"value":"open"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"closed"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"closed"}},"metadata":{"reported":{"value":{"timestamp":1638440452}}},"version":632,"timestamp":1638440452}
Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"open"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"open"}},"metadata":{"reported":{"value":{"timestamp":1638440454}}},"version":633,"timestamp":1638440454}

What I take from this is:

  1. get shadow does not work
  2. update/delta does not work (Device Shadow MQTT topics - AWS IoT Core)
  3. update/accepted works as expected

What do you get if you widen the subscribed topic?
Currently it is...
if (!client.subscribe("$aws/things/chicken-door/shadow/name/door/#"));
but do you get more if it is changed to...
if (!client.subscribe("$aws/things/chicken-door/shadow/#"));
Maybe it is not coming in exactly as/where you hoped.

Another thing to try is commenting out the sendData() lines in loop and see if you do eventually get a reply to the getShadow() in setup. The pubsub library may need to do a few client.loop() calls before the AWS reply comes in and maybe the sendData() is stopping the reply.

Subscribing to the shadow/# changes nothing to the output:

Attempting to connect to SSID: dehei.local...ok!
MQTT connecting connected!
Requesting Shadow [$aws/things/chicken-door/shadow/name/door/get]: 
Sending {"state":{"reported":{"value":"closed"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Sending {"state":{"reported":{"value":"open"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"closed"}},"metadata":{"reported":{"value":{"timestamp":1638447426}}},"version":870,"timestamp":1638447426}
Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"open"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"open"}},"metadata":{"reported":{"value":{"timestamp":1638447428}}},"version":871,"timestamp":1638447428}
Sending {"state":{"reported":{"value":"closed"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Sending {"state":{"reported":{"value":"open"}}} to $aws/things/chicken-door/shadow/name/door/update: 
Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"closed"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"closed"}},"metadata":{"reported":{"value":{"timestamp":1638447431}}},"version":872,"timestamp":1638447431}
Received [$aws/things/chicken-door/shadow/name/door/update]: {"state":{"reported":{"value":"open"}}}
Received [$aws/things/chicken-door/shadow/name/door/update/accepted]: {"state":{"reported":{"value":"open"}},"metadata":{"reported":{"value":{"timestamp":1638447433}}},"version":873,"timestamp":1638447433}

Empty loop (just printing millis()) results in this outpt:

Attempting to connect to SSID: dehei.local.....ok!
MQTT connecting connected!
Requesting Shadow [$aws/things/chicken-door/shadow/name/door/get]: 
12399
17400
22401
27402
32403
37404
42405

Still no shadow response.

Using MQTT Broker that is subscribed to
$aws/things/chicken-door/shadow/name/door/#
what does it get when you publish and empty message to
$aws/things/chicken-door/shadow/name/door/get
I'm wondering now if the returned MQTT message is to big for the default 256/128 byte pubsub buffer size.

You could try increasing the buffer size with setBufferSize() to something larger, the size would depend on how large the /get reply is.

If I publish an empty message to $aws/things/chicken-door/shadow/name/door/get I receive the following message on $aws/things/chicken-door/shadow/name/door/get/accepted:

{
  "state": {
    "desired": {
      "welcome": "aws-iot"
    },
    "reported": {
      "welcome": "aws-iot",
      "status": "off",
      "value": "closed"
    }
  },
  "metadata": {
    "desired": {
      "welcome": {
        "timestamp": 1637421413
      }
    },
    "reported": {
      "welcome": {
        "timestamp": 1637421413
      },
      "status": {
        "timestamp": 1637735730
      },
      "value": {
        "timestamp": 1638447783
      }
    }
  },
  "version": 1012,
  "timestamp": 1638793997
}

That would be more than 256 (321bytes). So I set the buffersize to 512:

void setup()
{
  Serial.begin(115200);
  delay(5000);
  Serial.println();
  Serial.println();

  WiFi.setHostname(THINGNAME);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  connectToWiFi(String("Attempting to connect to SSID: ") + String(WIFI_SSID));

  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);

  client.setServer(AWS_IOT_ENDPOINT, MQTT_PORT);
  client.setBufferSize(512);
  client.setCallback(messageReceived);

  connectToMqtt();
  getShadow();
}

Still no luck unfortunately.. here is the output:

Attempting to connect to SSID: dehei.local...ok!
MQTT connecting connected!
Requesting Shadow [$aws/things/chicken-door/shadow/name/door/get]: 
10658
15659
20660

When I copy and past the JSON reply into Notepad++ it says the length is 551 so try a bigger buffer of 1024 or 2048.

Same result for both 1024 and 2048. :S