////////////////////////////////////////   PROJET SC: VEILLEUSE CONNECTEE   (IMA3)
//Claire Vandamme
//Justine Senellart
//Camille Saâd



//--------------------------------------------------------------------------------------------------------------- INITIALISATION CONSTANTES et paramètres


//INIT CAPTEUR PRESENCE

//temps donné pour calibrer le capteur de présence.(10-60 secs according to the datasheet)
int calibrationTime = 10;        
//the time when the sensor outputs a low impulse
long unsigned int lowIn;         
//the amount of milliseconds the sensor has to be low 
//before we assume all motion has stopped
long unsigned int pause = 500;  

boolean lockLow = true;
boolean takeLowTime;  
int pirPin = 3;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;
//var meaning the parent receives a message
int MESSAGE=0;


//INIT NEOPIXEL LED RGB

//add the library
#include <Adafruit_NeoPixel.h>
//control pin
# define PININ 12
# define PINOUT 8
 
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PININ, NEO_RGB + NEO_KHZ800);


//INIT PHOTRESISTANCE (LUMINOSITE AMBIANTE)
#define CAPTEUR A0
int luminosite = 0; 
int seuil = 200; 

//INIT interrupteur
const int pinInter = 9 ;
int etatBouton;


//--------------------------------------------------------------------------------------------------------------------------------------SETUP ()


void setup() {
  //SETUP LIAISON SERIE 
  Serial.begin(9600);

  //SETUP INTER
  pinMode(pinInter, INPUT_PULLUP); //le bouton est une entrée
  etatBouton = HIGH; //on initialise l'état du bouton comme "relaché"

  //SETUP LEDS
  //pour les RGB
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  //Led en sortie
  pinMode(PININ, OUTPUT);

  
  //SETUP CAPTEUR PRESENCE ET LED ROUGE
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);
  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      }
  Serial.println(" done");
  Serial.println("SENSOR ACTIVE");
    
    
  delay(50);
}


//------------------------------------------------------------------------------------------------------------------------FONCTIONS SECONDAIRES

void couleur(int R, int G, int B)
{
  strip.setPixelColor(0,R,G,B); 
  strip.show();
}


/*
// fait avec application
void choix_couleur()
{
  int R,G,B;
  
  Serial.println(" Rouge =");
  while (Serial.available()<0){ delay(10);}
  R=Serial.read();
  Serial.print(R);
  Serial.print("  Vert =");
  while (Serial.available()<0){ delay(10);}
  G=Serial.read();
  Serial.print(G);
  Serial.print("   Bleu =");
  while (Serial.available()<0){ delay(10);}
  B=Serial.read();
  Serial.print(B);
  
  delay(3000);
  couleur(R,G,B);
}
*/

void eteindre()
{
  strip.setPixelColor(0,0,0,0); 
  strip.show();
  digitalWrite(pirPin, LOW);
  digitalWrite(ledPin, LOW);
  digitalWrite(PININ, LOW);
}

void choix_intensite()
{
  int k;
  k=Serial.read();
  strip.setBrightness(k);  //permet de régler la luminosité
}

//fonction qui allume les led de manière automatique selon la luminosité ambiante
void lumiere_auto()
{
  //On récupère la valeur du seuil
  luminosite = analogRead(CAPTEUR);
  
  //Monitoring
  Serial.print("Luminosite = ");
  Serial.print(luminosite);
  Serial.print(" / Seuil = ");
  Serial.print(seuil);
 
  //Allumage de la led si la luminosité est inférieur au seuil (on l'allume dans la couleur blanche  la base)
  if(luminosite < seuil) {
    couleur(255,255,255);
    //Monitoring
    Serial.println(" / LED ON");
  } 
  //Dans le cas contraire, on l'éteint
  else {
    digitalWrite(PININ, LOW);
    eteindre();
    Serial.println(" / LED OFF");
  }
  delay(50);
}

/*
void choix_type_allumage()
{
  int choix;
  Serial.println("Vous pouvez choisir entre l'allumage automatique (choix=1) de la veilleuse et l'allumage manuel (choix=2).");
  choix= Serial.read();
  if(choix==1)
  {
    lumiere_auto();
  }
  else if (choix==2)
  {
    int on_off;
    Serial.println("Voulez vous allumer la veilleuse? (non = 0; oui =1)");
    on_off=Serial.read();
    //permet d'utiliser un allumage application. 
  }
  else
  {
    Serial.println("ERROR CHOIX ALLUMAGE.");
  }
}
*/

void mouvement()
{
  int i=0;
     while(i<5)
     {
      
      //MOVEMENT DETECTION
       if(digitalRead(pirPin) == HIGH)
       {
        digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
        if(lockLow)
        { 
          //makes sure we wait for a transition to LOW before any further output is made:
          lockLow = false;            
          //Serial.println("---");
          //Serial.print("motion detected at ");
          //Serial.print(millis()/1000);
          //Serial.println(" sec"); 
          delay(50);
         }         
        takeLowTime = true;
       }
      
       
       //DETECTION'S END
       if(digitalRead(pirPin) == LOW)
       {       
         digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

         if(takeLowTime)
         {
          lowIn = millis();          //save the time of the transition from high to LOW
          takeLowTime = false;       //make sure this is only done at the start of a LOW phase
          }
       //if the sensor is low for more than the given pause, 
       //we assume that no more motion is going to happen
         if(!lockLow && millis() - lowIn > pause){  
           //makes sure this block of code is only executed again after 
           //a new motion sequence has been detected
           lockLow = true;                        
           //Serial.print("motion ended at ");      //output
           //Serial.print((millis() - pause)/1000);
           //Serial.println(" sec");
           Serial.println(i);
           i++;
           
           //CHILD IS AWAKE
          // if(i==5 || ((millis() - pause)/1000)-(millis()/1000)> 10 
           if(i==5){
            Serial.println("Sommeil agite !!!");
            MESSAGE = 1; //servira pour la progra html (peut-être)
            Serial.println("MESSAGE"); 
            i=0;
            }
           delay(20);
           }
       }
     }
}



//fonction regroupant l'utilisation de la led de manière automatique et du capteur de mouvement.
//on veut l'utilisation du capteur (soit réalisation de mouvement) uniquement quand la led est allumée

//--------------------------------------------------------------------------------------------------------------------automatique()
void automatique()
{
  //On récupère la valeur du seuil
  luminosite = analogRead(CAPTEUR);
  int i=0;
  
  //Monitoring
  Serial.print("Luminosite = ");
  Serial.print(luminosite);
  Serial.print(" / Seuil = ");
  Serial.print(seuil);

     // on l'éteint
 if (luminosite > seuil)
 {
  eteindre();
  Serial.println(" / LED OFF");
 }

  //Allumage de la led si la luminosité est inférieur au seuil (on l'allume dans la couleur blanche  la base)
  //enfant couché il doit dormir
  else
  {
    //Monitoring
    couleur(255,255,255);
    
      
    while(i<=5)
    {
      luminosite = analogRead(CAPTEUR);

      if(luminosite < seuil)
      {
         couleur(255,255,255);
         
         
        //DETECTION D'UN MOUVEMENT
      if(digitalRead(pirPin)==HIGH)
      {
        digitalWrite(ledPin,HIGH);   // la led modélise la déection d'un mouvement selon l'etat du capteur
        if (lockLow)
        {
          //être sûr d'attendre la transistion à l'état LOW du capteur pour continuer :
          lockLow= false;
          delay(50); 
        }
        takeLowTime = true;
      }

      //FIN DE LA DETECTION
      if(digitalRead(pirPin)==LOW)
      {
        digitalWrite(ledPin, LOW);
        if(takeLowTime)
        {
          lowIn= millis();      // enregistrement du temps qu'il faut pour passer de HIGH à LOW pour le capteur
          takeLowTime = false;  // être sûr que cela se fait uniquement au debut du passage à LOW
        }
        // Ainsi si le capteur est LOW plus longtemps que la pause, on suppose qu'il n'y plus de mouvement
        // if > être sûr que la suite s'execute seulement après un nouveau mouvement, donc nouvelle séquence de led allumée
        if(!lockLow && millis()-lowIn > pause)
        {
          lockLow = true;
          i++;
          Serial.println(i);

          //CHILD AWAKE
          if(i==5)
          {
            Serial.println("Sommeil agite !!!");
            MESSAGE = 1;
            i=0;
          }
          delay(20);
        } 
      }
       
        delay(500);
      }
      else
      {
        eteindre();
        i=0;
      }
      
      
    }
    delay(50);
  }

}




//-------------------------------------------------------------------------------------------------------------------------------------------FONCTIONS PRINCIPALES




//---------------------------------------------------------------------------------------------------------------------------------mainveilleuse()

//fonction du programme principal (à copier plus tard dans la LOOP()
//elle permet l'utilisation de la veilleuse de manière automatique selon la position de l'interrupteur, sinon c'est l'application qui gere le contrôle
//Elle est constituée de la fusion des fonctions secondaires: lumiere_auto(), mouvement() et automatique()
void mainVeilleuse_auto()
{
  etatBouton = digitalRead(pinInter); //Rappel :pinInter = 9

  //MODE AUTOMATIQUE
    //si la veilleuse est allumé et interrupteur = LOW on utilise le mode automatique. 
   while (etatBouton == LOW) //test si le bouton a un niveau logique HAUT
    {    
        delay(1000);
        
        etatBouton = digitalRead(pinInter);

        if(etatBouton==LOW)
        {
           //On récupère la valeur du seuil
          luminosite = analogRead(CAPTEUR);
          int i=0;
  
          //Monitoring
          Serial.print("Luminosite = ");
          Serial.print(luminosite);
          Serial.print(" / Seuil = ");
          Serial.print(seuil);

          // on l'éteint
          if (luminosite > seuil)
          {
            eteindre();
            Serial.println(" / LED OFF");
          }

          //Allumage de la led si la luminosité est inférieur au seuil (on l'allume dans la couleur blanche  la base)
          //enfant couché il doit dormir
          else
          {
            //Monitoring
            couleur(255,255,255);  
      
    
            while(i<=5 && etatBouton==LOW)
            {
              luminosite = analogRead(CAPTEUR);

              if(luminosite < seuil)
              {
                couleur(255,255,255); 
        
                //DETECTION D'UN MOUVEMENT
                if(digitalRead(pirPin)==HIGH)
                {
                  digitalWrite(ledPin,HIGH);   // la led modélise la déection d'un mouvement selon l'etat du capteur
                  if (lockLow)
                  {
                    //être sûr d'attendre la transistion à l'état LOW du capteur pour continuer :
                    lockLow= false;
                    delay(50); 
                  }
                  takeLowTime = true;
                }

                //FIN DE LA DETECTION
                if(digitalRead(pirPin)==LOW)
                {
                  digitalWrite(ledPin, LOW);
                  if(takeLowTime)
                  {
                    lowIn= millis();      // enregistrement du temps qu'il faut pour passer de HIGH à LOW pour le capteur
                    takeLowTime = false;  // être sûr que cela se fait uniquement au debut du passage à LOW
                  }
                  // Ainsi si le capteur est LOW plus longtemps que la pause, on suppose qu'il n'y plus de mouvement
                  // if > être sûr que la suite s'execute seulement après un nouveau mouvement, donc nouvelle séquence de led allumée
                  if(!lockLow && millis()-lowIn > pause)
                  {
                    lockLow = true;
                    i++;
                    Serial.println(i);

                    //CHILD AWAKE
                    if(i==5)
                    {
                      Serial.println("Sommeil agite !!!");
                      MESSAGE = 1;
                      i=0;
                    }
                    delay(20);
                  }  
                }
       
                delay(500);
              }
            
              else
              {
                eteindre();
                i=0;
              }

              etatBouton = digitalRead(pinInter); //Rappel :pinInter = 9
      
            }
            delay(50);
          }
        }
        else
        {
          eteindre();
          Serial.println("UTILISATION APPLICATION");
        }
        
        etatBouton = digitalRead(pinInter); //Rappel :pinInter = 9
    }

    //MODE MANUEL (APPLICATION)   
    //on est eteint avec l'interrupteur manuel on peut tjrs utiliser l'application pour gerer la veilleuse
    eteindre(); //la LED reste éteinte
    Serial.println("UTILISATION APPLICATION");

    delay(1000);
    

}

//-------------------------------------------------------------------------------------------------------------------------------------------TESTS & LOOP == MAIN PROG

//fonction permettant de faire les tests des foncions secondaires
void tests()
{
 //couleur(255,0,0);
 //choix_couleur();
 //eteindre();
 //choix_intensite();
 //choix_type_allumage();
 //mouvement();
 //lumiere_auto();
 //automatique();
 delay(200);
}


void loop() 

{
 //tests();

 mainVeilleuse_auto();
 delay(200);
}
