/**
   ESP32 + DHT22 Example for Wokwi
   
   https://wokwi.com/arduino/projects/322410731508073042
*/

#include "DHTesp.h"
#include <LiquidCrystal_I2C.h>
#include "WiFiClientSecure.h"
#include <PubSubClient.h>

// Add your MQTT Broker IP address, example:
//const char* mqtt_server = "192.168.1.144";
const char* mqtt_server = "d35c2116.ala.us-east-1.emqxsl.com";
const int mqtt_port     = 8883;     //Port to your Mosquitto broker server. Dont forget to forward it in your router for remote access
const char* mqtt_user   = "test";  //Depends on Mosquitto configuration, if it is not set, you do not need it
const char* mqtt_pass   = "test";       //Depends on Mosquitto configuration, if it is not set, you do not need it
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* CA_cert = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" \
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \
"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" \
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" \
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" \
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" \
"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" \
"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" \
"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" \
"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" \
"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" \
"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" \
"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" \
"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" \
"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" \
"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" \
"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" \
"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" \
"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" \
"-----END CERTIFICATE-----\n";

const char* ESP_CA_cert = \
  "-----BEGIN CERTIFICATE-----\n" \
  "-----END CERTIFICATE-----\n";

const char* ESP_RSA_key= \
  "-----BEGIN PRIVATE KEY-----\n" \
  "-----END PRIVATE KEY-----\n";

WiFiClientSecure espClient;
PubSubClient mqtt_client(espClient);

long lastMsg = 0;

const int DHT_PIN = 15;
LiquidCrystal_I2C lcd(0x27,20,2);
DHTesp dhtSensor;

void setup() {
 
  Serial.begin(115200);
  setup_wifi();
  //Set up the certificates and keys
  espClient.setCACert(CA_cert);          //Root CA certificate
  //espClient.setCertificate(ESP_CA_cert); //for client verification if the require_certificate is set to true in the mosquitto broker config
  //espClient.setPrivateKey(ESP_RSA_key);  //for client verification if the require_certificate is set to true in the mosquitto broker config

  mqtt_client.setServer(mqtt_server, mqtt_port);
  mqtt_client.setCallback(callback);
  dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
  lcd.init();
  lcd.backlight();
  lcd.print("Serial counter Example");
  delay(1000);
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
  
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();

  // Feel free to add more if statements to control more GPIOs with MQTT

  // If a message is received on the topic esp32/output, you check if the message is either "on" or "off". 
  // Changes the output state according to the message
  if (String(topic) == "esp32/output") {
    Serial.print("Changing output to ");
    if(messageTemp == "on"){
      Serial.println("on");
    }
    else if(messageTemp == "off"){
      Serial.println("off");
    }
  }
}
void reconnect() {
  // Loop until we're reconnected
  while (!mqtt_client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqtt_client.connect("ESP32", mqtt_user , mqtt_pass)) {
      Serial.println("connected");
      // Subscribe
      // mqtt_client.subscribe("esp32/output1");
      // mqtt_client.subscribe("esp32/output2");
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqtt_client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

float prevTemperature = 0.0;
float prevHumidity = 0.0;

void loop() {
  if (!mqtt_client.connected()) {
    reconnect();
  }
  mqtt_client.loop();

  TempAndHumidity  data = dhtSensor.getTempAndHumidity();
  Serial.println("Temp: " + String(data.temperature, 2) + "°C");
  Serial.println("Humidity: " + String(data.humidity, 1) + "%");
  lcd.setCursor(0,0);   
lcd.print("Temp :");
lcd.setCursor(7,0);   
lcd.print(String(data.temperature, 2));
lcd.setCursor(13,0);   
lcd.print((char)223);
lcd.setCursor(14,0);   
lcd.print("C");
  
lcd.setCursor(0,1);  
lcd.print("Humi : ");
lcd.setCursor(7,1);  
lcd.print(String(data.humidity, 2));
lcd.setCursor(12,1);   
lcd.print(" %");

if ( data.temperature >= 40){
   long now = millis();
    if (now - lastMsg > 1000) {
    lastMsg = now;
    Serial.println("Heater High Temp");
    lastMsg = now;
    
    // Convert the value to a char array
    char temperatureString[8];
    dtostrf(data.temperature, 1, 2, temperatureString);
  
    Serial.println(temperatureString);
    mqtt_client.publish("sensor/temp/alert", temperatureString);
    Serial.print("alert sent");
    }

}
  long now = millis();
  if (now - lastMsg > 10000) {
    lastMsg = now;
    
    // Convert the value to a char array
    char temperatureString[8];
    char humidityString[8];
   
     if (data.temperature != prevTemperature || data.humidity != prevHumidity) {
    // Update previous values
    prevTemperature = data.temperature;
    prevHumidity = data.humidity;
    dtostrf(data.temperature , 1, 2, temperatureString);
    dtostrf(data.humidity, 1, 2, humidityString);
    Serial.println(temperatureString);
    String payload = String(temperatureString) + ";" + String(humidityString);

    mqtt_client.publish("esp1/temp/humidity",  payload.c_str());
    Serial.print("Published temperature ");
    Serial.println(humidityString);
    Serial.print("Published humidity");
     }
   
  }
  delay(200); // Wait for a new reading from the sensor (DHT22 has ~0.5Hz sample rate)
}