////////////////////////////////////////////////
////Author: Mamadou Diallo		 //////
////EMail: misterdiallo1@gmail.com	//////
/////////////////////////////////////////////

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"

#include <LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
SoftwareSerial * gsm;

RTC_DS1307 rtc;

// Definition des pins des capteurs et actionneurs
#define capteur_hum_sol A1    //capteur humidite sol a connecter sur le A0
#define pin_hum_sol 2         //connecter le + du capteur humidite sol 
#define pompe 3               //connecter le S du relais sur la pin 3, il controle la pompe
#define electrovanne 4        //connecter le S du relais sur la pin 4, il controle l'electrovanne
#define capteur_reservoir 5   //connecter le capteur de niveau d'eau 

//Déclaration des variables du programme
int valeur_hum_sol = 0;  // on stocke les valeurs lu par le capteur d'humidité sol
int heure = 00;
int minut =   0;
int etat_sms = 0;

int Switch = 10; //switch boutton poussoir encoder
byte portA = 11; //encoder     invertion fritzing 6
byte portB = 9; // encoder
byte etat = 0;
bool etat_switch = false;


char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

LiquidCrystal_I2C  lcd(0x3F, 2, 1, 0, 4, 5, 6, 7); // 0x27 is the I2C bus address for an unmodified backpack


void setup ()
{
  Serial.begin(9600);

  // activate LCD module
  lcd.begin (16, 2); // for 16 x 2 LCD module
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("KHomiAuto");
  delay(1000);
  lcd.clear();

  //affichage du temps sur écran pendant 500ms
  DateTime now = rtc.now();
  lcd.setCursor(0, 0);
  lcd.print(now.hour());
  lcd.print(':');
  lcd.print(now.minute());
  delay(500);


  //GSM configuration et envoie sms pour alerter que le systéme est allumé
  gsm = new SoftwareSerial(8, 7);
  gsm->begin(9600);
  gsm->print("pin state low\n");
  delay(3000); // give time for GSM module to register on network.
  gsm->println("AT+CMGF=1"); // set SMS mode to text
  delay(200);
  gsm->println("AT+CNMI=2,2,0,0,0"); //  Module de jeu pour envoyer des données SMS vers série dès réception
  delay(200);
  gsm->println("AT+CMGF=1");// envoi du message
  delay(500);
  //Serial.println("AT+CMGS=\"46030329\"");
  gsm->println(String("AT+CMGS=") + String("\"41080188") + String("\""));
  delay(500);
  gsm->print("systeme allumer");
  delay(500);
  gsm->write(26);
  delay(500);

  //pin configuration
  pinMode(capteur_hum_sol, INPUT);
  pinMode(capteur_reservoir, INPUT);
  pinMode(portA, INPUT);
  pinMode(portB, INPUT);
  pinMode(Switch, INPUT_PULLUP);
  pinMode(pin_hum_sol, OUTPUT);
  pinMode(pompe, OUTPUT);
  pinMode(electrovanne, OUTPUT);
  attachInterrupt(0, control, CHANGE);
  attachInterrupt(1, control, CHANGE);

  ////////////////////////////////////// configuration de l'horloge //////////////////////////////////////
  if (! rtc.begin())
  {
    // Serial.print("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning())
  {
    Serial.print("RTC is NOT running!");
  }

  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));//auto update from computer time
    rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));// configurer manuellement l'heure

  ////////////////////////////////////////////////////////////////////////////////////////////////////////
}

void loop ()
{
  // on lit l'heure sur le rtc
  DateTime now = rtc.now();

  //on lance le debug pour verifier si il ya pas de probleme
  Debug();
  control();
  affiche_lcd();

  //on test si on n'a recu un message
  if (gsm->available() > 0)
  {
    if (gsm->read() == '#')
    {
      delay(10);
      if (gsm->read() == 'a') {
        if (reservoir_test() == true)
        {
          etat_sms = 1;
          arroser();
        }
        else // sinon on envoie un message alert que le reservoir est vide
        {
          sms("Reservoir vide");
        }
      }
    }

  }



  //on test si il est heure d'arroser
  else if ((now.hour() == heure ) && (now.minute() == minut) && (now.second() == 00))
  {

    if (reservoir_test() == true)
    {
      arroser();
      lcd.setCursor(0, 1);
      lcd.print("fin arrosage");
      sms("Arrosage terminer avec succes");
    }

    else // sinon on envoie un message alert que le reservoir est vide
    {

      lcd.setCursor(0, 1);
      lcd.print("reservoir vide");
      sms("Reservoir vide");
    }

  }
}

////////////////////////////////////// fonction arroser  //////////////////////////////////////

void arroser () {

  digitalWrite(pin_hum_sol, HIGH);  // on allume le capteur

  //on lit 10 fois le capteur
  for (int i = 0; i < 10; i++)
  {
    valeur_hum_sol = analogRead(capteur_hum_sol); // on lit la valeur analogique du capteur

  }

  if ((valeur_hum_sol < 500) && (etat_sms == 1))
  {
    sms("le sol est mouiller pas besoin darroser");
    etat_sms = 0;
  }


  else if ((valeur_hum_sol > 500 ) && reservoir_test() == true)
  {
    do {
      //on lit 10 fois le capteur
      for (int i = 0; i < 10; i++)
      {
        valeur_hum_sol = analogRead(capteur_hum_sol); // on lit la valeur analogique du capteur

      }
      ///////////////////// on test le sol si il est mouille, on actionne les moteurs  /////////////////////
      if ((valeur_hum_sol > 500 ) && (reservoir_test() == true))
      {
        digitalWrite(electrovanne, HIGH); // on allume electrovanne
        delay(500);                       // on attend 500ms
        digitalWrite(pompe, HIGH);        // on allume la pompe
      }

    }
    while ((valeur_hum_sol > 500 ) && (reservoir_test() == true));        // tant que le sol est sec, on arrose

    sms("Arrosage terminé avec succès");

  }

  if ((valeur_hum_sol < 500 ) || (reservoir_test() == false))            // si le sol est mouillé
  {
    digitalWrite(electrovanne, LOW);    // on éteint l'electrovanne
    digitalWrite(pompe, LOW);           // on éteint la pompe
    digitalWrite(pin_hum_sol, LOW);     // on éteint le capteur

  }

}


////////////////////////////////////// fonction control ecran  //////////////////////////////////////

void control() {
  etat = etat << 1 | digitalRead(portA);
  etat = etat << 1 | digitalRead(portB);

  byte etat_test = (etat | B11110000) - B11110000;//test des 4 bits de poids faible

  //bouton poussoir
  if (digitalRead(Switch) == false)
  {
    etat_switch = !etat_switch;
  }

  // heure configuration
  if (( etat_test == B0111 ) && (etat_switch == 0))
  {
    heure++;
  }
  else if (( etat_test == B1011 ) && (etat_switch == 0))
  {
    heure--;

    if ( heure < 0)
    {
      heure = 00;
    }
  }

  // minute configurration
  if (( etat_test == B0111 ) && (etat_switch == 1))
  {
    minut++;
  }
  else if (( etat_test == B1011 ) && (etat_switch == 1))
  {
    minut--;

    if ( minut < 0)
    {
      minut = 00;
    }
  }

  else if (heure == 25)
  {
    heure = 00;
  }
  else if (minut == 61)
  {
    minut = 00;
  }

}

////////////////////////////////////// fonction test reservoir vide ou pas //////////////////////////////////////


bool reservoir_test()
{
  if (digitalRead(capteur_reservoir) == 1)
  {
    return true;
  }
  else
  {
    return false;
  }
}

////////////////////////////////////// fonction envoi sms  //////////////////////////////////////

void sms( String texte)
{
  gsm->println("AT+CMGF=1");// envoi du message
  delay(500);
  //Serial.println("AT+CMGS=\"46030329\"");
  gsm->println(String("AT+CMGS=") + String("\"41080188") + String("\""));
  delay(500);
  gsm->print(texte);
  delay(500);
  gsm->write(26);
  delay(500);
}

////////////////////////////////////// fonction affichage  //////////////////////////////////////

void affiche_lcd()
{
  DateTime now = rtc.now();

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("H=");
  lcd.print(heure);
  lcd.setCursor(7, 0);
  lcd.print("M=");
  lcd.print(minut);
  /* lcd.setCursor(2, 1);
    lcd.println(etat_switch);*/
  Serial.print(now.hour());
  Serial.print(':');
  Serial.print(now.minute());
  Serial.print(':');
}

////////////////////////////////////// Débug //////////////////////////////////////

void Debug()
{
  DateTime now = rtc.now();

  Serial.print(now.hour());
  Serial.print(':');
  Serial.print(now.minute());
  Serial.print(':');
  Serial.print(now.second());
  Serial.print("   ");

  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  Serial.print(" ,");
  Serial.print(now.day());
  Serial.print('/');
  Serial.print(now.month());
  Serial.print('/');
  Serial.print(now.year());

  Serial.print("       valeur humidite sol     ");
  Serial.print(valeur_hum_sol);

  Serial.print("      heure          ");
  Serial.println(heure);

  delay(1000);
}
