////////////////////////////////////////////////////////////////////////////////
// Name:       IoTparty                                                       //
// Platform:   Arduino UNO R3                                                 //
// Created by: HARB rboek2@gmail.com november 2017 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 run: http://robotigs.com/flora/software/mobile/dashboard.php       //
// If programming do not forget to set BOTH dip-switches to off!              //
////////////////////////////////////////////////////////////////////////////////

// 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 <OneWire.h>         //Library can be installed through Arduino IDE menu

// Define Arduino board pins ---------------------------------------------------
OneWire       term1(2);     //The DS1820 temperatue sensor is connected to pin 2
#define ledRedPin    3   //3 Color LED, to which PWM pin this color is connected
#define ledGrePin    5   //3 Color LED, to which PWM pin this color is connected
#define ledBluPin    6   //3 Color LED, to which PWM pin this color is connected
#define pirPin      11      //To which digital input is the PIR sensor connected
#define relay1Pin   12            //Relay to which an 220 Vac light is connected
#define LED_BUILTIN 13           //Arduino boards contain an onboard LED_BUILTIN
#define ldrPin      A0      //Define to which I/O pin the LDR brick is connected

// Define variables ------------------------------------------------------------
bool   ledBinVal = LOW;       //You can chose HIGH-on or LOW-off for LED_BUILTIN
bool   pirVal1 = LOW;            //PIR sensor can be read ON=1=HIGH or OFF=0=LOW
bool   relVal1 = HIGH;              //You can choose either LOW=0=ON, HIGH=1=OFF
String html;              //HTML Response preapaired and counted into bodylength
unsigned int bodyLength;                                    //HTML answer length
String prgVal1 =  "2";  //You can choose either 0=OFF, 1=ON, 2=AUTO or 3=Unknown
word   waitSeconds = 50;      //Number of seconds to burn after motion detection
word   pirCounter = 0;        //Number of seconds to burn after motion detection
// 10 results during current tests in 2m16s. PIR setting time seems to be 2 mins
// 10 results during test2 in 0m22s.             PIR setting time seems to be 8s
// 100 results during test3 in 3m57s.            PIR setting time seems to be 8s
word   ldrVal = 0;                 //Contains last DAY/NIGHT measurement, 0-1023
word   ldrTrs = 600; //Treshold value on which to switch DAY/NIGHT, 0-1023=black
byte   ledRedVal =  10;     //Brightness of this Color, set by PWM 0=min 4=max!!
byte   ledGreVal =  20;    //Brightness of this Color, set by PWM 0=min 20=max!!
byte   ledBluVal =  10;     //Brightness of this Color, set by PWM 0=min 3=max!!
byte   present = 0;                     //Used for oneWire, present = ds.reset()
byte   i;                             //Used for oneWire, loopcounter byte array
byte   data[12];              //Used for oneWire to store data read from DS18B20
byte   type1_s = 0;     //0 = ok, except old DS1820 = 1, triggers different calc
byte   addr1[8]; //Array with the first 8 bytes of DS1820 ROM, including address
float  tmp1;                  //Used for oneWire to store calculated temperature
String Request  = "";                                    //Create receive string
String command  = "";                                    //Create receive string
String tempStr  = "";                                  //Create temporary string
//END OF PRECOMPILER OPTIONS ---------------------------------------------------


void setup() { //Setup runs once ***********************************************
  disable_jtag();              //Disable jtag to free port C, enabled by default
  Serial.begin(9600);   //Nothing more needed for the Serial Monitor to function
  pinMode(LED_BUILTIN, OUTPUT);  //Arduino boards contain an onboard LED_BUILTIN
  pinMode(ledRedPin, OUTPUT);             //Make the LED connections output pins
  pinMode(ledGrePin, OUTPUT);             //Make the LED connections output pins
  pinMode(ledBluPin, OUTPUT);             //Make the LED connections output pins
  digitalWrite(relay1Pin, relVal1);              //Turn the lamp relay ON or OFF
  pinMode(relay1Pin, OUTPUT);            //Make the lamp connections output pins
  analogWrite(ledRedPin, 0);            //Set the initial brightness of this LED
  analogWrite(ledGrePin, 0);            //Set the initial brightness of this LED
  analogWrite(ledBluPin, 0);            //Set the initial brightness of this LED
  analogReference(DEFAULT);           //Option may be different for other boards
  DS1820_init();             //Determins the type of DS1820 and reads properties
  ldrVal = analogRead(ldrPin);                         //Read voltage on LDR pin
  pirVal1 = digitalRead(pirPin);    //Read the status of the PIR movement sensor
  toggle_ledBin();                                           //Show we are awake
}//--(end setup )---------------------------------------------------------------


void loop() { //KEEP ON RUNNING THIS LOOP FOREVER ******************************
  DS1820_read();            //Reads the temperature from thermometer1 in Celsius
  Serial.println (tmp1);
  //ldrVal = analogRead(ldrPin);  //Reads light intensity from LDR voltage divider
  //readMotion();         //Read status of the PIR movement sensor and set counter
  //http_check();              //See if we received a http request and reply if so
  //setLamp();                 //Switches lamp ON or OFF according to menu setting
  toggle_ledBin();                  //Toggles the default on-board LED on or off

  //analogWrite(ledGrePin, ledGreVal);                     //Turn the GREEN LED on
  delay(20);                                        //Just to show the green LED
  //analogWrite(ledGrePin, 0);                                //Turn GREEN LED off
  delay(380);                                       //Just to show the green LED
} //End of void loop() ----------------------- KEEP ON RUNNING THIS LOOP FOREVER

  
void http_check(void) { //See if we received a http request and reply if so ****
  String Request = "";                                    //Reset receive string
  while (Serial.available() > 0) {   //Check if any request is made by a browser
    Request = String(Request + Serial.readString());   //Read incoming character
  } //End of while (Serial.available() > 0)           Entire block has been read
  if (Request != "") {                         //Did I really receive a request?
    //analyzeRequest();                             //Change settings if requested
    create_data_record();       //Join all readings and settings into one string
    bodyLength = html.length();  //Calculate the number of characters to be sent
    //bodyLength = bodyLength + 17;                           //Add the basic text
    Serial.println("HTTP/1.1 200 OK");                   //Answer to the request
    Serial.println("Connection: close");          //Close after html is finished
    Serial.print("Content-Length: ");        //Finish html after amount of chars
    Serial.println (bodyLength);
    Serial.println("Content-Type: text/html");         //Needed to be compatible
    Serial.println(" /n \n");                //Needed to end the headers somehow
    Serial.println(html);                                         //Entire tekst
  } //End of if (Request != "")
} //Exit http_check, end of See if we received a http request and reply if so---


void analyzeRequest(void) { //Change settings if requested *********************
    command = Request.substring(6, 19);                    //Extract the command

    //FRONTDOOR PROGRAM = INTERNET OF THINGS:   0=Off, 1=On, 2=Auto or 3=Unknown
    if (command == "frtdoorprg1=0") {                //Turn the lamp1/relay1 OFF
      prgVal1 = "0";                  //Set the lamp1/relay1 program mode to OFF
    } //End of if (command == "frtdoorprg1=0")
    if (command == "frtdoorprg1=1") {                 //Turn the lamp1/relay1 ON
      prgVal1 = "1";                   //Set the lamp1/relay1 program mode to ON
    } //End of if (command == "frtdoorprg1=1")
    if (command == "frtdoorprg1=2") {               //Turn the lamp1/relay1 AUTO
      prgVal1 = "2";                 //Set the lamp1/relay1 program mode to AUTO
    } //End of if (command == "frtdoorprg1=2")

    //FRONTDOOR TIMER SECONDS=INTERNET OF THINGS: 0=20, 1=60, 2=150 or 3=300 SEC
    if (command == "frtdoorsec1=0") {  //Set the number of seconds burning to 20
      waitSeconds = 20;           //The lamp will burn 20 seconds when activated
    } //End of if (command == "frtdoorsec1=0")
    if (command == "frtdoorsec1=1") {  //Set the number of seconds burning to 60
      waitSeconds = 60;           //The lamp will burn 60 seconds when activated
    } //End of if (command == "frtdoorsec1=1")
    if (command == "frtdoorsec1=2") { //Set the number of seconds burning to 150
      waitSeconds = 150;         //The lamp will burn 150 seconds when activated
    } //End of if (command == "frtdoorsec1=2")
    if (command == "frtdoorsec1=3") { //Set the number of seconds burning to 300
      waitSeconds = 300;         //The lamp will burn 300 seconds when activated
    } //End of if (command == "frtdoorsec1=3")
} //Exit analyzeRequest --------------------------------------------------------


void readMotion(void) { //Read status of the PIR movement sensor and set counter
  pirVal1 = digitalRead(pirPin);    //Read the status of the PIR movement sensor
  if (pirVal1 > 0) {                //Meaning that some motion has been detected
    analogWrite(ledRedPin, ledRedVal);          //Set the brightness of this LED
    if (pirCounter > 0) {       //If true then the light was already switched ON
        pirCounter = waitSeconds;      //Reset the counter to its maxcount value
    }else{                               //Meaning the light was in OFF position
      if (ldrVal < ldrTrs) {                              //True means it is DAY
        pirCounter = 0;    //Reset the counter to 0 meaning swtich the light OFF
      }else{                                            //Else means it is NIGHT
        pirCounter = waitSeconds;      //Reset the counter to its maxcount value
      }
    }
  }else{                                   //Meaning there is no motion detected
    analogWrite(ledRedPin, 0);       //Set the brightness of this LED to 0 = OFF
    if (pirCounter > 0) {                //If true then the light is switched ON
      pirCounter--;        //Reduces seconds left to wait b4 switching light OFF
    } //End of                        count down to zero for light to switch OFF
  } //End of if (pirVal1 > 0)                             end of motion detector
} //Exit readMotion ------------------------------------------------------------


void setLamp(void) { //Switches lamp ON or OFF according to menu setting *******
  if (prgVal1 == "0"){                //If the currently chosen program is 0=OFF
    relVal1 = 1;                                          //Switch the relay OFF
  } //----------
  
  if (prgVal1 == "1"){                 //If the currently chosen program is 1=ON
    relVal1 = 0;                                           //Switch the relay ON
  } //----------
  
  if (prgVal1 == "2"){               //If the currently chosen program is 2=AUTO
    if (pirCounter > 0){
      relVal1 = 0;                                         //Switch the relay ON
    } else {
      relVal1 = 1;                                        //Switch the relay OFF
    }
  }
  digitalWrite(relay1Pin, relVal1);              //Turn the lamp relay ON or OFF
  delay(1000);
} //Exit setLamp ---------------------------------------------------------------


void show_ledRel(void) { //Shows the BLUE LED as long as the Relay/Lamp is on **
//  show_ledRel();          //Shows the BLUE LED as long as the Relay/Lamp is on
  if (relVal1 > 0) {
    analogWrite(ledBluPin, 0);                  //Set the brightness of BLUE LED
  }else{
    analogWrite(ledBluPin, ledBluVal);          //Set the brightness of BLUE LED
  }
} //Exit show_ledRel -----------------------------------------------------------


void show_ledPir(void) { //Shows the BLUE LED as long as the PIR is on *********
  if (pirCounter = 0) {           //Turn LED on as long as the conter is running
    analogWrite(ledBluPin, ledBluVal);          //Set the brightness of BLUE LED
  }else{
    analogWrite(ledBluPin, 0);                               //Turn BLUE LED OFF
  }
} //Exit show_ledPir -----------------------------------------------------------

    
void create_data_record(void){  //Join all readings and settings into one string
  html = "<!DOCTYPE HTML>";        //Always start our HTML answer with this line
  html += "<html><head><title>Frontdoor1</title></head><body>";    //Normal page
  html += "fntdoortmp1=";
  html += String(tmp1, 1);
  html += "&fntdoorldr1=";
  html += ldrVal;
  html += "&frtdoorpir1=";
  html += pirVal1;
  html += "&frtdoorprg1=";
  html += prgVal1;
  html += "&frtdoorsec1=";
  html += waitSeconds;
  html += "&frtdoorrel1=";
  html += relVal1;
  html += "&frtdoortres=";
  html += ldrTrs;
  html += "fntdoorcmd1=";
  html += command;
  html += "</body></html>";                              //Terminating HTML page
} //Exit create_data_record ----------------------------------------------------


void DS1820_read(void) { //Reads the temperature from DS1820 in Celsius ********
  term1.reset();                              //Reset whatever still was running
  term1.select(addr1);                      //Set the parameters for the library
  term1.write(0x44);       //Start conversion, with parasite power on at the end
  delay(800);     //Maybe 750ms is enough, maybe not, takes a lot of time though
  present = term1.reset();              //We assume that the conversion is ready
  term1.select(addr1);                      //Set the parameters for the library
  term1.write(0xBE);                                          // Read Scratchpad
  for ( i = 0; i < 9; i++) {                                   //We need 9 bytes
    data[i] = term1.read();
  }
  int16_t raw = (data[1] << 8) | data[0];                      //Rotate the data
  tmp1 = (float)raw / 16.0;            //Untill they are in the correct position
} //Exit DS1820_read -----------------------------------------------------------


void DS1820_init(void) { //Determins the type of DS1820 thermometer1 ***********
  if (!term1.search(addr1)) {
    term1.reset_search();
    delay(250);
    return;
  }
  if (OneWire::crc8(addr1, 7) != addr1[7]) {
      return;
  }
  switch (addr1[0]) {         //The first ROM byte indicates which  tupe of chip
    case 0x10:
      type1_s = 1;
      break;
    case 0x28:
      type1_s = 0;
      break;
    case 0x22:
      type1_s = 0;
      break;
    default:
      return;
  } 
  term1.reset();
  term1.select(addr1);
  term1.write(0x44, 1);    //Start conversion, with parasite power on at the end
  delay(800);     //Maybe 750ms is enough, maybe not, takes a lot of time though
  present = term1.reset();
  term1.select(addr1);    
  term1.write(0xBE);                                           //Read Scratchpad
  for ( i = 0; i < 9; i++) {                                   //We need 9 bytes
    data[i] = term1.read();
  }

  int16_t raw = (data[1] << 8) | data[0];
  if (type1_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {       // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {     //// default is 12 bit resolution, 750 ms conversion time
    byte cfg = (data[4] & 0x60);     
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
  }
  tmp1 = (float)raw / 16.0;
} //Exit DS1820_init -----------------------------------------------------------

  
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 ----------------------------------------------------------


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


////////////////////////////////////////////////////////////////////////////////
// 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       -                          SPI //
// ~11   -  17 - PB3 -  11 - MOSI/OC2A/PCINT3  - PIR sensor in            PWM //
// ~10   -  16 - PB2 -  10 - SS/OC1B/PCINT2    -                          PWM //
// ~9    -  15 - PB1 -   9 - OC1A/PCINT1       -                          PWM //
// 8     -  14 - PB0 -   8 - PCINT0/CLK0/ICP1  - DS18B20                  DIO //
//                                                                            //
// CONNECTIONS RAILS TOP RIGHT: DIGITAL PWM<~> ****************************** //
// 7     -  13 - PD7 -   7 - PCINT23/AIN1      - SWITCH Relay 1           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           TXD //
// RX<-0 -   2 - PD0 -   0 - PCINT16/RCD       - Serial Monitor           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       -                          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 //
////////////////////////////////////////////////////////////////////////////////
// EEPROM MEMORY MAP:                                                         //
// Start End  Number Description                                              //
// 0000  0000      1 Never use this memory location to be AVR compatible      //
////////////////////////////////////////////////////////////////////////////////
//345678911234567892123456789312345678941234567895123456789612345678971234567898