////////////////////////////////////////////////////////////////////////////////
// Name:       FloraIoTUno-02 version 2019                                    //
// Platform:   Arduino UNO R3                                                 //
// Created by: HARB rboek2@gmail.com Januar 2019 GPL copyrights               //
// http://robotigs.com/robotigs/includes/bots_header.php?idbot=9              //
// This program acts as webserver. Receiving settings in requests and         //
//  transmitting sensor data as answers to the request.                       //
// To test internet: http://robotigs.com/flora/software/mobile/dashboard.php  //
// If uploading program do not forget to set BOTH dip-switches to off!        //
////////////////////////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////////////////////////
//3456789112345678921234567893123456789412345678951234567896123456789712345678//
// EEPROM MEMORY MAP:                                                         //
// Start End  Number Description                                              //
// 0000  0000      1 Never use this memory location to be AVR compatible      //
// 0001  0001      1 frontLightProg /Lamp: 1=off 2=on 3=auto RELAY1           //
// 0002  0003      2 frontLightON If LDR reaches this 2byte treshold RELAY1   //
// 0004  0005      2 frontLightSecsNumber seconds lamp switch ON RELAY1       //
////////////////////////////////////////////////////////////////////////////////




// SET PRECOMPILER OPTIONS *****************************************************
  //Initialse conditional compiling, uncomment to include, comment to exclude --
  // Do comment for runtime versions
  //#define RS232                 //Uncomment to include Serial Monitor sections

  //Define the needed header files for the precompiler, no charge if not used --
  #include <DHT.h> //Needed for DHT22 and DHT11 Temperature and humidity sensors
  #include <EEPROM.h>                       //Needed for read or write in EEPROM
    
  //Define PINS ----------------------------------------------------------------
  #define ledRedPin     3         //3 Colour LED, which PWM pin connects RED LED
  #define ledGrePin     5       //3 Colour LED, which PWM pin connects GREEN LED
  #define ledBluPin     6        //3 Colour LED, which PWM pin connects BLUE LED
  #define DHTPIN       10                   //Which DIO input pin connects DHT22
  #define pirPin       11                     //Which DIO input pin connects PIR
  #define Relay1Pin    12         //220Vac switch DIO output pin connects RELAY1
  #define ldrPin       A0   //Define to which I/O pin the LDR brick is connected
  #define DHTTYPE   DHT22     //What sensor is connected (AM2302) (AM2321) DHT22

  //Define EEPROM variables ----------------------------------------------------
  int    frontLightProg = 1;                    //Lamp: 1=off 2=on 3=auto RELAY1
  word   frontLightON   = 435;             //If LDR reaches this treshold RELAY1
  word   frontLightSecs = 300;            //Number seconds lamp switch ON RELAY1

  //Define DATABASE VARIABLES --------------------------------------------------
  int    frontRelay1    = HIGH;          //Status HIGH=off or LOW=on LAMP RELAY1
  int    frontPIR       = LOW;             //ON=1=HIGH or OFF=0=LOW movement PIR
  word   frontLDR       = 0;            //Light resistor measurement, 0-1023 LDR
  float  frontAirTemp;                    //Air temperature degree Celcius DHT22
  float  frontAirHum;                            //Air humidity percentage DHT22
  
  // Define variables ----------------------------------------------------------
  int    ledOnBoardVal  = LOW;   //You choose HIGH-on or LOW-off for LED_BUILTIN
  byte   brillance      = 0;     //Brightness of any color, just to test PWM LED
  byte   msWait         = 5;            //Test your patience during the test LED
  bool   ledBlueVal     = LOW;                 //HIGH-on or LOW-off for BLUE LED
  byte   ledRedPWM      = 4;                        //Brightness 1-4 PWM RED LED
  byte   ledGrePWM      = 20;                    //Brightness 1-20 PWM GREEN LED
  byte   ledBluPWM      = 10;                      //Brightness 1-3 PWM BLUE LED
  word   readCounter    = 0;      //Read sensors if counted down to zero SENSORS
  word   readTimer      = 9999;   //Fill readCounter after reaching zero SENSORS
  char   ssid[]         = "Ranonkel9_EXT";            //Network SSID (name) WIFI
  char   pass[]         = "Kat14_-5";                    //Network password WIFI
  String html           = "";                    //HTML Response preapaired WIFI
  int    command        = 0;                //Which user command to perform WIFI
  String Request        = "";                       //Create receive string WIFI
  int    bodyLength     = 0;                           //HTML answer length WIFI
  String tempo          = "";                             //Can be used anywhere 
  int    tmp1;                                            //Can be used anywhere 
  int    tmp2;                                            //Can be used anywhere 
  static unsigned long SwitchOFFtimer = millis()+ 300000;           //FRONTLIGHT

  //Initialize OBJECTS ---------------------------------------------------------
  DHT dht(DHTPIN, DHTTYPE);                            //Initialize DHT22 sensor
//END OF PRECOMPILER OPTIONS ---------------------------------------------------


void setup() { //Setup runs once ***********************************************
  disable_jtag();       //Disable jtag to free port C, enabled by default SYSTEM
  //EEPROMfirstTime();                    //First time use, set values in EEPROM
  frontLightProg = EEPROM.read(1);             ///Lamp: 1=off 2=on 3=auto RELAY1
  frontLightON   = eepromReadWord(2);      //If LDR reaches this treshold RELAY1
  frontLightSecs = eepromReadWord(4);     //Number seconds lamp switch ON RELAY1
  Serial.begin(57600);         //Nothing more needed for the Serial Monitor WIFI
  pinMode(LED_BUILTIN, OUTPUT);  //Arduino boards contain an onboard LED_BUILTIN
  pinMode(ledRedPin, OUTPUT);           //Make the LED connection output RED LED
  pinMode(ledGrePin, OUTPUT);         //Make the LED connection output GREEN LED
  pinMode(ledBluPin, OUTPUT);          //Make the LED connection output BLUE LED
  digitalWrite(Relay1Pin, HIGH);            //HIGH=off or LOW=on switches RELAY1
  pinMode(Relay1Pin, OUTPUT);      //Make the lamp connections output pins RELAY
  analogWrite(ledRedPin, 0);             //Set the initial brightness of RED LED
  analogWrite(ledGrePin, 0);           //Set the initial brightness of GREEN LED
  analogWrite(ledBluPin, 0);            //Set the initial brightness of BLUE LED
  
  //Start objects --------------------------------------------------------------
  dht.begin();                                          //Start DHT sensor DHT11
  
  //Test hardware and software -------------------------------------------------
  test_LEDs();       //PWM fade in and fade out for 3 colorLEDs on board ALL LED
} //End of setup ---------------------------------------------------------------



void loop() { //KEEP ON RUNNING THIS LOOP FOREVER ******************************
  readSensors();          //Read several sensors at timed intervals only SENSORS
  frontPIR = digitalRead(pirPin);   //Read the status of the PIR movement sensor
  setRelay1();                       //WATERING switch, calculate and set RELAY1
  http_check();              //See if we received a http request and reply if so
} //End of void loop() ----------------------- KEEP ON RUNNING THIS LOOP FOREVER




void setRelay1(){ //FRONTLIGHT switch, calculate and set RELAY1 ****************
    if (SwitchOFFtimer < millis()) { //If frontLightSecs SWITCH WATER OFF RELAY1
    frontRelay1 = HIGH;        //HIGH=off or LOW=on FRONTLIGHT RELAY1 SWITCH OFF
  } //End of if SwitchOFFtimer < millis         frontLightSecs SWITCH OFF RELAY1
  
  switch (frontLightProg) {       //Frontlight program: 1=off 2=on 3=auto RELAY1

    case 1:                                   //Program = 1 = Set FRONTLIGHT OFF
      frontRelay1 = HIGH;          //Status HIGH=off or LOW=on FRONTLIGHT RELAY1
    break;                     //End of Program = 1 = Set program FRONTLIGHT OFF
    
    case 2:                                    //Program = 2 = Set FRONTLIGHT ON
      frontRelay1 = LOW;           //Status HIGH=off or LOW=on FRONTLIGHT RELAY1
    break;                              //End of Program = 2 = Set FRONTLIGHT ON
    
    case 3:                                  //Program = 3 = Set FRONTLIGHT AUTO
      if (frontLDR > frontLightON and frontPIR == HIGH) {     //Treshold then ON
        frontRelay1 = LOW;      //Status HIGH=off or LOW=on FRONTLIGHT ON RELAY1
        SwitchOFFtimer = millis() + frontLightSecs*1000L;  //Set SWTICH OFF TIME
      }  //End of                        If measurement reaches treshold then ON
    break;                            //End of Program = 3 = Set FRONTLIGHT AUTO
    
  }                                               //End of switch frontLightProg
  digitalWrite(Relay1Pin, frontRelay1);                        //Switches RELAY1
} //Exit setRelay1 -------------------------------------------------------------




void http_check(void) { //See if we received a http request and reply if so ****
  Request = "";                                           //Reset receive string
  while (Serial.available() > 0) {   //Check if any request is made by a browser
    Request = String(Request + Serial.readString());  //Read incoming characters
  } //End of if (Serial.available() > 0)              Entire block has been read
  
  if (Request != "") {                        //Did we really receive a request?
    
    if (isDigit(Request[5])){                 //Check if we received any command
      tempo = Request.substring(5, 7);                   //Extract command 01-99
      command = tempo.toInt();          //Translate the function to a executable
      switch (command) {                         //Go to the according procedure
 
         case 1: //Command = 1 = Set program FRONTLIGHT ************************
           tempo = Request[8];             //Extract parameter 1=off 2=on 3=auto
           frontLightProg = tempo.toInt();          //Set program for FRONTLIGHT
           setRelay1();            //FRONTLIGHT switch, calculate and set RELAY1
           eepromWriteByte(1, frontLightProg);               //Set 1 byte EEPROM
         break; //End of command == 1     translates to command is 1=Set program

         case 2: //If LDR reaches treshold switch FRONTLIGHT ON ****************
           tempo = Request.substring(8, 12);       //Extract parameter 0000-9999
           frontLightON = tempo.toInt();          //Convert to decimal PARAMETER
           setRelay1();            //FRONTLIGHT switch, calculate and set RELAY1
           eepromWriteWord (2, frontLightON);               //Set 2 bytes EEPROM
         break; ///End of if (command == 2) Set switch ON FRONTLIGHT -----------

         case 3: //How many seconds to keep ON RELAY1   b4 switch FRONTLIGHT OFF
           tempo = Request.substring(8, 12);       //Extract parameter 0000-9999
           frontLightSecs = tempo.toInt();        //Convert to decimal PARAMETER
           setRelay1();            //FRONTLIGHT switch, calculate and set RELAY1
           eepromWriteWord(4, frontLightSecs);              //Set 2 bytes EEPROM
         break; //End of if (command == 3) Set switch OFF FRONTLIGHT -----------

      } //End of switch (command) the list with possible precedures ------------
    } //End of if (isDigit(Request[5])         /Check if we received any command
    
    sendHttpResponse();                               //Send a HTTP respnse WIFI
  } //End of if (Request != "") {              //Did we really receive a request
} //Exit http_check, end of See if we received a http request and reply if so---




void sendHttpResponse() { //Send a HTTP respnse WIFI ***************************
  refreshAnswer();                    //Replace the old answer by a new one DATA
  Serial.println("HTTP/1.1 200 OK");          //Start answer to the request WIFI
  Serial.println("Connection: close");       //Close after html is finished WIFI
  Serial.print("Content-Length: ");     //Finish html after amount of chars WIFI
  Serial.println (bodyLength);   //Name the amount of calculated characters WIFI
  Serial.println("Content-Type: text/html");      //Needed to be compatible WIFI
  Serial.println(" /n \n");                     //Needed to end the headers WIFI
  Serial.println(html);      //Broadcast the message to be shown in browser WIFI
} //Exit sendHttpResponse ------------------------------------------------------




void refreshAnswer(void) { //Replace the old answer by a new one WIFI **********
  if (String(frontAirTemp) == " NAN"){   //Correct answer if not connected DHT22
    frontAirTemp = 99.1;     //Both temperature and humidity will affected DHT22
    frontAirHum = -1;          //Humidity value gives status not connected DHT22
  }//End of String(propAirTemp) = " NAN" Answer corrected if not connected DHT22
  html =  String(frontLightProg) + " ";         //Lamp: 1=off 2=on 3=auto RELAY1
  html += String(frontRelay1) + " ";        //Status HIGH=off LOW=on LAMP RELAY1
  html += String(frontPIR) + " ";          //ON=1=HIGH or OFF=0=LOW movement PIR
  html += String(frontLDR) + " ";                //Light measurement, 0-1023 LDR
  html += String(frontAirTemp) + " ";     //Air temperature degree Celcius DHT22
  html += String(frontAirHum) + " ";             //Air humidity percentage DHT22
  html += String(frontLightON)+ " ";       //If LDR reaches this treshold RELAY1
  html += String(frontLightSecs);         //Number seconds lamp switch ON RELAY1
  bodyLength = html.length();  //Calculate the number of characters to sent WIFI
} //Exit refreshAnswer ---------------------------------------------------------



void readSensors() { //Read several sensors at timed intervals only ************
  if (readCounter == 0){       //Only perform measurements if counted down TIMER
    frontLDR = analogRead(ldrPin);              //Reads light intensity from LDR
    frontAirTemp = dht.readTemperature();    //Read temperature as Celsius DHT22
    frontAirHum = dht.readHumidity();     //Reading takes 250 milliseconds DHT22
    readCounter  =  readTimer;                         //RESET the counter TIMER
    refreshAnswer();                  //Replace the old answer by a new one DATA
    toggleBlueLed();                            //Toggles ON or OFF the BLUE LED
  }else{                                //Meaning counter was not yet zero TIMER
    readCounter--;                        //Decrement of the timer counter TIMER
  } //End of if (moistureCnt1 == 0)Perform measurements if counted down    TIMER
} //Exit readSensors -----------------------------------------------------------



void eepromWriteByte(word place, int parameter){ //Set EEPROM 1 byte and REFRESH
  EEPROM.write(place , parameter);            //Setting must be an integer WRITE
} //Exit eepromWriteByte -------------------------------------------------------



void eepromWriteWord(word place, word parameter){ //EEPROM 2 bytes and REFRESH*
  tmp1 = parameter/255;                           //Tmp1 contains the HIGH BYTE
  EEPROM.write(place, tmp1);                          //Setting HIGH byte WRITE
  tmp2 = parameter -(tmp1 * 255)   ;                       //Calculate LOW BYTE
  EEPROM.write(place + 1, tmp2);                      //Setting HIGH byte WRITE
} //Exit eepromWriteWord ------------------------------------------------------



word eepromReadWord(word address) { //EEPROM read a 2 byte word ****************
  tmp1 = EEPROM.read(address);             //Read the HIGH part of the word HIGH
  tmp2 = EEPROM.read(address+1);             //Read the LOW part of the word LOW
  return tmp1*255 + tmp2;                               // Return the word value
} //Exit eepromReadWord --------------------------------------------------------


  
void EEPROMfirstTime() { //First time use, set values in EEPROM ****************
  EEPROM.write(1, 1);                       //Watering: 1=off 2=on 3=auto RELAY1
  EEPROM.write(2, 1);                 //If LDR reaches this treshold HIGH RELAY1
  EEPROM.write(3, 11);                 //If LDR reaches this treshold LOW RELAY1
  EEPROM.write(4, 1)  ;              //Number seconds lamp switch ON HIGH RELAY1
  EEPROM.write(5, 55);                //Number seconds lamp switch ON LOW RELAY1
} //Exit EEPROMfirstTime -------------------------------------------------------


void test_LEDs(void){ //PWM fade in and fade out for 3 colorLEDs on board ******
  brillance = 0;
  while (brillance<50){
    analogWrite(ledRedPin, brillance);        //Set LED to desired PWM value RED
    brillance++;
    delay (msWait);
  }
  while (brillance>0){
    analogWrite(ledRedPin, brillance);        //Set LED to desired PWM value RED
    brillance--;
    delay (msWait);
  }
  analogWrite(ledRedPin, 0);            //Set LED to desired PWM value = off RED

  while (brillance<50){
    analogWrite(ledGrePin, brillance);      //Set LED to desired PWM value GREEN
    brillance++;
    delay (msWait);
  }
  while (brillance>0){
    analogWrite(ledGrePin, brillance);      //Set LED to desired PWM value GREEN
    brillance--;
    delay (msWait);
  }
  analogWrite(ledGrePin, 0);          //Set LED to desired PWM value = off GREEN

  while (brillance<50){
    analogWrite(ledBluPin, brillance);       //Set LED to desired PWM value BLUE
    brillance++;
    delay (msWait);
  }
  while (brillance>0){
    analogWrite(ledBluPin, brillance);       //Set LED to desired PWM value BLUE
    brillance--;
    delay (msWait);
  }
  analogWrite(ledBluPin, 0);           //Set LED to desired PWM value = off BLUE
} //Exit test_LEDs -------------------------------------------------------------



void toggleBlueLed(void){ //Toggles ON or OFF the blue LED *********************
  if (ledBluPWM > 0) {
    analogWrite(ledBluPin, 0);                  //Set the brightness of BLUE LED
    ledBluPWM = 0;
  }else{
    analogWrite(ledBluPin, 1);                  //Set the brightness of BLUE LED
    ledBluPWM = 5;
  }
} //Exit toggle_ledBin ---------------------------------------------------------




void toggle_ledOnBoard(void){ //Toggles the LED_BUILTIN on-board LED on or off *
  ledOnBoardVal = !ledOnBoardVal;                                 //Toggle value
  digitalWrite(LED_BUILTIN, ledOnBoardVal);     //Set Arduino boards onboard LED
} //Exit toggle_ledBin ---------------------------------------------------------




void disable_jtag(void) { //Disable jtag to free port C, enabled by default ****
#if defined(JTD)                           //Not all AVR controller include jtag
  MCUCR |= ( 1 << JTD );                                //Write twice to disable
  MCUCR |= ( 1 << JTD );                                       //So stutter once
#endif                                            //End of conditional compiling
} //Exit jtag_disable ----------------------------------------------------------




////////////////////////////////////////////////////////////////////////////////
// PIN ALLOCATIONS TABLE ARDUINO UNO                                          //
// Board -Atmel- PIN - IDE - Function          - Connection               ALT //
//                                                                            //
// CONNECTIONS RAILS TOP LEFT: DIGITAL PWM<~> ******************************* //
// SCL   -  28 - PC5 -19/A5- ADC5/SCL/PCINT13  -                          TWI //
// SDA   -  27 - PC4 -18/A4- ADC4/SDA/PCINT12  -                          TWI //
// AREF  -  21 - REF -     - AREF              -                              //
// GND   -  22 - GND -     - GND               -                              //
// 13    -  19 - PB5 -  13 - SCK/PCINT5        - LED Arduino LED_BUILTIN  SPI //
// 12    -  18 - PB4 -  12 - MISO/PCINT4       - SWITCH Relay 1 (purple)  SPI //
// ~11   -  17 - PB3 -  11 - MOSI/OC2A/PCINT3  - PIR sensor in (orange)   PWM //
// ~10   -  16 - PB2 -  10 - SS/OC1B/PCINT2    - DHT22 (yellow)           PWM //
// ~9    -  15 - PB1 -   9 - OC1A/PCINT1       -                          PWM //
// 8     -  14 - PB0 -   8 - PCINT0/CLK0/ICP1  -                          DIO //
//                                                                            //
// CONNECTIONS RAILS TOP RIGHT: DIGITAL PWM<~> ****************************** //
// 7     -  13 - PD7 -   7 - PCINT23/AIN1      -                          DIO //
// ~6    -  12 - PD6 -   6 - PCINT22/OCA0/AIN0 - LED blue                 PWM //
// ~5    -  11 - PD5 -   5 - PCINT21/OC0B/T1   - LED green                PWM //
// 4     -   6 - PD4 -   4 - PCINT20/XCK/T0    -                          INT //
// ~3    -   5 - PD3 -   3 - PCINT19/OC2B/INT1 - LED red                  PWM //
// ~2    -   4 - PD2 -   2 - PCINT18/INT0      -                          INT //
// TX->1 -   3 - PD1 -   1 - PCINT17/TXD       - Serial monitor / WIFI    TXD //
// RX<-0 -   2 - PD0 -   0 - PCINT16/RCD       - Serial Monitor / WIFI    RCD //
//                                                                            //
// CONNECTIONS RAILS BOTTOM LEFT: POWER ************************************* //
// 5V    -   7 - VCC -     - VCC               -                          VCC //
// RES   -   1 - RES -     - PCINT14/RESET     -                          RES //
// 3.3V  -     -     -     -                   -                              //
// 5V    -     -     -     -                   -                              //
// GND   -     -     -     -                   -                              //
// GND   -     -     -     -                   -                              //
// Vin   -     -     -     -                   -                              //
//                                                                            //
// CONNECTIONS RAILS BOTTOM RIGHT: ANALOG IN ******************************** //
// A0    -  23 - PC0 -A0/14- ADC0/PCINT8       - LDR module (green)       ADC //
// A1    -  24 - PC1 -A1/15- ADC1/PCINT9       -                          ADC //
// A2    -  25 - PC2 -A2/16- ADC2/PCINT10      -                          ADC //
// A3    -  26 - PC3 -A3/17- ADC3/PCINT12      -                          ADC //
// A4    -  27 - PC4 -A4/18- ADC4/SDA/PCINT12  -                          TWI //
// A5    -  28 - PC5 -A5/19- ADC5/SCL/PCINT13  -                          TWI //
////////////////////////////////////////////////////////////////////////////////
//3456789112345678921234567893123456789412345678951234567896123456789712345678//
// EEPROM MEMORY MAP:                                                         //
// Start End  Number Description                                              //
// 0000  0000      1 Never use this memory location to be AVR compatible      //
// 0001  0001      1 frontLightProg /Lamp: 1=off 2=on 3=auto RELAY1           //
// 0002  0003      2 frontLightON If LDR reaches this 2byte treshold RELAY1   //
// 0004  0005      2 frontLightSecsNumber seconds lamp switch ON RELAY1       //
////////////////////////////////////////////////////////////////////////////////