Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
Petit prog pour esp32
#29
voili avec affichage ip et cliquable

Code :
// ESP32 Dashboard avec mode AP pour configuration initiale
#include <WiFi.h>
#include <WebServer.h>
#include <EEPROM.h>
#include <ArduinoJson.h>

// Structure pour stocker la config en EEPROM
struct Config {
  char magic[4];  // "RMS" pour vérifier si config valide
  char ssid[32];
  char password[64];
  char dashUser[32];     // Nom d'utilisateur pour le dashboard
  char dashPass[32];     // Mot de passe pour le dashboard
  char ip1[16];
  char ip2[16];
  char ip3[16];
  char ip4[16];
  char name1[32];
  char name2[32];
  char name3[32];
  char name4[32];
};

Config config;
WebServer server(80);
bool isAPMode = false;

// Variables globales pour le test d'IP
String testingIP = "";
bool isTestingConnection = false;
unsigned long testStartTime = 0;

// Page de configuration en mode AP
const char config_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Configuration Dashboard RMS</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background: #1a1a2e;
            color: white;
        }
        .container {
            max-width: 600px;
            margin: 0 auto;
            background: rgba(255,255,255,0.1);
            padding: 30px;
            border-radius: 10px;
        }
        h1 {
            text-align: center;
            color: #4CAF50;
        }
        .section {
            background: rgba(0,0,0,0.3);
            padding: 20px;
            margin: 20px 0;
            border-radius: 5px;
        }
        h2 {
            color: #2196F3;
            margin-top: 0;
        }
        label {
            display: block;
            margin: 10px 0 5px;
        }
        input, select {
            width: 100%;
            padding: 10px;
            border: 1px solid #555;
            border-radius: 3px;
            background: #333;
            color: white;
            box-sizing: border-box;
        }
        .ip-group {
            display: grid;
            grid-template-columns: 2fr 1fr;
            gap: 10px;
            margin: 10px 0;
        }
        button {
            background: #4CAF50;
            color: white;
            padding: 12px 20px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
            width: 100%;
            margin-top: 20px;
        }
        button:hover {
            background: #45a049;
        }
        .scan-btn {
            background: #2196F3;
            margin: 10px 0;
        }
        #scanResults {
            max-height: 200px;
            overflow-y: auto;
            background: rgba(0,0,0,0.5);
            padding: 10px;
            border-radius: 3px;
            margin: 10px 0;
        }
        .network-item {
            padding: 5px;
            cursor: pointer;
            border-bottom: 1px solid #444;
        }
        .network-item:hover {
            background: rgba(255,255,255,0.1);
        }
        .loading {
            text-align: center;
            color: #4CAF50;
        }
        .info {
            background: #ff9800;
            color: black;
            padding: 10px;
            border-radius: 5px;
            margin: 10px 0;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Configuration Dashboard RMS</h1>
       
        <div class="info" id="networkInfo">
            <!-- L'info sera remplie dynamiquement -->
        </div>
       
        <div class="section">
            <h2>1. Configuration WiFi</h2>
            <div id="currentWifi" style="background: #4CAF50; color: white; padding: 10px; border-radius: 3px; margin-bottom: 10px; display: none;">
                ? Connecté à : <strong id="wifiName">---</strong>
            </div>
            <button class="scan-btn" onclick="scanNetworks()">? Scanner les réseaux</button>
            <div id="scanResults"></div>
           
            <label>SSID:</label>
            <input type="text" id="ssid" placeholder="Nom du réseau WiFi">
           
            <label>Mot de passe:</label>
            <input type="password" id="password" placeholder="Mot de passe WiFi">
        </div>
       
        <div class="section">
            <h2>2. Sécurité du Dashboard</h2>
            <label>Nom d'utilisateur:</label>
            <input type="text" id="dashUser" placeholder="admin">
           
            <label>Mot de passe:</label>
            <input type="password" id="dashPass" placeholder="Mot de passe dashboard">
            <p style="color: #aaa; font-size: 12px;">Laissez vide pour désactiver l'authentification</p>
        </div>
       
        <div class="section">
            <h2>3. Configuration des interfaces RMS</h2>
            <p style="color: #aaa;">Configurez entre 2 et 4 interfaces</p>
           
            <div class="ip-group">
                <input type="text" id="ip1" placeholder="IP Interface 1 (ex: 192.168.1.100)">
                <input type="text" id="name1" placeholder="Nom 1">
            </div>
           
            <div class="ip-group">
                <input type="text" id="ip2" placeholder="IP Interface 2 (ex: 192.168.1.101)">
                <input type="text" id="name2" placeholder="Nom 2">
            </div>
           
            <div class="ip-group">
                <input type="text" id="ip3" placeholder="IP Interface 3 (optionnel)">
                <input type="text" id="name3" placeholder="Nom 3">
            </div>
           
            <div class="ip-group">
                <input type="text" id="ip4" placeholder="IP Interface 4 (optionnel)">
                <input type="text" id="name4" placeholder="Nom 4">
            </div>
        </div>
       
        <button onclick="saveConfig()">? Sauvegarder et redémarrer</button>

        <button style="background: #666; margin-top: 10px;" onclick="window.location.href='/'">
            ↩️ Retour au Dashboard
        </button>
       
        <div id="message"></div>
    </div>
   
    <script>
        // Charger la config existante au démarrage
        window.onload = function() {
            // Afficher l'info réseau
            fetch('/networkinfo')
                .then(response => response.json())
                .then(info => {
                    const networkInfo = document.getElementById('networkInfo');
                    if (info.isAP) {
                        networkInfo.innerHTML = 'Mode Configuration - Connectez-vous au WiFi pour continuer';
                        networkInfo.style.background = '#ff9800';
                    } else {
                        networkInfo.innerHTML = `IP réseau : ${info.ip}`;
                        networkInfo.style.background = '#4CAF50';
                    }
                });
           
            fetch('/getconfig')
                .then(response => response.json())
                .then(data => {
                    // Pré-remplir les IPs et noms
                    if (data.ip1) document.getElementById('ip1').value = data.ip1;
                    if (data.ip2) document.getElementById('ip2').value = data.ip2;
                    if (data.ip3) document.getElementById('ip3').value = data.ip3;
                    if (data.ip4) document.getElementById('ip4').value = data.ip4;
                    if (data.name1) document.getElementById('name1').value = data.name1;
                    if (data.name2) document.getElementById('name2').value = data.name2;
                    if (data.name3) document.getElementById('name3').value = data.name3;
                    if (data.name4) document.getElementById('name4').value = data.name4;
                   
                    // AJOUT : Afficher le WiFi actuel si connecté
                    if (data.ssid && window.location.hostname !== '192.168.4.1') {
                        document.getElementById('currentWifi').style.display = 'block';
                        document.getElementById('wifiName').textContent = data.ssid;
                    }
                })
                .catch(err => {
                    console.log('Pas de config existante');
                });
        };
       
        function scanNetworks() {
            document.getElementById('scanResults').innerHTML = '<div class="loading">Scan en cours...</div>';
           
            fetch('/scan')
                .then(response => response.json())
                .then(data => {
                    let html = '';
                    data.networks.forEach(network => {
                        html += `<div class="network-item" onclick="selectNetwork('${network.ssid}')">
                                   ? ${network.ssid} (${network.rssi} dBm)
                                 </div>`;
                    });
                    document.getElementById('scanResults').innerHTML = html || 'Aucun réseau trouvé';
                });
        }
       
        function selectNetwork(ssid) {
            document.getElementById('ssid').value = ssid;
        }
       
        function saveConfig() {
            const config = {
                ssid: document.getElementById('ssid').value,
                password: document.getElementById('password').value,
                dashUser: document.getElementById('dashUser').value,
                dashPass: document.getElementById('dashPass').value,
                ip1: document.getElementById('ip1').value,
                ip2: document.getElementById('ip2').value,
                ip3: document.getElementById('ip3').value,
                ip4: document.getElementById('ip4').value,
                name1: document.getElementById('name1').value || 'Interface 1',
                name2: document.getElementById('name2').value || 'Interface 2',
                name3: document.getElementById('name3').value || 'Interface 3',
                name4: document.getElementById('name4').value || 'Interface 4'
            };
           
            // Validation
            if (!config.ssid || !config.password) {
                alert('Veuillez remplir les informations WiFi');
                return;
            }
           
            if (!config.ip1 || !config.ip2) {
                alert('Veuillez configurer au moins 2 interfaces');
                return;
            }
           
            document.getElementById('message').innerHTML = '<div class="loading">Sauvegarde en cours...</div>';
           
            fetch('/save', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(config)
            })
            .then(response => response.json())
            .then(data => {
                if (data.status === 'testing') {
                    document.getElementById('message').innerHTML =
                        '<div class="info">✅ Configuration sauvegardée!</div>' +
                        '<div class="loading">Test de connexion au réseau...</div>';
                   
                    // Commencer à vérifier l'IP
                    checkIPStatus(config.ssid);
                }
            })
            .catch(err => {
                document.getElementById('message').innerHTML =
                    '<div class="info" style="background: #ff4444;">Erreur de sauvegarde: ' + err + '</div>';
            });
        }
       
        function checkIPStatus(ssid) {
            const checkInterval = setInterval(() => {
                fetch('/checkip')
                    .then(response => response.json())
                    .then(data => {
                        if (data.status === 'connected' && data.ip) {
                            clearInterval(checkInterval);
                            document.getElementById('message').innerHTML =
                                '<div class="info">✅ Configuration sauvegardée!</div>' +
                                '<div class="info" style="background: #4CAF50; margin-top: 10px;">' +
                                '? Nouvelle adresse IP : <a href="http://' + data.ip + '" style="color: white; font-size: 24px; font-weight: bold;">' + data.ip + '</a></div>' +
                                '<div class="info">Cliquez sur l\'IP ou notez cette adresse! Redémarrage dans 10 secondes...</div>' +
                                '<div class="info">Connectez-vous au WiFi "' + ssid +
                                '" et accédez à <a href="http://' + data.ip + '" style="color: white; font-weight: bold;">http://' + data.ip + '</a></div>';
                           
                            // Redémarrer après 10 secondes
                            setTimeout(() => {
                                window.location.href = 'http://' + data.ip;
                            }, 10000);
                           
                        } else if (data.status === 'failed') {
                            clearInterval(checkInterval);
                            document.getElementById('message').innerHTML =
                                '<div class="info" style="background: #ff4444;">❌ Impossible de se connecter au réseau!</div>' +
                                '<div class="info">Vérifiez le mot de passe WiFi et réessayez.</div>' +
                                '<div class="info">Redémarrage dans 10 secondes...</div>';
                        }
                        // Si status est "testing", on continue à vérifier
                    })
                    .catch(err => {
                        // Si erreur, c'est peut-être que l'ESP32 a redémarré
                        clearInterval(checkInterval);
                    });
            }, 1000); // Vérifier chaque seconde
        }
    </script>
</body>
</html>
)rawliteral";

// Page de login
const char login_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login Dashboard RMS</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            background: #1a1a2e;
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
        .login-box {
            background: rgba(255,255,255,0.1);
            padding: 40px;
            border-radius: 10px;
            box-shadow: 0 0 20px rgba(0,0,0,0.5);
            width: 300px;
        }
        h2 {
            text-align: center;
            color: #4CAF50;
            margin-bottom: 30px;
        }
        input {
            width: 100%;
            padding: 12px;
            margin: 10px 0;
            border: 1px solid #555;
            border-radius: 5px;
            background: #333;
            color: white;
            box-sizing: border-box;
        }
        button {
            width: 100%;
            padding: 12px;
            margin-top: 20px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
        }
        button:hover {
            background: #45a049;
        }
        .error {
            color: #ff4444;
            text-align: center;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <div class="login-box">
        <h2>? Dashboard RMS</h2>
        <form action="/login" method="POST">
            <input type="text" name="user" placeholder="Nom d'utilisateur" required>
            <input type="password" name="pass" placeholder="Mot de passe" required>
            <button type="submit">Se connecter</button>
        </form>
        <div id="error" class="error"></div>
    </div>
    <script>
        if (window.location.search.includes('error=1')) {
            document.getElementById('error').textContent = 'Identifiants incorrects';
        }
    </script>
</body>
</html>
)rawliteral";

// Page dashboard modifiée avec bouton plein écran
const char dashboard_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dashboard RMS</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background: #222;
            font-family: Arial, sans-serif;
            height: 100vh;
            overflow: hidden;
        }
       
        #dashboard {
            display: grid;
            height: 100vh;
            gap: 2px;
            transition: all 0.3s ease;
        }
       
        #dashboard.fullscreen {
            display: block !important;
        }
       
        .layout-2 {
            grid-template-columns: 1fr 1fr;
            grid-template-rows: 1fr;
        }
       
        .layout-3 {
            grid-template-columns: 1fr 1fr;
            grid-template-rows: 1fr 1fr;
        }
        .layout-3 .frame-container:first-child {
            grid-row: span 2;
        }
       
        .layout-4 {
            grid-template-columns: 1fr 1fr;
            grid-template-rows: 1fr 1fr;
        }
       
        .frame-container {
            position: relative;
            overflow: hidden;
            background: white;
            display: none;
        }
       
        .frame-container.active {
            display: block;
        }
       
        .frame-container.fullscreen-active {
            display: block !important;
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            z-index: 50;
        }
       
        .frame-wrapper {
            width: 100%;
            height: 100%;
            transform-origin: top left;
            transition: transform 0.3s ease;
        }
       
        iframe {
            width: 100%;
            height: 100%;
            border: none;
            background: white;
        }
       
        .frame-header {
            position: absolute;
            top: 5px;
            left: 5px;
            display: flex;
            align-items: center;
            gap: 10px;
            z-index: 10;
        }
       
        .frame-label {
            background: rgba(0,0,0,0.8);
            color: white;
            padding: 5px 10px;
            font-size: 12px;
            border-radius: 3px;
            pointer-events: none;
        }
       
        .fullscreen-btn {
            background: rgba(0,0,0,0.8);
            color: white;
            border: none;
            padding: 5px 8px;
            font-size: 12px;
            border-radius: 3px;
            cursor: pointer;
            transition: background 0.2s;
        }
       
        .fullscreen-btn:hover {
            background: rgba(0,0,0,0.9);
        }
       
        .fullscreen-btn.exit {
            background: rgba(220,53,69,0.9);
        }
       
        .fullscreen-btn.exit:hover {
            background: rgba(220,53,69,1);
        }
       
        /* Contrôles de zoom */
        .zoom-controls {
            position: absolute;
            top: 5px;
            right: 5px;
            background: rgba(0,0,0,0.8);
            padding: 5px;
            border-radius: 3px;
            z-index: 10;
            display: flex;
            gap: 5px;
        }
       
        .zoom-btn {
            width: 25px;
            height: 25px;
            border: none;
            background: #444;
            color: white;
            cursor: pointer;
            border-radius: 3px;
            font-size: 16px;
            display: flex;
            align-items: center;
            justify-content: center;
        }
       
        .zoom-btn:hover {
            background: #666;
        }
       
        .zoom-value {
            color: white;
            font-size: 12px;
            min-width: 45px;
            text-align: center;
            display: flex;
            align-items: center;
        }
       
        .btn-config {
            position: fixed;
            bottom: 10px;
            right: 10px;
            background: #2196F3;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 5px;
            cursor: pointer;
            z-index: 100;
        }
       
        .btn-config:hover {
            background: #1976D2;
        }
       
        .hidden {
            display: none !important;
        }
    </style>
</head>
<body>
    <div id="dashboard">
        <div class="frame-container" id="frame1-container">
            <div class="frame-header">
                <span class="frame-label" id="label1">Interface 1</span>
                <button class="fullscreen-btn" onclick="toggleFullscreen(1)" id="fullscreen-btn-1">⛶</button>
            </div>
            <div class="zoom-controls">
                <button class="zoom-btn" onclick="zoom(1, -0.1)">−</button>
                <span class="zoom-value" id="zoom1">100%</span>
                <button class="zoom-btn" onclick="zoom(1, 0.1)">+</button>
            </div>
            <div class="frame-wrapper" id="wrapper1">
                <iframe id="frame1"></iframe>
            </div>
        </div>
       
        <div class="frame-container" id="frame2-container">
            <div class="frame-header">
                <span class="frame-label" id="label2">Interface 2</span>
                <button class="fullscreen-btn" onclick="toggleFullscreen(2)" id="fullscreen-btn-2">⛶</button>
            </div>
            <div class="zoom-controls">
                <button class="zoom-btn" onclick="zoom(2, -0.1)">−</button>
                <span class="zoom-value" id="zoom2">100%</span>
                <button class="zoom-btn" onclick="zoom(2, 0.1)">+</button>
            </div>
            <div class="frame-wrapper" id="wrapper2">
                <iframe id="frame2"></iframe>
            </div>
        </div>
       
        <div class="frame-container" id="frame3-container">
            <div class="frame-header">
                <span class="frame-label" id="label3">Interface 3</span>
                <button class="fullscreen-btn" onclick="toggleFullscreen(3)" id="fullscreen-btn-3">⛶</button>
            </div>
            <div class="zoom-controls">
                <button class="zoom-btn" onclick="zoom(3, -0.1)">−</button>
                <span class="zoom-value" id="zoom3">100%</span>
                <button class="zoom-btn" onclick="zoom(3, 0.1)">+</button>
            </div>
            <div class="frame-wrapper" id="wrapper3">
                <iframe id="frame3"></iframe>
            </div>
        </div>
       
        <div class="frame-container" id="frame4-container">
            <div class="frame-header">
                <span class="frame-label" id="label4">Interface 4</span>
                <button class="fullscreen-btn" onclick="toggleFullscreen(4)" id="fullscreen-btn-4">⛶</button>
            </div>
            <div class="zoom-controls">
                <button class="zoom-btn" onclick="zoom(4, -0.1)">−</button>
                <span class="zoom-value" id="zoom4">100%</span>
                <button class="zoom-btn" onclick="zoom(4, 0.1)">+</button>
            </div>
            <div class="frame-wrapper" id="wrapper4">
                <iframe id="frame4"></iframe>
            </div>
        </div>
    </div>
   
    <button class="btn-config" onclick="window.location.href='/config'">
        ⚙️ Configuration
    </button>
   
    <script>
        // Stocker les niveaux de zoom et l'état plein écran
        const zoomLevels = {1: 1, 2: 1, 3: 1, 4: 1};
        let currentFullscreen = null;
       
        // Fonction de basculement plein écran
        function toggleFullscreen(frameNum) {
            const container = document.getElementById(`frame${frameNum}-container`);
            const dashboard = document.getElementById('dashboard');
            const btn = document.getElementById(`fullscreen-btn-${frameNum}`);
            const configBtn = document.querySelector('.btn-config');
           
            if (currentFullscreen === frameNum) {
                // Sortir du plein écran
                container.classList.remove('fullscreen-active');
                dashboard.classList.remove('fullscreen');
                btn.classList.remove('exit');
                btn.textContent = '⛶';
                configBtn.classList.remove('hidden');
                currentFullscreen = null;
               
                // Réafficher toutes les autres vues actives
                for (let i = 1; i <= 4; i++) {
                    const otherContainer = document.getElementById(`frame${i}-container`);
                    if (otherContainer.classList.contains('active') && i !== frameNum) {
                        otherContainer.style.display = '';
                    }
                }
            } else {
                // Entrer en plein écran
               
                // D'abord sortir du plein écran si une autre vue l'est
                if (currentFullscreen !== null) {
                    toggleFullscreen(currentFullscreen);
                }
               
                container.classList.add('fullscreen-active');
                dashboard.classList.add('fullscreen');
                btn.classList.add('exit');
                btn.textContent = '✕';
                configBtn.classList.add('hidden');
                currentFullscreen = frameNum;
               
                // Masquer toutes les autres vues
                for (let i = 1; i <= 4; i++) {
                    if (i !== frameNum) {
                        const otherContainer = document.getElementById(`frame${i}-container`);
                        otherContainer.style.display = 'none';
                    }
                }
            }
        }
       
        // Fonction de zoom individuel
        function zoom(frameNum, delta) {
            zoomLevels[frameNum] = Math.max(0.5, Math.min(2, zoomLevels[frameNum] + delta));
            updateZoom(frameNum);
        }
       
        // Mettre à jour l'affichage du zoom
        function updateZoom(frameNum) {
            const wrapper = document.getElementById(`wrapper${frameNum}`);
            const zoomDisplay = document.getElementById(`zoom${frameNum}`);
            const scale = zoomLevels[frameNum];
           
            wrapper.style.transform = `scale(${scale})`;
            wrapper.style.width = `${100 / scale}%`;
            wrapper.style.height = `${100 / scale}%`;
            zoomDisplay.textContent = `${Math.round(scale * 100)}%`;
        }
       
        // Gestion de la touche Escape pour sortir du plein écran
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Escape' && currentFullscreen !== null) {
                toggleFullscreen(currentFullscreen);
            }
        });
       
        // Charger la config depuis l'ESP32
        fetch('/getconfig')
            .then(response => response.json())
            .then(config => {
                applyConfig(config);
            });
       
        function applyConfig(config) {
            const dashboard = document.getElementById('dashboard');
            let count = 0;
           
            // Compter les interfaces configurées
            for (let i = 1; i <= 4; i++) {
                if (config[`ip${i}`]) count++;
            }
           
            // Appliquer le layout
            dashboard.className = '';
            dashboard.classList.add(`layout-${count}`);
           
            // Configurer les frames
            let frameIndex = 1;
            for (let i = 1; i <= 4; i++) {
                if (config[`ip${i}`]) {
                    const container = document.getElementById(`frame${frameIndex}-container`);
                    const frame = document.getElementById(`frame${frameIndex}`);
                    const label = document.getElementById(`label${frameIndex}`);
                   
                    container.classList.add('active');
                    frame.src = `http://${config[`ip${i}`]}`;
                    label.textContent = config[`name${i}`] || `Interface ${i}`;
                   
                    frameIndex++;
                }
            }
        }
    </script>
</body>
</html>
)rawliteral";

void loadConfig() {
  EEPROM.begin(sizeof(Config));
  EEPROM.get(0, config);
 
  // Vérifier si config valide
  if (String(config.magic) != "RMS") {
    // Config invalide, mode AP
    isAPMode = true;
   
    // Initialiser la config avec des valeurs vides
    memset(&config, 0, sizeof(Config));
    strcpy(config.magic, "");
    strcpy(config.ssid, "");
    strcpy(config.password, "");
    strcpy(config.dashUser, "");
    strcpy(config.dashPass, "");
    strcpy(config.ip1, "");
    strcpy(config.ip2, "");
    strcpy(config.ip3, "");
    strcpy(config.ip4, "");
    strcpy(config.name1, "");
    strcpy(config.name2, "");
    strcpy(config.name3, "");
    strcpy(config.name4, "");
  }
}

void saveConfig() {
  strcpy(config.magic, "RMS");
  EEPROM.put(0, config);
  EEPROM.commit();
}

void clearConfig() {
  strcpy(config.magic, "");
  EEPROM.put(0, config);
  EEPROM.commit();
}

void startAPMode() {
  Serial.println("Démarrage en mode AP...");
  WiFi.mode(WIFI_AP);
  WiFi.softAP("RMS_Dashboard_Config", "rms12345");
 
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP: ");
  Serial.println(IP);
}

void handleConfigPage() {
  server.send(200, "text/html", config_html);
}

// Variables globales pour l'authentification
bool isAuthenticated = false;
String sessionID = "";

// Générer un ID de session aléatoire
String generateSessionID() {
  String id = "";
  for (int i = 0; i < 16; i++) {
    id += String(random(0, 16), HEX);
  }
  return id;
}

// Vérifier l'authentification
bool checkAuth() {
  // En mode AP, pas d'authentification
  if (isAPMode) {
    return true;
  }
 
  // Si pas de mot de passe configuré, accès libre
  if (strlen(config.dashUser) == 0 && strlen(config.dashPass) == 0) {
    return true;
  }
 
  // Si seulement un des deux est vide, accès libre aussi (config incomplète)
  if (strlen(config.dashUser) == 0 || strlen(config.dashPass) == 0) {
    return true;
  }
 
  // Vérifier le cookie de session
  if (server.hasHeader("Cookie")) {
    String cookie = server.header("Cookie");
    if (cookie.indexOf("session=" + sessionID) != -1 && sessionID != "") {
      return true;
    }
  }
  return false;
}

void handleNetworkInfo() {
  String json = "{";
  if (isAPMode) {
    json += "\"isAP\":true,";
    json += "\"ip\":\"192.168.4.1\"";
  } else {
    json += "\"isAP\":false,";
    json += "\"ip\":\"" + WiFi.localIP().toString() + "\"";
  }
  json += "}";
 
  server.send(200, "application/json", json);
}

void handleLogin() {
  if (server.method() == HTTP_POST) {
    String user = server.arg("user");
    String pass = server.arg("pass");
   
    if (user == config.dashUser && pass == config.dashPass) {
      // Login réussi
      sessionID = generateSessionID();
      server.sendHeader("Set-Cookie", "session=" + sessionID + "; Path=/");
      server.sendHeader("Location", "/");
      server.send(302);
    } else {
      // Login échoué
      server.sendHeader("Location", "/?error=1");
      server.send(302);
    }
  } else {
    server.send(200, "text/html", login_html);
  }
}

void handleRoot() {
  if (isAPMode) {
    server.send(200, "text/html", config_html);
  } else {
    if (!checkAuth()) {
      server.send(200, "text/html", login_html);
    } else {
      server.send(200, "text/html", dashboard_html);
    }
  }
}

void handleScan() {
  int n = WiFi.scanNetworks();
  String json = "{\"networks\":[";
 
  for (int i = 0; i < n; i++) {
    if (i > 0) json += ",";
    String ssid = WiFi.SSID(i);
    // Échapper les caractères spéciaux dans le SSID
    ssid.replace("\"", "\\\"");
    ssid.replace("\\", "\\\\");
    json += "{\"ssid\":\"" + ssid + "\",\"rssi\":" + String(WiFi.RSSI(i)) + "}";
  }
  json += "]}";
 
  server.send(200, "application/json", json);
}

void handleSave() {
  if (server.hasArg("plain")) {
    DynamicJsonDocument doc(1024);
    deserializeJson(doc, server.arg("plain"));
   
    // Sauvegarder la config
    strcpy(config.ssid, doc["ssid"]);
    strcpy(config.password, doc["password"]);
    strcpy(config.dashUser, doc["dashUser"] | "");
    strcpy(config.dashPass, doc["dashPass"] | "");
    strcpy(config.ip1, doc["ip1"]);
    strcpy(config.ip2, doc["ip2"]);
    strcpy(config.ip3, doc["ip3"] | "");
    strcpy(config.ip4, doc["ip4"] | "");
    strcpy(config.name1, doc["name1"] | "Interface 1");
    strcpy(config.name2, doc["name2"] | "Interface 2");
    strcpy(config.name3, doc["name3"] | "Interface 3");
    strcpy(config.name4, doc["name4"] | "Interface 4");
   
    saveConfig();
   
    // Démarrer le test de connexion
    isTestingConnection = true;
    testStartTime = millis();
    testingIP = "";
   
    // Mode AP+STA
    WiFi.mode(WIFI_AP_STA);
    WiFi.softAP("RMS_Dashboard_Config", "rms12345");
    WiFi.begin(config.ssid, config.password);
   
    Serial.println("Test de connexion au nouveau réseau...");
   
    // Répondre immédiatement
    server.send(200, "application/json", "{\"status\":\"testing\"}");
  }
}

// Nouvelle route pour vérifier le statut
void handleCheckIP() {
  String response = "{";
 
  if (isTestingConnection) {
    if (WiFi.status() == WL_CONNECTED && testingIP.isEmpty()) {
      testingIP = WiFi.localIP().toString();
      Serial.print("IP obtenue: ");
      Serial.println(testingIP);
    }
   
    if (!testingIP.isEmpty()) {
      response += "\"status\":\"connected\",\"ip\":\"" + testingIP + "\"";
    } else if (millis() - testStartTime > 10000) {
      response += "\"status\":\"failed\"";
      isTestingConnection = false;
    } else {
      response += "\"status\":\"testing\"";
    }
  } else {
    response += "\"status\":\"idle\"";
  }
 
  response += "}";
  server.send(200, "application/json", response);
}

void handleConfig() {
  String json = "{";
  json += "\"ssid\":\"" + String(config.ssid) + "\","; 
  json += "\"ip1\":\"" + String(config.ip1) + "\",";
  json += "\"ip2\":\"" + String(config.ip2) + "\",";
  json += "\"ip3\":\"" + String(config.ip3) + "\",";
  json += "\"ip4\":\"" + String(config.ip4) + "\",";
  json += "\"name1\":\"" + String(config.name1) + "\",";
  json += "\"name2\":\"" + String(config.name2) + "\",";
  json += "\"name3\":\"" + String(config.name3) + "\",";
  json += "\"name4\":\"" + String(config.name4) + "\"";
  json += "}";
 
  server.send(200, "application/json", json);
}

void handleReset() {
  clearConfig();
  server.send(200, "text/plain", "Config cleared");
}

void setup() {
  Serial.begin(115200);
 
  // Charger la config
  loadConfig();
 
  if (isAPMode) {
    // Mode AP pour configuration
    startAPMode();
  } else {
    // Mode normal - connexion WiFi
    WiFi.begin(config.ssid, config.password);
   
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
      delay(500);
      Serial.print(".");
      attempts++;
    }
   
    if (WiFi.status() != WL_CONNECTED) {
      // Échec connexion, retour en mode AP
      isAPMode = true;
      startAPMode();
    } else {
      Serial.println("\nConnecté!");
      Serial.print("IP: ");
      Serial.println(WiFi.localIP());
    }
  }
 
  // Routes
  server.on("/", handleRoot);
  server.on("/login", handleLogin);
  server.on("/config", handleConfigPage);  // Page de configuration
  server.on("/scan", handleScan);
  server.on("/save", HTTP_POST, handleSave);
  server.on("/getconfig", handleConfig);  // API pour récupérer la config
  server.on("/reset", handleReset);
  server.on("/checkip", handleCheckIP);  // NOUVELLE ROUTE POUR VÉRIFIER L'IP

  server.on("/networkinfo", handleNetworkInfo);
 
  server.begin();
  Serial.println("Serveur démarré");
}

void loop() {
  server.handleClient();
 
  // Si on est en train de tester la connexion, redémarrer après 15 secondes
  if (isTestingConnection && millis() - testStartTime > 15000) {
    ESP.restart();
  }
}
ESP32Wroom, Triac 40A "BTA40", Source UxIx2, Cumulus 300L 3000W.
Sonde temperature sur radiateur triac mise en route ventilateur a 25°
réactivité 30 seuil -50
2 esp32 pour gestion charge batteries
14 panneaux de 410wcc en autoconso micro-onduleur APS DS3
Suivi sur Domoticz
Répondre


Messages dans ce sujet
Petit prog pour esp32 - par lucky - 27-05-2025, 09:04 PM
RE: Petit prog pour esp32 - par Sgb31 - 28-05-2025, 07:51 AM
RE: Petit prog pour esp32 - par lucky - 28-05-2025, 08:03 AM
RE: Petit prog pour esp32 - par Sgb31 - 28-05-2025, 09:52 AM
RE: Petit prog pour esp32 - par Serge111 - 28-05-2025, 03:09 PM
RE: Petit prog pour esp32 - par grostoto - 28-05-2025, 07:57 PM
RE: Petit prog pour esp32 - par lucky - 28-05-2025, 08:07 PM
RE: Petit prog pour esp32 - par grostoto - 28-05-2025, 09:48 PM
RE: Petit prog pour esp32 - par lucky - 28-05-2025, 10:03 PM
RE: Petit prog pour esp32 - par grostoto - 28-05-2025, 10:07 PM
RE: Petit prog pour esp32 - par lucky - 29-05-2025, 08:21 AM
RE: Petit prog pour esp32 - par Philmaz - 29-05-2025, 05:32 PM
RE: Petit prog pour esp32 - par lucky - 29-05-2025, 06:03 PM
RE: Petit prog pour esp32 - par Philmaz - 29-05-2025, 07:45 PM
RE: Petit prog pour esp32 - par grostoto - 29-05-2025, 06:08 PM
RE: Petit prog pour esp32 - par lucky - 29-05-2025, 06:17 PM
RE: Petit prog pour esp32 - par grostoto - 29-05-2025, 07:49 PM
RE: Petit prog pour esp32 - par lucky - 29-05-2025, 08:14 PM
RE: Petit prog pour esp32 - par grostoto - 29-05-2025, 09:01 PM
RE: Petit prog pour esp32 - par lucky - 29-05-2025, 09:51 PM
RE: Petit prog pour esp32 - par Philmaz - 29-05-2025, 10:32 PM
RE: Petit prog pour esp32 - par grostoto - 29-05-2025, 11:21 PM
RE: Petit prog pour esp32 - par Philmaz - 30-05-2025, 07:26 AM
RE: Petit prog pour esp32 - par lucky - 30-05-2025, 07:41 AM
RE: Petit prog pour esp32 - par grostoto - 30-05-2025, 08:02 AM
RE: Petit prog pour esp32 - par Philmaz - 30-05-2025, 08:19 AM
RE: Petit prog pour esp32 - par lucky - 30-05-2025, 08:26 AM
RE: Petit prog pour esp32 - par Philmaz - 30-05-2025, 08:29 AM
RE: Petit prog pour esp32 - par Philmaz - 30-05-2025, 09:01 AM
RE: Petit prog pour esp32 - par lucky - 30-05-2025, 09:02 AM
RE: Petit prog pour esp32 - par lucky - 30-05-2025, 09:00 AM
RE: Petit prog pour esp32 - par grostoto - 30-05-2025, 09:11 AM
RE: Petit prog pour esp32 - par lucky - 30-05-2025, 03:26 PM
RE: Petit prog pour esp32 - par PhDV61 - 30-05-2025, 09:12 AM
RE: Petit prog pour esp32 - par lucky - 30-05-2025, 09:26 AM
RE: Petit prog pour esp32 - par bernard62 - 30-05-2025, 12:12 PM
RE: Petit prog pour esp32 - par glu3 - 30-05-2025, 02:21 PM
RE: Petit prog pour esp32 - par pdunet - 30-05-2025, 02:29 PM
RE: Petit prog pour esp32 - par lucky - 30-05-2025, 05:33 PM
RE: Petit prog pour esp32 - par grostoto - 30-05-2025, 07:50 PM
RE: Petit prog pour esp32 - par 59jag - 30-05-2025, 10:03 PM
RE: Petit prog pour esp32 - par lucky - 31-05-2025, 08:03 AM
RE: Petit prog pour esp32 - par lucky - 31-05-2025, 08:04 AM
RE: Petit prog pour esp32 - par 59jag - 31-05-2025, 09:22 AM
RE: Petit prog pour esp32 - par Sgb31 - 31-05-2025, 09:35 AM
RE: Petit prog pour esp32 - par lucky - 31-05-2025, 12:01 PM
RE: Petit prog pour esp32 - par pdunet - Il y a 21 minutes

Atteindre :


Utilisateur(s) parcourant ce sujet : GPL, 1 visiteur(s)