/******************************************/
// Include library
/*******************************************/
#include <Arduino.h>
#include <DHTesp.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <ESP32Servo.h>
#include <WiFi.h>
#include <PubSubClient.h>
/******************************************
// Define pin function 
*******************************************/
// line : iQNYB37XxXguTtyDsgphF7XdzNviFN0yS2mJzpDwPX8
#define Sprintln(a) (Serial.println(a))
#define Sprint(a)   (Serial.print(a))
/******************************************************************************************
//(20 Point)
1.กำหนดให้นักศึกษาตั้งค่า 
  Temperatuer setpoint อ้างอิง เลขท้ายประจำตัวนักศึกษาเช่น 116410205037-7   ต้องกำหนด 37.70 และ 
  Humidity setpoint    อ้างอิง ท้ายประจำตัวนักศึกษา +12 เช่น 116410205037-7 ต้องกำหนด 49.70
*******************************************************************************************/
#define TEMP_SETPOINT  (7.00)    // Tempaeratuer setpoint
#define HUMI_SETPOINT  (19.0)    // Humidity setpoint

#define SWITCH_ON   (18)  //Pin D18  SWITCH ON
#define SWITCH_OFF  (19)  //Pin D19  SWITCH OFF     

#define BUTTON_START  digitalRead(SWITCH_ON) == 1     // Set Input Pin
#define BUTTON_STOP   digitalRead(SWITCH_OFF)== 1     // Set Input Pin

#define DHT_PIN  (23) //Pin D23  DHT sensor

#define LED_1 (2)    //Pin D4  LED 2 (LIGHT)
#define LED_2 (4)    //Pin D15 LED 3 (BRIGHT)
#define LED_3 (15)   //Pin D2  LED 1 (DARK)
#define LED_4 (12)   //Pin D12 LED 4 (Light sensor monitoring)

#define RELAY (14)    //Pin D14 RELAY

#define LIGHT_SENSOR_PIN (35) //Pin D35  LDR sensor
#define ADC_READ_A1 analogRead(LIGHT_SENSOR_PIN)    // Read analog input LDR sensor

#define VR_Pin (34)
#define ADC_READ_A0 analogRead(VR_Pin)    // Read analog input Potentiometer (VR)

#define MIN_POS  (0)
#define MAX_POS  (180)
#define SERVO_PIN (5)

#define BETA (3950) // should match the Beta Coefficient of the thermistor
#define Debounce (3)  //SW debounce

#define ADMax (4095)
#define ADMin (0)
#define PWMMax (255)
#define PWMMin (0)
#define PerMin (0)
#define PerMax (180)

#define DARK   (40)
#define DIM    (800)
#define LIGHT  (2000)
#define BRIGHT (3200)

#define VOLTAGE (5)

#define OPEN_V (180)
#define CLOSE_V (180)

#define TimeDuty (10000)    //10 mS

#define ID_MQTT "Sukanya-final" // 
/******************************************
// Declaration of a Variable
*******************************************/
//-------- Set flag even control---
unsigned int  even = 1;     
unsigned long lastime = 0;
unsigned long lastime1 = 0;

unsigned int buffTemp = 0; 
unsigned int PreviousTemp = 0;
unsigned int CurrentTemp  = 0;

//-----LDR Sensor Characteristics---
const float GAMMA = 0.7;
const float RL10 = 50;
volatile float lux=0;

//-------DHT22 Temp&Humit Sensor-----
volatile float  Temp = 0;
volatile float  Humi = 0;
volatile unsigned int ADval[4]; //Average 4 samples

//-------Servo-----
int pos = 0;

//-----WiFi connect---
const char* ssid = "Wokwi-GUEST";
const char* password = "";

//-----MQTT Protocal---
//const char* mqtt_server = "broker.netpie.io";
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
/*
const char* mqtt_Client = "a28b70d3-603f-4043-9da2-421ce2b067d2";
const char* mqtt_username = "5g1eSw2jmtQL8cUFy1DoGZFghg51u9DX";
const char* mqtt_password = "iLk*~ZG)f!fVqLqZCsoG5BUbAD1TJTE-";
*/

WiFiClient espClient;

PubSubClient client(espClient);

char status_LED [50];     // Sent Status of LED to netpie

char msg[100];             // Sent data to NETPIE

char Serial_read = '0';   //command input of serial port

int Setpoint  = 27;       // Setpoint

unsigned int Alarm = 0;   //Set alarm flag

float Voltage = 0.0;      //Gain of analog voltage

long lasgMsg = 0;         //Timer

// ---- limits for sampling period -----------
const float T0MAX = 1;      // 
const float T0MIN = 0.001;
const int T0MSMAX = 1000;   // 
const int T0MSMIN = 1;
const int T1MSMAX = 1000;   // Potentiometer Sensor
const int T1MSMIN = 1;
const int T2MSMAX = 1000;   // LED Display
const int T2MSMIN = 1;
const int T3MSMAX = 1000;   // Relay Control
const int T3MSMIN = 1;
const int T4MSMAX = 1000;   // Button Control
const int T4MSMIN = 1;
const int T5MSMAX = 10000;  // LCD Display
const int T5MSMIN = 1;
const int T6MSMAX = 20000;  // DHT Sensor
const int T6MSMIN = 1;
const int T7MSMAX = 5000;   // LDR Sensor
const int T7MSMIN = 1;

float T = 0.08;  // sampling period

int T0_ms, T1_ms, T2_ms, T3_ms, T4_ms, T5_ms, T6_ms, T7_ms;
int T0ticks, T1ticks, T2ticks, T3ticks, T4ticks, T5ticks, T6ticks, T7ticks;

// -----------FreeRTOS handles and flags-----------------
TaskHandle_t xTask0h = NULL, xTask1h = NULL, xTask2h = NULL, xTask3h = NULL, xTask4h = NULL;
TaskHandle_t xTask5h = NULL, xTask6h = NULL, xTask7h = NULL;

QueueHandle_t xQueue_y = NULL, xQueue_u = NULL;

bool xQueueOK;

portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;

/*******************************************************************/
// create instance of class 
/*******************************************************************/
DHTesp dhtSensor;

/*******************************************************************/
LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 20,4);

/*******************************************************************/
Servo servo;
/*******************************************************************/

/**************************************************************************
// create tasks and queues
  //* Create the task, storing the handle. */
  //xReturned = xTaskCreate(
  //vTaskCode,        /* Function that implements the task. */
  //"NAME",           /* Text name for the task. */
  //STACK_SIZE,       /* Stack size in words, not bytes. */
  //( void * ) 1,     /* Parameter passed into the task. */
  //tskIDLE_PRIORITY, /* Priority at which the task is created. */
  //&xHandle );       /* Core where the task should run */
/***************************************************************************/
void freertos_init(void) 
{
  xQueueOK = 0;    // start wit false
  xQueue_y = xQueueCreate(1000,sizeof(float));
  xQueue_u = xQueueCreate(1000,sizeof(float));  
  
  if ((xQueue_y == NULL)|(xQueue_u == NULL)) 
      Serial.println("Error creating the queue");
  else  xQueueOK = 1;
  
  T0_ms = 1000*T;
  T0ticks = pdMS_TO_TICKS(T0_ms);  // period of Task0 in number of ticks

  /*****************************************************
  // (10 Point)
  2. กำหนดให้ตั้งค่า delays to tasks อ้างอิงลำดับโปรแกรมให้ 
       Algorithm ทำงานได้ตามลำดับความสำคัญของโปรแกรม
  *****************************************************/

  // initialize delays to tasks
  T1_ms = 100;    // Potentiometer Sensor (1.Analog input)
  T2_ms = 500;   // LED Display
  T3_ms = 1000;  // Relay Control
  T4_ms = 2000;  // Button Control      (7.Button)
  T5_ms = 1000;   // LCD Display 
  T6_ms = 1000;   // DHT,LDR Sensor
  T7_ms = 100;   // NETPIE

  T1ticks = pdMS_TO_TICKS(T1_ms); // period of Task1 in number of ticks
  T2ticks = pdMS_TO_TICKS(T2_ms); // period of Task2 in number of ticks
  T3ticks = pdMS_TO_TICKS(T3_ms); // period of Task3 in number of ticks
  T4ticks = pdMS_TO_TICKS(T4_ms); // period of Task4 in number of ticks
  T5ticks = pdMS_TO_TICKS(T5_ms); // period of Task5 in number of ticks  
  T6ticks = pdMS_TO_TICKS(T6_ms); // period of Task6 in number of ticks   
  T7ticks = pdMS_TO_TICKS(T7_ms); // period of Task7 in number of ticks    
  
  /*
  TaskFunction  : ชื่อฟังก์ชันที่จะให้ทำงานเป็น Task ซึ่งในฟังก์ชันนั้นควรจะเขียนโปรแกรมแบบทำงานวนลูป( infinite loop )
  TaskName      : ชื่อของ Task ( ข้อมูลตรงส่วนนี้จะใช้ตอน Debug ไม่มีผลต่อการทำงานของโปรแกรมโดยตรง )
  StackDepth    : ขนาด Stack ของ Task (เพื่อจอง memory) การกำหนดขนาดของ Task 
                  ถ้ากำหนดไว้น้อยเกินไปจะทำให้ ESP32 Restart ตัวเองตลอดเวลา 
                  แต่ถ้ากำหนดไว้มากไปก็ทำให้เสีย memory ทิ้งเปล่าๆ 
  PassParameter : ชื่อตัวแปรที่จะส่งค่าเข้ามาทำงานต่อใน Task 
  TaskPriority  : กำหนดเลข Priority ให้ Task ซึ่งค่า 0 คือ Priority ที่ต่ำที่สุด
  TaskHandle    : ชื่อตัวแปรของ Task ที่จะนำไปใช้ในการ Handle ทำงานอื่นๆต่อ 
  */
  //xTaskCreate(TaskFunction,TaskName,StackDepth,(void*)PassParameters,TaskPriority,TaskHandle)

  xTaskCreatePinnedToCore(Task0, "Task 0", 10000, NULL, 1, &xTask0h, 0);
  xTaskCreatePinnedToCore(Task1, "Task 1", 10000, NULL, 1, &xTask1h, 0); 
  xTaskCreatePinnedToCore(Task2, "Task 2", 10000, NULL, 1, &xTask2h, 0); 
  xTaskCreatePinnedToCore(Task3, "Task 3", 10000, NULL, 1, &xTask3h, 0);   

   // the following tasks may be suspended if flags are set to 0
  xTaskCreatePinnedToCore(Task4, "Task 4", 10000, NULL, 2, &xTask4h, 1); 
  xTaskCreatePinnedToCore(Task5, "Task 5", 10000, NULL, 2, &xTask5h, 1);   
  xTaskCreatePinnedToCore(Task6, "Task 6", 10000, NULL, 2, &xTask6h, 1);  
  xTaskCreatePinnedToCore(Task7, "Task 7", 10000, NULL, 2, &xTask7h, 1);

  /*
    xTaskCreated(…) : สร้าง Task ใหม่
    vTaskDelete(…) : ลบ Task ที่เคยสร้างไว้ ( เลิกใช้งาน Task )
    vTaskDelay(…) : สั่งให้ Task หยุดพการทำงานตามเวลาที่กำหนด
    vTaskSuspend(…) : สั่งให้ Task เข้าสู่ Suspend state ( หยุดทำงาน )
    vTaskResume(…) : สั่งให้ Task เข้าสู่ Ready state ( ออกจาก Suspend state )
    vTaskPriorityGet(…) : อ่านค่า Priority ของ Task
    vTaskPrioritySet(…) : เปลี่ยนค่า Priority ของ Task
  */
} 
/**************************************************************************
// Task0

**************************************************************************/
void Task0( void * parameter)   
{
  TickType_t xLastWakeTime;
  xLastWakeTime = xTaskGetTickCount();

  for(;;)   
  {
    //NetPieMQTT();

    vTaskDelayUntil(&xLastWakeTime, T0ticks);  // set period 
  }  

  vTaskDelete(NULL);
}  
/**************************************************************************
// Task1 : Potentiometer Sensor
**************************************************************************/
void Task1( void * parameter)   
{
  for(;;)   
  {
    PotentiometerSensor(); // Function Potentiometer(VR) Control
  
    vTaskDelay(T1ticks);
  }  
  vTaskDelete(NULL);
}  
/**************************************************************************
// Task2 : LED Display
// (10 Point)
   3. กำหนดให้เมื่อปรับค่า LDR Sensor สามารถควบคุม LED Green , Yellow , Red ได้ดังต่อไปนี้
      - LED Green ติดเมื่อรับค่าจาก LDR Sensor < 40   //#define DARK (40)
      - LED Yellow ติดเมื่อรับค่าจาก LDR Sensor < 2000  //#define LIGHT (2000)
      - LED Red ติดเมื่อรับค่าจาก LDR Sensor > 2000 
    โดยติดและดับตามลำดับการทำงาน
**************************************************************************/
void Task2( void * parameter)   
{
  for(;;)   
  {
    LED_Display(); // Function LED Display Control
   
    vTaskDelay(T2ticks);
  }  
  vTaskDelete(NULL);
}  
/**************************************************************************
// Task3 : Relay Control 
// (10 Point)
    4.กำหนดให้ Relay ตัดต่อวงจรติดดับ LED และ ควบคุมเซอร์โวมอเตอร์เปิดหมุน 180องศา และปิด 0 องศา (ปิดเปิดวาร์วน้ำ)
    ตามเงื่อนไข 
    Temperature  setpoint อ้างอิง เลขท้ายประจำตัวนักศึกษาเช่น 116410205037-7   ต้องกำหนด 37.70 และ 
    Humidity setpoint     อ้างอิง ท้ายประจำตัวนักศึกษา +12 เช่น 116410205037-7 ต้องกำหนด 49.70
    
**************************************************************************/
void Task3( void * parameter)   
{
  for(;;)   
  {
    ControlRelay(Temp, Humi ,even); // Function Relay Control
    
    vTaskDelay(T3ticks);
  }  

  vTaskDelete(NULL);
} 
/**************************************************************************
// Task4 : Button Control 
//(10 Point)
  5.กำหนดให้ Button สามารถควบคุมการทำงานของจอ LCD และ LED Green,Yellow, Red
  ให้แสดงผลตามเงื่อนไขได้
**************************************************************************/
void Task4( void * parameter)   
{
  for(;;)   
  {
    ButtonControl(); // Function Button Control

    vTaskDelay(T4ticks);
  }  
  vTaskDelete(NULL);
} 
/**************************************************************************
// Task5 : LCD Display  
// (10 Point)
   6.กำหนดให้ LCD แสดงผล Temperature, Humidity , Light , Servo position
**************************************************************************/
void Task5( void * parameter)   
{
  for(;;)   
  {   
    LCD_Display(); // Function LCD Display control

    vTaskDelay(T5ticks);
  }  

  vTaskDelete(NULL);
}
/**************************************************************************
// Task6 : DHT Sensor 
// (10 Point)
   7. กำหนดให้รับค่าจาก DHT Sensor
**************************************************************************/
void Task6( void * parameter)   
{
  for(;;)   
  {  
    DHTSensor(); // Function DHT Temp and humidity sensor
    
    LDRSensor(); // Function LDR sensor control

    vTaskDelay(T6ticks);
  }  

  vTaskDelete(NULL);
}
/**************************************************************************
// Task7 : LDR Sensor 
// (10 Point)
   8. กำหนดให้แสดงผล ข้อความผ่านทาง Serial port  ดังนี้
      Sprintln(" => Dark");           // #define DARK (40)
      Sprintln(" => Dim");            //#define DIM (800)
      Sprintln(" => Light");          //#define LIGHT (2000)
      Sprintln(" => Bright");         //#define BRIGHT (3200)
      Sprintln(" => Very bright");    // > 32000
    และนำค่า ADC_READ_A1 จาก LDR Sensor กำหนดค่า PWM Lamp control 
    สั่ง LED4 เปล่งแสงได้
**************************************************************************/
void Task7( void * parameter)
{
  for(;;)
  {
     
    //NetPieMQTTPotocal(); //Function MQTT Protocal
    vTaskDelay(T7ticks);
  }
  vTaskDelete(NULL);
}
/**************************************************************************
**************************************************************************/  
/**********************************************************************************
Function Name:   setup Loop 
Description  :  Hardware setup loop control 
Parameters   :   void
Return value : void
// (10 Point)
  9. กำหนดให้ตั้ง Hardware setup ให้โปรแกรมสามารถทำงานได้ตามกำหนด
***********************************************************************************/
void setup() 
{
    Serial.begin(115200); //Start UART begin

    pinMode(LED_1, OUTPUT);   //Pin D2   LED 1 (DARK)
    pinMode(LED_2, OUTPUT);   //Pin D4   LED 2 (LIGHT)
    pinMode(LED_3, OUTPUT);   //Pin D15  LED 3 (BRIGHT)
    pinMode(LED_4, OUTPUT);   //Pin D12  LED 4 (Light sensor monitoring)

    pinMode(RELAY, OUTPUT);   //Pin D14 RELAY     

    pinMode(SWITCH_ON, INPUT); //Pin D18  SWITCH ON
    pinMode(SWITCH_OFF,INPUT); //Pin D19  SWITCH OFF 

    pinMode(LIGHT_SENSOR_PIN, INPUT); // Set A/D Input LDR sensor
    pinMode(VR_Pin, INPUT);           // Set A/D Input potentiometer sensor

   /*******************************************/
    servo.attach(SERVO_PIN, 500, 2400); // Servo instance 

    /*******************************************/
    dhtSensor.setup(DHT_PIN, DHTesp::DHT22);  // Servo DHT22 

    /*******************************************/
    freertos_init();     // create tasks and queues here

    /*******************************************/
    LCD.init();         // initial LCD on lib
    LCD.backlight();    // Blink LCD backlight on

    LCD.setCursor(0,0); // Clear LCD display (colunm,row)
    LCD.print("Smart Farm");

    LCD.setCursor(0,1);
    LCD.print("Mechatronics Eng");

    LCD.setCursor(0,2);
    LCD.print("Temperature Control");
    
    LCD.setCursor(0,3);
    LCD.print("Servo Control");

    delay (2000);

    /*******************************************/
    Sprintln();
    Sprint("Connecting to ");
    Sprintln(ssid);

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) 
    {
        delay(500);
        Sprint(".");
    }

    Sprintln("");
    Sprintln("WiFi connected");
    Sprintln("IP address: ");
    Sprintln(WiFi.localIP());
    client.setServer(mqtt_server, mqtt_port);
    client.setCallback(callback);
   
    /*******************************************/
}
/**********************************************************************************
Function Name: Main Loop
Description  : Main loop control 
Parameters   : void
Return value : void
***********************************************************************************/
void loop() 
{
    NetPieMQTTPotocal(); //Function MQTT Protocal

    if (!client.connected()) 
    {
        reconnect();
    }
    client.loop();
}
/**********************************************************************************
Function Name :  PotentiometerSensor
Description   :  Control position of Potentiometer Sensor
Parameters    :  void
Return value  :  void
***********************************************************************************/
void PotentiometerSensor (void)
{
   /*
    #define ADMax (4095)
    #define ADMin (0)
    #define PerMin (0)
    #define PerMax (180)
   */

    int AdjustVR = map(ADC_READ_A0,ADMin,ADMax,PerMin,PerMax);   // 2^12 = 4096
    // A/D averaging
    ADval[3] = ADval[2];
    ADval[2] = ADval[1];
    ADval[1] = ADval[0];
    ADval[0] = AdjustVR;    // read new analog input
                            // average of 4 samples
    int adcval = (ADval[3] + ADval[2] + ADval[1] + ADval[0])>>2;

    if(!even)
    {
      pos = ServoMotor(adcval); // Function servo control
    }
}
/**********************************************************************************
Function Name : LED_Display
Description   : LED_Display
Parameters    : void
Return value  : void
***********************************************************************************/
void LED_Display (void)
{
    int analogValue = ADC_READ_A1;

    if(even)
    {
      if (analogValue < DARK) // #define DARK (40)
      {
        //  Sprintln(" => Dark");
        digitalWrite(LED_1,HIGH);
        digitalWrite(LED_2,LOW);
        digitalWrite(LED_3,LOW);
      } 
      else if (analogValue < LIGHT) //#define LIGHT (2000)
      {
        //  Sprintln(" => Light");
        digitalWrite(LED_1,LOW);
        digitalWrite(LED_2,HIGH);
        digitalWrite(LED_3,LOW);
      } 
      else 
      {
        //  Sprintln(" => Very bright");
        digitalWrite(LED_1,LOW);
        digitalWrite(LED_2,LOW);
        digitalWrite(LED_3,HIGH);
      }
    }
    else
    {
      digitalWrite(LED_1,LOW);
      digitalWrite(LED_2,LOW);
      digitalWrite(LED_3,LOW);
    }
}
/**********************************************************************************
Function Name  : ButtonControl
Description    : ButtonControl
Parameters     : void
Return value   : void
***********************************************************************************/
void ButtonControl (void)
{
    if(BUTTON_START)
    {
        long now1 = millis();
        if((now1 - lastime) > Debounce) //  Software debounce
        {
          lastime = 0;
          even = 1;
        }
    }

    if(BUTTON_STOP)
    {
      long now = millis();
        if((now - lastime1) > Debounce) //  Software debounce
        {
          lastime1 = 0;
          even = 0;
        }
    }

}
/**********************************************************************************
Function Name  : LCD_Display
Description    : LCD_Display
Parameters     : void
Return value   : void
***********************************************************************************/
void LCD_Display (void)
{
    if(even)
    {
      LCD.clear();
      LCD.setCursor(0,0);
      LCD.print("Temp:" + String(Temp) + " C");
      LCD.setCursor(0,1);
      LCD.print("Humidity: " + String(Humi) + "%");
      LCD.setCursor(0,2);
      LCD.print("Light :"+String(lux)+ " lux");
      LCD.setCursor(0,3);
      LCD.print("Servo position :" + String(pos));
    }
    else
    {
      LCD.clear();
    }

}
/**********************************************************************************
Function Name  : DHTSensor
Description    : DHTSensor
Parameters     : void
Return value   : void
***********************************************************************************/
void DHTSensor (void)
{
    TempAndHumidity  data = dhtSensor.getTempAndHumidity();
    
    Temp = data.temperature;
    Humi = data.humidity;

  //  Sprintln("Temp: " + String(data.temperature, 2) + "°C");
  //  Sprintln("Humidity: " + String(data.humidity, 1) + "%");
  //  Sprintln("---");
}
/**********************************************************************************
Function Name : LDRSensor
Description   : LDRSensor
Parameters    : void
Return value  : void
***********************************************************************************/
void LDRSensor (void)
{
    if(even)
    {
      int analogValue = ADC_READ_A1;   // 2^12 = 4096
      float voltage = analogValue / 4096. * 5;
      float resistance = 2000 * voltage / (1 - voltage / 5);
      lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));

   //   Sprint("Lux: ");
   //   Sprint(lux);
   //   Sprintln("          ");

      // We'll have a few threshholds, qualitatively determined

      if (analogValue < DARK) // #define DARK (40)
      {
      //  Sprintln(" => Dark");
      } 
      else if (analogValue < DIM) //#define DIM (800)
      {
      //  Sprintln(" => Dim");
      } 
      else if (analogValue < LIGHT) //#define LIGHT (2000)
      {
      //  Sprintln(" => Light");
      } 
      else if (analogValue < BRIGHT)  //#define BRIGHT (3200)
      {
      //  Sprintln(" => Bright");
      } 
      else 
      {
      //  Sprintln(" => Very bright");
      }
      /*
      #define ADMax 4095
      #define ADMin 0
      #define PWMMax 255
      #define PWMMin 0
      */
      int AdjustLED = map(analogValue,ADMin,ADMax,PWMMin,PWMMax);
      digitalWrite(LED_4,AdjustLED);
      
  //    Sprint("PWM Lamp control: ");
  //    Sprintln(AdjustLED);
  //    Sprintln("---");

    }
}
/**********************************************************************************
Function Name : ServoMotor
Description   : ServoMotor
Parameters    : int
Return value  : int
***********************************************************************************/
int ServoMotor(int servo_pos) 
{
  if(servo_pos <= MAX_POS)
  {
    servo.write(servo_pos);
  }
  else
  {
    servo.write(MAX_POS-servo_pos);
  }
  return servo_pos;
}
/**********************************************************************************
Function Name :  ControlRelay
Description   :  ControlRelay
Parameters    :  int Temp_t, int Humi_t, int even_t
Return value  :  void
***********************************************************************************/
void ControlRelay(int Temp_t, int Humi_t, int even_t)
{
    if((Temp_t > TEMP_SETPOINT) || (Humi_t > HUMI_SETPOINT))
    {
      digitalWrite(RELAY, HIGH);  // On Relay

      if(even_t)                  // Button control set flag
      {
        pos = ServoMotor(OPEN_V); // Function servo control 
                                  // #define OPEN_V (180)
      }
    }
    else
    {
      digitalWrite(RELAY,LOW);  // Off Relay

      if(even_t)                // Button control set flag
      {
        pos = ServoMotor(CLOSE_V); // Function servo control
                                  // #define CLOSE_V (0)
      }
    }
}
/**********************************************************************************
Function Name : NetPieMQTT
Description   : NetPieMQTT
Parameters    : void
Return value  : void
***********************************************************************************/
void NetPieMQTTPotocal(void)
{
    int humidity = Humi;
    int temperature = Temp;

    if (Serial.available())
    {
        Serial_read = Serial.read();
        if (Serial_read == '1')
        {
          Setpoint = temperature + 5 ;
        }
        if (Serial_read == '2')
        {
          Setpoint = temperature - 5;
        }
    }

    PreviousTemp = CurrentTemp;
    CurrentTemp  = temperature;

    if (PreviousTemp != CurrentTemp)
    {
       buffTemp = 1;
    }
    else if(PreviousTemp == CurrentTemp)
    {
      buffTemp = 0;
    }

    if (buffTemp)
    {
      if(temperature > Setpoint)
      {
        Alarm = 1;
      }
      else
      {
        Alarm = 0;
      }
    }

    long now = millis();
    if(now - lasgMsg > TimeDuty)
    {
        lasgMsg = now ;

        if ((temperature > Setpoint)&&(Alarm))
        {
            String temp = "Over Temperature";
            temp.toCharArray(status_LED, (temp.length() + 1));
        }
        else
        {
            String temp = "Normal Temperature";
            temp.toCharArray(status_LED, (temp.length() + 1));
        }

        client.publish("@msg/MQTTBox/", {status_LED}, 1);
        delay(1);
        
        String data = "{\"data\": {\"humidity\":"         + String(humidity)        +
                                 ",\"temperature\":"      + String(temperature)     +
                                 ",\"Setpoint\":"         + String(Setpoint)        +
                                 ",\"Alarm\":"            + String(Alarm)           +
                                 ",\"Light\":"            + String(lux)             +
                                 ",\"ServoPos\":"        + String(pos)             +
                                 "}}";

        Serial.println(data);
        
        data.toCharArray(msg, (data.length() + 1));

        client.publish("Sukanya-final", msg);
        //client.publish("@shadow/data/update", msg);
        delay(10);
    }
}
/**********************************************************************************
Function Name  : reconnect
Description    : Wifi reconnected
Parameters     : void
Return value   : void
***********************************************************************************/
void reconnect(void) 
{
    while (!client.connected()) 
    {
    //    Sprint("Attempting MQTT connection…");
    //    Sprintln(mqtt_server);
      //  if (client.connect(mqtt_Client, mqtt_username, mqtt_password)) 
        if (client.connect(ID_MQTT)) 
        {
    //       Sprintln("connected");
            client.subscribe("Sukanya-final/#");
        } 
        else 
        {
            Sprint("failed, rc=");
            Sprint(client.state());
            Sprintln("try again in 5 seconds");
            delay(5000);
        }
    }
}
/**********************************************************************************
Function Name  : callback
Description    : callback
Parameters     : char* topic, byte* payload, unsigned int length
Return value   : void
***********************************************************************************/
void callback(char* topic, byte* payload, unsigned int length) 
{
    Sprint("Message arrived [");
    Sprint(topic);
    Sprint("] ");
    String message;
    for (int i = 0; i < length; i++) 
    {
        message = message + (char)payload[i];
    }
    Sprintln(message);
    
    if(String(topic) == "@msg/led") 
    {
        if(message == "on")
        {
            Alarm = 1;
          //  digitalWrite(LED_1,HIGH);
            digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
            client.publish("Sukanya-final", "{\"data\" : {\"led\" : \"on\"}}");
            Serial.println("LED on");
        } 
        else if (message == "off")
        {
            Alarm = 0;
        //    digitalWrite(LED_1,LOW);
            digitalWrite(LED_BUILTIN, LOW);   // turn the LED on (HIGH is the voltage level)
            client.publish("Sukanya-final", "{\"data\" : {\"led\" : \"off\"}}");
            Sprintln("LED off");
        }
    }
}
/**********************************************************************************

***********************************************************************************/
esp:VIN
esp:GND.2
esp:D13
esp:D12
esp:D14
esp:D27
esp:D26
esp:D25
esp:D33
esp:D32
esp:D35
esp:D34
esp:VN
esp:VP
esp:EN
esp:3V3
esp:GND.1
esp:D15
esp:D2
esp:D4
esp:RX2
esp:TX2
esp:D5
esp:D18
esp:D19
esp:D21
esp:RX0
esp:TX0
esp:D22
esp:D23
led1:A
led1:C
r1:1
r1:2
ldr1:VCC
ldr1:GND
ldr1:DO
ldr1:AO
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
led2:A
led2:C
led3:A
led3:C
r2:1
r2:2
r3:1
r3:2
dht1:VCC
dht1:SDA
dht1:NC
dht1:GND
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
r6:1
r6:2
r7:1
r7:2
led6:A
led6:C
led7:A
led7:C
lcd2:GND
lcd2:VCC
lcd2:SDA
lcd2:SCL
servo1:GND
servo1:V+
servo1:PWM
pot1:GND
pot1:SIG
pot1:VCC
NOCOMNCVCCGNDINLED1PWRRelay Module
relay1:VCC
relay1:GND
relay1:IN
relay1:NC
relay1:COM
relay1:NO
led4:A
led4:C
led5:A
led5:C
r4:1
r4:2
r5:1
r5:2
led8:A
led8:C
r8:1
r8:2