#include <WiFi.h>
#include "time.h"
#include "ThingSpeak.h"
#include "DHTesp.h"

const int HOUSE_NO = 4; // corresponding feild no in database

// time config
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 0;
const int   daylightOffset_sec = 19800;
struct tm timeinfo;

// returns the current time hour
int getTime() {
  getLocalTime(&timeinfo);
  return timeinfo.tm_hour;
}

// Pin assignment
const int LIGHT_SENSOR_PIN = 36;

// For four rooms
const int no_of_rooms = 3;
DHTesp dhtSensor[no_of_rooms];
const int DHT_PIN[no_of_rooms] = {23, 21, 18};
const int PIR_SENSOR_PIN[no_of_rooms] = {22, 19, 5};

// wifi credentials
const char* ssid = "Wokwi-GUEST";

WiFiClient  client;
// Thingspeak credentials
unsigned long channelNumber = 1;
const char * writeAPIKey = "CAYMRHP2YRCZU3CG";

void setup() {
  Serial.begin(115200);

  // connecting to wifi
  WiFi.mode(WIFI_STA); //Optional
  WiFi.begin(ssid);
  Serial.println("\nConnecting");

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

  Serial.println("\nConnected to the WiFi network");
  Serial.print("Local ESP32 IP: ");
  Serial.println(WiFi.localIP());

  // setting up thingspeak
  ThingSpeak.begin(client);

  for(int i = 0; i < no_of_rooms; i++) {
    dhtSensor[i].setup(DHT_PIN[i], DHTesp::DHT22);
    pinMode(PIR_SENSOR_PIN[i], INPUT);
  }
}

// to calculate the power consumption for lights based on brightness of the rooms
float  lightingPower() {    
  float power = 0;

  int brightness, PIRState;
  int power_per_bulb = 8; // in Watts

  brightness = analogRead(LIGHT_SENSOR_PIN);

  for(int i = 0; i < no_of_rooms; i++) {
    PIRState = digitalRead(PIR_SENSOR_PIN[i]); // check if someone's in the room

    if(PIRState == HIGH) {
      // Custom thresholds set based on wokwi psr guidelines
      if (brightness <= 170) {
        power += 0; // Very bright
      } else if(170 < brightness && brightness <= 511) {
        power += 0.5*power_per_bulb; // A bit dim
        Serial.print("Light bulb is ON in room ");
        Serial.print(i+1);
        Serial.print(" with half brightness \n");
      } else if (brightness > 511) {
        power += power_per_bulb; // dark
        Serial.print("Light bulb is ON in room ");
        Serial.print(i+1);
        Serial.print("\n");
      }
    }
  }
  return power;
}

// to calculate the power consumption for cooling based on temperature
float cooling_power()
{
  float power = 0;

  float temperature;
  int PIRState;
  float power_per_fan = 28; // in watts

  // for room 1 that has ac
  PIRState = digitalRead(PIR_SENSOR_PIN[0]);
  TempAndHumidity  data = dhtSensor[0].getTempAndHumidity();
  temperature = float(data.temperature);
  if(PIRState == HIGH && temperature>32) {
    power += 1500; //power consumed by ac in watts
    Serial.print("AC is ON");
    Serial.print("\n");
  }

  // for all other room
  for(int i = 1; i < no_of_rooms; i++) {
    PIRState = digitalRead(PIR_SENSOR_PIN[i]);
    TempAndHumidity  data = dhtSensor[i].getTempAndHumidity();
    temperature = float(data.temperature);

    if(PIRState == HIGH) {
      if (temperature>33) {
        power += power_per_fan; // fan at max speed 5
        Serial.print("Fan is ON in room ");
        Serial.print(i+1);
        Serial.print(" at full speed\n");
      } else if (temperature <=33 && temperature>32 ) {
        power += power_per_fan*0.75; // fan speed 4
        Serial.print("Fan is ON in room ");
        Serial.print(i+1);
        Serial.print(" with speed 4\n");
      } else if (temperature<=32 && temperature>30) {
        power += power_per_fan*0.5; // fan speed 3
        Serial.print("Fan is ON in room ");
        Serial.print(i+1);
        Serial.print(" with speed 3\n");
      }
    }
  }

  return power;
}

// power demand of washing machine based on usage time
float washingMachinePower() {
  const int power_required = 1000; // in watts

  // usage time
  const int washing_machine_use_start = 17; // 5pm
  const int washing_machine_use_end = 19; // 7pm
  
  int time = getTime();

  if (time >= washing_machine_use_start && time <= washing_machine_use_end) {
    Serial.println("Washing Machine is ON");
    return power_required;
  } else {
    return 0;
  }

}

// power demand of television based on usage time
float televisionPower() {
  const int power_required = 100; // in watts

  // usage time
  const int television_use_start = 20; // 8pm
  const int television_use_end = 24; // midnight
  
  int time = getTime();

  if (time >= television_use_start && time <= television_use_end) {
    Serial.println("Television is ON");
    return power_required;
  } else {
    return 0;
  }

} 

// Constants power consumption for refrigerator
const int refrigeratorPower = 150; // in watts

void loop() {
  // put your main code here, to run repeatedly:
  float total_power = washingMachinePower() + televisionPower() + refrigeratorPower + lightingPower() + cooling_power();
  total_power /= 1000; // converting to kilowatts

  Serial.print("Total power Required: ");
  Serial.print(total_power);

  Serial.println("\n---------------");

  int x = ThingSpeak.writeField(channelNumber, HOUSE_NO, total_power, writeAPIKey);
}