Le microgiciel
tip
En cas de doute, référez-vous à la documentation officielle du Huzzah32
Mode d'emploi#
Pour que la badgeuse fasse son travail, il faut préalablement injecter du code (le micrologiciel) dans la carte ESP32.
Pour cela, sur votre ordinateur :
- téléchargez et installez l’environnement de développement Arduino ;
- téléchargez et installez le driver « SiLabs CP2104 USB » ;
- installez les librairies Arduino-ESP32 puis ArduinoJson, MFRC522, U8g2lib (procédure);
- créez un nouveau projet, copiez le code ci-dessous et modifiez les paramètres WIFI_SSID, WIFI_PASS, SERVER_POST_URL, BADGER_KEY et API_X_KEY (cf. info) ;
- branchez la carte ESP32 avec un câble USB ;
- dans le menu "Outils / Type de carte", sélectionnez "Adafruit ESP32 Feather" ;
- Enregistrez le projet, puis cliquez sur « Upload ».
info
Détails du paramètrage :
- WIFI_SSID : le nom de votre point d'accès Wifi
- WIFI_PASS : le mot de passe de votre point d'accès Wifi
- SERVERPOST_URL : l'adresse du _endpoint de badgeage de l'API
- BADGER_KEY : l'identifiant unique de la badgeuse
- API_X_KEY : clé d'authentification de l'API (entête)
Code source du microgiciel#
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <SPI.h>
#include <MFRC522.h>
#include "U8g2lib.h"
#include <Wire.h>
#define USE_SERIAL Serial
#define SS_PIN 12
#define RST_PIN 13
/* Paramètres */
const char* WIFI_SSID = "Mon wifi";
const char* WIFI_PASS = "Mon mot de passe";
const char* SERVER_POST_URL = "http://monserveur.fr/api/badging";
const String BADGER_KEY = "XXXXXXXX";
const String API_X_KEY = "XXXXXXX";
/**************/
MFRC522 mfrc522(SS_PIN, RST_PIN);
WiFiMulti wifiMulti;
StaticJsonDocument<1200> jsonResponse;
U8G2_SH1106_128X64_NONAME_F_HW_I2C oled (U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
const byte COLOR_BLACK = 0b000;
const byte COLOR_RED = 0b100;
const byte COLOR_GREEN = 0b010;
const byte COLOR_BLUE = 0b001;
const byte COLOR_MAGENTA = 0b101;
const byte COLOR_CYAN = 0b011;
const byte COLOR_YELLOW = 0b110;
const byte COLOR_WHITE = 0b111;
const byte PIN_LED_R = 14;
const byte PIN_LED_G = 32;
const byte PIN_LED_B = 15;
// OLED
int brightness = 255;
// Wifi
int wifiState = 0;
byte badgeId[4];
String myBadgeIdStr;
unsigned long previousMillis = 0;
unsigned long interval = 30000;
void setup() {
pinMode(PIN_LED_R, OUTPUT);
pinMode(PIN_LED_G, OUTPUT);
pinMode(PIN_LED_B, OUTPUT);
displayColor(COLOR_BLACK);
USE_SERIAL.begin(115200);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for (uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
oled.begin();
oled.setContrast(brightness);
printOled("Connexion...", 32);
// Connexion Wifi
wifiMulti.addAP(WIFI_SSID, WIFI_PASS);
wifiMulti.addAP(WIFI_SSID2, WIFI_PASS2);
displayColor(COLOR_RED);
USE_SERIAL.println("Connecting Wifi");
while (wifiMulti.run() != WL_CONNECTED) {
USE_SERIAL.print(".");
delay(500);
}
wifiState = 1;
printOled("Wifi OK", 32);
USE_SERIAL.println("");
USE_SERIAL.println("WiFi connected");
displayColor(COLOR_GREEN);
USE_SERIAL.println("IP address: ");
USE_SERIAL.println(WiFi.localIP());
USE_SERIAL.print("RSSI: ");
USE_SERIAL.println(WiFi.RSSI());
// NFC - RC522
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); //set parameters
SPI.begin(); // init SPI
delay(10);
mfrc522.PCD_Init();
mfrc522.PCD_DumpVersionToSerial();
delay(2000);
printOledMini(WiFi.SSID(), 50);
delay(5000);
oled.clear();
}
void loop() {
if (wifiMulti.run() != WL_CONNECTED) {
wifiState = 0;
printOled("Wifi perdu", 32);
displayColor(COLOR_RED);
return;
}
if (wifiState == 0 && wifiMulti.run() == WL_CONNECTED) {
wifiState = 1;
displayColor(COLOR_GREEN);
printOled("Wifi retrouve", 32);
delay(5000);
oled.clear();
}
if ( ! mfrc522.PICC_IsNewCardPresent()) {
delay(50);
return;
}
// Récupération des informations de la carte RFID
if ( ! mfrc522.PICC_ReadCardSerial()) {
delay(50);
return;
}
MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
USE_SERIAL.println(mfrc522.PICC_GetTypeName(piccType));
if ( piccType != MFRC522::PICC_TYPE_MIFARE_MINI
&& piccType != MFRC522::PICC_TYPE_MIFARE_1K
&& piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
Serial.println(F("Ce modèle de badge ne fonctionne pas (attendu : MIFARE Classic)"));
return;
}
// Affichage des informations de la carte RFID
Serial.print("MYID:");
myBadgeIdStr = "";
for (byte i = 0; i < 4; i++) {
myBadgeIdStr += String(mfrc522.uid.uidByte[i], HEX);
}
Serial.println(myBadgeIdStr);
Serial.print("RFID TAG ID:");
for (byte i = 0; i < mfrc522.uid.size; ++i) { // read id (in parts)
Serial.print(mfrc522.uid.uidByte[i], HEX); // print id as hex values
Serial.print(" "); // add space between hex blocks to increase readability
}
Serial.println();
// wait for WiFi connection
if ((wifiMulti.run() == WL_CONNECTED)) {
displayColor(COLOR_BLUE);
HTTPClient http;
USE_SERIAL.print("[HTTP] begin...\n");
http.begin(SERVER_POST_URL);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
http.addHeader("x-api-key", API_X_KEY);
USE_SERIAL.print("[HTTP] POST...\n");
// start connection
String httpRequestData = "cardCode=" + myBadgeIdStr + "&badgerKey=" + BADGER_KEY;
Serial.println(httpRequestData);
int httpCode = http.POST(httpRequestData);
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
USE_SERIAL.printf("[HTTP] POST... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
USE_SERIAL.println(payload);
DeserializationError error = deserializeJson(jsonResponse, payload);
if (error) {
USE_SERIAL.print(F("deserializeJson() failed: "));
USE_SERIAL.println(error.f_str());
return;
} else {
const char* user = jsonResponse["user"];
const char* creditDisp = jsonResponse["credit_disp"];
const char* inout = jsonResponse["inout"];
const int credit = jsonResponse["credit"];
printOledUser(user, inout, creditDisp);
USE_SERIAL.println(creditDisp);
if (credit <= 0) {
displayColor(COLOR_RED);
} else {
displayColor(COLOR_GREEN);
}
delay(10000);
}
} else if (httpCode == 400) {
// badge inconnu
String payload = http.getString();
USE_SERIAL.println(payload);
DeserializationError error = deserializeJson(jsonResponse, payload);
if (error) {
USE_SERIAL.print(F("Error 400, deserializeJson() failed: "));
USE_SERIAL.println(error.f_str());
return;
} else {
const char* unknownCardCode = jsonResponse["message"]["cardCode"];
printOledUnknown(unknownCardCode);
USE_SERIAL.print("Badge inconnu : ");
USE_SERIAL.println(unknownCardCode);
displayColor(COLOR_YELLOW);
}
delay(10000);
displayColor(COLOR_GREEN);
}
} else {
USE_SERIAL.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
displayColor(COLOR_RED);
printOled("Erreur serveur", 32);
delay(10000);
displayColor(COLOR_GREEN);
}
http.end();
}
oled.clear();
}
// Fontes : https://github.com/olikraus/u8g2/wiki/fntlistall
void printOled(String text, int line) {
oled.setFont(u8g2_font_ncenB14_tr);
oled.clearBuffer();
oled.setCursor(5, line);
oled.print(text);
oled.sendBuffer();
}
void printOledMini(String text, int line) {
oled.setFont(u8g2_font_courR08_tr);
oled.clearBuffer();
oled.setCursor(5, line);
oled.print(text);
oled.sendBuffer();
}
void printOledUser(String textUser, String textEntreeSortie, String credit) {
oled.clearBuffer();
oled.setFont(u8g2_font_courR08_tr);
oled.setCursor(2, 10);
oled.print(textUser);
oled.setFont(u8g2_font_ncenB14_tr);
oled.setCursor(2, 35);
oled.print(credit);
oled.setFont(u8g2_font_timR18_tf);
oled.setCursor(80, 63);
oled.print(textEntreeSortie);
oled.sendBuffer();
}
void printOledUnknown(String textBadgeNum) {
oled.clearBuffer();
oled.setFont(u8g2_font_courR08_tr);
oled.setCursor(2, 10);
oled.print("Badge inconnu");
oled.setFont(u8g2_font_ncenB14_tr);
oled.setCursor(2, 32);
oled.print(textBadgeNum);
oled.sendBuffer();
}
void displayColor(byte color) {
digitalWrite(PIN_LED_R, bitRead(color, 0));
digitalWrite(PIN_LED_G, bitRead(color, 1));
digitalWrite(PIN_LED_B, bitRead(color, 2));
}
/**
Helper routine to dump a byte array as hex values to Serial.
*/
void printHex(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
/**
Helper routine to dump a byte array as dec values to Serial.
*/
void printDec(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], DEC);
}
}