#include <WiFi.h>
#include <ESP32Servo.h>
#include <ThingsBoard.h>
#include <DHTesp.h>
#include <PubSubClient.h>

#define WIFI_AP_NAME "Wokwi-GUEST"
#define WIFI_PASSWORD ""
#define THINGSBOARD_SERVER "thingsboard.cloud"
#define THINGSBOARD_ACCESTOKEN "1O40Yhg7pWYNIV6xRzn7"

#define SERIAL_DEBUG_BAUD 115200

#define LDR_PIN 36
const float GAMMA = 0.7;
const float RL10 = 33;

WiFiClient espClient;
ThingsBoard tb(espClient);
int status = WL_IDLE_STATUS;

DHTesp dht;
#define DHT_PIN 15

#define SERVO_PIN 13
Servo myservo;

boolean isRoofOpen = false;

unsigned long lastLogTime = 0;
int logInterval = 0.2*60*1000;

void setup() {
  pinMode(LDR_PIN, INPUT);
  Serial.begin(SERIAL_DEBUG_BAUD);
  initialWifi();
  myservo.attach(SERVO_PIN,500,2400);
  dht.setup (DHT_PIN, DHTesp:: DHT22);
}

void loop()
{
  int analogValue = analogRead(LDR_PIN);
  float voltage = analogValue / 4095. * 5;
  float resistance = 2000 * voltage / (1 - voltage / 5);
  float lux = (pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA))) *1.8118;

  Serial.print("lux : ");
  Serial.print(lux);

  TempAndHumidity lastValues = dht.getTempAndHumidity();
  float temp = lastValues.temperature;
  float hum = lastValues.humidity;
  Serial.printf("   Temperature : %.2f %s", temp, "'C");
  Serial.printf("   Humidity: %.1f %s", hum, "%");

  //logic
  if (temp <20 && hum >85 && lux <1750) {
    myservo.write(90);
    isRoofOpen = false;
    Serial.println ("Status Atap : Tutup\n");
  }
  else{
    myservo.write(0);
    isRoofOpen = true;
    Serial.println ("Status Atap: Buka\n");
    }
// koneksi kembali Wifi, 
  if(WiFi.status() !=WL_CONNECTED) {
  reconnect();
  return;
    }

//koneksi kembali Thingsboard
  if (!tb.connected()){
    Serial.print ("sambung ke: ");
    Serial.print (THINGSBOARD_SERVER);
    Serial.print ("dgn token ");
    Serial.println (THINGSBOARD_ACCESTOKEN);
    }
  if(!tb.connect(THINGSBOARD_SERVER, THINGSBOARD_ACCESTOKEN)){
    Serial.println("kesalahan koneksi");
    return;
  }

unsigned long currentLogTime = millis();
if (currentLogTime - lastLogTime > logInterval){
  lastLogTime = currentLogTime;
  Serial.println();
  Serial.print("kirim data...");
  }
  if(isnan(hum) || isnan(temp)) {
  Serial.println("DHT salah baca pak!");
  } 
  if (isnan(lux)) {
  Serial.println("LDR salah baca pak!");
  }
  else {
// kirim nilai temp dan hum
  tb.sendTelemetryFloat("temperature",temp);
  tb.sendTelemetryFloat("humidity", hum);
  tb.sendTelemetryFloat("lux",lux);
  tb.sendTelemetryBool("isroofopen", isRoofOpen);
  tb.sendTelemetryString("ROOF STATUS", (isRoofOpen? "ROOF OPEN" : "ROOF CLOSE"));
  Serial.println("Sending data selesai");
  }

  tb.loop();

  delay(1000);
}



void initialWifi()
{
  Serial.println("Connecting to AP....");
  WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
  while (WiFi.status() !=WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected to AP");
}

void reconnect(){
  status =WiFi.status();
  if (status = !WL_CONNECTED){
    WiFi.begin(WIFI_AP_NAME,WIFI_PASSWORD);
    while (WiFi.status() != WL_CONNECTED){
      delay(500);
      Serial.print(".");
    }
    Serial.println("Connected to AP");
  }
}