/*
Voici une solution à notre défi programmation Arduino.
Il existe plein d'autres façons de le résoudre, vous n'aurez donc certainement
pas le même code qu'ici. Ce programme-ci a néanmoins été écrit en tâchant d'être
le plus clair et compréhensible.
*/

/* On déclare un objet 'moteur' pour contrôler le moteur, 
en utilisant la librairie ESP32Servo */
#include <ESP32Servo.h> 
Servo moteur;

/* On déclare un objet 'led_rgb', pour contrôler la LED de couleur, 
en utilisant la librairie Adafruit_NeoPixel */
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel led_rgb(
    1 /* nombre de pixels */, 23 /* broche */, 
    NEO_GRB + NEO_KHZ800 /* type de LED */);

/* On déclare un objet 'clavier', en utilisant la librairie Keypad */
#include <Keypad.h>
const byte ROWS = 4;
const byte COLS = 4;
const char keys[ROWS][COLS] = { /* ce tableau associe à chaque touche un chiffre/une lettre */
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {18, 5, 17, 16}; /* numéros de broches des rangées */
byte colPins[COLS] = {4, 0, 2, 15};   /* numéro de broches des colonnes */
Keypad clavier = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

/* On déclare les variables globales du programme */
String code = ""; /* enregistre le code tapé par l'utilisateur */
String password = "123A"; /* enregistre le code de verrouillage attendu */

/*
La fonction setup() sert à configurer et initialiser le microcontrôleur. 
Cette fonction est executée une seule fois, lorque le microcontrôleur démarre.
*/
void setup() {
  /* on démarre la connexion série, à vitesse 115200 bit/s */
  Serial.begin(115200);
  Serial.println();
  Serial.println("Bonjour le monde !");

  /* on démarre la LED de couleur */
  led_rgb.begin();

  /* on initialise le moteur en position verrouillée */
  moteur.attach(13); /* utilise la broche N°13 pour contrôler le moteur */
  fermer();   /* position verrouillée */
}


/*
Après l'initialisation, la fonction loop() est exécutée en boucle indéfiniment.
*/
void loop() {
  /* lire l'état du clavier */
  char key = clavier.getKey(); 

  if (key != NO_KEY) {
    /* touche appuyée -> j'ajoute le chiffre au code courant */
    code += key;
    Serial.print("Code tapé: ");
    Serial.println(code);

    if (code == password) {
      /* si on a tapé le mot de passe entier:
      pendant 1s, on ouvre et on allume en vert */
      Serial.println("On ouvre...");
      setColor(0, 255, 0);
      ouvrir();
      delay(1000);
      fermer();
      Serial.println("Et on referme !");
      setColor(0, 0, 0);
      /* et on remet à zéro pour le prochain utilisateur */
      code = "";
    } else if (password.startsWith(code)) {
      /* on n'a pas le mot de passe entier, mais c'est bien parti:
      un petit flash bleu */
      Serial.println("jusqu'ici c'est bon...");
      setColor(0, 0, 128);
      delay(250);
      setColor(0, 0, 0);
    } else {
      /* le code ne correspond pas au début du mot de passe, on remet à zéro */
      Serial.println("faux");
      setColor(255, 0, 0);
      delay(250);
      setColor(0, 0, 0);
      code = "";
    }
  }

  /* et on attend 10 millisecondes */
  delay(10);
}

/* quelques fonctions utiles... */

/* choisir la couleur de la LED, avec trois composantes 0 <= rouge, vert, bleu <= 255 */
void setColor(int r, int g, int b) {
  led_rgb.setPixelColor(0, led_rgb.Color(r, g, b));
  led_rgb.show();
}

/* ouvrir la porte = tourner à 90°C */
void ouvrir() {
  moteur.write(90);
}

/* fermer la porte = remettre droit */
void fermer() {
  moteur.write(0);
}