Accès labo 2

Gestion d’accès NFC et commande électrique pour Atelier

Bienvenue dans mon atelier

Que s’est-il passé ?

En approchant de la porte, un capteur PIR détecte le mouvement. L’écran s’allume et affiche, à l’aide de 8 icônes, les équipements sous tension de l’atelier et invite le passant à présenter son badge afin de désactiver la caméra de surveillance.
On peut alors pénétrer dans la pièce qui contient les machines, auxquelles je fais référence dans mes articles et qui m’ont permis de fabriquer la plupart de mes bidules.

  • La petite CNC de bureau Genmitsu 3020-PRO MAX V2
  • Le graveur laser Genmitsu L8 40W
  • L’imprimante Creality K1c
  • Le SpacePi X4 Creality
  • L’imprimante Creality K2 PRO
  • Le CFS Creality

Comment cela est arrivé ?

Je souhaitais contrôler l’alimentation électrique des équipements de l’atelier depuis mon bureau situé trois étages plus haut.

Démarrer le PC, ouvrir une session RDP, faire les mises à jour, préparer un travail d’impression, de gravure ou d’usinage…
Tout cela, sans devoir descendre dans mon labo, me paraissait d’un intérêt certain.

J’avais, en outre, tout un tas de chinoiseries parmi lesquelles, un lecteur de puces NFC MFRC522 et quelques badges MIFARE Classic 1K que je souhaitais mieux connaître.
Le CFS étant équipé d’un lecteur de ces mêmes puces, afin d’identifier les filaments, j’étais deux fois partant pour la découverte.

Bref, de quoi démarrer un projet audacieux et ma foi, un peu exagéré 😉

Joindre l’utile à l’agréable

En effet, comment mieux apprendre qu’en ayant un projet concret ?
Tout d’abord, définir mes exigences :

  • Commander quatre prises de courant dont celles de la caméra et du PC;
  • Mesurer et afficher la température
  • Détecter le mouvement
  • Lire un badge NFC et afficher l’état sur 3 LEDs
  • Afficher les équipements sous tension
  • Liaison MQTT avec ma centrale Home Assistant via une connexion Ethernet

Un premier élément sera placé à l’extérieur du local. Il sera chargé de détecter la présence, de lire le badge et d’afficher l’état d’alimentation des équipements ainsi que les messages destinés à la personne se présentant à la porte.

Le second sera installé à l’intérieur. Il fournira l’alimentation électrique, la connexion Ethernet, l’affichage de la température, les signaux pour commander une prise TTL comme celle décrite dans Prise de courant commutée par un signal TTL

commande labo 1

Le schéma des deux éléments

La partie supérieure droite montre l’élément extérieur.
A gauche, il s’agit de l’élément interne.
En bas à droite du connecteur J2, un exemple du circuit utilisé dans la prise TTL mentionnée plus haut.

Schéma Accès NFC

La partie hardware

Tot lès arèdja vinous d’ôriyant. *

Les liens ci-dessous sont donnés à titre d’exemples !

Element externe

Elément interne

  • Un connecteur 13 pins femelle;
  • Un microcontrôleur ESP32 Devkit1c;
  • Un module BME280 I2C;
  • Un module Enc28j60 SPI;
  • Un écran OLED 0,91″ SPI;
  • Un bouton poussoir NO;
  • 3 résistances Pull-Up;
  • Un boîtier imprimé en PLA;
  • Un câble d’alimentation muni d’une fiche plate;
  • Une alimentation IRM10-5.

La partie software

J’ai ajouté une difficulté supplémentaire. Le lecteur NFC doit être capable de détecter trois types de badges et agir en conséquence :

  • Un badge « caméra » commutera l’alimentation de la surveillance vidéo
  • Un badge « alimentation » commutera toutes les prises de courant
  • Un badge inconnu affichera une alarme sur l’écran

Platformio.ini

[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
monitor_speed=115200
lib_deps = 
     olikraus/U8g2@^2.36.5
     miguelbalboa/MFRC522@^1.4.12
     uipethernet/UIPEthernet@^2.0.12
     adafruit/Adafruit BME280 Library@^2.3.0
     sstaub/TickTwo@^4.4.0
     thomasfredericks/Bounce2@^2.72
     knolleary/PubSubClient@^2.8

jagprod.h

#ifndef jagprod_h
#define jagprod_h

// WiFi
#define sid "votre SSID"
#define wifi_sesame "Votre mot de passe WiFi"

// IP (Si utilisation en DHCP, supprimer cette partie)
const uint8_t ip[4] = {Adresse IP de l'hôte dans votre réseau};
const uint8_t mask[4] = {Masque de sous-réseaux};
const uint8_t ns[4] = {Adresse IP du serveur DNS};
const uint8_t gw[4] = {Adresse de la passerelle};

// MQTT
const char *mqtt_serveur = "adresse IP du serveur MQTT";
const uint16_t mqtt_port = port MQTT;
const char *mqtt_identifiant = "identifiant MQTT";
const char *mqtt_sesame = "Mot de passe MQTT";

#endif

main.cpp

// Les relais sont commandés par un niveau bas !!!
#include <Arduino.h>
#include <jagprod.h>
#include <SPI.h>
#include <WiFi.h>
#include <esp_wifi.h>

// I2C
#include <Wire.h>
const int i2c_sda_pin = 21;
const int i2c_scl_pin = 22;

// Affichage
#include <U8g2lib.h>
U8G2_SH1106_128X64_NONAME_F_HW_I2C ecran_externe(U8G2_R0, U8X8_PIN_NONE); // 0x76
const int cs_ecran_interne_pin = 25;
const int dc_ecran_interne_pin = 26;
const int rst_ecran_interne_pin = 27;
U8G2_SSD1306_128X64_NONAME_1_4W_HW_SPI ecran_interne(U8G2_R0, cs_ecran_interne_pin, dc_ecran_interne_pin, rst_ecran_interne_pin);
const int led_verte_pin = 32;
const int led_rouge_pin = 33;
const int led_orange_pin = 16;
bool led_verte = false;
bool led_orange = false;
bool led_rouge = false;
uint16_t wifi_icon = 0x01fd;
uint16_t musique_icon = 0x0238;
uint16_t camera_icon = 0x009d;
uint16_t alim_icon = 0x0081;
uint16_t k1_icon = 0x00f4;
uint16_t k2_icon = 0x00f5;
uint16_t radiateur_icon = 0x02bc;
uint16_t drybox_icon = 0x00dd;
int x_message2 = 5;
String message2 = "";
bool ethernet_state = false;
bool EtatEcran_interne = true;
bool EtatEcran_externe = false;
void affichage_externe();
static unsigned char tetemort_bits[] = {
    0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
    0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00,
    0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
    0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00,
    0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff,
    0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x03, 0x00,
    0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff,
    0xff, 0xff, 0x07, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
    0x00, 0x80, 0xff, 0xe0, 0x3f, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x7f, 0xc0,
    0x1f, 0xf0, 0x1f, 0x00, 0x00, 0xc0, 0x3f, 0x80, 0x0f, 0xe0, 0x1f, 0x00,
    0x00, 0xc0, 0x3f, 0x80, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0xc0, 0x3f, 0x80,
    0x0f, 0xe0, 0x1f, 0x00, 0x00, 0xc0, 0x3f, 0x80, 0x0f, 0xe0, 0x1f, 0x00,
    0x00, 0x80, 0x3f, 0x80, 0x0f, 0xe0, 0x0f, 0x00, 0x00, 0x80, 0x7f, 0xc0,
    0x1d, 0xf0, 0x0d, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x38, 0xf8, 0x07, 0x00,
    0x00, 0x00, 0xff, 0xff, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0xfe, 0x7f,
    0xf0, 0xff, 0x03, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0xf0, 0xff, 0x03, 0x00,
    0x00, 0x00, 0xfc, 0x3f, 0xe0, 0xff, 0x01, 0x00, 0x00, 0x00, 0xfc, 0x3f,
    0xe0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x18, 0x1e, 0xc0, 0xc3, 0x00, 0x00,
    0x00, 0x00, 0x18, 0xfe, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfc,
    0xff, 0x41, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xe1, 0x3f, 0x6c, 0x00, 0x00,
    0x00, 0x00, 0xb0, 0x0d, 0x80, 0x6d, 0x00, 0x00, 0x80, 0x01, 0x20, 0x6c,
    0xb7, 0x21, 0x00, 0x00, 0x80, 0x07, 0x60, 0x61, 0x37, 0x34, 0x80, 0x01,
    0xe0, 0x0f, 0x60, 0x0d, 0x80, 0x35, 0xc0, 0x01, 0xe0, 0x0f, 0x40, 0x6c,
    0xb7, 0x11, 0xe0, 0x01, 0xe0, 0x1f, 0xc0, 0x61, 0x37, 0x1c, 0xf0, 0x03,
    0xe0, 0x3f, 0x80, 0x0f, 0x80, 0x0f, 0xf8, 0x07, 0xfe, 0x3f, 0x80, 0xff,
    0xff, 0x0f, 0xfc, 0x0f, 0xff, 0x7f, 0x00, 0xff, 0xff, 0x07, 0xfc, 0x7f,
    0xff, 0xff, 0x01, 0xfc, 0xff, 0x01, 0xfe, 0xff, 0xfe, 0xff, 0x03, 0xf8,
    0xff, 0x00, 0xff, 0xff, 0xf0, 0xff, 0x0f, 0xe0, 0x3f, 0xc0, 0xff, 0x7f,
    0x80, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xfc, 0xff, 0x03,
    0x00, 0xfe, 0xff, 0x01, 0x00, 0xe0, 0xff, 0x0f, 0x80, 0xff, 0x3f, 0x00,
    0x00, 0x00, 0xff, 0x7f, 0xf0, 0xff, 0x07, 0x00, 0x00, 0x00, 0xf0, 0xff,
    0xfd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
    0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xfd, 0x07, 0x00, 0x00,
    0x00, 0x00, 0xe0, 0xff, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f,
    0xe0, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x0f,
    0xf0, 0xff, 0xff, 0x03, 0x00, 0xfc, 0xff, 0x1f, 0xf8, 0xff, 0x7f, 0x00,
    0x00, 0xf8, 0xff, 0x3f, 0xfc, 0xff, 0x1f, 0x00, 0x00, 0xe0, 0xff, 0x3f,
    0xfc, 0xff, 0x0f, 0x00, 0x00, 0xc0, 0xff, 0x03, 0xf8, 0xff, 0x03, 0x00,
    0x00, 0x80, 0xff, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00,
    0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00,
    0x00, 0x00, 0x7c, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00,
    0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// Sonde
#include <Adafruit_BME280.h>
Adafruit_BME280 sonde;
bool errorbme280 = false;
float temperature;
float humidity;
float pression;

// RFID
#include <MFRC522.h>
const int rfid_rst_pin = 17;
const int rfid_cs_pin = 5;
MFRC522 rfid(rfid_cs_pin, rfid_rst_pin);
String uid = "";
bool OkPourBadger = true;
MFRC522::MIFARE_Key cle = {{0xzz, 0xzz, 0xzz, 0xzz, 0xzz, 0xzz}}; // Definir ici votre propre clé
String blocdata = "";

// Ethernet IP
#include <UIPEthernet.h>
const int cs_enc28j60_pin = 15;
bool network_statut = false;
#include <Dns.h>
int dnsetat = 0;
DNSClient dnscli;

void network_monitor()
{
  if (Ethernet.linkStatus() != 1)
  {
    network_statut = false;
    return;
  }
  else
  {
    Serial.println("✅ Lien Ethernet ok");
    if (dnsetat != 1)
    {
      Ethernet.begin(mac, ip, ns, gw, mask);
      Serial.println("Stack IP redémarré !");
    }
    dnscli.begin(Ethernet.dnsServerIP());
    IPAddress ipcloud;
    int result = dnscli.getHostByName("cloud.vicou.be", ipcloud);
    dnsetat = result;
    if (dnsetat == 1)
    {
      Serial.println("Liaison IP ok");
      network_statut = true;
    }
  }
}

// MQTT
#include <PubSubClient.h>
unsigned long derniere_connexion_mqtt = 0;
unsigned long mqtt_timeout = 5000;
bool mqtt_statut = false;
EthernetClient labo4;
PubSubClient mqtt_client(labo4);
void mqtt_reception(char *topic, byte *payload, unsigned int length);
char tempBuf[8], humBuf[8], presBuf[8];
char tempStr[20], humStr[20], presStr[20];
const char *evenement = "Mise en route";
String evenement_temp;
static String message;

// Timers
#include <TickTwo.h>
void mesure();
void RetourAuDebut();
TickTwo Intervalle_mesure(mesure, 300000);
TickTwo DelaiBadgeage(RetourAuDebut, 10000, 1);
TickTwo network_monitor_timer(network_monitor, 10000);

// Boutons poussoirs
#include <Bounce2.h>
const int poussoir_pin = 34;
Bounce2::Button poussoir = Bounce2::Button();

// PIR
bool MouvementDetecte = false;
const int pir_pin = 35;

// Commande
const int relaisradiateur = 13;
const int relaismusique = 14;
const int relaiswifi = 2;
const int relaisalim = 4;
bool etatrelaisradiateur = true;
bool etatrelaiswifi = true;
bool etatrelaisalim = true;
bool etatrelaismusique = true;
bool etatrelaistapo = true;
bool etatrelaisk1 = true;
bool etatrelaisk2 = true;
bool etatrelaisdrybox = true;

void badbadge(MFRC522::StatusCode status)
{
  Serial.print("Authentification échouée: ");
  Serial.println(rfid.GetStatusCodeName(status));
  rfid.PICC_HaltA();
  rfid.PCD_StopCrypto1();
  Serial.println("Badge invalide");
  x_message2 = 15;
  message2 = "Alarme Activée";
  led_verte = false;
  led_orange = false;
  led_rouge = true;
  camera_icon = 0x009d;
  ecran_externe.clearBuffer();
  ecran_externe.sendBuffer();
  for (int i = 0; i < 20; i++)
  {
    ecran_externe.setDrawColor(1);
    ecran_externe.drawXBMP(32, 0, 64, 64, tetemort_bits);
    ecran_externe.sendBuffer();
    digitalWrite(led_rouge_pin, true);
    delay(30);
    ecran_externe.setDrawColor(0);
    ecran_externe.drawXBMP(32, 0, 64, 64, tetemort_bits);
    ecran_externe.sendBuffer();
    digitalWrite(led_rouge_pin, false);
    delay(30);
  }
  ecran_externe.setDrawColor(1);
}

MFRC522::StatusCode readBlock(byte blockAddr, byte buffer[18], byte &size)
{
  size = sizeof(byte) * 18;
  MFRC522::StatusCode status = rfid.MIFARE_Read(54, buffer, &size);
  return status;
}

void setup()
{
  Serial.begin(115200);
  WiFi.mode(WIFI_OFF);
  btStop();
  esp_wifi_stop();
  esp_wifi_deinit();

  // Commande
  pinMode(relaisradiateur, OUTPUT);
  pinMode(relaismusique, OUTPUT);
  pinMode(relaiswifi, OUTPUT);
  pinMode(relaisalim, OUTPUT);
  digitalWrite(relaisradiateur, etatrelaisradiateur);
  digitalWrite(relaisalim, etatrelaisalim);
  digitalWrite(relaiswifi, etatrelaiswifi);
  digitalWrite(relaismusique, etatrelaismusique);
  Serial.println("Relais initialisés");

  // Boutons poussoirs
  pinMode(poussoir_pin, INPUT);
  poussoir.attach(poussoir_pin);
  poussoir.setPressedState(LOW);
  poussoir.interval(5);
  Serial.println("Poussoir initialisé");

  // Affichage
  SPI.begin();
  ecran_interne.begin();
  ecran_interne.clearBuffer();
  ecran_interne.sendBuffer();
  ecran_interne.setFont(u8g2_font_cu12_t_symbols);
  ecran_interne.enableUTF8Print();
  Wire.begin(i2c_sda_pin, i2c_scl_pin);
  ecran_externe.begin();
  ecran_externe.enableUTF8Print();
  ecran_externe.clearBuffer();
  ecran_externe.sendBuffer();
  pinMode(led_verte_pin, OUTPUT);
  pinMode(led_orange_pin, OUTPUT);
  pinMode(led_rouge_pin, OUTPUT);
  digitalWrite(led_verte_pin, led_verte);
  digitalWrite(led_orange_pin, led_orange);
  digitalWrite(led_rouge_pin, led_rouge);
  Serial.println("Affichage initialisé");

  // RFID
  rfid.PCD_Init();
  Serial.println("RFID initialisé");

  // PIR
  pinMode(pir_pin, INPUT);
  Serial.println("PIR initialisé");

  // Sonde
  if (!sonde.begin(0x76))
  {
    ecran_interne.firstPage();
    do
    {
      ecran_interne.setCursor(0, 30);
      ecran_interne.print("Erreur bme280");
    } while (ecran_interne.nextPage());
    errorbme280 = true;
  }
  Serial.println("Capteurs initialisés");

  // Ethernet IP
  Ethernet.init(cs_enc28j60_pin);

  // MQTT
  mqtt_client.setServer(mqtt_serveur, mqtt_port);
  mqtt_client.setCallback(mqtt_reception);

  network_monitor();
  mesure();
  Intervalle_mesure.start();
  network_monitor_timer.start();
}

void loop()
{
  // Timers
  Intervalle_mesure.update();
  DelaiBadgeage.update();
  network_monitor_timer.update();

  if (!mqtt_client.connected())
  {
    mqtt_statut = false;
  }

  if (Ethernet.linkStatus() == LinkON)
  { // Pour éviter les blocages si le câble réseau est déconnecté !
    Ethernet.maintain();
    mqtt_client.loop();
  }
  else
  {
    mqtt_client.disconnect();
    mqtt_statut = false;
    network_statut = false;
    Serial.println("Liaison Ethernet Perdue !!! ");
  }

  if (network_statut == true and mqtt_statut == false and millis() - derniere_connexion_mqtt > mqtt_timeout)
  {
    Serial.println("Tentative de connexion MQTT");
    if (mqtt_client.connect("labo4", mqtt_identifiant, mqtt_sesame))
    {
      Serial.println("connecté ✅");
      mqtt_statut = true;
      // Réabonnement aux topics
      mqtt_client.subscribe("homeassistant/status");
      mqtt_client.subscribe("labo4/radiateur/relais");
      mqtt_client.publish("labo4/radiateur/connecte", "online");
      mqtt_client.subscribe("labo4/musique/relais");
      mqtt_client.publish("labo4/musique/connecte", "online");
      mqtt_client.subscribe("labo4/wifi/relais");
      mqtt_client.publish("labo4/wifi/connecte", "online");
      mqtt_client.subscribe("labo4/alim/relais");
      mqtt_client.publish("labo4/alim/connecte", "online");
      mqtt_client.subscribe("labo4/tapo/etat");
      mqtt_client.subscribe("labo4/k1/etat");
      mqtt_client.subscribe("labo4/k2/etat");
      mqtt_client.subscribe("labo4/drybox/etat");
    }
    else
    {
      Serial.print("⚠️ Échec (code ");
      Serial.print(mqtt_client.state());
      mqtt_statut = false;
    }
    derniere_connexion_mqtt = millis();
  }

  // Bouton poussoir
  poussoir.update();
  if (poussoir.pressed())
  {
    if (etatrelaismusique == true and etatrelaiswifi == true and etatrelaisalim == true and etatrelaisk1 == true and etatrelaisk2 == true and etatrelaisdrybox == true)
    { // Si les 6 appareils ci-dessus sont éteints, alors on les allumes sauf la caméra qui reste indépendante et le radiateur est éteint
      etatrelaismusique = false;
      etatrelaiswifi = false;
      etatrelaisalim = false;
      etatrelaisk1 = false;
      etatrelaisk2 = false;
      etatrelaisdrybox = false;
      etatrelaisradiateur = true;
    }
    else
    { // Si un seul des 6 appareils ci-dessus est allumé, alors on éteint tout sauf la caméra qui reste indépendante
      etatrelaismusique = true;
      etatrelaiswifi = true;
      etatrelaisalim = true;
      etatrelaisradiateur = true;
      etatrelaisk1 = true;
      etatrelaisk2 = true;
      etatrelaisdrybox = true;
    }
    evenement = "poussoir";
    digitalWrite(relaisradiateur, etatrelaisradiateur);
    digitalWrite(relaisalim, etatrelaisalim);
    digitalWrite(relaiswifi, etatrelaiswifi);
    digitalWrite(relaismusique, etatrelaismusique);
    if (Ethernet.linkStatus() == 1 and mqtt_client.connected())
    { // Envoie les commandes à la boîte de prises concernée
      mqtt_client.publish("labo4/k1/relais", etatrelaisk1 ? "1" : "0", true);
      mqtt_client.publish("labo4/k2/relais", etatrelaisk2 ? "1" : "0", true);
      mqtt_client.publish("labo4/drybox/relais", etatrelaisdrybox ? "1" : "0", true);
      mqtt_client.publish("labo4/radiateur/etat", etatrelaisradiateur ? "OFF" : "ON", true);
      mqtt_client.publish("labo4/musique/etat", etatrelaismusique ? "OFF" : "ON", true);
      mqtt_client.publish("labo4/wifi/etat", etatrelaiswifi ? "OFF" : "ON", true);
      mqtt_client.publish("labo4/alim/etat", etatrelaisalim ? "OFF" : "ON", true);
      mqtt_client.publish("labo4/journal", evenement);
    }
    affichage_externe();
  }

  if (digitalRead(pir_pin) == true and MouvementDetecte == false)
  { // On détecte un mouvement pour la première fois
    x_message2 = 15;
    MouvementDetecte = true;
    message2 = "Veuillez Badger";
    led_orange = true;
    DelaiBadgeage.start();
    EtatEcran_externe = true;
    evenement = "mouvement";
    if (Ethernet.linkStatus() == 1 and mqtt_client.connected())
    {
      mqtt_client.publish("labo4/journal", evenement);
    }
    affichage_externe();
  }

  if (MouvementDetecte == true and OkPourBadger == true)
  {
    if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial())
    {
      uid = "";
      for (byte i = 0; i < rfid.uid.size; i++)
      {
        uid.concat(String(rfid.uid.uidByte[i] < 0x10 ? " 0" : " "));
        uid.concat(String(rfid.uid.uidByte[i], HEX));
      }
      OkPourBadger = false;
      uid.toUpperCase();
      Serial.println(uid);
      MFRC522::StatusCode status;
      status = (MFRC522::StatusCode)rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, 55, &cle, &(rfid.uid));
      if (status != MFRC522::STATUS_OK)
      {
        evenement_temp = uid + " : Echec Authentification";
        evenement = evenement_temp.c_str();
        if (Ethernet.linkStatus() == 1 and mqtt_client.connected())
        {
          mqtt_client.publish("labo4/journal", evenement);
        }
        badbadge(status);
        RetourAuDebut();
        return;
      }
      Serial.print("Lecture secteur ");
      byte buffer[18];
      byte sz = 0;
      status = readBlock(54, buffer, sz);
      if (status != MFRC522::STATUS_OK)
      {
        Serial.print("Lecture bloc 54");
        Serial.print(" échouée: ");
        Serial.println(rfid.GetStatusCodeName(status));
      }
      else
      {
        blocdata = "";
        Serial.print("Bloc 54");
        Serial.print(": ");
        for (byte j = 0; j < 16; j++)
        {
          char temp[3];
          sprintf(temp, "%02X", buffer[j]);
          blocdata += temp;
        }
        Serial.println();
      }
      rfid.PICC_HaltA();
      rfid.PCD_StopCrypto1();
      if (blocdata == "....") //Placer entre guillemets, les 32 bits qui doivent âtre lus pour identifier un badge de type "caméra"
      {
        Serial.println("Badge Caméra");
        evenement_temp = uid + " : Badge Caméra";
        evenement = evenement_temp.c_str();
        etatrelaistapo = !etatrelaistapo;
        if (Ethernet.linkStatus() == 1 and mqtt_client.connected())
        {
          mqtt_client.publish("labo4/tapo/relais", etatrelaistapo ? "1" : "0", true);
          mqtt_client.publish("labo4/journal", evenement);
        }
        if (etatrelaistapo == true)
        {
          EtatEcran_interne = false;
          x_message2 = 15;
          message2 = "Alarme activée";
          led_verte = true;
          led_orange = false;
          led_rouge = false;
        }
        else
        {
          ;
          EtatEcran_interne = true;
          x_message2 = 5;
          message2 = "Caméra désactivée";
          led_verte = true;
          led_orange = false;
          led_rouge = false;
        }
      }
      if (blocdata == "...")//Placer entre guillemets, les 32 bits qui doivent âtre lus pour identifier un badge de type "Alimentation"
      {
        evenement_temp = uid + " : Badge Alimentation";
        evenement = evenement_temp.c_str();
        Serial.println("Badge Alimentation");
        if (etatrelaismusique == true and etatrelaiswifi == true and etatrelaisalim == true and etatrelaisk1 == true and etatrelaisk2 == true and etatrelaisdrybox == true)
        {
          etatrelaiswifi = false;
          etatrelaismusique = false;
          etatrelaisalim = false;
          etatrelaisk1 = false;
          etatrelaisk2 = false;
          etatrelaisdrybox = false;
          etatrelaisradiateur = true;
          x_message2 = 10;
          message2 = "Labo opérationnel";
        }
        else
        {
          etatrelaiswifi = true;
          etatrelaismusique = true;
          etatrelaisalim = true;
          etatrelaisk1 = true;
          etatrelaisk2 = true;
          etatrelaisdrybox = true;
          etatrelaisradiateur = true;
          x_message2 = 15;
          message2 = "Courant Coupé";
        }
        digitalWrite(relaisradiateur, etatrelaisradiateur);
        digitalWrite(relaisalim, etatrelaisalim);
        digitalWrite(relaiswifi, etatrelaiswifi);
        digitalWrite(relaismusique, etatrelaismusique);
        if (Ethernet.linkStatus() == 1 and mqtt_client.connected())
        {
          mqtt_client.publish("labo4/k1/relais", etatrelaisk1 ? "1" : "0", true);
          mqtt_client.publish("labo4/k2/relais", etatrelaisk2 ? "1" : "0", true);
          mqtt_client.publish("labo4/drybox/relais", etatrelaisdrybox ? "1" : "0", true);
          mqtt_client.publish("labo4/radiateur/etat", etatrelaisradiateur ? "OFF" : "ON", true);
          mqtt_client.publish("labo4/musique/etat", etatrelaismusique ? "OFF" : "ON", true);
          mqtt_client.publish("labo4/wifi/etat", etatrelaiswifi ? "OFF" : "ON", true);
          mqtt_client.publish("labo4/alim/etat", etatrelaisalim ? "OFF" : "ON", true);
          mqtt_client.publish("labo4/journal", evenement);
        }
        led_verte = true;
        led_orange = false;
        led_rouge = false;
      }
      if (blocdata != "..." and blocdata != "...")//Remplacer les points par les 32 bits d'identification d'un badge de type "caméra" puis d'un badge de type "Alimentation"
      {
        evenement_temp = uid + " : Badge inconnu";
        evenement = evenement_temp.c_str();
        if (Ethernet.linkStatus() == 1 and mqtt_client.connected())
        {
          mqtt_client.publish("labo4/journal", evenement);
        }
        badbadge(status);
      }
    }
    radiateur_icon = etatrelaisradiateur ? 0x0014 : 0x02bc;
    musique_icon = etatrelaismusique ? 0x0014 : 0x0238;
    wifi_icon = etatrelaiswifi ? 0x0014 : 0x01fd;
    alim_icon = etatrelaisalim ? 0x0014 : 0x0081;
    k1_icon = etatrelaisk1 ? 0x0014 : 0x00f4;
    k2_icon = etatrelaisk2 ? 0x0014 : 0x00f5;
    drybox_icon = etatrelaisdrybox ? 0x0014 : 0x00dd;
    camera_icon = etatrelaistapo ? 0x009d : 0x0014;
    affichage_externe();
  }
}

void affichage_externe()
{
  digitalWrite(led_verte_pin, led_verte);
  digitalWrite(led_orange_pin, led_orange);
  digitalWrite(led_rouge_pin, led_rouge);
  if (EtatEcran_externe == false)
  {
    ecran_externe.clear();
  }
  else
  {
    ecran_externe.firstPage();
    do
    {
      ecran_externe.setFont(u8g2_font_streamline_all_t);
      ecran_externe.drawFrame(0, 0, 128, 64);
      ecran_externe.drawGlyph(68, 23, wifi_icon);
      ecran_externe.drawGlyph(35, 23, camera_icon);
      ecran_externe.drawGlyph(104, 23, musique_icon);
      ecran_externe.drawGlyph(104, 61, alim_icon);
      ecran_externe.drawGlyph(68, 61, radiateur_icon);
      ecran_externe.drawGlyph(2, 23, k1_icon);
      ecran_externe.drawGlyph(2, 61, k2_icon);
      ecran_externe.drawGlyph(35, 61, drybox_icon);
      ecran_externe.setFont(u8g2_font_cu12_t_symbols);
      ecran_externe.setCursor(x_message2, 36);
      ecran_externe.print(message2);
    } while (ecran_externe.nextPage());
  }
}

void mesure()
{
  temperature = sonde.readTemperature();
  temperature = temperature - 3.8;
  humidity = sonde.readHumidity();
  pression = sonde.readPressure() / 100.0F; // Conversion en hPa;
  sprintf(tempStr, "Temp: %.1f °C", temperature);
  sprintf(humStr, "Hum: %.1f %%", humidity);
  sprintf(presStr, "Pres: %.1f hPa", pression);
  if (Ethernet.linkStatus() == LinkON and mqtt_client.connected())
  {
    dtostrf(temperature, 4, 1, tempBuf);
    dtostrf(humidity, 4, 1, humBuf);
    dtostrf(pression, 4, 1, presBuf);
    mqtt_client.publish("labo4/temp", tempBuf, true);
    mqtt_client.publish("labo4/humi", humBuf, true);
    mqtt_client.publish("labo4/pres", presBuf, true);
    Serial.println("Capteurs publiés");
  }
  if (EtatEcran_interne == false)
  {
    ecran_interne.clear();
  }
  else
  {
    ecran_interne.firstPage();
    do
    {
      ecran_interne.drawFrame(0, 0, 128, 64);
      ecran_interne.setCursor(4, 18);
      ecran_interne.print(tempStr);
      ecran_interne.setCursor(4, 38);
      ecran_interne.print(humStr);
      ecran_interne.setCursor(4, 58);
      ecran_interne.print(presStr);
    } while (ecran_interne.nextPage());
  }
}

void RetourAuDebut()
{
  MouvementDetecte = false;
  OkPourBadger = true;
  led_rouge = false;
  led_orange = false;
  led_verte = false;
  message2 = "";
  digitalWrite(led_verte_pin, led_verte);
  digitalWrite(led_orange_pin, led_orange);
  digitalWrite(led_rouge_pin, led_rouge);
  ecran_externe.clear();
  Serial.println("Retour au début exécuté");
}

void mqtt_reception(char *topic, byte *payload, unsigned int length)
{
  message = "";
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  for (int i = 0; i < length; i++)
  {
    message += (char)payload[i];
  }
  Serial.print("contenu : ");
  Serial.println(message);
  if (strcmp(topic, "labo4/radiateur/relais") == 0)
  {
    etatrelaisradiateur = message.toInt();
    digitalWrite(relaisradiateur, etatrelaisradiateur);
    radiateur_icon = etatrelaisradiateur ? 0x0014 : 0x02bc;
    mqtt_client.publish("labo4/radiateur/etat", etatrelaisradiateur ? "OFF" : "ON", true);
  }
  else if (strcmp(topic, "labo4/musique/relais") == 0)
  {
    etatrelaismusique = message.toInt();
    digitalWrite(relaismusique, etatrelaismusique);
    musique_icon = etatrelaismusique ? 0x0014 : 0x0238;
    mqtt_client.publish("labo4/musique/etat", etatrelaismusique ? "OFF" : "ON", true);
  }
  else if (strcmp(topic, "labo4/wifi/relais") == 0)
  {
    etatrelaiswifi = message.toInt();
    digitalWrite(relaiswifi, etatrelaiswifi);
    wifi_icon = etatrelaiswifi ? 0x0014 : 0x01fd;
    mqtt_client.publish("labo4/wifi/etat", etatrelaiswifi ? "OFF" : "ON", true);
  }
  else if (strcmp(topic, "labo4/alim/relais") == 0)
  {
    etatrelaisalim = message.toInt();
    digitalWrite(relaisalim, etatrelaisalim);
    alim_icon = etatrelaisalim ? 0x0014 : 0x0081;
    mqtt_client.publish("labo4/alim/etat", etatrelaisalim ? "OFF" : "ON", true);
  }
  else if (strcmp(topic, "labo4/k1/etat") == 0)
  {
    if (message == "ON")
    {
      etatrelaisk1 = 0;
    }
    if (message == "OFF")
    {
      etatrelaisk1 = 1;
    }
    k1_icon = etatrelaisk1 ? 0x0014 : 0x00f4;
  }
  else if (strcmp(topic, "labo4/k2/etat") == 0)
  {
    if (message == "ON")
    {
      etatrelaisk2 = 0;
    }
    if (message == "OFF")
    {
      etatrelaisk2 = 1;
    }
    k2_icon = etatrelaisk2 ? 0x0014 : 0x00f5;
  }
  else if (strcmp(topic, "labo4/drybox/etat") == 0)
  {
    if (message == "ON")
    {
      etatrelaisdrybox = 0;
    }
    if (message == "OFF")
    {
      etatrelaisdrybox = 1;
    }
    drybox_icon = etatrelaisdrybox ? 0x0014 : 0x00dd;
  }
  else if (strcmp(topic, "labo4/tapo/etat") == 0)
  {
    if (message == "ON")
    {
      etatrelaistapo = 1;
    }
    if (message == "OFF")
    {
      etatrelaistapo = 0;
    }
    camera_icon = etatrelaistapo ? 0x009d : 0x0014;
    EtatEcran_interne = etatrelaistapo ? false : true;
  }
  else if (strcmp(topic, "homeassistant/status") == 0)
  {
    if (message == "online")
    {
      evenement = "Homeassistant online";
      mqtt_client.publish("labo4/radiateur/connecte", "online");
      mqtt_client.publish("labo4/musique/connecte", "online");
      mqtt_client.publish("labo4/wifi/connecte", "online");
      mqtt_client.publish("labo4/alim/connecte", "online");
    }
    else if (message == "offline")
    {
      evenement = "Homeassistant offline";
    }
    mqtt_client.publish("labo4/journal", evenement);
  }
  Serial.println(evenement);
  affichage_externe();
}

Le code ci-dessus prend en charge la quadruple prise Ethernet (décrite sur ce site) que j’ai dû réaliser parce que je n’en avait pas prévu assez pour mes acquisitions ultérieures . A savoir, la K2 PRO et le SpacePi.

Mince alors …

je vais devoir apprendre et programmer mes badges MIFARE Classic 1K 🙁

Cela fera l’objet d’un autre appareil décrit dans l’article : Lecteur programmateur de puces NFC Mifare 1K

Les boîtiers

Les boîtiers sont réalisés à partir du modèle « Boîtes rectangulaires personnalisables »

Les fichiers, s’ils ne sont pas directement téléchargeables sont disponibles à la demande.

Bibliographie

« Tot lès arèdja vinous d’ôriyant » veut dire : tous les machins venus d’orient.

Les traductions sont tirées du
DICTIONNAIRE POPULAIRE DE WALLON LIEGEOIS
par Simon Stasse
Edité par le comité de la Société Royale Littéraire La Wallonne en 2004

N’hésitez pas à laisser un commentaire ou poser vos questions via le formulaire ci-dessous

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *