2022_Projet_IOT-Surveillance_connectée

Dans l'objectif de sécuriser une salle de notre école, nous avons décidé de créer un dispositif permettant de réguler son accès et de répertorier les entrées et sorties dans un document en ligne consultable à tout moment. Pour ce faire, nous allons utiliser les puces RFID de nos cartes étudiantes pour pouvoir les scanner à l'entrée de la zone sensible. Aussi, nous allons mettre en place un système de surveilance vidéo qui intégrera de la reconnaissance faciale pour détecter le moindre intru.

Slides & Videos

Members

NameContribution
Ludovic DUVALProgrammation du module RFID et de l'ESP-12F.
Programmation de la réception et envoi des données sur le google sheet avec Google Apps Script.
Recherche du matériel.
Thibault FLORESRecherche de l'état d'art.
Recherche du matériel.
Découverte et compréhension de librairies pour la programmation.
Assistant pour la programmation du module RFID et de l'ESP-12F.
Assistant pour la programmation du module caméra de l'ESP32-CAM.
Aeneas RUS LINProgrammation du module caméra de l'ESP32-CAM et mise en place du programme de reconnaissance faciale de l'ESP32-CAM.
Câblage et soudage des différents modules du projet.
Modélisation 3D et impression du boîtier.
Organisation du travail et des tâches.

State of the Art

Business Aspect

La reconnaissance faciale, nouvelle méthode de pointage

Il existe déjà de nombreux systèmes de ce type :

  • Système de pointage à reconnaissance faciale. La plupart des technologies existantes se trouvent aux alentours de 500€, 300€ pour les entrées de gamme et jusqu’à 2500€ pour les matériels plus perfectionnés. Les applications dans le domaine professionnel sont nombreuses, notamment pour le pointage en entreprise. Les entreprises peuvent capturer, gérer et intégrer en toute sécurité les données de temps et de présence de leurs employés dans des systèmes de paie tels que ADP, QuickBooks, Paychex, etc., quand cela leur convient et de n’importe où via le Web. On les retrouve aussi dans les laboratoires et endroits aux accès sécurisés et contrôlés.

 

  • Les avantages :

Technologie de reconnaissance faciale à toute épreuve pour identifier instantanément les employés

Alternative hygiénique sans contact aux lecteurs d’empreintes digitales et manuels.

Evite la triche, les employés ne peuvent pas pointer pour les autres

  • Une caméra de surveillance à reconnaissance faciale. La technologie existe aussi et coûte entre 80€ et 400€. Elle est utilisée dans le domaine de la sécurité.

Cependant, notre problème est plus spécifique et nécessite une adaptation des systèmes. De plus, notre budget ne sera pas le même que les systèmes existants déjà.

Technical Aspect

ESP32-CAM Video Streaming and Face Recognition with Arduino IDE

Les principales techniques utilisées dans ce projet sont : -La vidéo surveillance avec reconnaissance faciale -La lecture de carte RFID -L’écriture en ligne. Afin de réaliser le système de surveillance, nous utilisons un lecteur de cartes RFID compatible Arduino, il a une portée de détection assez faible, ce qui le rend efficace pour la lecture de carte d’accès. On en retrouve différents types dans le commerce. Pour le domaine de la sécurité, le même type de lecteur est utilisé. Pour ce qui est de la caméra, nous utilisons un ESP32 CAM avec une caméra compatible. La résolution de la caméra est de 720p x 720 p, elle permet d’obtenir une image net, cependant il est possible dobtenir une image de meilleure qualité. Notre caméra fonctionne aussi par Wi-Fi. La plupart des systèmes de vidéo surveillance utilisent quant à eux des caméras de meilleure qualité. La plupart fonctionnent de manière filaire ce qui les rend plus difficiles à optimiser en matière de placement. L’utilisation d’Arduino permet une configuration efficace et spécifique. Dans le commerce, la plupart des installateurs utilisent leur propre logiciel ainsi que des PCB réalisés sur mesure. Il est difficile d’avoir davantage d’information à cause des normes de sécurité liées à ce domaine.

Project Description

Problem Definition
Le problème que nous cherchons à maîtriser grâce à ce projet est un problème de sécurité et intégrité des biens du BDE de Sup Galilée. En effet, cette association possède un local ouvert au public dans lequel les étudiants peuvent se détendre et retrouver leurs camarades. Une zone de ce local est particulièrement sensible car c’est dans cette partie que sont stockés une partie des biens de valeur de l’association, servant notamment à l’approvisionnement du snack. Cette zone se présente sous la forme d’un bar derrière lequel se trouvent des placards et des étagères contenant les biens (voir ci-contre).
Challenges & Motivation
L’objectif de ce projet est donc dans un premier temps de contrôler l’accès à cette zone sensible qui se fait par une trappe au niveau du bar (sur la gauche dans l’image). Le but est de faire en sorte que seules quelques personnes compétentes et autorisées puissent entrer. Pour cela nous allons concevoir un boîtier contenant un lecteur RFID qui pourra actionner une barrière et l’ouvrir si la personne qui se présente est apte à entrer dans la zone. Pour le savoir, nous allons utiliser le système RFID contenu dans les cartes étudiantes. Ainsi, lorsqu’une personne voudra entrer, elle devra passer sa carte devant le lecteur RFID et le système ouvrira ou non la barrière en fonction de l’identité de la personne qu’on aura récupéré grâce aux données RFID.

Dans un deuxième temps, nous souhaitons mettre en place un système de surveillance à l’intérieur de la zone via caméra. Ce système aura pour but d’enregistrer les activités, suspectes ou non à l’intérieur de la zone. L’objectif est d’identifier de potentiels intrus via reconnaissance faciale et de valider l’accès qui aura été donné par le système RFID. Si une personne passe la première barrière du système RFID mais a utilisé la carte d’un autre étudiant afin de passer, il sera filmé et identifié.

Le dernier objectif du système est de répertorier toutes les entrées et sorties dans la zone dans un tableau. On y stockera les identités des personnes ayant pénétré dans la zone ainsi que les horaires et les dates d'entrée et sortie. Les données seront exportées dans un document Google Sheet stocké en ligne et consultable à tout moment sur tout appareil connecté à internet avec les autorisations nécessaires.
Real and Complete Usecases

Le système d’accès : dans un premier temps, nous allons essayer d’identifier les étudiants grâce aux puces RFID contenues dans les cartes étudiantes. Celles-ci possèdent aussi un code barre que l’on peut scanner dans le cas où la méthode RFID ne fonctionnerait pas. Lorsque l’individu est reconnu par le système en tant que personne autorisée, la barrière permettant l’accès à la zone s’ouvre pour laisser passer la personne. On pourra ainsi savoir qui utilise la zone et quand ces personnes y entrent et en sortent. Ces données seront enregistrées dans un fichier excel sur le Google Drive du BDE. Le système de surveillance : il s’applique à la zone derrière le bar de la salle où se trouvent les biens. Il a pour but de sonner une alarme ainsi que d’enregistrer l’apparence et les actions d’un intrus lorsqu’il pénètre dans cette zone. L’observation est réalisée à l’aide d’une caméra qui est toujours allumée mais qui enregistre que quand une personne est dans la zone. Pour savoir si une personne est autorisée ou non, on utilise un système de reconnaissance faciale. Si la reconnaissance faciale ne correspond pas aux données renvoyées par le système d’accès, la personne sera considérée comme intrus.

Technical Description

Afin de réaliser ce projet, nous avons mis en commun nos différentes qualités. Nous avons utilisé l’ensemble des connaissances propres à chacun. Ces connaissances viennent à la fois de projets personnels, de notre enseignement académique, mais aussi de la documentation sur internet. Nous avons utilisé nos skills dans le domaine de l’électronique afin de mettre en place les connectiques entre les différents éléments de notre système. Nous avons mis en avant nos apprentissages sur l’environnement de développement Arduino. Nous avons utilisé nos enseignements pour les mettre à profit de ce projet.

Il a été indispensable de comprendre les codes exemples permettant de faire fonctionner les différents modules. Afin de rendre le code plus léger et de l’adapter à la faible mémoire des ESP, il a été indispensable de réduire les codes et de les optimiser.
 

Nous avons aussi utilisé nos compétences en design 3D afin de créer un boitier compact et fonctionnel. Il a été indispensable de trouver quelqu’un dans le groupe avec un bon esprit de leadership, c’est pourquoi un chef de projet est indispensable pour le bon fonctionnement du groupe. Nous avons appris à utiliser les différents outils de GOOGLE plus en détails tels que les googlent sheets et GOOGLE app script pour les faire communiquer avec notre système de surveillance.

Hardware

Materials
ImageNamePart NumberPriceCountLink
Carte ESP8266 ESP-12FESP8266 ESP-12F11€1🛒
Lecteur RFID‎JZK6,50€1🛒
Carte de développement Bluetooth ESP32-CAMDX13237211,50€1🛒
Kit électronique‎FR-EL-CK-00318€1🛒
Supports de Batterie AAWeewooday-Battery-Ke0312,50€1🛒
Adaptateur, Indicateur de Communication FT232RL7,99€1🛒
Schematic

Software

Arduino Code

var ss = SpreadsheetApp.openById('17J4FlfJIhlSSz_mlQSM4RuHyEAhmnrKBzPVJw6mSPEk');
var sheet = ss.getSheetByName('Sheet1');
var timezone = "Europe/Paris"


//MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
function doGet(e){
  Logger.log( JSON.stringify(e) );
  //----------------------------------------------------------------------------------
  //write_google_sheet() function in esp32 sketch, is send data to this code block
  //----------------------------------------------------------------------------------
  //get gps data from ESP32
  if (e.parameter == 'undefined') {
    return ContentService.createTextOutput("Received data is undefined");
  }
  //----------------------------------------------------------------------------------
  var Curr_Date = new Date();
  var Curr_Time = Utilities.formatDate(Curr_Date, timezone, 'HH:mm:ss');
  var name = stripQuotes(e.parameters.name);
  //Logger.log('name=' + name);
  //----------------------------------------------------------------------------------
  var nextRow = sheet.getLastRow() + 1;
  sheet.getRange("A" + nextRow).setValue(Curr_Date);
  sheet.getRange("B" + nextRow).setValue(Curr_Time);
  sheet.getRange("C" + nextRow).setValue(name);
  //----------------------------------------------------------------------------------

  //returns response back to ESP32
  return ContentService.createTextOutput("Card holder name is stored in column C");
  //----------------------------------------------------------------------------------
}


//MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
function stripQuotes( value ) {
  return value.toString().replace(/^["']|['"]$/g, "");
}

//MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
//Extra Function. Not used in this project.
//planning to use in future projects.
//this function is used to handle POST request
function doPost(e) {
  var val = e.parameter.value;
  
  if (e.parameter.value !== undefined){
    var range = sheet.getRange('A2');
    range.setValue(val);
  }
}
//MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
#include "esp_camera.h"
#include 

//
// WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality
//            Ensure ESP32 Wrover Module or other board with PSRAM is selected
//            Partial images will be transmitted if image exceeds buffer size
//

// Select camera model
//#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
//#define CAMERA_MODEL_ESP_EYE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
#define CAMERA_MODEL_AI_THINKER // Has PSRAM
//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM

#include "camera_pins.h"

const char* ssid = "Ananas";
const char* password = "catbread";
void startCameraServer();

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  Serial.println();
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  
  // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
  //                      for larger pre-allocated frame buffer.
  if(psramFound()){
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

#if defined(CAMERA_MODEL_ESP_EYE)
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
#endif

  // camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }

  sensor_t * s = esp_camera_sensor_get();
  // initial sensors are flipped vertically and colors are a bit saturated
  if (s->id.PID == OV3660_PID) {
    s->set_vflip(s, 1); // flip it back
    s->set_brightness(s, 1); // up the brightness just a bit
    s->set_saturation(s, -2); // lower the saturation
  }
  // drop down frame size for higher initial frame rate
  s->set_framesize(s, FRAMESIZE_QVGA);

#if defined(CAMERA_MODEL_M5STACK_WIDE) || defined(CAMERA_MODEL_M5STACK_ESP32CAM)
  s->set_vflip(s, 1);
  s->set_hmirror(s, 1);
#endif

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  startCameraServer();

  Serial.print("Camera Ready! Use 'http://");
  Serial.print(WiFi.localIP());
  Serial.println("' to connect");
}

void loop() {
  // put your main code here, to run repeatedly:


}
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
//-----------------------------------------
#define RST_PIN  D3
#define SS_PIN   D4
#define BUZZER   D2     
//-----------------------------------------
/* Be aware of Sector Trailer Blocks */
int blockNum = 2;  
/* Create another array to read data from Block */
/* Legthn of buffer should be 2 Bytes more than the size of Block (16 Bytes) */
byte bufferLen = 18;
byte readBlockData[18];
//-----------------------------------------
String card_holder_name;
const String sheet_url = "https://script.google.com/macros/s/AKfycbyHFGk0PHcxqFmBRMBD_O6_JbHDj3dP6UwSV5YvHr2V9sOT8ScuJ3dS1H8f1A77Jpml/exec?name=";
//-----------------------------------------
// Fingerprint for demo URL, expires on ‎Monday, ‎May ‎2, ‎2022 7:20:58 AM, needs to be updated well before this date
// 0x9a, 0x71, 0xde, 0xe7, 0x1a, 0xb2, 0x25, 0xca, 0xb4, 0xf2, 0x36, 0x49, 0xab, 0xce, 0xf6, 0x25, 0x62, 0x04, 0xe4, 0x3c
const uint8_t fingerprint[20] = {0x9a, 0x71, 0xde, 0xe7, 0x1a, 0xb2, 0x25, 0xca, 0xb4, 0xf2, 0x36, 0x49, 0xab, 0xce, 0xf6, 0x25, 0x62, 0x04, 0xe4, 0x3c};
//-----------------------------------------
#define WIFI_SSID "Ananas"
#define WIFI_PASSWORD "catbread"
//-----------------------------------------

MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
MFRC522::MIFARE_Key key;
String tag;
int attente = 2000;
int valid = 0;
int i,j;
int UID_receive[4];
char* UID_c;
char* identite;


#define NB_max 10 
int UID_ref[NB_max][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};
char* liste_identite[NB_max] = {"User1","User2","User3","User4","User5","User6","User7","User8","User9","User10"};
int admin[4] = {162,80,234,26};
int NB_id = 0;

int UID_equals(int* a, int* b){
  for(int k = 0; k < 4; k++){
    if (a[k] != b[k]) return 0;
  }
  return 1;
}

#define LED_BLEUE D0
#define LED_VERTE D1
#define LED_ROUGE D8

/****************************************************************************************************
 * setup() function
 ****************************************************************************************************/
void setup()
{
  pinMode(LED_BLEUE, OUTPUT);
  pinMode(LED_VERTE, OUTPUT);
  pinMode(LED_ROUGE, OUTPUT);
  digitalWrite(LED_BLEUE, LOW);
  digitalWrite(LED_VERTE, LOW);
  digitalWrite(LED_ROUGE, LOW);
  //--------------------------------------------------
  /* Initialize serial communications with the PC */
  Serial.begin(9600);
  //Serial.setDebugOutput(true);
  //--------------------------------------------------
  //WiFi Connectivity
  Serial.println();
  Serial.print("Connecting to AP");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED){
    Serial.print(".");
    delay(200);
  }
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
  //--------------------------------------------------
  /* Set BUZZER as OUTPUT */
  pinMode(BUZZER, OUTPUT);
  //--------------------------------------------------
  /* Initialize SPI bus */
  SPI.begin();
  rfid.PCD_Init(); // Init MFRC522
  //--------------------------------------------------
}




/****************************************************************************************************
 * loop() function
 ****************************************************************************************************/
 void loop()
{
  //Serial.printf(".\n");
  //Serial.printf("###################\n");
  if ( ! rfid.PICC_IsNewCardPresent())
    return;
  //Serial.printf("........\n");
  if (rfid.PICC_ReadCardSerial()) {
    for (i = 0; i < 4; i++) {
      UID_receive[i] = rfid.uid.uidByte[i];
    }

    if(UID_equals(admin, UID_receive)){
      if (NB_id == NB_max - 1){
        Serial.printf("Nombre maximal d'utilisateurs atteint !\n");
      }else{
        digitalWrite(LED_VERTE, HIGH);
        Serial.printf("Patientez 5s\n");
        delay(1000);
        Serial.printf("Patientez 4s\n");
        delay(1000);
        Serial.printf("Patientez 3s\n");
        delay(1000);
        Serial.printf("Patientez 2s\n");
        delay(1000);
        Serial.printf("Patientez 1s\n");
        delay(1000);
        digitalWrite(LED_VERTE, LOW);
        digitalWrite(LED_BLEUE, HIGH);
        Serial.printf("Scannez le nouvelle utilisateur.\n");
        while(! rfid.PICC_IsNewCardPresent());
        if (rfid.PICC_ReadCardSerial()) {
          for (i = 0; i < 4; i++) {
            UID_receive[i] = rfid.uid.uidByte[i];
          }
        }
        for (i = 0; i < 4; i++) {
          UID_ref[NB_id][i] = UID_receive[i];
        }
        NB_id++;
        Serial.printf("La carte est enregistrée !\n");
        
        delay(1000);
        digitalWrite(LED_BLEUE, LOW);
      }
    }else{
      //Serial.printf("..........................\n");
      for(i=0;iclient(new BearSSL::WiFiClientSecure);
          //-------------------------------------------------------------------------------
          client->setFingerprint(fingerprint);
          // Or, if you want to ignore the SSL certificate
          //then use the following line instead:
          // client->setInsecure();
          //-----------------------------------------------------------------
          card_holder_name = sheet_url + identite;
          card_holder_name.trim();
          Serial.println(card_holder_name);
          //-----------------------------------------------------------------
          HTTPClient https;
          Serial.print(F("[HTTPS] begin...\n"));
          //-----------------------------------------------------------------

          //NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
          if (https.begin(*client, (String)card_holder_name)){
            //-----------------------------------------------------------------
            // HTTP
            Serial.print(F("[HTTPS] GET...\n"));
            // start connection and send HTTP header
            int httpCode = https.GET();
            //-----------------------------------------------------------------
            // httpCode will be negative on error
            if (httpCode > 0) {
              // HTTP header has been send and Server response header has been handled
              Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
              // file found at server
            }
            //-----------------------------------------------------------------
            else 
            {Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());}
            //-----------------------------------------------------------------
            https.end();
            delay(1000);
          }
          //NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
          else {
            Serial.printf("[HTTPS} Unable to connect\n");
          }
          //NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
        }
        digitalWrite(LED_VERTE, LOW);
        //MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
      }else{
        digitalWrite(LED_ROUGE, HIGH);
        Serial.printf("Personne non reconnue !\n");
        delay(2000);
        digitalWrite(LED_ROUGE, LOW);
      }
    }
  }
  valid = 0;
  i = 0;
  rfid.PICC_HaltA();
  rfid.PCD_StopCrypto1();
  //Serial.printf("........................................................\n");
}

External Services

GoogleSheet

C’est sur ce document en ligne que nous envoyons les données d’entrée et sortie dans la zone protégée. On récupère notamment l’identifiant des personnes autorisées à entrer dans la zone au moment où elles scannent leur carte étudiante.

Google Apps Script

C’est grâce à cette application que nous pouvons recevoir les données de l’arduino et les transférer sur le Google Sheet.