/*
 * Aplikacia sa prihlasi do WIFI siete a kazdych 10 sec. cita instrukcie, co ma robit
 * Nasledne operaciu vykona 
 * Ak sa nevie prihlasit do wifi siete, pracuje v specialnom rezime  a kazdu minutu overuje, ci sa siet neobnovila
 * 
 */


#include <ESP8266WiFi.h>
#include <WiFiClient.h>
//#include <time.h>


/* 
//ESP Web Server Library to host a web page
#include <ESP8266WebServer.h>

*/

// Json podpora
#include <ArduinoJson.h>



// Pripojenie display
#include <Wire.h>

#define D8 16
#define D5 14
#define D7 13
#define D6 12
#define LED_D4 2
#define D1 5
#define D2 4
#define D3 0

// BMP280


#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_BME280.h> // D1 -> SCL; d2-> SDA

// nastavení adresy senzoru
#define BMP280_ADRESA (0x76)
// inicializace senzoru BMP z knihovny
  Adafruit_BMP280 bmp;


#define SEALEVELPRESSURE_HPA (1013.25)
  Adafruit_BME280 bme; // I2C

//#include <ESP8266HTTPClient.h>


// DHT Senzor teploty a vlhksti
#include "DHT.h"
// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

DHT dht(D5, DHTTYPE); 

struct dhtOutput {
   float t; //temp
   float h; //humidity
};






//---------------------------------------------------------------
//On board LED Connected to GPIO2
  
//SSID and Password of your WiFi router
const char* ssid = "mno_guest2";
//const char* ssid = "mno_4G";
const char* password = "testtest";
int defaultDelay;
 


//==============================================================
//                  SETUP
//==============================================================


//const char* host = "192.168.1.5";
const String host = "maky.ddns.net";
const String url = "http://"+ host+"/public/ArduinoRegister.php?mac="+WiFi.macAddress()+"&service=Teplota";

float bmp_temp = -100;
float bme_altitude = -100;
  
void setup(void){
  Serial.begin(9600);
  Serial.println("Arduino starting");
  Serial.println("WifiTempDeepSleep2020.ino");
  Serial.println("SSID:"+String(ssid));
  Serial.println("Password:"+String(password));
 
  Serial.setTimeout(2000);

  // Wait for serial to initialize.
  while (!Serial) { }

  Serial.println("Device Started");


  float pressure = 0;

  
  defaultDelay = 180000; // defaultne cakam 3 minuty
  struct dhtOutput dhtOut = readDHT11();

  if (!bme.begin(0x76)){
     Serial.println("BME280 senzor tlaku nenajdeny!");
  }else{
     dhtOut.t = bme.readTemperature();
     dhtOut.h = bme.readHumidity();
     pressure = bme.readPressure() / 100.0F;
     bme_altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
     Serial.println("BME280 Humidity: "+String(dhtOut.h) +" %\t Temperature: " + String(dhtOut.t) + " °C Pressure: " + String(pressure) + " hPA");
  }


  if (!bmp.begin(BMP280_ADRESA)) {
    Serial.println("BMP280 senzor tlaku nenajdeny!");
  }else{
     bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,  // Operating Mode. 
                  Adafruit_BMP280::SAMPLING_X2,     // Temp. oversampling 
                  Adafruit_BMP280::SAMPLING_X16,    // Pressure oversampling 
                  Adafruit_BMP280::FILTER_X16,      // Filtering. 
                  Adafruit_BMP280::STANDBY_MS_500); // Standby time. 
     pressure = (bmp.readPressure()/100.00);
     bmp_temp = bmp.readTemperature();
     Serial.println("BMP Presure:" + String(pressure) + " hPa");
     Serial.println("BMP Temperature:" + String(bmp_temp) + " °C");
  }


  
  odosliTeplotuNaServer(dhtOut,pressure);
  int sec = defaultDelay/1000;
  Serial.print("ESP8266 in sleep mode for ");
  Serial.print(String(sec));
  Serial.println(" sec");
  
  ESP.deepSleep(sec * 1000000);
  //ESP.deepSleep(2 * 1000000);
  
}
//==============================================================
//                     LOOP
//==============================================================

void loop(void){
}

struct dhtOutput readDHT11(){
  dht.begin();
  struct dhtOutput out;
  out.t = -100;
  out.h = -100;
  
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  int pocetPokusov = 10;

  while((isnan(h) || isnan(t)) && pocetPokusov > 0) {
    delay(2000);
    h = dht.readHumidity();
    t = dht.readTemperature();
    Serial.print(h);
    Serial.print(t);
    pocetPokusov--;
  }
  if (isnan(h) || isnan(t)) {
      Serial.println("Failed to read from DHT sensor!");
      return(out);
  }
  out.h = h;
  out.t = t;
  
  // Compute heat index in Celsius (isFahreheit = false)

  Serial.println("Humidity: "+String(h) +" %\t Temperature: " + String(t) + " °C ");
  return(out);
}

void odosliTeplotuNaServer(struct dhtOutput out, float pressure){

   //WiFi.disconnect();   
  WiFi.enableAP(0); // Toto zabezpeci, ze Arduino nezobrazuje svoj nazov vo wifi
  WiFi.begin(ssid, password);     //Connect to your WiFi router
  Serial.println("");

  int pocetPokusov = 30;
   
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED && pocetPokusov-- > 0) {
    delay(500);
    Serial.print(".");
  }

  if (WiFi.status() != WL_CONNECTED){
      Serial.print("ERROR: WIFI not connected");
      return;
  }
  
  //If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP

  // citam hodnotu napajania
  float pomer = 1000/192;  // pomer odporov 1M/470k
  float voltage =  (analogRead(A0) * 5.0)/1024;
  voltage = voltage * pomer;
  Serial.println("Voltge:" + String(voltage) + "V");
  
  WiFiClient client;
  Serial.print("\n[Connecting to %s ... "+ host);
  if (client.connect(host, 80))
  {

    if(out.t == -100){
      out.t = bmp_temp;
    }
    Serial.println("connected]");
    Serial.println("Sending a request to:");
    String teplota =  "&temp=" + String(out.t) 
                    + "&humidity=" + String(out.h) 
                    + "&ipAddress="+ WiFi.localIP().toString() 
                    + "&voltage=" + String(voltage)
                    + "&pressure=" + String(pressure);
    Serial.println(url+teplota);

    


    client.println("GET " + url + teplota + " HTTP/1.1"); +
    client.println("Host: " + host);
    client.println("Connection: close");
    client.println();


    int timeout = millis() + 5000;
    while (client.available() == 0) {
      if (timeout - millis() < 0) {
         Serial.println(">>> Client Timeout !");
         client.stop();
         return;
      }
    }

    Serial.println("[Response:]");
    
    while(client.available()) {
        String line = client.readStringUntil('\n');
        if (line.startsWith("{\"response")){
          Serial.println(line);

          //DynamicJsonBuffer jsonBuffer(300);
          DynamicJsonDocument doc(1024);
          
          //JsonObject& root = jsonBuffer.parseObject(line);
          auto error = deserializeJson(doc, line);
          if(error) {
                Serial.print(F("deserializeJson() failed with code "));
                Serial.println(error.c_str());
                return;
          }else{
               if (doc.containsKey("delay")){
                   defaultDelay = doc["delay"];
               }
               Serial.println("Delay:"+String(defaultDelay));
               break;
          }
        }
    }
    client.stop();
    Serial.println("[Disconnected]");
    /*
    setPin(LED_BUILTIN,false);
    delay(1000);
    setPin(LED_BUILTIN,true);
    */
  }
  else
  {
    Serial.println("connection failed!]");
    client.stop();
  }
}