Muudame ESP32 töökindlamaks + lõplik ESP32 programmikood

Mis juhtub siis kui internet kaob, WiFi tugijaam hangub, server ei vasta jne? Veel olulisem, mis juhtub siis kui olukord taastub? ESP32 peab oskama reageerida ega tohi end kokku jooksutada. Samuti peab ta oskama normaalse olukorra taastumkist kontrollida ja uuesti tööle hakkama.

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Ühendus MQTT serveriga katkes! ");
  mqttClient.connect();
}

Kui ühendus MQTT-serveriga katkeb, siis alustame uuesti ühenduse loomist käsuga mqttClient.connect().

WiFi-ga on lihtsam, selle eest hoolitseb ESP32 ise püüdes ühenduse katkemisel seda taas luua.

Sarnane võiks olla ESP32 programmikood:

// Laeme vajalikud programmiteekid
#include <DHT.h>
#include <WiFi.h>
#include <WebServer.h>
#include <AsyncMqttClient.h>
#include <HTTPClient.h>

// Määrame DHT anduri klemmi ja tüübi
#define DHTPIN 4
#define DHTTYPE DHT22

// Määrame WiFi leviala nime ja parooli
#define WIFI_SSID "leviala_nimi"
#define WIFI_PASS "leviala_parool"

// Määrame MQTT serveri kasutaja, slasõna, serveri aadressi, pordi ja teema
#define MQTT_USER "rohetest1"
#define MQTT_PASS "rohetest1"
#define MQTT_SERVER "nuti.fi"
#define MQTT_PORT 1883
#define MQTT_TOPIC String("rohekool")

// Määrame intervali, mille järel mõõtmisi ja andmete edatamist teostatakse (millisekundites)
#define INTERVAL 10000

// Loome veebiserveri, DHT ja MQTT-klineid objektid
WebServer MyServer(80);
DHT dht(DHTPIN, DHTTYPE);
AsyncMqttClient mqttClient;

// Määrame muutujad intervali arvutamiseks
long newTime;
long oldTime;

// Määrame muutujad, mida kasutame veebi või MQTT kaudu edastamiseks
String TEMP = "Andur pole veel valmis!";
String HUMI = "Andur pole veel valmis!";
String NOISE = "0.0";
String PROBE = "";

// Määrame veebiserveri aadressi
String serverName = "http://192.168.0.183/test.php";

void setup() {
  // Avame ühenduse arvutiga määratud kiirusel
  Serial.begin(115200);

  // Katkestame ja unustame eelnevalt salvestatud WiFi ühenduse
  WiFi.disconnect(true);

  // Tagastame arvutile ESP32 MAC-aadressi
  Serial.println("ESP32 kliendi režiimis! \n");
  Serial.print("MAC-aadress: ");
  Serial.println(WiFi.macAddress());

  // Anname muyutuja PROBE väärtuseks MAC-aadressi (semikoolonid eemaldatud)
  uint8_t MAC_array[6];
  char MAC_char[18];
  WiFi.macAddress(MAC_array);
  for (int i = 0; i < sizeof(MAC_array); ++i){
      sprintf(MAC_char, "%s%02x", MAC_char, MAC_array[i]);
  }
  PROBE = String(MAC_char);

  // Määrame WiFi režiimi ja alustame ühenduse loomist (need jäävad meelde kuni restardini)
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  // Alsutame suhtlust DHT anduriga
  dht.begin();

  // Määrame sündmused (events) MQTT-serveri kohta
  mqttClient.onConnect(onMqttConnect); 
  mqttClient.onDisconnect(onMqttDisconnect); 
  mqttClient.onPublish(onMqttPublish); 

  // Määrame MQTT-serveri parameetrid
  mqttClient.setServer(MQTT_SERVER, MQTT_PORT);
  mqttClient.setCredentials(MQTT_USER, MQTT_PASS);

  // Määrame sündmused (events) WiFi kohta
  WiFi.onEvent(WiFiConnected, ARDUINO_EVENT_WIFI_STA_CONNECTED);
  WiFi.onEvent(WiFiDisconnected, ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
  WiFi.onEvent(WiFiGotIp, ARDUINO_EVENT_WIFI_STA_GOT_IP);

  // Määram sündmused ESP32 veebiserveri kohta
  MyServer.on("/", handle_OnConnect);

  // Käovotame ESP32 veebiserveri
  Serial.println("Käivitan veebiserveri. ");
  MyServer.begin();

  // Anname väärtused intervali arvutamiseks kasutatud muutujatele
  newTime = millis();
  oldTime = newTime;
}

// Määrame funktsiooni, mida kutsub välja WiFi sündmus
void WiFiConnected(WiFiEvent_t event, WiFiEventInfo_t info){
  Serial.println("ESP32 ühendus tugijaamaga on loodud. ");
}

// Määrame funktsiooni, mida kutsub välja WiFi sündmus
// Katkestame MQTT-klindi töö jõuga
void WiFiDisconnected(WiFiEvent_t event, WiFiEventInfo_t info){
  // Katkemise põhjused https://github.com/espressif/esp-idf/blob/master/components/esp_wifi/include/esp_wifi_types.h
  Serial.print("ESP32 ühendus tugijaamaga katkes põhjusega: ");
  Serial.println(info.wifi_sta_disconnected.reason);
  mqttClient.disconnect(true);
}

// Määrame funktsiooni, mida kutsub välja WiFi sündmus
// MQTT-klient alustab ühenduse loomist
void WiFiGotIp(WiFiEvent_t event, WiFiEventInfo_t info){
  Serial.print("ESP32 sai IP-aadressi: ");
  Serial.println(WiFi.localIP());
  mqttClient.connect();
}

// Määrame funktsiooni, mida kutsub välja ESP32 veebiserveri sündmus
// Vastame saabunud päringule
void handle_OnConnect() {
  Serial.println("Saabus veebipäring / ...");
  MyServer.send(200, "text/html", "<h1>Minu tehtud :)</h1><p>Temperatuur: "+TEMP+" &deg;C<br>&Otilde;huniiskus: "+HUMI+" %RH</p>"); 
}

// Määrame funktsiooni, mida kutsub välja MQTT sündmus
void onMqttConnect(bool sessionPresent) {
  Serial.print("Ühendus MQTT serveriga loodud: ");
  Serial.println(sessionPresent);
}

// Määrame funktsiooni, mida kutsub välja MQTT sündmus
// Anname teada katkestuse põhjusest
// MQTT-klient alustab taas ühenduse loomist
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  // Põhjused https://github.com/marvinroger/async-mqtt-client/blob/develop/src/AsyncMqttClient/DisconnectReasons.hpp
  String text; 
  switch (reason) {
    case AsyncMqttClientDisconnectReason::TCP_DISCONNECTED:
      text = "TCP_DISCONNECTED";
      break;
    case AsyncMqttClientDisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION:
      text = "MQTT_UNACCEPTABLE_PROTOCOL_VERSION";
      break;
    case AsyncMqttClientDisconnectReason::MQTT_IDENTIFIER_REJECTED:
      text = "MQTT_IDENTIFIER_REJECTED";
      break;
    case AsyncMqttClientDisconnectReason::MQTT_SERVER_UNAVAILABLE:
      text = "MQTT_SERVER_UNAVAILABLE";
      break;
    case AsyncMqttClientDisconnectReason::MQTT_MALFORMED_CREDENTIALS:
      text = "MQTT_MALFORMED_CREDENTIALS";
      break;
    case AsyncMqttClientDisconnectReason::MQTT_NOT_AUTHORIZED:
      text = "MQTT_NOT_AUTHORIZED";
      break;
    case AsyncMqttClientDisconnectReason::ESP8266_NOT_ENOUGH_SPACE:
      text = "ESP8266_NOT_ENOUGH_SPACE";
      break;
    case AsyncMqttClientDisconnectReason::TLS_BAD_FINGERPRINT:
      text = "TLS_BAD_FINGERPRINT";
      break;
  }
  Serial.print("Ühendus MQTT serveriga katkes: ");
  Serial.println(text);

  mqttClient.connect();
}

// Määrame funktsiooni, mida kutsub välja MQTT sündmus
void onMqttPublish(uint16_t packetId) {
  Serial.print("Sõnum saadetud. Sõnumi ID: ");
  Serial.println(packetId);
}

void loop() {
  // Tegeleme ESP32 veebiserverile saabunud päringutega
  MyServer.handleClient();

  // newTime saab pidevalt väärtuseks ESP32 töötamise aja viimasest restardist millisekundites
  newTime = millis();

  // Kui newTime ja oldTime vahe on suurem kui määratud interval, siis alsutame { ja } vahel täitmist
  if (newTime - oldTime > INTERVAL) {

    // oldTime saab väärtuseks newTime väärtuse
    oldTime = newTime;

    // Määrame muutuja h ja f murdarvuna ning kohe omistame neile väärtused
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    // Kui muutujate h ja f väärtused puuduvad siis täidame { ja } vahel
    if (isnan(h) || isnan(t)) {
      TEMP = "Kontrolli andurit!";
      HUMI = "Kontrolli andurit!";
    // Kui muutujate h ja f väärtused on olemas siis täidame { ja } vahel
    } else {
      TEMP = String(t,1);
      HUMI = String(h,1);
    }

    // Kui MQTT-serveriga on ühendus loodud, siis täidame { ja } vahel
    if (mqttClient.connected()) {
      // Postitame MQTT sõnumi 
      mqttClient.publish(String(MQTT_TOPIC+"/"+PROBE+"/data").c_str(), 1, false, String("Temp: "+TEMP+", Humi: "+HUMI).c_str());
    // Kui MQTT-serveriga ühendust pole loodud, siis tagastame vastava teate
    } else Serial.println("MQTT pole ühendatud! ");

    // Kui WiFi-ga on ühendus loodud, siis täidame { ja } vahel
    if (WiFi.status() == WL_CONNECTED) { 

      // Loome HTTPClient objekti
      HTTPClient http;
      // Liidame muutujad kokku
      String serverPath = serverName + "?temp="+TEMP+"&humi="+HUMI+"&noise="+NOISE+"&probe="+PROBE;
      // Teeme päringu Raspberry Pi veebiserveri vastu
      http.begin(serverPath.c_str());
      // Määrame muutuja ja omistame sellele tulemuse koodui
      int httpResponseCode = http.GET();

      // Vea- ja olekukoodid https://github.com/espressif/arduino-esp32/blob/master/libraries/HTTPClient/src/HTTPClient.h ja https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
      // Kui tulemuse kood on suurem 0
      if (httpResponseCode>0) {
        Serial.print("GET päringu olekukood: ");
        Serial.println(httpResponseCode);
        // Määrame muutuja ja omistame sellele saadud vastuse
        String payload = http.getString();
        Serial.print("GET päringu vastus: ");
        Serial.println(payload);
      // Kui tulemuse kood on väiksem või võrdne 0
      } else {
        Serial.print("GET päringu veakood: ");
        Serial.println(httpResponseCode);
      }

      // Lõpetame päringu ja vabastame mälu
      http.end();

    // Kui WiFi-ga ühendust pole loodud, siis tagastame vastava teate
    } else Serial.println("ESP32 ei oma IP aadressi! ");

  }
  
}