Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <WiFi.h>
- #include <WiFiUdp.h>
- #include <WebServer.h>
- // --- Configuration Wi-Fi ---
- const char* ssid = "WIFI";
- const char* password = "PASSWORD";
- IPAddress receiverIP(192, 168, 1, 100); // IP de l'autre ESP (ou le vôtre)
- const int receiverPort = 1337;
- const int localPort = 1337;
- WiFiUDP udp;
- WebServer server(80);
- // --- Pinout ---
- const int boutonMorse = 2; // Bouton physique pour Morse (Point/Trait)
- // Pas de bouton physique pour le mode, tout se fait via le Web
- // --- États du système ---
- enum Mode {
- MODE_EMETTEUR,
- MODE_RECEPTEUR
- };
- Mode systemeMode = MODE_EMETTEUR;
- // --- Configuration Morse ---
- const unsigned long DUREE_POINT = 200;
- const unsigned long SEUIL_TRAIT = DUREE_POINT * 1.5;
- const unsigned long TEMPS_FIN_LETTRE = 800;
- unsigned long debutAppui = 0;
- unsigned long dernierRelachement = 0;
- bool appuiEnCours = false;
- String lettreEnCours = "";
- // --- Buffers ---
- String messageRecu = "";
- String historiqueRecu = ""; // Pour afficher l'historique sur le web
- const int MAX_HISTORIQUE = 50;
- // --- Fonctions utilitaires ---
- void changerModeWeb(Mode nouveauMode) {
- systemeMode = nouveauMode;
- String msg = (nouveauMode == MODE_EMETTEUR) ? "ÉMISSION" : "RÉCEPTION";
- Serial.println(">>> MODE CHANGÉ : " + msg + " <<<");
- }
- // Fonction pour échapper les caractères spéciaux dans un JSON (sans toucher au HTML)
- String escapeJson(String str) {
- str.replace("\\", "\\\\"); // Échapper les antislashs
- str.replace("\"", "\\\""); // Échapper les guillemets (crucial pour le JSON)
- str.replace("\n", "\\n"); // Échapper les sauts de ligne
- str.replace("\r", "\\r"); // Échapper les retours chariot
- str.replace("\t", "\\t"); // Échapper les tabulations
- // On NE touche PAS à < et > pour que le HTML reste fonctionnel
- return str;
- }
- void setup() {
- pinMode(boutonMorse, INPUT_PULLUP);
- Serial.begin(115200); // Débit plus élevé pour le serial et le web
- while (!Serial)
- ;
- Serial.println("=== ESP32 Morse Web ===");
- // Petit délai pour stabiliser l'alimentation avant le Wi-Fi
- delay(1000);
- Serial.print("Connexion au Wi-Fi...");
- WiFi.begin(ssid, password);
- // Augmentez le délai d'attente pour éviter les redémarrages brutaux
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000); // Passez de 500ms à 1000ms pour donner plus de temps à l'alimentation
- Serial.print(".");
- }
- Serial.println(" Connecté !");
- Serial.print("Adresse IP: ");
- Serial.println(WiFi.localIP());
- // Initialisation UDP
- if (udp.begin(localPort)) {
- Serial.println("UDP écouteur démarré sur le port " + String(localPort));
- } else {
- Serial.println("Erreur démarrage UDP");
- }
- // --- Configuration du Serveur Web ---
- // --- 1. Page d'accueil (HTML + CSS + JS) ---
- server.on("/", []() {
- String html = "";
- String modeTexte = (systemeMode == MODE_EMETTEUR) ? "Passer en Réception" : "Passer en Émission";
- String modeClasse = (systemeMode == MODE_EMETTEUR) ? "mode-emetteur" : "mode-recepteur";
- String boutonDisabled = (systemeMode == MODE_RECEPTEUR) ? "disabled" : "";
- String modeAction = (systemeMode == MODE_EMETTEUR) ? "RECEPTEUR" : "EMETTEUR";
- html += "<!DOCTYPE html><html><head>";
- html += "<title>ESP32 Morse</title>";
- html += "<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
- html += "<style>";
- html += "body { font-family: Arial, sans-serif; text-align: center; padding: 20px; background: #f0f0f0; }";
- html += ".container { max-width: 600px; margin: 0 auto; background: white; padding: 20px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }";
- html += "h1 { color: #333; }";
- html += ".status { font-size: 1.2em; font-weight: bold; margin: 10px 0; padding: 10px; border-radius: 5px; }";
- html += ".mode-emetteur { background-color: #d4edda; color: #155724; }";
- html += ".mode-recepteur { background-color: #cce5ff; color: #004085; }";
- html += ".btn { padding: 15px 30px; font-size: 1.2em; cursor: pointer; border: none; border-radius: 5px; color: white; background: #007bff; transition: 0.3s; }";
- html += ".btn:disabled { background: #ccc; cursor: not-allowed; }";
- html += ".btn:hover:not(:disabled) { background: #0056b3; }";
- html += ".log-box { margin-top: 20px; padding: 10px; border: 1px solid #ddd; border-radius: 5px; background: #fafafa; min-height: 100px; text-align: left; overflow-y: auto; max-height: 200px; }";
- html += ".log-entry { margin: 5px 0; padding: 2px; border-bottom: 1px solid #eee; }";
- html += ".log-entry.sent { color: green; }";
- html += ".log-entry.received { color: blue; }";
- html += ".morse-current { font-size: 1.5em; font-weight: bold; color: #333; margin-top: 10px; }";
- html += "</style>";html += "</head><body>";
- html += "<div class='container'>";
- html += "<h1>ESP32 Morse</h1>";
- html += "<div class='status " + modeClasse + "' id='statusDisplay'>Mode actuel : ...</div>";
- html += "<button class='btn' onclick='changeMode(\"" + modeAction + "\")'>" + modeTexte + "</button>";
- html += "<div class='log-box' id='logBox'><strong>Historique :</strong><br></div>";
- if (systemeMode == MODE_EMETTEUR) {
- html += "<div class='morse-current' id='morseDisplay'>Morse en cours : </div>";
- }
- html += "</div>";
- // Script JS pour le rafraîchissement automatique
- html += "<script>";
- html += "function changeMode(mode) {";
- html += " fetch('/changeMode?m=' + mode);";
- html += " location.reload();";
- html += "}";
- html += "";
- html += "function updateUI() {";
- html += " fetch('/update')";
- html += " .then(response => response.json())";
- html += " .then(data => {";
- html += " var statusEl = document.getElementById('statusDisplay');";
- html += " if(statusEl) {";
- html += " var modeText = (data.mode === 'EMETTEUR') ? 'ÉMISSION (Morse)' : 'RÉCEPTION (Écoute)';";
- html += " statusEl.innerText = 'Mode actuel : ' + modeText;";
- html += " statusEl.className = 'status ' + (data.mode === 'EMETTEUR' ? 'mode-emetteur' : 'mode-recepteur');";
- html += " }";
- html += "";
- html += " var logBox = document.getElementById('logBox');";
- html += " if(logBox) {";
- html += " var newContent = '<strong>Historique :</strong><br>' + data.history;";
- html += "";
- html += " if (logBox.innerHTML !== newContent) {";
- html += " logBox.innerHTML = newContent;";
- html += "";
- html += " var isUserAtBottom = (logBox.scrollHeight - logBox.scrollTop) <= (logBox.clientHeight + 10);";
- html += "";
- html += " if (isUserAtBottom) {";
- html += " logBox.scrollTop = logBox.scrollHeight;";
- html += " }";
- html += " }";
- html += " }";
- html += "";
- html += " var morseEl = document.getElementById('morseDisplay');";
- html += " if(morseEl) {";
- html += " if (data.mode === 'EMETTEUR') {";
- html += " morseEl.innerText = 'Morse en cours : ' + data.currentMorse;";
- html += " } else {";
- html += " morseEl.innerText = '';";
- html += " }";
- html += " }";
- html += " })";
- html += " .catch(err => console.error('Erreur update:', err));";
- html += "}";
- html += "";
- html += "setInterval(updateUI, 500);";
- html += "updateUI();";
- html += "</script>";
- server.send(200, "text/html", html);
- });
- // --- 2. Endpoint pour changer le mode ---
- server.on("/changeMode", []() {
- String mode = server.arg("m");
- if (mode == "RECEPTEUR") {
- changerModeWeb(MODE_RECEPTEUR);
- } else if (mode == "EMETTEUR") {
- changerModeWeb(MODE_EMETTEUR);
- }
- server.send(200, "text/plain", "Mode changé");
- });
- // --- 3. NOUVEL ENDPOINT : Renvoi des données JSON pour le JS ---
- server.on("/update", []() {
- String modeStr = (systemeMode == MODE_EMETTEUR) ? "EMETTEUR" : "RECEPTEUR";
- // Échappement CRITIQUE pour éviter de casser le JSON
- String historySafe = escapeJson(historiqueRecu);
- String morseSafe = escapeJson(lettreEnCours);
- String json = "{";
- json += "\"mode\": \"" + modeStr + "\", ";
- json += "\"history\": \"" + historySafe + "\", ";
- json += "\"currentMorse\": \"" + morseSafe + "\"";
- json += "}";
- server.send(200, "application/json", json);
- });
- server.begin();
- Serial.println("Serveur web démarré sur http://" + WiFi.localIP().toString());
- }
- void loop() {
- server.handleClient(); // Gérer les requêtes web
- // --- 1. Gestion de la réception UDP ---
- int packetSize = udp.parsePacket();
- if (packetSize > 0) {
- char packetBuffer[packetSize + 1];
- udp.read(packetBuffer, packetSize);
- packetBuffer[packetSize] = 0;
- String message = String(packetBuffer);
- if (message.endsWith("\n")) {
- message = message.substring(0, message.length() - 1);
- }
- // Mise à jour de l'historique
- String timestamp = String(millis()) + "ms";
- String entry = "<div class='log-entry received'>[" + timestamp + "] Reçu: <b>" + message + "</b></div>";
- if (historiqueRecu.length() > 0) {
- historiqueRecu += "<br>" + entry;
- } else {
- historiqueRecu = entry;
- }
- // Limiter la taille de l'historique
- if (historiqueRecu.length() > 2000) {
- int lastBr = historiqueRecu.lastIndexOf("<br>");
- if (lastBr > 0) historiqueRecu = historiqueRecu.substring(lastBr + 4);
- }
- Serial.print("Reçu: ");
- Serial.println(message);
- }
- // --- 2. Gestion selon le mode ---
- if (systemeMode == MODE_EMETTEUR) {
- gestionEmission();
- } else {
- // En mode réception, on peut juste attendre, mais on vérifie toujours les paquets
- // Le code de réception est déjà géré au début de la boucle
- delay(10);
- }
- }
- void gestionEmission() {
- int etatBouton = digitalRead(boutonMorse);
- unsigned long tempsActuel = millis();
- // Détection du début d'appui
- if (etatBouton == LOW && !appuiEnCours) {
- // Petit délai de stabilisation pour éviter les faux appuis (debouncing)
- delay(50);
- // Vérification à nouveau après le délai
- if (digitalRead(boutonMorse) == LOW) {
- appuiEnCours = true;
- debutAppui = tempsActuel;
- }
- }
- if (etatBouton == HIGH && appuiEnCours) {
- appuiEnCours = false;
- dernierRelachement = tempsActuel;
- unsigned long duree = tempsActuel - debutAppui;
- // Augmenter légèrement le seuil pour le trait si nécessaire,
- // mais surtout éviter la détection immédiate après un relâchement
- if (duree < SEUIL_TRAIT) {
- lettreEnCours += ".";
- } else {
- lettreEnCours += "-";
- }
- }
- // Logique de fin de lettre inchangée
- if (lettreEnCours.length() > 0 && !appuiEnCours) {
- if (tempsActuel - dernierRelachement > TEMPS_FIN_LETTRE) {
- traduireEtEnvoyer();
- dernierRelachement = tempsActuel;
- }
- }
- }
- void traduireEtEnvoyer() {
- String code = lettreEnCours;
- String caractere = "";
- // Traduction Morse
- if (code == ".-") caractere = "A";
- else if (code == "-...") caractere = "B";
- else if (code == "-.-.") caractere = "C";
- else if (code == "-..") caractere = "D";
- else if (code == ".") caractere = "E";
- else if (code == "..-.") caractere = "F";
- else if (code == "--.") caractere = "G";
- else if (code == "....") caractere = "H";
- else if (code == "..") caractere = "I";
- else if (code == ".---") caractere = "J";
- else if (code == "-.-") caractere = "K";
- else if (code == ".-..") caractere = "L";
- else if (code == "--") caractere = "M";
- else if (code == "-.") caractere = "N";
- else if (code == "---") caractere = "O";
- else if (code == ".--.") caractere = "P";
- else if (code == "--.-") caractere = "Q";
- else if (code == ".-.") caractere = "R";
- else if (code == "...") caractere = "S";
- else if (code == "-") caractere = "T";
- else if (code == "..-") caractere = "U";
- else if (code == "...-") caractere = "V";
- else if (code == ".--") caractere = "W";
- else if (code == "-..-") caractere = "X";
- else if (code == "-.--") caractere = "Y";
- else if (code == "--..") caractere = "Z";
- else if (code == ".----") caractere = "1";
- else if (code == "..---") caractere = "2";
- else if (code == "...--") caractere = "3";
- else if (code == "....-") caractere = "4";
- else if (code == ".....") caractere = "5";
- else if (code == "-....") caractere = "6";
- else if (code == "--...") caractere = "7";
- else if (code == "---..") caractere = "8";
- else if (code == "----.") caractere = "9";
- else if (code == "-----") caractere = "0";
- if (caractere != "") {
- Serial.print("Envoi: ");
- Serial.println(caractere);
- envoyerLettre(caractere);
- // Ajouter à l'historique local
- String timestamp = String(millis()) + "ms";
- String entry = "<div class='log-entry sent'>[" + timestamp + "] Envoyé: <b>" + caractere + "</b></div>";
- if (historiqueRecu.length() > 0) {
- historiqueRecu += "<br>" + entry;
- } else {
- historiqueRecu = entry;
- }
- if (historiqueRecu.length() > 2000) {
- int lastBr = historiqueRecu.lastIndexOf("<br>");
- if (lastBr > 0) historiqueRecu = historiqueRecu.substring(lastBr + 4);
- }
- } else {
- Serial.print("Code inconnu: ");
- Serial.println(code);
- }
- lettreEnCours = "";
- }
- void envoyerLettre(String lettre) {
- String message = lettre + "\n";
- udp.beginPacket(receiverIP, receiverPort);
- udp.print(message);
- udp.endPacket();
- Serial.println("Paquet envoyé.");
- }
Advertisement
Add Comment
Please, Sign In to add comment