
//librerias externas--------------------
#include <avr/power.h>
#include <SD.h>

#include "stdio.h"
/*
#include <SimpleDHT.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BMP3XX.h"
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
*/

//librerias propias--------------------
#include <GloboSonda.h>


//definiciones------------------------
#define PIN_SD_CS 53

#define PIN_LED_SD 11 
#define PIN_LED_GPS 12 
#define PIN_LED_SMS 13
#define PIN_POWERKEY_SIM808 48
//pin sensor temperatura y humedad
#define PIN_DHT22 2
//pines sensor presion atmosferica
#define SCK_BMP 4
#define MISO_BMP 5
#define MOSI_BMP 6
#define CS_BMP 7

//variables globales---------------------------------------------------
//inicializacion sensores
SensorDht dht(PIN_DHT22);
SensorBMP bmp(SCK_BMP, MISO_BMP, MOSI_BMP, CS_BMP );
SensorAcelerometro acele;
ArchivoSD arch(PIN_SD_CS);
Sim808Manager sim808;
ArchivoConfig cnf;
ReporteManager report(&cnf, &sim808);
StatusManager statusManager(PIN_LED_SD,PIN_LED_GPS,PIN_LED_SMS);

unsigned long timer=millis();
//---------------------------------------------------------------------

void setup() {
   initCOM();
  ModoBajaPotencia();
   
  //led de estatus en modo inicio
  statusManager.EmpiezaInicio();
  
  //Inicia acelerometro
  acele.Init();
  Utiles::Utiles::printCOM("Inicia archivo...");
  if (!arch.init_()) {
    Utiles::printCOM("Fallo en la tarjeta SD, no se encuentra");
  }
  else if(!cnf.ini())
  {
    Utiles::printCOM("Fallo al leer configuraciones");
  }

  //inicia modulo sim808---------------
  Serial2.begin(9600);
  Utiles::printCOM("inicia Sim");
  if(sim808.inicia(&Serial2, PIN_POWERKEY_SIM808,9600))
  {
    Utiles::printCOM("Modulo sim iniciado...");

      Utiles::printCOM("GPS iniciado...");
      DataGPSSimManager* coor=sim808.GetGPSValid();
      coor->getTimeStamp(arch.Timestamp);
      
      Utiles::printCOM("Datos gps validos...");
      //envia mensaje inicial------------------------------
      //report.enviaInfo();
      //report.enviaData();  
  }
  else
  {
    Utiles::printCOM("Fallo al iniciar SIM808");
  }
  
  statusManager.FinInicio();
  Utiles::printCOM("...FIN INICIALIZACIONES");
}

void loop() {
  //actualiza led estado------------------
  statusManager.Procesa();
  if(Utiles::isTime(&timer,cnf.TimerSD))
     RegistraSensores();
  else
    delay (150);
 
}

void RegistraSensores()
{
    char strFecha[24];
    //consigue nueva coordenada gps
    DataGPSSimManager* coor=sim808.GetGPS();
    
    coor->getFecha(strFecha);
    //actualiza estado gps
    statusManager.SetStatusGPS(coor->IsValid);

    //actualiza codigo de tiempo para archivos sd
    if(coor->IsValid)
    {
      coor->getTimeStamp(arch.Timestamp);
    }
    else
    {
      char strtimestamp[24];
       coor->getTimeStamp(strtimestamp);
       if(!strstr(strtimestamp,"00000000"))
        strcpy(arch.Timestamp, strtimestamp);
    }
    //actualiza estado sd
    statusManager.SetStatusSD(arch.compruebaFile());
    
    //guarda información en archivo
    arch.openFile();
    //escribe los milisegundos
    arch.writeVal(millis());   

   //Sensor temperatura y humedad--------------------------------
   arch.writeVal(dht.GetT());
   report.TempExt=dht.GetT();
   arch.writeVal(dht.GetH());   
   
   //sensor Presion----------------------------------------------
   arch.writeVal(bmp.GetT());
   report.TempInt=bmp.GetT();
   arch.writeVal(bmp.GetA());

   arch.writeVal(bmp.GetP());
   report.Pres=bmp.GetP();
   //sensor acelerometro magnetometro---------------------------
   float ax= acele.GetAx();
   arch.writeVal(ax);
    float ay = acele.GetAy();
   arch.writeVal(ay);
    float az = acele.GetAz();
   arch.writeVal(az);
   /*float a = sqrt(pow(ax,2)+pow(ay,2)+pow(az,2));   
   //para comprobar si está bien
   char charVal[10];                
   dtostrf(a, 2, 3, charVal);
   Utiles::printCOM("Aceleración: ");
   Utiles::printCOM(charVal);
   */
   arch.writeVal(acele.GetMx());
   arch.writeVal(acele.GetMy());
   arch.writeVal(acele.GetMz());
   
   // gps-----------------------------------------------------
   arch.writeVal((long unsigned int )(coor->IsValid?1:0));
   arch.writeVal((long unsigned int )coor->nSatelites);
   arch.writeVal(coor->pdop);
   arch.writeVal(coor->hdop);
   arch.writeVal(coor->vdop);
   arch.writeVal(strFecha);
   arch.writeValPrec(coor->lat);
   arch.writeValPrec(coor->lon);
   arch.writeVal(coor->altitude);
   arch.writeVal(coor->heading);
   arch.writeVal(coor->speed_kmh);
  
   arch.closeFile();
   
  //envia reporte (sms) si es necesario
  report.procesa();
  //actualiza estado sms
  statusManager.SetStatusSMS(report.SMSEnviados || report.GPRSdata);
  Utiles::printCOM("");
}

/*
 * Para log en puerto COM en modo DEBUG
 */
void initCOM()
{   
  Serial.begin(9600);
  Serial.println("Iniciando");
  UtilesDebug=true;
}

/*
 * Deshabilita hardware que no se usa para consumir menos
 */
void ModoBajaPotencia()
{
  //reduce frecuencia relog----------------------------
  /*if(ReduccionVelocidad > 1)
    {
      CLKPR = _BV(CLKPCE);  // enable change of the clock prescaler
    CLKPR = _BV(CLKPS0);  // divide frequency by 2
  }*/
  //deshabilita perifericos para reducir consumo--------
  power_adc_disable();
  //power_aca_disable();
  //power_adca_disable();
  
  power_usart1_disable();
  power_usart3_disable();
  
  /*
  power_timer5_disable();
  power_timer4_disable();
  power_timer3_disable();
  power_timer1_disable();
  power_timer0_disable();
  power_spi_disable();
  if(!UtilesDebug)
    power_usart0_disable();
  power_usart2_disable();
  
  power_usart0_disable();
  power_twi_disable();
  */
}
