#include  "WiFi.h" 
WiFiClient client;

#include <HTTPClient.h>
HTTPClient http;

#include "DHTesp.h"

const int DHT_PIN = 15;

DHTesp dhtSensor;

float t;
float h;
float hi; 
float dp;

String thingSpeakAddress = "api.thingspeak.com";
String writeAPIKey = "V1M05ZSX43O6YT12";
String request_string;
const int updateThingSpeakInterval = 10 * 1000; //update data tiap x detik sekali

unsigned long lastConnectionTime = millis(); 
boolean lastConnected = false;

void setup()
{
  Serial.begin(9600);
  WiFi.disconnect();
  WiFi.begin("Wokwi-GUEST", "");
  while ((!(WiFi.status() == WL_CONNECTED))) {
    delay(300);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
}


void loop()
{
  delay(1000);
  TempAndHumidity data = dhtSensor.getTempAndHumidity();
  
  t = data.temperature;
  h = data.humidity;
  if (isnan(h) || isnan(t) ) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  hi = dhtSensor.computeHeatIndex(t, h); 
  dp = (t - (100 - h) / 5);
  Serial.print("temperatur: ");
  Serial.print(t);
  Serial.print("     humidity: ");
  Serial.print(h);
  Serial.print("     heat index: ");
  Serial.print(hi);
  Serial.print("     dew point: ");
  Serial.println(dp);

  kirim_thingspeak(writeAPIKey, t, h, hi, dp);

/*
  // Disconnect dari ThingSpeak
  if (!client.connected() && lastConnected)
  {
    Serial.println("...disconnected");
    Serial.println();
    client.stop();
  }

  // Update data ke ThingSpeak
  if(!client.connected() && 
    ((millis() - lastConnectionTime) > updateThingSpeakInterval))
  {
    String packetData = "field1=" + String(t) +
                        "&field2=" + String(h) +
                        "&field3=" + String(hi) +
                        "&field4=" + String(dp);
    post_thingspeak(writeAPIKey, packetData); 
  }
  lastConnected = client.connected();
*/
/*
  if ((millis() - lastConnectionTime) > updateThingSpeakInterval) {

    String packetData = "&field1=" + String(t) +
                        "&field2=" + String(h) +
                        "&field3=" + String(hi) +
                        "&field4=" + String(dp);
    post_thingspeak(writeAPIKey, packetData);
    lastConnectionTime = millis();
  }
*/  
}

void post_thingspeak(String _apiKey, String _packetData)
{
  http.begin(client, "https://api.thingspeak.com/");      
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
  String httpRequestData = "key=" + _apiKey + _packetData;           
  /*
  // If you need an HTTP request with a content type: application/json, use the following:
  http.addHeader("Content-Type", "application/json");
  // JSON data to send with HTTP POST
  String httpRequestData = "{\"api_key\":\"" + apiKey + "\",\"field1\":\"" + String(random(40)) + "\"}";           
  // Send HTTP POST request
  */
  int httpResponseCode = http.POST(httpRequestData);
  String payload = http.getString();

  Serial.print("Status code: ");
  Serial.println(httpResponseCode);
  Serial.print("Server esponse: ");
  Serial.println(payload);  
  http.end();
  
  /*
  if (client.connect("api.thingspeak.com", 80)) {
    request_string = "POST /update HTTP/1.1\n";
    request_string += "Host: api.thingspeak.com\n";
    request_string += "Connection: close\n";
    request_string += "X-THINGSPEAKAPIKEY: "+ _apiKey + "\n";
    request_string += "Content-Type: application/x-www-form-urlencoded\n";
    request_string += "Content-Length: ";
    request_string += _packetData.length();
    client.print("\n\n");
    client.print(_packetData);


    Serial.println(_packetData);
    lastConnectionTime = millis();

    if (client.connected())
    {
      Serial.println("Connecting to ThingSpeak...");
      Serial.println();
      //failedCounter = 0;
    }
    else
    {
      //failedCounter++;
      //Serial.println("Connection to ThingSpeak failed ("+String(failedCounter, DEC)+")"); 
      Serial.println("Connection to ThingSpeak failed A");
    }
  }
  else
  {
    //failedCounter++;

    //Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")"); 
    Serial.println("Connection to ThingSpeak failed B");
    lastConnectionTime = millis(); 
  } 
  */

}


void kirim_thingspeak(String apiKey, float temp, float hum, float hi, float dp) {
  if (client.connect("api.thingspeak.com", 80)) {
    request_string = "/update?key=";
    request_string += apiKey;
    request_string += "&field1=";
    request_string += temp;
    request_string += "&field2=";
    request_string += hum;
    request_string += "&field3=";
    request_string += hi;
    request_string += "&field4=";
    request_string += dp;

    Serial.println(String("GET ") + request_string + " HTTP/1.1\r\n" +
                 "Host: " + thingSpeakAddress + "\r\n" +
                 "Connection: close\r\n\r\n");
                 
    client.print(String("GET ") + request_string + " HTTP/1.1\r\n" +
                 "Host: " + thingSpeakAddress + "\r\n" +
                 "Connection: close\r\n\r\n");
    
    unsigned long timeout = millis();
    while (client.available() == 0) {
      if (millis() - timeout > 15000) {
        Serial.println(">>> Client Timeout !");
        client.stop();
        return;
      }
    }

    while (client.available()) {
      String line = client.readStringUntil('\r');
      Serial.print(line);
    }

    Serial.println();
    Serial.println("closing connection");


  }
}