/* Author: Wahyu Priambodo / 2207421048 / TMJ-4B */
#include "WiFi.h"
#include "ThingsBoard.h"
#include "DHTesp.h"
#include "Arduino_MQTT_Client.h"

// WiFi CONFIGURATIONS
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASS ""
WiFiClient esp32; // initialize esp32 as WiFiClient object

#define LED 12
#define LEDFail 14
#define LEDWait 27

// THINGSBOARD CONFIGURATIONS
#define THINGSBOARD_TOKEN "kxdCzkh8RKDl1uAkBA5D"
#define THINGSBOARD_SERVER "thingsboard.cloud"

Arduino_MQTT_Client mqttClient(esp32); // initialize esp32 as MQTT

constexpr uint16_t MAX_MESSAGE_SIZE = 256U; // set the max message
ThingsBoard tbcloud(mqttClient, MAX_MESSAGE_SIZE); // initialize the MQTT Client (esp32) object of TB

// DHT22 SENSOR CONFIGURATIONS
const int dhtPin = 15; // set pin 15 for DHT22
DHTesp dht22; // initialize dht22 as DHTesp sensor object

// FUNCTION TO CONNECT TO WOKWI DEFAULT WIFI
void connectToWiFi() {
  Serial.println("Connecting to WiFi...");
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 20) {
    WiFi.begin(WIFI_SSID, WIFI_PASS, 6);
    delay(500);
    Serial.print(".");
    attempts++;
  }
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("\nFailed to connect to WiFi."); 
  } else {
    Serial.println("\nConnected to WiFi");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  }
}
// FUNCTION TO CONNECT TO THINGSBOARD CLOUD VIA THINGSBOARD SERVER & TOKEN
void connectToThingsBoard() {
  if (!tbcloud.connected()) {
    Serial.println("Connecting to ThingsBoard server");
    digitalWrite(LED, LOW);
    digitalWrite(LEDFail, LOW);
    digitalWrite(LEDWait, HIGH);
    if (!tbcloud.connect(THINGSBOARD_SERVER, THINGSBOARD_TOKEN)) {
      Serial.println("Failed to connect to ThingsBoard");
      digitalWrite(LED, LOW);
      digitalWrite(LEDWait, LOW);
      digitalWrite(LEDFail, HIGH);
    } else {
      Serial.println("Connected to ThingsBoard");
      digitalWrite(LEDWait, LOW);
      digitalWrite(LEDFail, LOW);
      digitalWrite(LED, HIGH);
    }
  }
}

// FUNCTION TO SEND JSON DATA TO THINGSBOARD CLOUD
void sendDataToThingsBoard(float temp, int hum) {
  String jsonData = "{\"temperature\":" + String(temp) + ",\"humidity\":" + String(hum) + "}";
  tbcloud.sendTelemetryJson(jsonData.c_str());
  Serial.println("Data sent");
}

void setup() {
  Serial.begin(115200);
  dht22.setup(dhtPin, DHTesp::DHT22);
  connectToWiFi();
  connectToThingsBoard();
  pinMode(LED, OUTPUT);
  pinMode(LEDFail, OUTPUT);
  pinMode(LEDWait, OUTPUT);
}

void loop() {
  connectToWiFi();
  TempAndHumidity data = dht22.getTempAndHumidity();
  float temp = data.temperature;
  int hum = data.humidity;
  Serial.println(temp);
  Serial.println(hum);

  if (!tbcloud.connected()) {
    connectToThingsBoard();
  }

  sendDataToThingsBoard(temp, hum);
  delay(3000);
  tbcloud.loop();
}