From 2526d637eb7913e1261de5a9ea3e491dd3dc43a9 Mon Sep 17 00:00:00 2001 From: scayac Date: Thu, 8 Jan 2026 12:26:55 +0100 Subject: [PATCH] =?UTF-8?q?Suppresion=20support=20ESP32=20et=20ajout=20sup?= =?UTF-8?q?port=20ESP32-S3=20Gestion=20de=20la=20LED=20WS2812=20pour=20ind?= =?UTF-8?q?iquer=20l'=C3=A9tat=20des=20modules=20Mise=20=C3=A0=20jour=20de?= =?UTF-8?q?=20la=20documentation=20pour=20refl=C3=A9ter=20les=20changement?= =?UTF-8?q?s=20mat=C3=A9riels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 149 +++++++++++++++++++++--------------------------- html/index.html | 60 ++++++++++++++++++- platformio.ini | 19 +++--- src/main.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 264 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index 6c15956..555a15e 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,10 @@ # BleQuiz -Application HTML5 de quiz temps réel pour plusieurs modules ESP32 via Bluetooth Low Energy (BLE) +Application HTML5 de quiz temps réel pour plusieurs modules ESP32-S3 via Bluetooth Low Energy (BLE) ## 📋 Description -BleQuiz permet de créer un système de quiz interactif en temps réel où plusieurs ESP32 peuvent être connectés simultanément via Bluetooth. Chaque module ESP32 surveille des GPIOs (boutons) et envoie instantanément les événements à une interface web HTML5. - -**Cas d'usage :** -Quiz en classe, jeux de rapidité, systèmes de vote, buzzers interactifs. +BleQuiz permet de créer un système de quiz interactif en temps réel où plusieurs ESP32-S3 peuvent être connectés simultanément via Bluetooth. Chaque module ESP32-S3 surveille des GPIOs (boutons) et envoie instantanément les événements à une interface web HTML5. **Adresse de test :** [https://blequiz.apps.christophe-scaya.fr/](https://blequiz.apps.christophe-scaya.fr/) (serveur de démonstration, utiliser le fichier `quiz_exemple.txt`) @@ -16,24 +13,57 @@ Quiz en classe, jeux de rapidité, systèmes de vote, buzzers interactifs. ### ESP32 (src/main.cpp) -Par défaut, le code surveille 4 GPIOs : **2, 4, 5, 6** (compatibles ESP32 Wrover et ESP32-C3) +Par défaut, le code surveille 4 GPIOs : **2, 4, 5, 6** d'un module ESP32-S3 supermini générique. Pour modifier les GPIOs surveillés, éditez cette ligne : ```cpp const int GPIO_PINS[] = {2, 4, 5, 6}; // GPIOs à surveiller (A, B, C, D) ``` -Pour changer le nom du module (important pour différencier plusieurs ESP32) : -```cpp -String moduleName = "ESP32-Module-1"; // Changer pour chaque ESP32 -``` +### LED WS2812 (ESP32-S3) + +Le projet supporte une LED WS2812 sur le **GPIO 48** (ESP32-S3) pour indiquer l'état du module : + +**États de la LED** : +- ⚪ **Blanc clignotant** (500ms) → Déconnecté de la page web +- ⚪ **Blanc fixe** → Connecté, en attente de réponse ou affichage des scores +- 🔴 **Rouge** → Bouton GPIO 2 pressé (réponse A) +- 🟢 **Vert** → Bouton GPIO 4 pressé (réponse B) +- 🔵 **Bleu** → Bouton GPIO 5 pressé (réponse C) +- 🟡 **Jaune** → Bouton GPIO 6 pressé (réponse D) + +**Comportement selon les phases du quiz** : +1. **Connexion initiale** → ⚪ Blanc fixe (GPIO actifs) +2. **Question affichée** → ⚪ Blanc fixe (attente de réponse) +3. **Bouton pressé** → 🔴🟢🔵🟡 Couleur correspondante +4. **Résultats affichés** → LED garde sa couleur (GPIO désactivés) +5. **Question suivante** → ⚪ Blanc fixe (GPIO réactivés) +6. **Scores finaux** → ⚪ Blanc fixe (GPIO désactivés) +7. **Déconnexion** → ⚪ Blanc clignotant + +**Configuration** : La bibliothèque `Adafruit NeoPixel` est automatiquement installée via PlatformIO. + +### Identification automatique des modules (GPIO 8, 9, 10) + +Chaque module ESP32-S3 peut être identifié automatiquement via 3 GPIOs configurés en **INPUT_PULLUP** : -### GPIOs avec Pull-up -Les GPIOs sont configurés en **INPUT_PULLUP**, ce qui signifie : -- **État normal (non connecté)** : HIGH (3.3V) -- **État actif (connecté à GND)** : LOW (0V) +**Configuration des jumpers** (connecter à GND pour LOW, laisser ouvert pour HIGH) : +- **GPIO 8** = bit 0 +- **GPIO 9** = bit 1 +- **GPIO 10** = bit 2 + +**Table d'identification** : +| GPIO 10 | GPIO 9 | GPIO 8 | Binaire | Nom du module | +|---------|--------|--------|---------|---------------| +| HIGH | HIGH | HIGH | 000 | **BleQuiz-1** | +| HIGH | HIGH | LOW | 001 | **BleQuiz-2** | +| HIGH | LOW | HIGH | 010 | **BleQuiz-3** | +| HIGH | LOW | LOW | 011 | **BleQuiz-4** | +| LOW | HIGH | HIGH | 100 | **BleQuiz-5** | +| LOW | HIGH | LOW | 101 | **BleQuiz-6** | +| LOW | LOW | HIGH | 110 | **BleQuiz-7** | +| LOW | LOW | LOW | 111 | **BleQuiz-8** | -Le système envoie une notification à la page HTML **quand un GPIO passe à l'état BAS**. ## 🚀 Installation et utilisation @@ -45,32 +75,16 @@ Le système envoie une notification à la page HTML **quand un GPIO passe à l' ### 2. Configuration des ESP32 -Le projet supporte deux environnements (voir `platformio.ini`) : -- **esp32dev** : ESP32 Wrover standard -- **esp32-c3-supermini** : Seeed XIAO ESP32-C3 (ou module générique ESP32-C3) - -**Compiler et téléverser pour ESP32 Wrover** : +**Compiler et téléverser pour ESP32-S3** : ```bash -pio run -e esp32dev -pio run -e esp32dev --target upload +pio run -e esp32-s3-supermini +pio run -e esp32-s3-supermini --target upload ``` - -**Compiler et téléverser pour ESP32-C3** : -```bash -pio run -e esp32-c3-supermini -pio run -e esp32-c3-supermini --target upload -``` - **Monitorer le port série** (optionnel) : ```bash pio device monitor ``` -⚠️ **Important** : Si vous utilisez plusieurs modules, modifiez le nom de chaque module dans `src/main.cpp` : -```cpp -String moduleName = "ESP32-Module-1"; // Changer pour Module-2, Module-3, etc. -``` - ### 3. Démarrer le serveur HTTPS ⚠️ **Important** : Web Bluetooth nécessite HTTPS (ou localhost en HTTP) @@ -114,7 +128,7 @@ https://localhost:8443 ### 5. Utiliser l'application 1. **Charger un fichier de questions** : Cliquez sur "Choisir un fichier" et sélectionnez votre fichier de quiz (voir `quiz_exemple.txt`) -2. **Connecter les modules** : Cliquez sur "Connecter un module" et sélectionnez votre ESP32 +2. **Connecter les modules** : Cliquez sur "Connecter un module" et sélectionnez votre ESP32-S3 dans la liste Bluetooth 3. **Lancer le quiz** : Naviguez entre les questions, les modules répondent en appuyant sur leurs boutons 4. **Répétez** pour connecter plusieurs modules simultanément @@ -190,13 +204,6 @@ L'application web offre : ## ⚙️ Personnalisation -### Changer le nom du module ESP32 - -Dans `src/main.cpp`, modifiez : -```cpp -String moduleName = "ESP32-Module-1"; // Changer pour chaque ESP32 (Module-2, Module-3, etc.) -``` - ### Modifier les GPIOs surveillés Dans `src/main.cpp`, adaptez selon votre matériel : @@ -204,23 +211,13 @@ Dans `src/main.cpp`, adaptez selon votre matériel : const int GPIO_PINS[] = {2, 4, 5, 6}; // GPIOs à surveiller ``` -**GPIOs recommandés** : -- **ESP32 Wrover** : 2, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23 -- **ESP32-C3** : 2, 3, 4, 5, 6, 7, 8, 9, 10 - ### Changer les UUID Bluetooth Dans `src/main.cpp` et `index.html`, modifiez (doit être identique des deux côtés) : ```cpp #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" -``` - -### Modifier le délai de lecture - -Dans `src/main.cpp`, dernière ligne de `loop()` : -```cpp -delay(100); // Modifier selon vos besoins (en millisecondes) +#define COMMAND_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a9" ``` ### Format du fichier de quiz @@ -252,12 +249,12 @@ Créez un fichier texte avec ce format (voir `quiz_exemple.txt`) : ## 🐛 Dépannage -### L'ESP32 n'apparaît pas dans la liste Bluetooth +### L'ESP32-S3 n'apparaît pas dans la liste Bluetooth - Vérifiez que le module est alimenté correctement (USB ou externe 5V) - Consultez le moniteur série : `pio device monitor` pour voir les messages de démarrage - Assurez-vous que le Bluetooth est activé sur votre ordinateur - Sur Linux, vérifiez que BlueZ est à jour : `bluetoothctl --version` -- Redémarrez l'ESP32 (bouton RESET ou débrancher/rebrancher) +- Redémarrez l'ESP32-S3 (bouton RESET ou débrancher/rebrancher) ### Pas de données reçues dans l'interface web - Vérifiez que les UUID correspondent dans `src/main.cpp` et `index.html` @@ -266,8 +263,8 @@ Créez un fichier texte avec ce format (voir `quiz_exemple.txt`) : - Vérifiez que le module est bien connecté (voyant dans l'interface) ### Déconnexions fréquentes -- Réduisez la distance entre l'ESP32 et l'ordinateur (< 5 mètres) -- Assurez-vous que l'alimentation de l'ESP32 est stable (câble USB de qualité) +- Réduisez la distance entre l'ESP32-S3 et l'ordinateur (< 5 mètres) +- Assurez-vous que l'alimentation de l'ESP32-S3 est stable (câble USB de qualité) - Évitez les interférences (WiFi 2.4GHz, micro-ondes) - Augmentez le délai dans la boucle principale si trop de données sont envoyées @@ -285,21 +282,28 @@ Créez un fichier texte avec ce format (voir `quiz_exemple.txt`) : ## 📝 Caractéristiques techniques - **Protocole** : Bluetooth Low Energy (BLE 4.0+) -- **Compatibilité ESP32** : ESP32 Wrover, ESP32-C3 (Seeed XIAO) -- **GPIOs configurables** : 4 par défaut (extensible) -- **Connexions simultanées** : Jusqu'à 10 modules ESP32 +- **LED WS2812** : Indicateur visuel d'état sur GPIO 48 +- **Identification automatique** : Via GPIOs 8, 9, 10 (BleQuiz-1 à BleQuiz-8) +- **GPIOs boutons** : 4 par défaut (2, 4, 5, 6) +- **Connexions simultanées** : Jusqu'à 8+ modules ESP32 - **Fréquence de mise à jour** : 100ms par défaut - **Portée Bluetooth** : ~10 mètres en intérieur - **Navigateurs supportés** : Chrome 56+, Edge 79+, Opera 43+ - **Serveurs fournis** : Python 3 (SSL auto-signé) et Node.js +- **Bibliothèques** : Adafruit NeoPixel (pour LED WS2812) ## 🎯 Notes d'utilisation -- **Modules multiples** : Chaque module doit avoir un nom unique configuré dans `src/main.cpp` +- **Identification automatique** : Les modules se nomment automatiquement BleQuiz-1 à BleQuiz-8 selon les GPIOs 8, 9, 10 - **Sécurité BLE** : Le code utilise un mode sans bonding (pas de mémorisation d'appairage) - **Web Bluetooth** : La page HTML doit obligatoirement être servie en HTTPS ou via localhost - **Détection de changement** : Les événements GPIO sont envoyés instantanément lors des transitions HIGH→LOW - **Mode Pull-up** : Les boutons doivent connecter le GPIO à GND (pas à VCC) +- **LED WS2812** : Feedback visuel automatique sur ESP32-S3, la LED indique l'état de connexion et les réponses +- **Commandes BLE** : + - `START` : Active la détection GPIO (blanc fixe) + - `RESET` : Fige la LED, désactive les GPIO (affichage résultats) + - `SCORES` : Blanc fixe, GPIO désactivés (scores finaux) ## 🚀 Démarrage rapide (Linux) @@ -316,17 +320,6 @@ pio run -e esp32dev --target upload # - Commencer le quiz ! ``` -## 🔐 Sécurité - -Le projet est conçu pour un usage éducatif et de démonstration. Pour un usage en production : - -- **Authentification BLE** : Implémenter un système de pairing sécurisé -- **Chiffrement des données** : Activer le chiffrement des caractéristiques BLE -- **Certificat SSL valide** : Remplacer le certificat auto-signé par un certificat CA -- **Validation côté serveur** : Ajouter une validation des réponses côté serveur -- **Limitation de connexions** : Implémenter une limite et un contrôle d'accès -- **Logs d'audit** : Enregistrer les actions pour le suivi et la sécurité - ## 📚 Ressources - [Web Bluetooth API Documentation](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API) @@ -337,15 +330,3 @@ Le projet est conçu pour un usage éducatif et de démonstration. Pour un usage ## 📄 Licence Ce projet est open source. Libre d'utilisation, modification et distribution. - -## 👥 Contribution - -Les contributions sont les bienvenues ! N'hésitez pas à : -- Signaler des bugs -- Proposer de nouvelles fonctionnalités -- Améliorer la documentation -- Soumettre des pull requests - ---- - -**Créé avec ❤️ pour l'éducation et l'apprentissage interactif** diff --git a/html/index.html b/html/index.html index d6f594a..d5a293b 100644 --- a/html/index.html +++ b/html/index.html @@ -533,10 +533,11 @@ // Configuration BLE const SERVICE_UUID = '4fafc201-1fb5-459e-8fcc-c5c9c331914b'; const CHARACTERISTIC_UUID = 'beb5483e-36e1-4688-b7f5-ea07361b26a8'; + const COMMAND_UUID = 'beb5483e-36e1-4688-b7f5-ea07361b26a9'; let questions = []; let currentQuestionIndex = 0; - let connectedModules = new Map(); // moduleName -> { device, characteristic, answer, scores } + let connectedModules = new Map(); // moduleName -> { device, characteristic, commandCharacteristic, answer, scores } let resultsShown = false; const fileInput = document.getElementById('fileInput'); @@ -627,6 +628,7 @@ const server = await device.gatt.connect(); const service = await server.getPrimaryService(SERVICE_UUID); const characteristic = await service.getCharacteristic(CHARACTERISTIC_UUID); + const commandCharacteristic = await service.getCharacteristic(COMMAND_UUID); // Lire l'état initial const initialValue = await characteristic.readValue(); @@ -640,6 +642,7 @@ connectedModules.set(moduleName, { device: device, characteristic: characteristic, + commandCharacteristic: commandCharacteristic, answer: null, totalScore: 0, gpios: data.gpios @@ -803,6 +806,55 @@ } showResultsBtn.disabled = true; + + // Envoyer la commande RESET immédiatement à tous les modules + // (LED garde sa couleur, GPIO désactivés) + resetAllModules(); + } + + async function resetAllModules() { + console.log('Envoi de RESET à tous les modules...'); + for (let [name, module] of connectedModules.entries()) { + try { + if (module.commandCharacteristic) { + const encoder = new TextEncoder(); + await module.commandCharacteristic.writeValue(encoder.encode('RESET')); + console.log(`RESET envoyé à ${name}`); + } + } catch (error) { + console.error(`Erreur envoi RESET à ${name}:`, error); + } + } + } + + async function sendCommandToAllModules(command) { + console.log(`Envoi de ${command} à tous les modules...`); + for (let [name, module] of connectedModules.entries()) { + try { + if (module.commandCharacteristic) { + const encoder = new TextEncoder(); + await module.commandCharacteristic.writeValue(encoder.encode(command)); + console.log(`${command} envoyé à ${name}`); + } + } catch (error) { + console.error(`Erreur envoi ${command} à ${name}:`, error); + } + } + } + + async function sendScoresCommand() { + console.log('Envoi de SCORES à tous les modules...'); + for (let [name, module] of connectedModules.entries()) { + try { + if (module.commandCharacteristic) { + const encoder = new TextEncoder(); + await module.commandCharacteristic.writeValue(encoder.encode('SCORES')); + console.log(`SCORES envoyé à ${name}`); + } + } catch (error) { + console.error(`Erreur envoi SCORES à ${name}:`, error); + } + } } function handleFileSelect(event) { @@ -997,6 +1049,9 @@ } } + // Envoyer la commande START à tous les modules + sendCommandToAllModules('START'); + // Mettre à jour les contrôles document.getElementById('progress').textContent = `${currentQuestionIndex + 1} / ${questions.length}`; @@ -1047,6 +1102,9 @@ } scoresDetails.innerHTML = html; + + // Envoyer la commande SCORES à tous les modules (blanc fixe, GPIO désactivés) + sendScoresCommand(); } window.disconnectModule = function(moduleName) { diff --git a/platformio.ini b/platformio.ini index 9e6e11f..4c97d96 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,12 +1,11 @@ -[env:esp32dev] +[env:esp32-s3-supermini] platform = espressif32 -board = esp32dev +board = esp32-s3-devkitc-1 framework = arduino -monitor_speed = 115200 - -[env:esp32-c3-supermini] -platform = espressif32 -board = seeed_xiao_esp32c3 -board_build.mcu = esp32c3 -framework = arduino -monitor_speed = 115200 \ No newline at end of file +board_upload.flash_size = 4MB +board_build.partitions = default.csv +build_flags = + -DARDUINO_USB_CDC_ON_BOOT=1 + -DBOARD_HAS_PSRAM +lib_deps = + adafruit/Adafruit NeoPixel@^1.12.0 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index b3ddd3c..c760133 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,35 +3,91 @@ #include #include #include +#include + +// Configuration LED WS2812 +#define LED_PIN 48 +#define LED_COUNT 1 +Adafruit_NeoPixel led(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); + +// Couleurs +#define COLOR_OFF led.Color(0, 0, 0) +#define COLOR_WHITE led.Color(255, 255, 255) +#define COLOR_RED led.Color(255, 0, 0) +#define COLOR_GREEN led.Color(0, 255, 0) +#define COLOR_BLUE led.Color(0, 0, 255) +#define COLOR_YELLOW led.Color(255, 255, 0) // UUID pour le service et la caractéristique BLE #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" +#define COMMAND_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a9" // Configuration des GPIO à surveiller // GPIO compatibles ESP32 Wrover ET ESP32-C3 : 2, 4, 5, 6 const int GPIO_PINS[] = {2, 4, 5, 6}; // GPIOs à surveiller (A, B, C, D) const int NUM_PINS = sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]); +// GPIO pour l'identification du module (8, 9, 10) +const int ID_GPIO_PINS[] = {8, 9, 10}; // Bit 0, Bit 1, Bit 2 +const int NUM_ID_PINS = sizeof(ID_GPIO_PINS) / sizeof(ID_GPIO_PINS[0]); + // Variables globales BLEServer* pServer = NULL; BLECharacteristic* pCharacteristic = NULL; +BLECharacteristic* pCommandCharacteristic = NULL; bool deviceConnected = false; bool oldDeviceConnected = false; uint8_t gpioStates = 0; // Stocke l'état des GPIOs (bit à bit) +unsigned long lastBlinkTime = 0; +bool blinkState = false; +bool gpioEnabled = false; // false = GPIO désactivés (résultats ou scores), true = GPIO actifs -// Nom du module (peut être modifié pour chaque ESP32) -String moduleName = "ESP32-Module-1"; +// Nom du module (sera déterminé automatiquement) +String moduleName = "BleQuiz-1"; + +// Callback pour la caractéristique de commande +class CommandCallbacks: public BLECharacteristicCallbacks { + void onWrite(BLECharacteristic* pCharacteristic) { + std::string value = pCharacteristic->getValue(); + if (value.length() > 0) { + String command = String(value.c_str()); + Serial.println("Commande reçue: " + command); + + if (command == "RESET") { + // Garder la LED dans sa couleur actuelle, désactiver les GPIO + gpioEnabled = false; + Serial.println("Résultats affichés - LED figée, GPIO désactivés"); + } else if (command == "START") { + // Passer en blanc fixe, activer les GPIO + gpioEnabled = true; + led.setPixelColor(0, COLOR_WHITE); + led.show(); + Serial.println("Question démarrée - Blanc fixe, GPIO actifs"); + } else if (command == "SCORES") { + // Passer en blanc fixe, désactiver les GPIO + gpioEnabled = false; + led.setPixelColor(0, COLOR_WHITE); + led.show(); + Serial.println("Scores affichés - Blanc fixe, GPIO désactivés"); + } + } + } +}; class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; - Serial.println("Client connecté"); + gpioEnabled = true; + led.setPixelColor(0, COLOR_WHITE); + led.show(); + Serial.println("Client connecté - Blanc fixe"); }; void onDisconnect(BLEServer* pServer) { deviceConnected = false; - Serial.println("Client déconnecté"); + gpioEnabled = false; + Serial.println("Client déconnecté - Mode clignotant"); } }; @@ -39,6 +95,31 @@ void setup() { Serial.begin(115200); Serial.println("Démarrage du module ESP32 Bluetooth..."); + // Initialiser la LED WS2812 (éteinte au démarrage) + led.begin(); + led.setPixelColor(0, COLOR_OFF); + led.show(); + + // Configuration des GPIO d'identification (8, 9, 10) en entrée avec pull-up + for (int i = 0; i < NUM_ID_PINS; i++) { + pinMode(ID_GPIO_PINS[i], INPUT_PULLUP); + } + + // Lire l'ID du module (GPIO 8=bit0, 9=bit1, 10=bit2) + uint8_t moduleId = 0; + for (int i = 0; i < NUM_ID_PINS; i++) { + if (digitalRead(ID_GPIO_PINS[i]) == LOW) { + moduleId |= (1 << i); + } + } + moduleId += 1; // ID de 1 à 8 (000=1, 001=2, ..., 111=8) + moduleName = "BleQuiz-" + String(moduleId); + + Serial.print("ID du module détecté: "); + Serial.println(moduleId); + Serial.print("Nom du module: "); + Serial.println(moduleName); + // Configuration des GPIO en entrée avec pull-up for (int i = 0; i < NUM_PINS; i++) { pinMode(GPIO_PINS[i], INPUT_PULLUP); @@ -73,6 +154,13 @@ void setup() { // Créer un descripteur BLE2902 pour les notifications pCharacteristic->addDescriptor(new BLE2902()); + // Créer la caractéristique de commande (pour RESET) + pCommandCharacteristic = pService->createCharacteristic( + COMMAND_UUID, + BLECharacteristic::PROPERTY_WRITE + ); + pCommandCharacteristic->setCallbacks(new CommandCallbacks()); + // Démarrer le service pService->start(); @@ -92,11 +180,24 @@ void setup() { } Serial.println("En attente de connexion..."); - Serial.print("Nom du module: "); - Serial.println(moduleName); } void loop() { + // Gestion du clignotement blanc uniquement si déconnecté + if (!deviceConnected) { + unsigned long currentTime = millis(); + if (currentTime - lastBlinkTime >= 500) { + lastBlinkTime = currentTime; + blinkState = !blinkState; + if (blinkState) { + led.setPixelColor(0, COLOR_WHITE); + } else { + led.setPixelColor(0, COLOR_OFF); + } + led.show(); + } + } + // Lire l'état de toutes les GPIO uint8_t currentStates = 0; for (int i = 0; i < NUM_PINS; i++) { @@ -106,6 +207,30 @@ void loop() { } } + // Détecter les changements d'état des GPIO (passage à LOW) + // Uniquement si connecté ET GPIO activés + uint8_t newPresses = currentStates & ~gpioStates; + if (newPresses != 0 && deviceConnected && gpioEnabled) { + // Allumer la LED selon le GPIO pressé + if (newPresses & (1 << 0)) { // GPIO 2 + led.setPixelColor(0, COLOR_RED); + led.show(); + Serial.println("GPIO 2 pressé - LED ROUGE"); + } else if (newPresses & (1 << 1)) { // GPIO 4 + led.setPixelColor(0, COLOR_GREEN); + led.show(); + Serial.println("GPIO 4 pressé - LED VERTE"); + } else if (newPresses & (1 << 2)) { // GPIO 5 + led.setPixelColor(0, COLOR_BLUE); + led.show(); + Serial.println("GPIO 5 pressé - LED BLEUE"); + } else if (newPresses & (1 << 3)) { // GPIO 6 + led.setPixelColor(0, COLOR_YELLOW); + led.show(); + Serial.println("GPIO 6 pressé - LED JAUNE"); + } + } + // Créer un message JSON avec l'état des GPIO String message = "{\"module\":\"" + moduleName + "\",\"gpios\":["; for (int i = 0; i < NUM_PINS; i++) {