#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <Servo.h>
//-------------------VARIABLES GLOBALES--------------------------
int contconexion = 0;
unsigned long previousMillis = 0;
char ssid[50];     
char pass[50];
const char *ssidConf = "wifiConf";
const char *passConf = "12345678";
IPAddress ip(192,168,1,200);     
IPAddress gateway(192,168,1,1);   
IPAddress subnet(255,255,255,0); 
String mensaje = "";
int value = LOW;
int grados=0;
int pos=0;
int lado;
      
WiFiClient espClient;
ESP8266WebServer server(80);
WiFiServer server1(80);
WiFiClient client = server1.available();
Servo cortina;
//-------------------Variables de la casa---------------------
int luz1_cocina=5;            //D1
int luz2_cocina=4;            //D2
int cortina1_cocina=0;        //D3
int cortina2_cocina=2;        //D4
int microf_cocina=12;         //D6
int cargar_password=13;       //D7
//-----------CODIGO HTML PAGINA DE CONFIGURACION---------------
String pagina = "<!DOCTYPE html>"
"<html>"
"<head>"
"<title>Tutorial Eeprom</title>"
"<meta charset='UTF-8'>"
"</head>"
"<body>"
"</form>"
"<form action='guardar_conf' method='get'>"
"SSID:<br><br>"
"<input class='input1' name='ssid' type='text'><br>"
"PASSWORD:<br><br>"
"<input class='input1' name='pass' type='password'><br><br>"
"<input class='boton' type='submit' value='GUARDAR'/><br><br>"
"</form>"
"<a href='escanear'><button class='boton'>ESCANEAR</button></a><br><br>";
String paginafin = "</body>"
"</html>";
//------------------------SETUP WIFI-----------------------------
void setup_wifi() {
// Conexión WIFI
  WiFi.mode(WIFI_STA); //para que no inicie el SoftAP en el modo normal
  WiFi.config(ip, gateway, subnet);
  WiFi.begin(ssid, pass);
 
  while (WiFi.status() != WL_CONNECTED and contconexion <50)
    { //Cuenta hasta 50 si no se puede conectar lo cancela
    ++contconexion;
    delay(250);
    Serial.print(".");
  }
  if (contconexion <50) {   
      Serial.println("");
      server1.begin();
      Serial.println("WiFi conectado");
      // Muestro la IP local asignada. URL del servidor
      Serial.print("Usa esta URL para conectar al servidor: ");
      Serial.println(WiFi.localIP());
      Serial.println(ssid);
      Serial.println(pass);
  }
  else {
      Serial.println("");
      Serial.println("Error de conexion");
  }
}
//-------------------PAGINA DE CONFIGURACION--------------------
void paginaconf() {
  server.send(200, "text/html", pagina + mensaje + paginafin);
}
//--------------------MODO_CONFIGURACION------------------------
void modoconf() {
  WiFi.softAP(ssidConf, passConf);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("IP del acces point: ");
  Serial.println(myIP);
  Serial.println("WebServer iniciado...");
  server.on("/", paginaconf); //esta es la pagina de configuracion
  server.on("/guardar_conf", guardar_conf); //Graba en la eeprom la configuracion
  server.on("/escanear", escanear); //Escanean las redes wifi disponibles
 
  server.begin();
  while (true) {
      server.handleClient();
  }
}
//---------------------GUARDAR CONFIGURACION-------------------------
void guardar_conf() {
 
  Serial.println(server.arg("ssid"));//Recibimos los valores que envia por GET el formulario web
  grabar(0,server.arg("ssid"));
  Serial.println(server.arg("pass"));
  grabar(50,server.arg("pass"));
  mensaje = "Configuracion Guardada...";
  paginaconf();
}
//----------------Función para grabar en la EEPROM-------------------
void grabar(int addr, String a) {
  int tamano = a.length();
  char inchar[50];
  a.toCharArray(inchar, tamano+1);
  for (int i = 0; i < tamano; i++) {
    EEPROM.write(addr+i, inchar[i]);
  }
  for (int i = tamano; i < 50; i++) {
    EEPROM.write(addr+i, 255);
  }
  EEPROM.commit();
}
//-----------------Función para leer la EEPROM------------------------
String leer(int addr) {
   byte lectura;
   String strlectura;
   for (int i = addr; i < addr+50; i++) {
      lectura = EEPROM.read(i);
      if (lectura != 255) {
        strlectura += (char)lectura;
      }
   }
   return strlectura;
}
//---------------------------ESCANEAR----------------------------
void escanear() { 
  int n = WiFi.scanNetworks(); //devuelve el número de redes encontradas
  Serial.println("escaneo terminado");
  if (n == 0) { //si no encuentra ninguna red
    Serial.println("no se encontraron redes");
    mensaje = "no se encontraron redes";
  } 
  else
  {
    Serial.print(n);
    Serial.println(" redes encontradas");
    mensaje = "";
    for (int i = 0; i < n; ++i)
    {
      // agrega al STRING "mensaje" la información de las redes encontradas
      mensaje = (mensaje) + "<p>" + String(i + 1) + ": " + WiFi.SSID(i) + " (" + WiFi.RSSI(i) + ") Ch: " + WiFi.channel(i) + " Enc: " + WiFi.encryptionType(i) + " </p>\r\n";
      //WiFi.encryptionType 5:WEP 2:WPA/PSK 4:WPA2/PSK 7:open network 8:WPA/WPA2/PSK
      delay(10);
    }
    Serial.println(mensaje);
    paginaconf();
  }
}
//--------------------------funcion PINES--------------------------
void pines(){
 
  //Cocina
  pinMode(luz1_cocina, OUTPUT);
  digitalWrite(luz1_cocina, LOW);
  pinMode(luz2_cocina, OUTPUT);
  digitalWrite(luz2_cocina, LOW);
  //cargar_password
  pinMode(cargar_password,INPUT);
  }
//------------------------------SETUP----------------------------------
void setup() {
 
  // Inicia Serial
  Serial.begin(115200);
  Serial.println("");
  pines();
  EEPROM.begin(512);
 
  if (digitalRead(cargar_password) == 0) {
    Serial.println("Bienvenido al modo configuracion");
    modoconf();
  }
 
  leer(0).toCharArray(ssid, 50);
  leer(50).toCharArray(pass, 50);
 
  setup_wifi();     
}
//--------------------------LOOP--------------------------------
void loop() {
 
  // Compruebo si hay un cliente disponible (una petición)
 
  WiFiClient client = server1.available();
 
  if (!client) {
    return; // En caso de no haber un cliente, no hago nada
  }
 
  // Espero hasta que el cliente realice una petición
 
  Serial.println("¡Nuevo cliente!");
  while(!client.available()){
    delay(1);
  }
 
  // Leo la primera linea de la petición del cliente
 
  String request = client.readStringUntil('\r');     // Leo hasta retorno de carro
  //Serial.println(request);                         //Imprimo la petición
  client.flush();                                    //Limpio el buffer
 
  //LLamo a las funciónes 
      
 if (request.indexOf("/cocina")!=-1)
        cocina(request); 
 if(request.indexOf("/predeterminados")!=-1)
        predeterminados(request);   
   delay(1000);
}
//----------------------funcion Cocina---------------------------
void cocina(String request){
   //cortinas
  if(request.indexOf("/cortina1=izq")!=-1 ){
    lado=1;
    Cortina(lado, cortina1_cocina);
  }
   if(request.indexOf("/cortina1=der")!=-1){
    lado=0;
    Cortina(lado, cortina1_cocina);
  }
  if(request.indexOf("/cortina2=izq")!=-1){
    lado=1;
    Cortina(lado, cortina2_cocina);
  }
   if(request.indexOf("/cortina2=der")!=-1){
    lado=0;
    Cortina(lado, cortina2_cocina);
  }
    
  //luz
  if(request.indexOf("/luz1=on")!=-1){
    lado=1;
    Luz(lado, luz1_cocina);
  }
  if(request.indexOf("/luz1=off")!=-1){
    lado=0;
    Luz(lado, luz1_cocina);
  }
  if(request.indexOf("/luz2=on")!=-1){
    lado=1;
    Luz(lado, luz2_cocina);
  }
  if(request.indexOf("/luz2=off")!=-1){
    lado=0;
    Luz(lado, luz2_cocina);
  }
}
//-----------------funcion predeterminados----------------------------
void predeterminados(String request){
  if(request.indexOf("/opcion1")){
    predet_1();
    }
  if(request.indexOf("/opcion2")){
    predet_2();
    }
  if(request.indexOf("/opcion3")){
    predet_3();
    }
  }
//------------------------PREDETERMINADOS---------------------
//------------------------opcion 1 --------------------------
//Enciende todas las luces de la cocina y cierra las cortinas
void predet_1(){
  delay(1000);
  Luz(1,luz1_cocina);
  delay(1000);
  Luz(1,luz2_cocina);
  delay(1000);
  Cortina(0,cortina1_cocina);
  delay(1000);
  Cortina(0,cortina2_cocina);
  delay(1000);
 }
//------------------------opcion 2 --------------------------
//apaga todas las luces de la casa y cierra todas las cortinas
void predet_2(){
 
  delay(1000);
  Luz(0,luz1_cocina);
  delay(1000);
  Luz(0,luz2_cocina);
  delay(1000);
 
  Cortina(0,cortina1_cocina);
  delay(1000);
  Cortina(0,cortina2_cocina);
  delay(1000); 
 
  }
//------------------------opcion 3 --------------------------
//apaga todas las luces de la casa y abre todas las cortinas
void predet_3(){
  delay(1000);
  Luz(0,luz1_cocina);
  delay(1000);
  Luz(0,luz2_cocina);
  delay(1000);
 
  Cortina(1,cortina1_cocina);
  delay(1000);
  Cortina(1,cortina2_cocina);
  delay(1000);
    
 }
//------------------------FUNCIUONES DE SALIDA--------------------
//----------------------funcion cortina-------------------------------
void Cortina(int lado, int pin){
 
   Serial.println("accion: Cortina");
  cortina.attach(pin);
 
  if (lado==1){
    if (pos==0){
      for (grados=0;grados<=180;grados+=1){
        cortina.write(grados);
        delay(5);
          }
        }
      pos=1;
    }
      
  if (lado==0){
    if (pos==1){ 
      for (grados=180;grados>=0;grados -=1){
      cortina.write(grados);
      delay(5);
        }
      }
      pos=0;
  }
}
 
//---------------------funcion Luz----------------------------
void Luz(int lado, int pin){
  Serial.println("accion: Luz");
 
    if (lado==1)  {
    digitalWrite(pin, HIGH);
  }
  if (lado==0)  {
    digitalWrite(pin, LOW);
  }
}