ESP32 Freezes After 12 Hours

Good afternoon, I want to make a continuously operable gateway that measures temperature with esp32.
The device sends data via mqtt every 1.5 seconds.
Esp freezes after 12 hours or 24 hours.
I read that some users operate the device every 6-7 months without resetting, how can I operate the device for a long time without resetting it.

Note: As a workaround in the code I reset the device with MQTT, Ethernet and ESP.restart () every 12 hours.

Note1 = LEDs indicate that the system is working.
*Red lights when ethernet or mqtt cannot be connected.
*Blue indicates trying to connect to mqtt or ethernet.
*Green indicates that the system is active.
When the device was frozen, the green led was still on.

The ones i use:
Arduino IDLE == 1.8.14
ESP Library Version == 1.0.6
MQTT Library Version == 2.5.0
ESP Library Version == 2.0.9
ESP Link == Buy ESP32-WROOM-32U Wifi Bluetooth Development Module with Affordable Price - Direnc.net®

#include <UIPEthernet.h>
#include <ArduinoJson.h>
#include <MQTT.h>
#include <DHT.h>
//////////////////////// ETHERNET CONFİG //////////////////////////
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
//////////////////////// ETHERNET CONFİG //////////////////////////


//////////////////////// LED & DHT22 CONFİG //////////////////////////
byte red = 2;
byte green = 0;
byte blue = 4;
byte temp = 15;
#define DHTTYPE DHT22
DHT dht = DHT(temp, DHTTYPE);
//////////////////////// LED & DHT22 CONFİG //////////////////////////


//////////////////////// MQTT CONFİG //////////////////////////
#define mqttServer IPAddress(xxx,xxx,xx,xxx)
const char* mqttUser = "test";
const char* mqttPassword = "test";
const char* deviceId = "Ai-Sens 1";
//////////////////////// MQTT CONFİG //////////////////////////


unsigned long lastMillis = 0;
byte x;
byte y;
EthernetClient net;
MQTTClient client;


//Receives an external reset command every 12 hours
void callback(String &topic, String &payload) { 
  if (payload == "1")
  {
    ESP.restart();
    }
  
}
void setup_eth() {
  delay(10);
  digitalWrite(blue, HIGH); // turn the LED on
  //Serial.print("connecting ethernet...");
  if (Ethernet.begin(mac) == 0) {
    // Serial.println("Failed to configure Ethernet using DHCP");
    for (;;)
      ;
  }
  Ethernet.begin(mac, Ethernet.localIP());
  digitalWrite(blue, LOW);
}

void connect() {
  //Serial.print("connecting mqtt...");
  digitalWrite(blue, HIGH);
  while (!client.connected()) {

    if (client.connect(deviceId, mqttUser, mqttPassword)) {
      // Subscribe

      //client.subscribe("esp/data1");
    } else {
      delay(500);
    }
  }
  //Serial.println("\nconnected!");
  digitalWrite(blue, LOW);
  //client.subscribe("esp/data1");
}



void setup() {
  //Serial.begin(115200);

  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  digitalWrite(red, LOW);
  digitalWrite(green, LOW);
  digitalWrite(blue, LOW);

  dht.begin();
  setup_eth();

  client.setHost(mqttServer, 1883);
  client.setKeepAlive(90);
  client.begin(mqttServer, net);

  connect();

}

void loop() {
  client.loop();
  delay(10);
  
  client.subscribe("esp/rst");
  client.onMessage(callback);
  
  StaticJsonBuffer<300> JSON;
  JsonObject& JSONencoder = JSON.createObject();

  if (millis() - lastMillis > 1500) {
    digitalWrite(green, LOW);
    digitalWrite(blue, LOW);
    digitalWrite(red, LOW);
    if (!client.connected()) {
      digitalWrite(red, HIGH);
      if (y == 5) {

        //Serial.println("Reboot System Now....");
        ESP.restart();
        y = 0;
      }
      y++;
      connect();
    }

    if (Ethernet.linkStatus() == LinkON) {
      // Serial.println("On");
      digitalWrite(green, HIGH);
    }
    else {
      digitalWrite(red, HIGH);

      if (x == 5) {
        //Serial.println("Reboot System Now....");
        ESP.restart();
        x = 0;
      }
      x++;
    }
    lastMillis = millis();
    //Serial.println(Ethernet.maintain ());

    JSONencoder["DEVICE = "] = deviceId;
    JSONencoder["USER = "] = mqttUser;
    JSONencoder["TEMP = "] = dht.readTemperature();
    JSONencoder["HUMD = "] = dht.readHumidity();
    JSONencoder["STATE = "] = true;

    char JSONmessageBuffer[100];
    JSONencoder.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));

    client.publish("esp/data1", JSONmessageBuffer);
  }
}

May be you want to check the connection before sending?

Also on this

Have you double checked if 100 is enough? (Would not crash though)

First of all, thank you for interest.
My connect () function, which controls the incoming connection, resets the device in case of a problem on the mqqt side after 5 repetitions.
What I am doubting is the RAM filling and locking of the device over time, what do you think about this issue.
Note: I have run wi-fi or ethernet using various MQTT libraries. My device (including PubClient) lasts a maximum of 48 hours.

I had a ESP32 device in a somehow "locked state" after some hours because the supply-voltage on the Vin-Pin was 4,2V.

After carefully adjusting it to 5V it runs flawlessly.

Your code uses variable type String.
Variable type String causes memory-problems.
At least when defined globally.
Yours are parameters of the callback-function you are using.
You could change this to use array of char or PString or something like that.

Mabye then some kind of type-casting is needed.

What looks odd to me is

  client.onMessage(callback);

but the definition of the callback-function is

void callback(String &topic, String &payload) { 

The definition has parameters your calling has not.
I'm not familiar with registering callbackfunctions on server-events. So I don not really know if this might be causing the problems.

You can use

ESP.getFreeHeap();

to log if available RAM is decreasing over time.

best regards Stefan

First of all, thank you for interest.
I reshaped my code by paying attention to what you said. This is the final version.
When I examined the incoming data, I saw that the communication was interrupted between 4 and 9 hours.
The problem may be node-red or "mqtt broker". What software can I use as a gateway?

#include <UIPEthernet.h>
#include <ArduinoJson.h>
#include <MQTT.h>
#include <DHT.h>
//////////////////////// ETHERNET CONFİG //////////////////////////
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
//////////////////////// ETHERNET CONFİG //////////////////////////


//////////////////////// LED & DHT22 CONFİG //////////////////////////
byte red = 2;
byte green = 0;
byte blue = 4;
byte temp = 15;
#define DHTTYPE DHT22
DHT dht = DHT(temp, DHTTYPE);
//////////////////////// LED & DHT22 CONFİG //////////////////////////


//////////////////////// MQTT CONFİG //////////////////////////
#define mqttServer IPAddress(xxx,xxx,xx,xxx)
//////////////////////// MQTT CONFİG //////////////////////////


unsigned long lastMillis = 0;

byte x;
byte y;
EthernetClient net;
MQTTClient client;


void callback(String &topic, String &payload) {
  if (payload == "1")
  {
    ESP.restart();
  }

}
void setup_eth() {
  delay(100);
  digitalWrite(blue, HIGH); // turn the LED on
  //Serial.print("connecting ethernet...");
  if (Ethernet.begin(mac) == 0) {
    //Serial.println("Failed to configure Ethernet using DHCP");
    for (;;)
      ;
  }
  Ethernet.begin(mac, Ethernet.localIP());
  digitalWrite(blue, LOW);

}

void connect() {
  //Serial.print("connecting mqtt...");
  digitalWrite(blue, HIGH);

  while (!client.connected()) {
    if (client.connect("Ai-Sens 1", "test", "test")) {
      // Subscribe

      //client.subscribe("esp/data1");
    } else {

      delay(500);
    }

  }
  //Serial.println("\nconnected!");
  digitalWrite(blue, LOW);
  client.subscribe("esp/rst");
}



void setup() {
  //Serial.begin(115200);

  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  digitalWrite(red, LOW);
  digitalWrite(green, LOW);
  digitalWrite(blue, LOW);

  dht.begin();
  setup_eth();

  client.setHost(mqttServer, 1883);
  client.setKeepAlive(90);
  client.begin(mqttServer, net);
  client.onMessage(callback);

  connect();

}

void loop() {
  StaticJsonBuffer<300> JSON;
  JsonObject& JSONencoder = JSON.createObject();

  client.loop();
  delay(100);



  if (millis() - lastMillis > 2000) {
    digitalWrite(green, LOW);
    digitalWrite(blue, LOW);
    digitalWrite(red, LOW);
    if (!client.connected()) {
      digitalWrite(red, HIGH);
      if (y == 5) {

        //Serial.println("Reboot System Now....");
        ESP.restart();
        y = 0;
      }
      y++;
      connect();
    }

    if (Ethernet.linkStatus() == LinkON) {
      //Serial.println("On");
      digitalWrite(green, HIGH);
    }
    else {
      digitalWrite(red, HIGH);

      if (x == 5) {
        //Serial.println("Reboot System Now....");
        ESP.restart();
        x = 0;
      }
      x++;
    }
    lastMillis = millis();
    //Serial.println(Ethernet.maintain ());

    JSONencoder["DEVICE = "] = "Ai-Sens 1";
    JSONencoder["USER = "] = "Test";
    JSONencoder["TEMP = "] = dht.readTemperature();
    JSONencoder["HUMD = "] = dht.readHumidity();
    JSONencoder["STATE = "] = true;

    char JSONmessageBuffer[100];
    JSONencoder.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));

    client.publish("esp/data1", JSONmessageBuffer);

  }
}

Since you are running only a single task on the ESP32 the delay(100) will interfere with the response of the callback function.

Next, where are the print statements that you are using to determine where/when the ESP32 is locking up?

void loop() {
  StaticJsonBuffer<300> JSON;
Serial.println("a");
  JsonObject& JSONencoder = JSON.createObject();
Serial.println("b");

  client.loop();
Serial.println("c");
  //delay(100);



  if (millis() - lastMillis > 2000) {
    digitalWrite(green, LOW);
    digitalWrite(blue, LOW);
    digitalWrite(red, LOW);
    if (!client.connected()) {
      digitalWrite(red, HIGH);
      if (y == 5) {

        //Serial.println("Reboot System Now....");
        ESP.restart();
        y = 0;
      }
      y++;
      connect();
    }
Serial.println("e");
    if (Ethernet.linkStatus() == LinkON) {
      //Serial.println("On");
Serial.println("f");
      digitalWrite(green, HIGH);
    }
    else {
Serial.println("g");
      digitalWrite(red, HIGH);

      if (x == 5) {
        //Serial.println("Reboot System Now....");
        ESP.restart();
        x = 0;
      }
      x++;
    }
Serial.println("h");
    lastMillis = millis();
Serial.println("i");
    //Serial.println(Ethernet.maintain ());

    JSONencoder["DEVICE = "] = "Ai-Sens 1";
Serial.println("j");
    JSONencoder["USER = "] = "Test";
Serial.println("k");
    JSONencoder["TEMP = "] = dht.readTemperature();
Serial.println("l");
    JSONencoder["HUMD = "] = dht.readHumidity();
Serial.println("m");
    JSONencoder["STATE = "] = true;
Serial.println("n");
    char JSONmessageBuffer[100];
Serial.println("o");
    JSONencoder.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
Serial.println("p");
    client.publish("esp/data1", JSONmessageBuffer);
Serial.println("q");
  }
}

Like how I added serial prints to the above code. Now you'll look at the monitor and see something useful like, for instance, the last print out is always a 'z' you'll come to understand where/when the issue is happening and go from there.

Also, from my experiences with a DHT, I do not trust them to return good data every time it is read. When I used a DHT, I would at least check for NaN's. I imagine putting a NaN into a JSON string and then sending it to the MQTT Broker is not a pleasant experience.

Also, I have recommended to you to use the MQTT keepalive setting for reliable MQTT connections.

If you think the ram is filling up then have the loop() print the free ram on each loop as well as the letters.