// Setpoint---------------------------------------------
float new_temperature_setpoint = 0;
float temperature_setpoint = 32.0;
float new_humidity_setpoint = 0;
float humidity_setpoint = 50.0;

#include <DallasTemperature.h>
#include <Wire.h>
#include <OneWire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// #include <Adafruit_SH110X.h>
#include "DHT.h"
#include <Keypad.h>


#include "icon.h"
#include "constants.h"
#include "temperature_sensor.h"
#include "humidity_sensor.h"
#include "keypad.h"
#include "display.h"



// intervals------------------------------------------------------
unsigned long previousMillis_for_updating_display = INTERVAL_FOR_UPDATING_DISPLAY;
unsigned long previousMillis_for_reading_sensors = INTERVAL_FOR_READING_SENSORS;

// state------------------------------------------------
// input_setpoint / output / input
String state = "output";


// Keypad Functions ------------------------------------------------
void correctKEY() { // do this if the correct KEY is entered
  display_key_msg("Correct Password");
  state = "input_setpoint";
}

void incorrectKEY() { // do this if an incorrect KEY is entered
  display_key_msg("Incorrect Password");
  state = "output";
}

void checkKEY() {
  int correct = 0;
  //loop to let users enter four keys
  for (int i = 0; i < PASSWORD_LENGTH ; i++ ) {
    //compare the entered key with the password
    if (attempt[i] == PASSWORD[i]) {
      correct++; // incease it, whenever there is a correct key
    }
  }

  // if the correct keys become four keys do ...
  if (correct == PASSWORD_LENGTH) {
    correctKEY();
  } else {
    incorrectKEY();
  }

  // clear previous key input
  for (int zz = 0; zz < PASSWORD_LENGTH; zz++) {
    attempt[zz] = 0;
  }
}

void readKeypad(String for_why) {
  if (for_why == "for_password")
  {
    char key = keypad.getKey();
    if (key != NO_KEY)
    {
      switch (key)
      {
        case '*':       // the password should be entered after this symbol
          display.setTextSize(1);         // set text size
          display.setTextColor(OLED_WHITE);    // set text color
          z = 0;
          state = "input";
          break;
        case '#':      // the password should be finished by this symbol
          if (state == "input")
          {
            // delay(100); // added debounce
            display.clearDisplay();
            // display.display();
            if (z == PASSWORD_LENGTH)
            {
              checkKEY();  // call this function
            }
            else
            {
              incorrectKEY();
            }
            z = 0;
            break;
          }
        default:
          if (state == "input")
          {
            attempt[z] = key;
            z++;
            if (z == 1)
            {
              display.clearDisplay();
            }
            display_pass(z);
            // Serial.println("*");
          }
      }
    }
  }
  else if (for_why == "for_control")
  {
    char key = keypad.getKey();
    if (key != NO_KEY)
    {
      switch (key)
      {
        case '#'://-----------------------------------
          display.clearDisplay();
          state = "output";
          delay(100); // added debounce
          for (int i = 0; i < 4; i++)
          {
            attempt_setpoint[i] = '_';
          }
          new_temperature_setpoint = 0;
          break;

        default://-----------------------------------
          if (z2 == 2)
          {
            attempt_setpoint[z2] = '.';
            attempt_setpoint[z2 + 1] = key;

            String neww = "0.#";
            neww[2] = key;
            float temp = neww.toFloat();
            new_temperature_setpoint += temp;
            temperature_setpoint = new_temperature_setpoint;

            for (int i = 0; i < 4; i++)
            {
              attempt_setpoint[i] = '_';
            }
            z2 = 0;
            new_temperature_setpoint = 0;/////////
            state = "output";
            break;
          }
          else
          {
            attempt_setpoint[z2] = key;
            String temp_str = "0";
            temp_str[0] = key;
            int newint = temp_str.toInt();
            if (new_temperature_setpoint == 0)
            {
              new_temperature_setpoint += newint;
            }
            else
            {
              new_temperature_setpoint *= 10;
              new_temperature_setpoint += newint;
            }
            z2++;
          }
          display.clearDisplay();
          display_setpoint();
          // Serial.println("*");
      }
    }
    display_setpoint();
  }
}


// ========================= Void Setup ============================
void setup() {
  Serial.begin(115200);
  //  Relays Pin Configuration-----------------------
  pinMode(SSR_PIN1, OUTPUT);
  pinMode(SSR_PIN2, OUTPUT);
  pinMode(SSR_PIN3, OUTPUT);
  pinMode(SSR_PIN4, OUTPUT);

  digitalWrite(SSR_PIN1, LOW);
  digitalWrite(SSR_PIN2, LOW);
  digitalWrite(SSR_PIN3, LOW);
  digitalWrite(SSR_PIN4, LOW);


  //  OLED Display Configuration---------------------

  //  OLED SH110--------------------------------------------------
  // display.begin(i2c_Address, true); // Address 0x3C default


  //  OLED SDD1306--------------------------------------------------
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
   //  Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }


  display.clearDisplay();
  display.fillRoundRect(10, 15, 50, 40, 4, OLED_WHITE);
  display.setTextSize(1);         // set text size
  display.setTextColor(OLED_BLACK);    // set text color
  display.setCursor(20, 25);
  display.println("SMART");
  display.setCursor(15, 35);
  display.println("POULTRY");
  
  //  display.drawBitmap(35, 2, hen_bitmap_64px, 64, 64, 1);
  display.drawBitmap(64, 2, smart_poultry_farm_bitmap_64px, 64, 64, 1);
  display.setTextColor(OLED_WHITE);
  display.display();
  delay(SPLASH_SCREEN_DURATION);





  




  //  DS18B20 Configuration--------------------------
  sensors.begin();

  //  DHT11 Configuration----------------------------
  for (int i = 0; i < NUM_DHT11_SENSORS; i++) {
    dht[i].begin();
  }

}


// ========================= Void Loop ============================
void loop() {

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis_for_reading_sensors >= INTERVAL_FOR_READING_SENSORS) {
    previousMillis_for_reading_sensors = currentMillis;
    reading_ds18b20_sensors();
    reading_dht11_sensors();

    float sum = 0.0;
    for (int i = 0; i < NUM_DS18B20_SENSORS; i++) {
      sum += ds18b20_SensorDataArray[i].tempC;
    }
    average_temperature = sum / NUM_DS18B20_SENSORS;

    sum = 0.0;
    for (int i = 0; i < NUM_DHT11_SENSORS; i++) {
      sum += dht11_SensorDataArray[i].humidity;
    }
    average_humidity = sum / NUM_DHT11_SENSORS;

    // digitalWrite(SSR_PIN1, LOW);
    // digitalWrite(SSR_PIN2, LOW);
    // digitalWrite(SSR_PIN3, LOW);
    // digitalWrite(SSR_PIN4, LOW);
    // delay(1000);
    // digitalWrite(SSR_PIN1, HIGH);
    // digitalWrite(SSR_PIN2, HIGH);
    // digitalWrite(SSR_PIN3, HIGH);
    // digitalWrite(SSR_PIN4, HIGH);

    //  Relay Control with Pi controller---------------
//    if (Output > 0) {
//      if (Output > 30) {
//        digitalWrite(SSR_PIN4, HIGH);
//      } else if (Output > 20) {
//        digitalWrite(SSR_PIN3, HIGH);
//        digitalWrite(SSR_PIN4, LOW);
//      } else if (Output > 10) {
//        digitalWrite(SSR_PIN2, HIGH);
//        digitalWrite(SSR_PIN3, LOW);
//        digitalWrite(SSR_PIN4, LOW);
//      } else {
//        digitalWrite(SSR_PIN1, HIGH);
//        digitalWrite(SSR_PIN2, LOW);
//        digitalWrite(SSR_PIN3, LOW);
//        digitalWrite(SSR_PIN4, LOW);
//      }
//    } else {
//      digitalWrite(SSR_PIN1, LOW);
//      digitalWrite(SSR_PIN2, LOW);
//      digitalWrite(SSR_PIN3, LOW);
//      digitalWrite(SSR_PIN4, LOW);
//    }
  
  }



  //  State Management-------------------------------
  if (state == "input_setpoint")
  {
    readKeypad("for_control");
  }
  else {
    readKeypad("for_password");
    if (state == "output") {
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis_for_updating_display >= INTERVAL_FOR_UPDATING_DISPLAY) {
        previousMillis_for_updating_display = currentMillis;
        updateDisplay();
      }
    }
  }
}
esp:0
esp:1
esp:2
esp:3
esp:4
esp:5
esp:6
esp:7
esp:8
esp:9
esp:10
esp:11
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:20
esp:21
esp:26
esp:33
esp:34
esp:35
esp:36
esp:37
esp:38
esp:39
esp:40
esp:41
esp:42
esp:45
esp:46
esp:3V3
esp:5V
esp:GND.1
esp:TX
esp:RX
esp:RST
esp:GND.2
temp1:GND
temp1:DQ
temp1:VCC
temp2:GND
temp2:DQ
temp2:VCC
temp3:GND
temp3:DQ
temp3:VCC
temp4:GND
temp4:DQ
temp4:VCC
r1:1
r1:2
dht1:VCC
dht1:SDA
dht1:NC
dht1:GND
dht2:VCC
dht2:SDA
dht2:NC
dht2:GND
dht3:VCC
dht3:SDA
dht3:NC
dht3:GND
dht4:VCC
dht4:SDA
dht4:NC
dht4:GND
r2:1
r2:2
r3:1
r3:2
r4:1
r4:2
r5:1
r5:2
oled1:GND
oled1:VCC
oled1:SCL
oled1:SDA
keypad1:R1
keypad1:R2
keypad1:R3
keypad1:R4
keypad1:C1
keypad1:C2
keypad1:C3
keypad1:C4
NOCOMNCVCCGNDINLED1PWRRelay Module
relay3:VCC
relay3:GND
relay3:IN
relay3:NC
relay3:COM
relay3:NO
NOCOMNCVCCGNDINLED1PWRRelay Module
relay4:VCC
relay4:GND
relay4:IN
relay4:NC
relay4:COM
relay4:NO
NOCOMNCVCCGNDINLED1PWRRelay Module
relay5:VCC
relay5:GND
relay5:IN
relay5:NC
relay5:COM
relay5:NO
NOCOMNCVCCGNDINLED1PWRRelay Module
relay6:VCC
relay6:GND
relay6:IN
relay6:NC
relay6:COM
relay6:NO