256dpi / arduino-mqtt

MQTT library for Arduino
MIT License
1.02k stars 236 forks source link

Can't connect back to AWS #331

Open RaymondReddingt0n opened 2 months ago

RaymondReddingt0n commented 2 months ago
void fetchDeviceData() {
  WiFiSSLClient ssl_client;

  // Define GET url
  const char* serverName = "xd6v8fwy40.execute-api.eu-north-1.amazonaws.com";
  const char* resourcePath = "/prod?thermostat_id=";

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\nStarting connection to server...");

    if (ssl_client.connect(serverName, 443)) {
      Serial.println("Connected to server");

      String connectionUrl = "GET /prod/thermostat?thermostat_id=" + arduino_id + " HTTP/1.1";

      // Send HTTP request
      ssl_client.println(connectionUrl);
      ssl_client.println("Host: xd6v8fwy40.execute-api.eu-north-1.amazonaws.com");
      ssl_client.println("Connection: close");
      ssl_client.println();

      // Wait for the server to respond
      String responseBody = "";
      bool bodyStarted = false;

      // Wait for the server to respond
      while (ssl_client.connected() || ssl_client.available()) {
        String line = ssl_client.readStringUntil('\n');
        if (!bodyStarted) {
          // Detect the end of headers and start of the body
          if (line == "\r" || line == "") {
            bodyStarted = true;
            continue;
          }
        }
        if (bodyStarted) {
          responseBody += line;
        }
      }

      Serial.println("Response:");
      Serial.println(responseBody);

      // Parse JSON
      StaticJsonDocument<1024> doc;
      DeserializationError error = deserializeJson(doc, responseBody);

      if (error) {
        Serial.print("JSON deserialization failed: ");
        Serial.println(error.c_str());
        return;
      }

      compressorOn = doc["compressor_status"];
      defrostOn = doc["defrosting_status"];
      fansOn = doc["fans_status"];
      manualMode = doc["manualMode"];
      delay_time = doc["delay_time"];
      safeDelta = doc["safe_delta"];
      tempD_lim_inf = doc["temp_defrosting_lower"];
      tempD_lim_sup = doc["temp_defrosting_upper"];
      tempT = doc["temp_t"];

      ssl_client.stop();  // Close the connection
    } else {
      Serial.println("Connection to server failed");
    }
  } else {
    Serial.println("WiFi not connected");
  }
}

void sendDeviceData() {
  // Connection to AWS
  WiFiClient wifi;
  ESP_SSLClient net;

  timeClient.update();

  // Get the current epoch time in UTC
  unsigned long utcTime = timeClient.getEpochTime();

  // Print the UTC time in Unix format
  Serial.print("Current UTC time in Unix format: ");
  Serial.println(utcTime);

  net.setX509Time(utcTime);

  // Configure WiFiClientSecure to use the AWS certificates we generated
  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);

  net.setBufferSizes(1024 /* rx */, 512 /* tx */);

  net.setDebugLevel(0);
  net.setClient(&wifi);

  // Connect to the MQTT broker on the AWS endpoint we defined earlier
  client.begin(AWS_IOT_ENDPOINT, 8883, net);
  client.setKeepAlive(delay_time / 1000 + 2);
  client.onMessage(messageReceived);

  // Try to connect to AWS and count how many times we retried.
  int retries = 0;
  Serial.println("Connecting to AWS IOT...");

  Serial.println(client.connected());

  while (!client.connect(DEVICE_NAME)) {
    Serial.print(".");
    delay(10000);
  }

  Serial.println("\nconnected!");
  Serial.println(client.connected());

  // If we land here, we have successfully connected to AWS!
  // And we can subscribe to topics and send messages.

  timeClient.update();

  // Get the current epoch time in UTC
  utcTime = timeClient.getEpochTime();

  // Convert epoch time to readable date and time
  int currentYear = 1970;
  unsigned long secondsInYear = 31536000;
  while (utcTime >= secondsInYear) {
    utcTime -= secondsInYear;
    currentYear++;
    if (currentYear % 4 == 0) {
      secondsInYear = 31622400; // Leap year
    } else {
      secondsInYear = 31536000;
    }
  }

  // Extract month, day, hour, minute, and second
  int month = 1;
  unsigned long secondsInMonth[] = {2678400, 2419200, 2678400, 2592000, 2678400, 2592000, 2678400, 2678400, 2592000, 2678400, 2592000, 2678400};
  if (currentYear % 4 == 0) {
    secondsInMonth[1] = 2505600; // February in a leap year
  }
  while (utcTime >= secondsInMonth[month - 1]) {
    utcTime -= secondsInMonth[month - 1];
    month++;
  }
  int day = utcTime / 86400 + 1;
  int hour = (utcTime % 86400) / 3600;
  int minute = (utcTime % 3600) / 60;
  int second = utcTime % 60;

  // Format timestamp as "DD/MM/YYYY HH:MM:SS"
  char timestamp[20];
  sprintf(timestamp, "%02d/%02d/%04d %02d:%02d:%02d", day, month, currentYear, hour, minute, second);

  // Print the UTC time in Unix format
  Serial.print("Current UTC time in Unix format: ");
  Serial.println(utcTime);

  Serial.println("Sending device data to AWS...");

  // Create a JSON object to hold all the data
  DynamicJsonDocument dataDoc(1024); // Adjust size as needed
  dataDoc["thermostat_id"] = arduino_id;
  dataDoc["timestamp"] = timestamp;
  dataDoc["temp_a"] = String(tempA);
  dataDoc["temp_d"] = String(tempD);
  dataDoc["temp_f"] = String(tempF);
  dataDoc["temp_r"] = String(tempR);
  dataDoc["compressor_status"] = compressorOn;
  dataDoc["fans_status"] = fansOn;
  dataDoc["defrosting_status"] = defrostOn;
  dataDoc["temp_setpoint"] = String(tempS);
  dataDoc["temp_defrosting_lower"] = String(tempD_lim_inf);
  dataDoc["temp_defrosting_upper"] = String(tempD_lim_sup);
  dataDoc["safe_delta"] = String(safeDelta);
  dataDoc["delay_time"] = String(delay_time);
  dataDoc["message"] = message;
  dataDoc["alarm"] = alarm;
  dataDoc["manualMode"] = manualMode;
  dataDoc["temp_t"] = tempT;

  // Serialize JSON object to string
  String jsonData;
  serializeJson(dataDoc, jsonData);

  // Publish temperature data to AWS IoT
  if (client.publish(AWS_IOT_TOPIC_1, jsonData)) {
    Serial.println("Logs data published to AWS IoT.");
  } else {
    Serial.println("Failed to publish logs data.");
  }

  Serial.println("Json temp logs: ");
  Serial.println(jsonData);

  client.disconnect();
  net.stop();
}

In these two functions, the first one is to handle a GET request and the second one is to establish an MQTT connection to AWS and send data to it. They are called in order one after the other on the void loop() infinitely. The loop order is supposed to happen as follows:

However, in reality, only the first three work.

And then on the next sendDeviceData(), on the following line, I get the following error:

while (!client.connect(DEVICE_NAME)) {

17:07:37.010 -> Firmware name: "C:\Users\myname~1\AppData\Local\Temp\arduino_build_443729/aws_database.ino", compiled on: Aug 30 2024
17:07:37.151 -> Fault on interrupt or bare metal(no OS) environment
17:07:37.151 -> Error: Main stack(20007800) was overflow
17:07:37.151 -> ===== Thread stack information =====
17:07:37.293 ->   addr: 20007b00    data: 51c2bcaf
17:07:37.293 ->   addr: 20007b04    data: 0d895147
17:07:37.293 ->   addr: 20007b08    data: f64f630a
[...]
17:07:47.756 -> ====================================
17:07:47.896 -> Usage fault is caused by attempts to switch to an invalid state (e.g., ARM)
17:07:47.896 -> Show more call stack info by run: addr2line -e "C:\Users\myname~1\AppData\Local\Temp\arduino_build_443729/aws_database.ino".elf -a -f 0001633e 000160ec 0001b834 00027ef6 0001ba38 0001bde2 000240f6 0001bf96 0000a3d8 00022e78 00023c66 00005af8 0001c6ba 00006e54 0000717e 0000753a

I believe it might be due to the fact I'm using two different libraries, one for the get and the other for the send, which might be interfering with each other. These are the libraries I'm using for this portion of the code:

#include "WiFiSSLClient.h"
#include <MQTTClient.h>
#include <ESP_SSLClient.h>

I'm also using these libraries:

#include <WiFiS3.h>
#include <ArduinoJson.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <NTPClient.h>
#include "certs.h"
#include <ArduinoHttpClient.h>

One way I found to counter this issue could be closing each connection from each library, however that doesn't seem to be working unless I'm missing something.

Any help would be greatly appreciated! Thank you.

256dpi commented 2 months ago

The error Error: Main stack(20007800) was overflow indicates that the process is running out of stack space. Are you running on an RTOS?

RaymondReddingt0n commented 2 months ago

Hi, thanks for the quick response. I don't know what that is. I'm using an Arduino UNO WiFi R4, on my Windows laptop.