gpt5
This commit is contained in:
@@ -1,133 +0,0 @@
|
||||
# Guide de Test du Portail Captif
|
||||
|
||||
## Test Rapide - Portail Captif
|
||||
|
||||
### Étape 1 : Compiler et téléverser le firmware principal
|
||||
|
||||
```bash
|
||||
# Si PlatformIO est installé
|
||||
pio run -e main --target upload
|
||||
|
||||
# Ou via VS Code
|
||||
# Utiliser la tâche "PlatformIO: Upload Main Project"
|
||||
```
|
||||
|
||||
### Étape 2 : Configuration initiale
|
||||
|
||||
1. **Mode Point d'accès** : Assurez-vous que `useStationMode = false` dans le code
|
||||
2. **Redémarrez l'ESP32** après le téléversement
|
||||
|
||||
### Étape 3 : Test du portail captif
|
||||
|
||||
1. **Connectez-vous au WiFi** :
|
||||
- Nom : `HOKA_Clock`
|
||||
- Mot de passe : `hoka`
|
||||
|
||||
2. **Test automatique** :
|
||||
- Ouvrez votre navigateur
|
||||
- Essayez d'aller sur n'importe quel site (google.com, facebook.com, etc.)
|
||||
- Vous devriez être automatiquement redirigé vers l'interface de l'horloge
|
||||
|
||||
3. **Test manuel** :
|
||||
- Accédez directement à : `http://192.168.1.1`
|
||||
|
||||
### Étape 4 : Vérification des fonctionnalités
|
||||
|
||||
1. **Interface web** : L'interface de configuration de l'horloge doit s'afficher
|
||||
2. **Clé d'accès** : Utilisez `hoka` comme clé pour modifier les paramètres
|
||||
3. **Redirection** : Toutes les tentatives de navigation doivent rediriger vers l'horloge
|
||||
|
||||
## Test Dédié - Portail Captif Simple
|
||||
|
||||
Pour tester uniquement la fonctionnalité de portail captif sans l'affichage LED :
|
||||
|
||||
### Étape 1 : Compiler le test
|
||||
|
||||
```bash
|
||||
pio run -e captive_portal_test --target upload
|
||||
```
|
||||
|
||||
### Étape 2 : Connection et test
|
||||
|
||||
1. **WiFi** : `HOKA_Clock_Test` (mot de passe : `hoka`)
|
||||
2. **Navigation** : Essayez d'aller sur n'importe quel site
|
||||
3. **Résultat attendu** : Page de test confirmant que le portail captif fonctionne
|
||||
|
||||
## Surveillance et débogage
|
||||
|
||||
### Monitoring série
|
||||
|
||||
```bash
|
||||
pio device monitor
|
||||
```
|
||||
|
||||
### Messages à surveiller
|
||||
|
||||
```
|
||||
=== ESP32 P10 RGB Digital Clock ===
|
||||
WIFI mode : AP avec Portail Captif
|
||||
Serveur DNS démarré pour portail captif
|
||||
HTTP server started
|
||||
Captive Portal active - navigate to any website
|
||||
```
|
||||
|
||||
### Débogage des problèmes
|
||||
|
||||
1. **Le portail ne s'ouvre pas** :
|
||||
- Vérifiez que `useStationMode = false`
|
||||
- Redémarrez l'ESP32
|
||||
- Testez l'accès direct à `http://192.168.1.1`
|
||||
|
||||
2. **Problèmes de redirection** :
|
||||
- Effacez le cache du navigateur
|
||||
- Testez avec un navigateur différent
|
||||
- Vérifiez les logs série pour voir les requêtes
|
||||
|
||||
3. **Compilation échoue** :
|
||||
- Vérifiez que `DNSServer` est dans les dépendances
|
||||
- Utilisez l'environnement `main` ou `captive_portal_test`
|
||||
|
||||
## Personnalisation
|
||||
|
||||
### Modifier le nom du réseau WiFi
|
||||
|
||||
Dans `src/main.cpp` :
|
||||
```cpp
|
||||
const char* ap_ssid = "MON_HORLOGE"; // Changez ici
|
||||
```
|
||||
|
||||
### Modifier l'IP du portail
|
||||
|
||||
```cpp
|
||||
const IPAddress apIP(192, 168, 1, 1); // Changez ici
|
||||
```
|
||||
|
||||
### Ajouter des routes personnalisées
|
||||
|
||||
```cpp
|
||||
server.on("/ma-route", maFonction);
|
||||
```
|
||||
|
||||
## Compatibilité testée
|
||||
|
||||
✅ **Android** : Notification automatique "Se connecter au réseau"
|
||||
✅ **iOS** : Ouverture automatique du navigateur captif
|
||||
✅ **Windows** : Redirection lors de la première navigation
|
||||
✅ **macOS** : Détection automatique du portail captif
|
||||
✅ **Linux** : Redirection manuelle nécessaire
|
||||
|
||||
## Prochaines étapes
|
||||
|
||||
Une fois le portail captif testé et fonctionnel :
|
||||
|
||||
1. **Personnalisez l'interface** web selon vos besoins
|
||||
2. **Ajoutez des fonctionnalités** (WPS, configuration WiFi avancée, etc.)
|
||||
3. **Optimisez les performances** selon votre configuration matérielle
|
||||
4. **Testez avec différents appareils** pour garantir la compatibilité
|
||||
|
||||
## Support
|
||||
|
||||
Pour toute question ou problème :
|
||||
- Vérifiez les logs série avec `pio device monitor`
|
||||
- Consultez la documentation dans `CAPTIVE_PORTAL_README.md`
|
||||
- Testez d'abord avec l'environnement `captive_portal_test`
|
||||
@@ -1,156 +0,0 @@
|
||||
# Configuration du Portail Captif pour ESP32 P10 RGB Digital Clock
|
||||
|
||||
## Modifications apportées
|
||||
|
||||
Ce document décrit les modifications apportées pour transformer l'interface web de l'horloge ESP32 en portail captif.
|
||||
|
||||
### 1. Modifications du fichier `platformio.ini`
|
||||
|
||||
Ajout de la dépendance `DNSServer` dans l'environnement principal :
|
||||
|
||||
```ini
|
||||
[env:main]
|
||||
src_filter = +<main.cpp>
|
||||
lib_deps =
|
||||
adafruit/Adafruit BusIO@^1.16.1
|
||||
adafruit/Adafruit GFX Library@^1.11.9
|
||||
adafruit/RTClib@^2.1.4
|
||||
https://github.com/2dom/PxMatrix.git
|
||||
DNSServer # <-- NOUVELLE DÉPENDANCE
|
||||
```
|
||||
|
||||
### 2. Modifications du fichier `src/main.cpp`
|
||||
|
||||
#### 2.1 Inclusion de la bibliothèque DNSServer
|
||||
|
||||
```cpp
|
||||
#include <DNSServer.h>
|
||||
```
|
||||
|
||||
#### 2.2 Déclaration des objets pour le portail captif
|
||||
|
||||
```cpp
|
||||
// Serveur web et DNS pour portail captif
|
||||
WebServer server(80);
|
||||
DNSServer dnsServer;
|
||||
|
||||
// Configuration du portail captif
|
||||
const byte DNS_PORT = 53;
|
||||
const IPAddress apIP(192, 168, 1, 1);
|
||||
```
|
||||
|
||||
#### 2.3 Modification de la fonction `set_ESP32_Access_Point()`
|
||||
|
||||
- Ajout du démarrage du serveur DNS
|
||||
- Configuration pour rediriger toutes les requêtes DNS vers l'ESP32
|
||||
|
||||
```cpp
|
||||
// Démarrage du serveur DNS pour le portail captif
|
||||
dnsServer.start(DNS_PORT, "*", apIP);
|
||||
```
|
||||
|
||||
#### 2.4 Nouvelles fonctions de gestion des requêtes
|
||||
|
||||
- `handleCaptivePortal()` : Gère les redirections du portail captif
|
||||
- `handleNotFound()` : Traite toutes les requêtes non définies
|
||||
|
||||
#### 2.5 Configuration des routes spéciales
|
||||
|
||||
Ajout de routes communes utilisées par les systèmes d'exploitation pour détecter les portails captifs :
|
||||
|
||||
```cpp
|
||||
server.on("/generate_204", handleRoot); // Android
|
||||
server.on("/fwlink", handleRoot); // Microsoft
|
||||
server.on("/hotspot-detect.html", handleRoot); // Apple
|
||||
server.onNotFound(handleNotFound); // Toutes autres requêtes
|
||||
```
|
||||
|
||||
#### 2.6 Gestion du DNS dans la tâche WebServer
|
||||
|
||||
Ajout du traitement des requêtes DNS dans la boucle principale :
|
||||
|
||||
```cpp
|
||||
// Gestion du serveur DNS pour le portail captif (uniquement en mode AP)
|
||||
if (!useStationMode) {
|
||||
dnsServer.processNextRequest();
|
||||
}
|
||||
```
|
||||
|
||||
## Fonctionnement du portail captif
|
||||
|
||||
### 1. Comment ça marche ?
|
||||
|
||||
1. **Point d'accès WiFi** : L'ESP32 crée un réseau WiFi nommé "HOKA_Clock"
|
||||
2. **Serveur DNS** : Toutes les requêtes DNS sont redirigées vers l'IP de l'ESP32 (192.168.1.1)
|
||||
3. **Interception web** : Toutes les tentatives de navigation sont capturées
|
||||
4. **Redirection** : L'utilisateur est automatiquement redirigé vers l'interface de l'horloge
|
||||
|
||||
### 2. Expérience utilisateur
|
||||
|
||||
1. L'utilisateur se connecte au WiFi "HOKA_Clock" (mot de passe : "hoka")
|
||||
2. Quand il essaie de naviguer sur n'importe quel site web, il est automatiquement redirigé vers l'interface de l'horloge
|
||||
3. Il peut alors configurer l'horloge directement via l'interface web
|
||||
|
||||
### 3. Compatibilité
|
||||
|
||||
Le portail captif est compatible avec :
|
||||
- **Android** : Détection automatique et affichage de la notification de connexion
|
||||
- **iOS/macOS** : Ouverture automatique du navigateur captif
|
||||
- **Windows** : Redirection automatique lors de la première navigation
|
||||
|
||||
## Configuration recommandée
|
||||
|
||||
### Variables importantes :
|
||||
- **SSID** : `HOKA_Clock` (peut être modifié dans `ap_ssid`)
|
||||
- **Mot de passe** : `hoka` (peut être modifié dans `ap_password`)
|
||||
- **IP** : `192.168.1.1` (définie dans `apIP`)
|
||||
- **Clé d'accès** : `hoka` (définie dans `KEY_TXT`)
|
||||
|
||||
### Mode de fonctionnement :
|
||||
- **Mode Station** (`useStationMode = true`) : Se connecte à un WiFi existant
|
||||
- **Mode Point d'Accès** (`useStationMode = false`) : Crée un portail captif
|
||||
|
||||
## Avantages du portail captif
|
||||
|
||||
1. **Facilité d'accès** : Pas besoin de connaître l'adresse IP
|
||||
2. **Expérience intuitive** : Ouverture automatique de l'interface
|
||||
3. **Compatibilité universelle** : Fonctionne sur tous les appareils
|
||||
4. **Configuration simple** : L'utilisateur est guidé automatiquement
|
||||
|
||||
## Compilation et déploiement
|
||||
|
||||
Pour compiler et déployer le projet avec le portail captif :
|
||||
|
||||
```bash
|
||||
# Compilation
|
||||
pio run -e main
|
||||
|
||||
# Upload vers l'ESP32
|
||||
pio run -e main --target upload
|
||||
|
||||
# Monitoring série (optionnel)
|
||||
pio device monitor
|
||||
```
|
||||
|
||||
## Dépannage
|
||||
|
||||
### Problèmes courants :
|
||||
|
||||
1. **Le portail ne s'ouvre pas automatiquement**
|
||||
- Vérifiez que le mode AP est activé (`useStationMode = false`)
|
||||
- Testez l'accès direct via http://192.168.1.1
|
||||
|
||||
2. **Erreurs de compilation**
|
||||
- Vérifiez que la dépendance `DNSServer` est bien ajoutée
|
||||
- Assurez-vous d'utiliser l'environnement `main`
|
||||
|
||||
3. **Redirection en boucle**
|
||||
- Vérifiez la fonction `handleCaptivePortal()`
|
||||
- Testez avec différents navigateurs
|
||||
|
||||
## Notes de développement
|
||||
|
||||
- Le portail captif n'est actif qu'en mode Point d'Accès
|
||||
- En mode Station, le comportement reste inchangé
|
||||
- La gestion DNS ajoute une charge minime au processeur
|
||||
- Compatible avec l'architecture FreeRTOS existante
|
||||
@@ -1,157 +0,0 @@
|
||||
# 🌐 Portail Captif ESP32 - Résumé des Modifications
|
||||
|
||||
## ✅ Modifications Terminées
|
||||
|
||||
Votre projet ESP32 P10 RGB Digital Clock a été modifié avec succès pour inclure un **portail captif** fonctionnel.
|
||||
|
||||
### 📋 Fichiers Modifiés
|
||||
|
||||
1. **`platformio.ini`**
|
||||
- ✅ Ajout de la dépendance `DNSServer` à l'environnement `main`
|
||||
- ✅ Ajout de l'environnement de test `captive_portal_test`
|
||||
|
||||
2. **`src/main.cpp`**
|
||||
- ✅ Inclusion de la bibliothèque `#include <DNSServer.h>`
|
||||
- ✅ Déclaration des objets `DNSServer dnsServer` et `IPAddress apIP`
|
||||
- ✅ Modification de `set_ESP32_Access_Point()` pour démarrer le serveur DNS
|
||||
- ✅ Ajout des fonctions `handleCaptivePortal()` et `handleNotFound()`
|
||||
- ✅ Configuration des routes spéciales pour Android, iOS, Windows
|
||||
- ✅ Intégration du traitement DNS dans `WebServerTask()`
|
||||
|
||||
3. **`.vscode/tasks.json`**
|
||||
- ✅ Ajout de la tâche "PlatformIO: Test Captive Portal"
|
||||
|
||||
### 📁 Fichiers Créés
|
||||
|
||||
1. **`examples/captive_portal_test.cpp`**
|
||||
- Test simplifié pour vérifier uniquement le portail captif
|
||||
|
||||
2. **`CAPTIVE_PORTAL_README.md`**
|
||||
- Documentation complète des modifications
|
||||
|
||||
3. **`CAPTIVE_PORTAL_QUICK_TEST.md`**
|
||||
- Guide de test rapide
|
||||
|
||||
## 🚀 Comment Utiliser le Portail Captif
|
||||
|
||||
### Mode de Fonctionnement
|
||||
|
||||
**Par défaut**, le projet est configuré en mode Point d'Accès avec portail captif :
|
||||
- Variable `useStationMode = false` dans le code
|
||||
- Création d'un réseau WiFi "HOKA_Clock"
|
||||
- Redirection automatique de toutes les requêtes web
|
||||
|
||||
### Étapes pour Tester
|
||||
|
||||
1. **Compilez et téléversez** :
|
||||
```bash
|
||||
pio run -e main --target upload
|
||||
```
|
||||
|
||||
2. **Connectez-vous au WiFi** :
|
||||
- Nom : `HOKA_Clock`
|
||||
- Mot de passe : `hoka`
|
||||
|
||||
3. **Testez la redirection** :
|
||||
- Ouvrez un navigateur
|
||||
- Essayez d'aller sur n'importe quel site
|
||||
- Vous êtes automatiquement redirigé vers l'interface de l'horloge
|
||||
|
||||
## 🔧 Configuration Actuelle
|
||||
|
||||
```cpp
|
||||
// WiFi Point d'Accès
|
||||
const char* ap_ssid = "HOKA_Clock";
|
||||
const char* ap_password = "hoka";
|
||||
|
||||
// IP du portail captif
|
||||
const IPAddress apIP(192, 168, 1, 1);
|
||||
|
||||
// Clé d'accès interface web
|
||||
#define KEY_TXT "hoka"
|
||||
|
||||
// Mode par défaut
|
||||
bool useStationMode = false; // Portail captif activé
|
||||
```
|
||||
|
||||
## 🌍 Compatibilité Universelle
|
||||
|
||||
Le portail captif fonctionne avec :
|
||||
|
||||
| Plateforme | Comportement |
|
||||
|------------|--------------|
|
||||
| **Android** | 📱 Notification automatique "Se connecter au réseau" |
|
||||
| **iOS/iPadOS** | 🍎 Ouverture automatique du navigateur captif |
|
||||
| **Windows** | 🪟 Redirection lors de la première navigation |
|
||||
| **macOS** | 🖥️ Détection automatique du portail |
|
||||
| **Linux** | 🐧 Redirection manuelle nécessaire |
|
||||
|
||||
## 🛠️ Tests Disponibles
|
||||
|
||||
### Test Principal (Horloge + Portail Captif)
|
||||
```bash
|
||||
pio run -e main --target upload
|
||||
```
|
||||
|
||||
### Test Portail Captif Uniquement
|
||||
```bash
|
||||
pio run -e captive_portal_test --target upload
|
||||
```
|
||||
|
||||
## 📊 Avantages du Portail Captif
|
||||
|
||||
✅ **Facilité d'accès** : Plus besoin de connaître l'IP
|
||||
✅ **Expérience intuitive** : Ouverture automatique
|
||||
✅ **Compatibilité universelle** : Tous appareils/OS
|
||||
✅ **Configuration simple** : Guidage automatique
|
||||
✅ **Professionnel** : Comme les hotspots WiFi publics
|
||||
|
||||
## 🔍 Surveillance et Debug
|
||||
|
||||
### Monitoring série
|
||||
```bash
|
||||
pio device monitor
|
||||
```
|
||||
|
||||
### Messages de succès attendus
|
||||
```
|
||||
WIFI mode : AP avec Portail Captif
|
||||
Serveur DNS démarré pour portail captif
|
||||
HTTP server started
|
||||
Captive Portal active - navigate to any website
|
||||
```
|
||||
|
||||
## 🎯 Fonctionnement Technique
|
||||
|
||||
1. **DNS Hijacking** : Toutes les requêtes DNS → 192.168.1.1
|
||||
2. **Route Interception** : Capture des URLs de détection OS
|
||||
3. **Redirection HTTP** : Code 302 vers l'interface ESP32
|
||||
4. **FreeRTOS Integration** : Traitement asynchrone DNS + HTTP
|
||||
|
||||
## 📝 Notes Importantes
|
||||
|
||||
- Le portail captif n'est actif qu'en mode Point d'Accès (`useStationMode = false`)
|
||||
- En mode Station WiFi, le comportement reste inchangé
|
||||
- La charge CPU additionnelle est négligeable
|
||||
- Compatible avec l'architecture FreeRTOS existante
|
||||
|
||||
## 🚨 Dépannage Rapide
|
||||
|
||||
| Problème | Solution |
|
||||
|----------|----------|
|
||||
| Portail ne s'ouvre pas | Vérifier `useStationMode = false` |
|
||||
| Redirection ne fonctionne pas | Tester http://192.168.1.1 directement |
|
||||
| Erreur compilation | Vérifier dépendance `DNSServer` |
|
||||
|
||||
---
|
||||
|
||||
**🎉 Félicitations !** Votre horloge ESP32 dispose maintenant d'un portail captif professionnel avec **accès libre sans authentification**. Les utilisateurs seront automatiquement redirigés vers l'interface de configuration, rendant l'expérience beaucoup plus intuitive et moderne.
|
||||
|
||||
## 🔓 Mise à Jour : Accès Sans Authentification
|
||||
|
||||
**Nouvelle fonctionnalité :** La validation de clé a été supprimée pour simplifier l'accès.
|
||||
|
||||
- ✅ **Accès immédiat** à l'interface web
|
||||
- ✅ **Pas de clé à saisir**
|
||||
- ✅ **Configuration directe** via le portail captif
|
||||
- ⚠️ **Sécurité :** Protection par mot de passe WiFi uniquement
|
||||
@@ -1,226 +0,0 @@
|
||||
# Guide des Panneaux P10 en Cascade
|
||||
|
||||
## 🔗 Vue d'ensemble
|
||||
|
||||
Ce projet supporte maintenant plusieurs panneaux P10 connectés en cascade pour créer des affichages plus larges ou plus hauts.
|
||||
|
||||
## 📐 Configurations Supportées
|
||||
|
||||
### Configurations Horizontales (recommandées)
|
||||
- **1x1** : 32x16 pixels (1 panneau) - Configuration standard
|
||||
- **2x1** : 64x16 pixels (2 panneaux) - Ideal pour texte plus long
|
||||
- **3x1** : 96x16 pixels (3 panneaux) - Texte défilant étendu
|
||||
- **4x1** : 128x16 pixels (4 panneaux) - Affichage type bandeau
|
||||
- **6x1** : 192x16 pixels (6 panneaux) - Grand bandeau
|
||||
- **8x1** : 256x16 pixels (8 panneaux) - Très grand bandeau
|
||||
|
||||
### Configurations Verticales/Mixtes
|
||||
- **2x2** : 64x32 pixels (4 panneaux) - Affichage carré
|
||||
- **1x2** : 32x32 pixels (2 panneaux) - Plus de hauteur
|
||||
- **4x2** : 128x32 pixels (8 panneaux) - Grand affichage
|
||||
|
||||
## 🛠️ Connexion Physique
|
||||
|
||||
### Connexion en Cascade (Chaînage)
|
||||
```
|
||||
ESP32 ──── Panneau 1 ──── Panneau 2 ──── Panneau 3 ──── ...
|
||||
(Premier) (Deuxième) (Troisième)
|
||||
```
|
||||
|
||||
### Détails de Connexion
|
||||
1. **Premier panneau** : Connecté directement à l'ESP32 (voir WIRING.md)
|
||||
2. **Panneaux suivants** : Connectés via les ports de sortie du panneau précédent
|
||||
3. **Alimentation** : Chaque panneau doit être alimenté en 5V individuellement
|
||||
|
||||
### Important - Alimentation
|
||||
```
|
||||
⚠️ ATTENTION ALIMENTATION !
|
||||
|
||||
Chaque panneau P10 consomme environ 1-2A sous 5V
|
||||
- 2 panneaux : 5V/4A minimum
|
||||
- 4 panneaux : 5V/8A minimum
|
||||
- 6 panneaux : 5V/12A minimum
|
||||
|
||||
Utilisez une alimentation adaptée !
|
||||
```
|
||||
|
||||
## 🎯 Compilation pour Cascade
|
||||
|
||||
### Commandes PlatformIO
|
||||
|
||||
```bash
|
||||
# 2 panneaux horizontaux (64x16)
|
||||
pio run -e cascade_2x1 --target upload
|
||||
|
||||
# 3 panneaux horizontaux (96x16)
|
||||
pio run -e cascade_3x1 --target upload
|
||||
|
||||
# 4 panneaux horizontaux (128x16)
|
||||
pio run -e cascade_4x1 --target upload
|
||||
|
||||
# 2x2 panneaux (64x32)
|
||||
pio run -e cascade_2x2 --target upload
|
||||
|
||||
# 6 panneaux horizontaux (192x16)
|
||||
pio run -e cascade_6x1 --target upload
|
||||
|
||||
# 8 panneaux horizontaux (256x16)
|
||||
pio run -e cascade_8x1 --target upload
|
||||
|
||||
# Test de cascade (2 panneaux)
|
||||
pio run -e test_cascade --target upload
|
||||
```
|
||||
|
||||
### Configuration Personnalisée
|
||||
|
||||
Pour une configuration non-standard, modifiez `platformio.ini` :
|
||||
|
||||
```ini
|
||||
[env:custom_cascade]
|
||||
extends = env:main
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-DMATRIX_WIDTH=32 ; Largeur d'un panneau
|
||||
-DMATRIX_HEIGHT=16 ; Hauteur d'un panneau
|
||||
-DMATRIX_PANELS_X=5 ; Nombre panneaux horizontaux
|
||||
-DMATRIX_PANELS_Y=1 ; Nombre panneaux verticaux
|
||||
-DCASCADE_MODE=1
|
||||
```
|
||||
|
||||
## 🧪 Test des Panneaux
|
||||
|
||||
### Test d'Alignement
|
||||
```bash
|
||||
pio run -e test_cascade --target upload
|
||||
```
|
||||
|
||||
Ce test affiche :
|
||||
1. **Bordures** : Contour de chaque panneau
|
||||
2. **Numérotation** : P1, P2, P3... sur chaque panneau
|
||||
3. **Couleurs** : Test de toutes les couleurs
|
||||
4. **Texte défilant** : Test sur toute la largeur
|
||||
|
||||
### Vérifications Visuelles
|
||||
- ✅ Tous les panneaux s'allument
|
||||
- ✅ Bordures alignées correctement
|
||||
- ✅ Numérotation séquentielle (P1, P2, P3...)
|
||||
- ✅ Couleurs uniformes sur tous les panneaux
|
||||
- ✅ Texte défile sans coupure
|
||||
|
||||
## ⚙️ Ajustements Automatiques
|
||||
|
||||
### Luminosité Auto-Adaptée
|
||||
```cpp
|
||||
// Le code ajuste automatiquement la luminosité :
|
||||
1-2 panneaux : 125/255 (luminosité normale)
|
||||
3-4 panneaux : 100/255 (réduite)
|
||||
5-6 panneaux : 80/255 (plus réduite)
|
||||
7+ panneaux : 60/255 (très réduite)
|
||||
```
|
||||
|
||||
### Centrage Automatique
|
||||
- **Horloge** : Centrée automatiquement sur la largeur totale
|
||||
- **Texte défilant** : Utilise toute la largeur disponible
|
||||
- **Interface web** : Fonctionne normalement
|
||||
|
||||
## 🌐 Interface Web Adaptée
|
||||
|
||||
L'interface web fonctionne normalement avec les cascades :
|
||||
- Configuration identique
|
||||
- Texte défilant adapté à la largeur
|
||||
- Couleurs appliquées sur tous les panneaux
|
||||
- Luminosité globale
|
||||
|
||||
## 🔧 Dépannage Cascade
|
||||
|
||||
### Problème : Un panneau ne s'allume pas
|
||||
1. ✅ Vérifiez l'alimentation 5V de chaque panneau
|
||||
2. ✅ Vérifiez les connexions en cascade
|
||||
3. ✅ Testez avec moins de panneaux
|
||||
|
||||
### Problème : Affichage décalé
|
||||
1. ✅ Vérifiez l'ordre des panneaux (P1, P2, P3...)
|
||||
2. ✅ Utilisez le test d'alignement
|
||||
3. ✅ Vérifiez les paramètres PANELS_X et PANELS_Y
|
||||
|
||||
### Problème : Scintillement
|
||||
1. ✅ Réduisez la luminosité
|
||||
2. ✅ Vérifiez l'alimentation (suffisamment puissante ?)
|
||||
3. ✅ Réduisez `PxMATRIX_SPI_FREQUENCY`
|
||||
|
||||
### Problème : Texte coupé
|
||||
1. ✅ Vérifiez que TOTAL_WIDTH est correct
|
||||
2. ✅ Utilisez le test de texte défilant
|
||||
3. ✅ Vérifiez la configuration PANELS_X
|
||||
|
||||
## 📋 Checklist Installation Cascade
|
||||
|
||||
### Étape 1 : Préparation
|
||||
- [ ] Alimentation suffisante calculée (2A × nombre de panneaux)
|
||||
- [ ] Panneaux P10 testés individuellement
|
||||
- [ ] Câbles de connexion préparés
|
||||
|
||||
### Étape 2 : Connexion Physique
|
||||
- [ ] Premier panneau connecté à l'ESP32
|
||||
- [ ] Panneaux en cascade connectés
|
||||
- [ ] Alimentation 5V sur chaque panneau
|
||||
- [ ] Masse commune vérifiée
|
||||
|
||||
### Étape 3 : Configuration Logicielle
|
||||
- [ ] Environnement cascade choisi (ex: cascade_2x1)
|
||||
- [ ] Code compilé et téléversé
|
||||
- [ ] Test d'alignement réussi
|
||||
|
||||
### Étape 4 : Test Final
|
||||
- [ ] Tous les panneaux s'allument
|
||||
- [ ] Numérotation correcte visible
|
||||
- [ ] Horloge centrée correctement
|
||||
- [ ] Texte défile sur toute la largeur
|
||||
- [ ] Interface web accessible
|
||||
|
||||
## 💡 Conseils Optimisation
|
||||
|
||||
### Performance
|
||||
- Plus de panneaux = plus de données à traiter
|
||||
- Réduisez la luminosité si nécessaire
|
||||
- Utilisez une alimentation stable
|
||||
|
||||
### Esthétique
|
||||
- Alignez physiquement les panneaux parfaitement
|
||||
- Utilisez des supports adaptés
|
||||
- Protégez les connexions
|
||||
|
||||
### Fiabilité
|
||||
- Alimentation dimensionnée correctement
|
||||
- Connexions bien fixées
|
||||
- Test avant installation finale
|
||||
|
||||
## 🎨 Exemples d'Utilisation
|
||||
|
||||
### Bandeau d'Information (4x1)
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ 12:34 ESP32 CLOCK │
|
||||
│ Aujourd'hui 15°C - Beau... │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
### Affichage Carré (2x2)
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ 12:34 │
|
||||
│ ESP32 CLOCK │
|
||||
│ │
|
||||
│ Message long... │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### Grand Bandeau (8x1)
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────┐
|
||||
│ 12:34 - ESP32 DIGITAL CLOCK │
|
||||
│ Très long message défilant avec beaucoup d'informations... │
|
||||
└───────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
La cascade de panneaux P10 permet de créer des affichages personnalisés adaptés à vos besoins !
|
||||
@@ -1,192 +0,0 @@
|
||||
# Guide du Countdown (Compte à Rebours)
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
La fonctionnalité de countdown permet d'afficher un compte à rebours en temps réel vers une date et heure cible spécifique. Le countdown s'affiche dans la rotation du texte défilant et peut être configuré via l'interface web.
|
||||
|
||||
## Fonctionnalités
|
||||
|
||||
### ✅ Affichage Dynamique
|
||||
- **Format adaptatif** : Affiche jours, heures, minutes et secondes selon le temps restant
|
||||
- **Couleur personnalisable** : Couleur spécifique pour le countdown (orange par défaut)
|
||||
- **Indication d'expiration** : Affichage "EXPIRED!" en rouge quand le countdown est fini
|
||||
- **Compatible cascade** : Fonctionne avec tous les types de configuration de panneaux
|
||||
|
||||
### ✅ Configuration Complète
|
||||
- **Activation/désactivation** : Checkbox pour activer ou désactiver le countdown
|
||||
- **Titre personnalisé** : Nom de l'événement (ex: "NOUVEL AN", "ANNIVERSAIRE")
|
||||
- **Date et heure cible** : Configuration précise de la cible
|
||||
- **Couleur RGB** : Personnalisation de la couleur d'affichage
|
||||
- **Sauvegarde** : Tous les paramètres sont sauvegardés en mémoire flash
|
||||
|
||||
## Configuration via Interface Web
|
||||
|
||||
### 1. Accès à l'Interface
|
||||
1. Connectez-vous au WiFi de l'ESP32 ou configurez votre WiFi
|
||||
2. Ouvrez l'adresse IP dans votre navigateur
|
||||
3. Entrez la clé de sécurité : `p10rgbesp32ws`
|
||||
|
||||
### 2. Section Countdown Timer
|
||||
La section "Countdown Timer" contient :
|
||||
|
||||
#### Activation
|
||||
- **Checkbox "Active"** : Cochez pour activer le countdown
|
||||
|
||||
#### Configuration de l'Événement
|
||||
- **Title** : Nom de l'événement (max 50 caractères)
|
||||
- Exemples : "NEW YEAR", "BIRTHDAY", "WEDDING", "VACATION"
|
||||
|
||||
#### Date et Heure Cible
|
||||
- **Target Date** : Jour, Mois, Année
|
||||
- **Target Time** : Heure, Minute, Seconde (format 24h)
|
||||
|
||||
#### Couleur
|
||||
- **RGB** : Valeurs Red, Green, Blue (0-255)
|
||||
- Orange par défaut : R=255, G=165, B=0
|
||||
- Rouge pour urgence : R=255, G=0, B=0
|
||||
- Bleu pour célébration : R=0, G=100, B=255
|
||||
|
||||
### 3. Boutons d'Action
|
||||
- **"Set Countdown"** : Sauvegarde la configuration complète
|
||||
- **"Set Countdown Color"** : Sauvegarde uniquement la couleur
|
||||
|
||||
## Formats d'Affichage
|
||||
|
||||
Le countdown adapte automatiquement son format selon le temps restant :
|
||||
|
||||
### Avec Jours
|
||||
```
|
||||
NEW YEAR: 15d 08h 30m 45s
|
||||
```
|
||||
|
||||
### Sans Jours (moins de 24h)
|
||||
```
|
||||
NEW YEAR: 08h 30m 45s
|
||||
```
|
||||
|
||||
### Dernière Heure
|
||||
```
|
||||
NEW YEAR: 30m 45s
|
||||
```
|
||||
|
||||
### Dernière Minute
|
||||
```
|
||||
NEW YEAR: 45s
|
||||
```
|
||||
|
||||
### Expiré
|
||||
```
|
||||
NEW YEAR - EXPIRED!
|
||||
```
|
||||
|
||||
## Intégration dans l'Affichage
|
||||
|
||||
Le countdown s'intègre dans la rotation du texte défilant :
|
||||
|
||||
### Mode 1 (Couleurs Fixes)
|
||||
1. **Date** : Affichage de la date actuelle
|
||||
2. **Texte personnalisé** : Votre message personnel
|
||||
3. **Countdown** : Compte à rebours (si actif)
|
||||
|
||||
### Mode 2 (Couleurs Changeantes)
|
||||
1. **Date** : Couleur 1
|
||||
2. **Texte personnalisé** : Couleur 2
|
||||
3. **Countdown** : Couleur 3 (si actif)
|
||||
4. **Changement** : Rotation des couleurs
|
||||
|
||||
## Exemples d'Utilisation
|
||||
|
||||
### 1. Nouvel An
|
||||
```
|
||||
Title: NEW YEAR 2026
|
||||
Date: 31/12/2025 23:59:59
|
||||
Couleur: Rouge (255,0,0)
|
||||
```
|
||||
|
||||
### 2. Anniversaire
|
||||
```
|
||||
Title: BIRTHDAY
|
||||
Date: 15/06/2025 00:00:00
|
||||
Couleur: Rose (255,105,180)
|
||||
```
|
||||
|
||||
### 3. Événement Professionnel
|
||||
```
|
||||
Title: CONFERENCE
|
||||
Date: 20/03/2025 09:00:00
|
||||
Couleur: Bleu (0,100,255)
|
||||
```
|
||||
|
||||
### 4. Vacances
|
||||
```
|
||||
Title: HOLIDAYS
|
||||
Date: 01/07/2025 12:00:00
|
||||
Couleur: Vert (0,255,100)
|
||||
```
|
||||
|
||||
## Test et Développement
|
||||
|
||||
### Test du Countdown
|
||||
Un exemple de test spécifique est disponible :
|
||||
|
||||
```bash
|
||||
# Compiler et uploader le test countdown
|
||||
pio run -e countdown_test --target upload
|
||||
|
||||
# Monitorer la sortie série
|
||||
pio device monitor
|
||||
```
|
||||
|
||||
Le test configure automatiquement un countdown de 5 minutes dans le futur et affiche :
|
||||
- L'heure actuelle en haut
|
||||
- Le countdown en défilement
|
||||
- Changement de couleur à l'expiration
|
||||
|
||||
### VS Code
|
||||
Utilisez la tâche : **"PlatformIO: Test Countdown"**
|
||||
|
||||
## Sauvegarde et Persistance
|
||||
|
||||
Tous les paramètres du countdown sont sauvegardés dans la mémoire flash NVS :
|
||||
- `cd_Active` : État activé/désactivé
|
||||
- `cd_Year`, `cd_Month`, `cd_Day` : Date cible
|
||||
- `cd_Hour`, `cd_Minute`, `cd_Second` : Heure cible
|
||||
- `cd_Title` : Titre de l'événement
|
||||
- `CD_R`, `CD_G`, `CD_B` : Couleur RGB
|
||||
|
||||
Les paramètres persistent après redémarrage de l'ESP32.
|
||||
|
||||
## Dépannage
|
||||
|
||||
### Le countdown ne s'affiche pas
|
||||
1. Vérifiez que la checkbox "Active" est cochée
|
||||
2. Confirmez que tous les champs de date/heure sont remplis
|
||||
3. Vérifiez que la date cible est dans le futur
|
||||
|
||||
### Problème de format
|
||||
- Le countdown s'adapte automatiquement au temps restant
|
||||
- Si le temps est négatif, "EXPIRED!" s'affiche
|
||||
|
||||
### Couleur incorrecte
|
||||
- Vérifiez les valeurs RGB (0-255)
|
||||
- En mode 2, les couleurs du countdown rotent automatiquement
|
||||
|
||||
### RTC non synchronisé
|
||||
- Configurez d'abord la date/heure système via l'interface web
|
||||
- Le countdown dépend du module RTC DS3231
|
||||
|
||||
## Intégration dans Votre Projet
|
||||
|
||||
Le countdown peut être facilement adapté pour d'autres usages :
|
||||
|
||||
1. **Minuteur** : Countdown de courte durée (minutes/heures)
|
||||
2. **Événements multiples** : Modification pour gérer plusieurs countdowns
|
||||
3. **Notifications** : Ajout de signaux visuels à l'expiration
|
||||
4. **API externe** : Récupération de dates cibles depuis Internet
|
||||
|
||||
## Performance
|
||||
|
||||
- **Mise à jour** : Chaque seconde
|
||||
- **Mémoire** : ~200 bytes pour les variables countdown
|
||||
- **Cascade** : Compatible avec tous les formats de panneaux
|
||||
- **Stabilité** : Pas d'impact sur les autres fonctionnalités
|
||||
@@ -1,148 +0,0 @@
|
||||
# 🔓 Suppression de la Validation de Clé - ESP32 Portail Captif
|
||||
|
||||
## ✅ Modification Effectuée
|
||||
|
||||
La validation de clé d'accès au serveur web a été **supprimée** pour permettre un **accès libre** à l'interface de configuration de l'horloge.
|
||||
|
||||
## 🔧 Changements Appliqués
|
||||
|
||||
### 1. Suppression de la Validation dans `handleSettings()`
|
||||
|
||||
**Avant :**
|
||||
```cpp
|
||||
void handleSettings() {
|
||||
String incoming_Settings = server.arg("key");
|
||||
|
||||
if (incoming_Settings != KEY_TXT) {
|
||||
server.send(200, "text/plain", "+ERR");
|
||||
Serial.println("Wrong key!");
|
||||
return;
|
||||
}
|
||||
// ... suite du code
|
||||
}
|
||||
```
|
||||
|
||||
**Après :**
|
||||
```cpp
|
||||
void handleSettings() {
|
||||
String incoming_Settings = server.arg("key");
|
||||
|
||||
Serial.println("\n-------------Settings");
|
||||
Serial.print("Key : ");
|
||||
Serial.println(incoming_Settings);
|
||||
|
||||
// Validation de clé supprimée - accès libre
|
||||
incoming_Settings = server.arg("sta");
|
||||
// ... suite du code
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Modification du Message de Démarrage
|
||||
|
||||
**Avant :**
|
||||
```cpp
|
||||
Serial.println("Use key: " KEY_TXT);
|
||||
```
|
||||
|
||||
**Après :**
|
||||
```cpp
|
||||
Serial.println("No authentication required - Open access");
|
||||
```
|
||||
|
||||
## 🌐 Impact sur l'Interface Web
|
||||
|
||||
### ✅ Avantages
|
||||
|
||||
1. **Accès immédiat** : Plus besoin de saisir une clé
|
||||
2. **Expérience simplifiée** : Interface directement accessible
|
||||
3. **Portail captif optimisé** : Redirection sans barrière d'authentification
|
||||
4. **Facilité d'utilisation** : Idéal pour usage personnel ou familial
|
||||
|
||||
### ⚠️ Considérations de Sécurité
|
||||
|
||||
- **Réseau ouvert** : Toute personne connectée au WiFi peut modifier les paramètres
|
||||
- **Usage recommandé** : Environnements privés ou de confiance
|
||||
- **Protection par WiFi** : La sécurité repose sur le mot de passe WiFi "hoka"
|
||||
|
||||
## 🎯 Fonctionnement Actuel
|
||||
|
||||
### 1. Connexion au Portail Captif
|
||||
1. **Connexion WiFi** : "HOKA_Clock" (mot de passe : "hoka")
|
||||
2. **Redirection automatique** vers l'interface
|
||||
3. **Accès immédiat** aux paramètres sans authentification
|
||||
|
||||
### 2. Configuration Accessible
|
||||
- ✅ **Réglage de l'heure et date**
|
||||
- ✅ **Modification des couleurs**
|
||||
- ✅ **Configuration du texte défilant**
|
||||
- ✅ **Paramètres de luminosité**
|
||||
- ✅ **Configuration du countdown**
|
||||
|
||||
## 📊 Résultats de Compilation
|
||||
|
||||
```
|
||||
✅ SUCCESS - Compilation réussie
|
||||
RAM: [= ] 14.3% (used 46824 bytes from 327680 bytes)
|
||||
Flash: [====== ] 63.7% (used 834905 bytes from 1310720 bytes)
|
||||
Taille: -56 bytes (optimisation due à la suppression du code de validation)
|
||||
```
|
||||
|
||||
## 🔄 Comment Réactiver la Validation (si nécessaire)
|
||||
|
||||
Si vous souhaitez remettre la validation de clé, ajoutez ces lignes dans `handleSettings()` :
|
||||
|
||||
```cpp
|
||||
void handleSettings() {
|
||||
String incoming_Settings = server.arg("key");
|
||||
|
||||
Serial.println("\n-------------Settings");
|
||||
Serial.print("Key : ");
|
||||
Serial.println(incoming_Settings);
|
||||
|
||||
// Réactiver la validation
|
||||
if (incoming_Settings != KEY_TXT) {
|
||||
server.send(200, "text/plain", "+ERR");
|
||||
Serial.println("Wrong key!");
|
||||
Serial.println("-------------");
|
||||
return;
|
||||
}
|
||||
|
||||
incoming_Settings = server.arg("sta");
|
||||
// ... reste du code
|
||||
}
|
||||
```
|
||||
|
||||
## 🌟 Interface Web Simplifiée
|
||||
|
||||
L'interface web fonctionne maintenant comme suit :
|
||||
|
||||
1. **Page principale** : Accessible immédiatement via le portail captif
|
||||
2. **Paramètres** : Modification directe sans authentification
|
||||
3. **Retour instantané** : Réponse "+OK" pour toutes les modifications valides
|
||||
|
||||
## 🎉 Avantages du Portail Captif sans Authentification
|
||||
|
||||
### Pour l'Utilisateur
|
||||
- **Simplicité maximale** : Connexion → Configuration
|
||||
- **Pas de mot de passe à retenir** (autre que le WiFi)
|
||||
- **Expérience fluide** sur tous les appareils
|
||||
|
||||
### Pour l'Administrateur
|
||||
- **Moins de support** : Pas de problème de clé oubliée
|
||||
- **Configuration rapide** : Idéal pour démonstrations
|
||||
- **Accès d'urgence** : Modification rapide des paramètres
|
||||
|
||||
## 🚀 Prêt à Utiliser
|
||||
|
||||
Le système est maintenant configuré pour un **accès libre** via le portail captif :
|
||||
|
||||
1. **Compilez et téléversez** le firmware
|
||||
2. **Connectez-vous** au WiFi "HOKA_Clock"
|
||||
3. **Naviguez** vers n'importe quel site → redirection automatique
|
||||
4. **Configurez** l'horloge directement sans authentification
|
||||
|
||||
---
|
||||
|
||||
**Date de modification :** 15 août 2025
|
||||
**Status :** ✅ Implémenté et testé
|
||||
**Sécurité :** Protection par mot de passe WiFi uniquement
|
||||
@@ -1,103 +0,0 @@
|
||||
# 🔧 Résolution du Problème de Compilation
|
||||
|
||||
## ✅ Problème Résolu
|
||||
|
||||
**Erreur initiale :**
|
||||
```
|
||||
src/main.cpp: In function 'void handleCaptivePortal()':
|
||||
src/main.cpp:429:5: error: 'handleRoot' was not declared in this scope
|
||||
handleRoot();
|
||||
^~~~~~~~~~
|
||||
```
|
||||
|
||||
## 🎯 Cause du Problème
|
||||
|
||||
Le problème était un **ordre de déclaration des fonctions**. La fonction `handleCaptivePortal()` était déclarée avant `handleRoot()`, mais tentait d'appeler cette dernière.
|
||||
|
||||
En C++, les fonctions doivent être déclarées avant d'être utilisées.
|
||||
|
||||
## 🛠️ Solution Appliquée
|
||||
|
||||
**Ajout de déclarations anticipées** dans `src/main.cpp` après les includes :
|
||||
|
||||
```cpp
|
||||
// Prototypes des tâches FreeRTOS
|
||||
void DisplayTask(void *pvParameters);
|
||||
void WebServerTask(void *pvParameters);
|
||||
void WiFiTask(void *pvParameters);
|
||||
|
||||
// Prototypes des gestionnaires web ← AJOUTÉ
|
||||
void handleRoot(); ← AJOUTÉ
|
||||
void handleSettings(); ← AJOUTÉ
|
||||
void handleCaptivePortal(); ← AJOUTÉ
|
||||
void handleNotFound(); ← AJOUTÉ
|
||||
```
|
||||
|
||||
## ✅ Résultats de Compilation
|
||||
|
||||
### Projet Principal (main)
|
||||
```
|
||||
✅ SUCCESS - Compilation réussie
|
||||
RAM: [= ] 14.3% (used 46824 bytes from 327680 bytes)
|
||||
Flash: [====== ] 63.7% (used 834961 bytes from 1310720 bytes)
|
||||
```
|
||||
|
||||
### Test Portail Captif (captive_portal_test)
|
||||
```
|
||||
✅ SUCCESS - Compilation réussie
|
||||
RAM: [= ] 13.9% (used 45464 bytes from 327680 bytes)
|
||||
Flash: [====== ] 58.1% (used 762045 bytes from 1310720 bytes)
|
||||
```
|
||||
|
||||
## 🚀 État Actuel
|
||||
|
||||
- ✅ **Portail captif** : Intégré et fonctionnel
|
||||
- ✅ **Compilation** : Aucune erreur
|
||||
- ✅ **Tests** : Deux environnements disponibles
|
||||
- ✅ **Documentation** : Complète
|
||||
|
||||
## 📋 Commandes de Compilation
|
||||
|
||||
```bash
|
||||
# Projet principal avec portail captif
|
||||
pio run -e main
|
||||
|
||||
# Test portail captif uniquement
|
||||
pio run -e captive_portal_test
|
||||
|
||||
# Upload vers ESP32
|
||||
pio run -e main --target upload
|
||||
```
|
||||
|
||||
## 🎯 Fonctionnalités Ajoutées
|
||||
|
||||
1. **Serveur DNS** : Redirige toutes les requêtes vers l'ESP32
|
||||
2. **Routes spéciales** : Support Android, iOS, Windows, macOS
|
||||
3. **Redirection automatique** : Portail captif universel
|
||||
4. **Compatibilité FreeRTOS** : Intégration parfaite
|
||||
|
||||
## 🔍 Améliorations Appliquées
|
||||
|
||||
- **Déclarations de fonctions** : Ordre correct
|
||||
- **Page HTML test** : Caractères échappés correctement
|
||||
- **Dépendances** : DNSServer ajouté
|
||||
- **Configuration** : Variables IP et DNS
|
||||
|
||||
## 🎉 Prêt à Tester !
|
||||
|
||||
Le projet est maintenant prêt pour :
|
||||
|
||||
1. **Compilation** sans erreurs
|
||||
2. **Téléversement** vers l'ESP32
|
||||
3. **Test du portail captif** en conditions réelles
|
||||
|
||||
### Instructions de Test
|
||||
|
||||
1. Compilez et téléversez : `pio run -e main --target upload`
|
||||
2. Connectez-vous au WiFi : "HOKA_Clock" (mot de passe: "hoka")
|
||||
3. Naviguez vers n'importe quel site → Redirection automatique !
|
||||
|
||||
---
|
||||
**Date de résolution :** 15 août 2025
|
||||
**Status :** ✅ Résolu et testé
|
||||
**Prochaine étape :** Test matériel sur ESP32
|
||||
-174
@@ -1,174 +0,0 @@
|
||||
# Guide de Démarrage Rapide - ESP32 P10 Digital Cl2. **Test du RTC** :
|
||||
```bash
|
||||
pio run -e rtc_test --target upload
|
||||
```
|
||||
|
||||
3. **Test du countdown** :
|
||||
```bash
|
||||
pio run -e countdown_test --target upload
|
||||
```
|
||||
|
||||
### Étape 5 : Upload principal# 🚀 Démarrage en 5 minutes
|
||||
|
||||
### Étape 1 : Préparation
|
||||
1. **Installez PlatformIO** dans VS Code
|
||||
2. **Ouvrez ce dossier** dans VS Code
|
||||
3. **Connectez votre ESP32** en USB
|
||||
|
||||
### Étape 2 : Configuration WiFi
|
||||
Modifiez dans `src/main.cpp` lignes ~100 :
|
||||
```cpp
|
||||
const char* ssid = "VOTRE_WIFI";
|
||||
const char* password = "VOTRE_MOT_DE_PASSE";
|
||||
```
|
||||
|
||||
### Étape 3 : Câblage (IMPORTANT !)
|
||||
|
||||
#### Panneau P10 → ESP32
|
||||
```
|
||||
HUB75 → ESP32
|
||||
R1 → GPIO2
|
||||
G1 → GPIO15
|
||||
B1 → GPIO4
|
||||
R2 → GPIO16
|
||||
G2 → GPIO17
|
||||
B2 → GPIO5
|
||||
A → GPIO19
|
||||
B → GPIO23
|
||||
C → GPIO18
|
||||
CLK → GPIO14
|
||||
STB → GPIO32
|
||||
OE → GPIO33
|
||||
GND → GND (plusieurs connexions)
|
||||
```
|
||||
|
||||
#### RTC DS3231 → ESP32
|
||||
```
|
||||
VCC → 3.3V
|
||||
GND → GND
|
||||
SDA → GPIO21
|
||||
SCL → GPIO22
|
||||
```
|
||||
|
||||
### Étape 4 : Test rapide
|
||||
1. **Test du panneau P10** :
|
||||
```bash
|
||||
pio run -e p10_test --target upload
|
||||
```
|
||||
|
||||
2. **Test du RTC** :
|
||||
```bash
|
||||
pio run -e rtc_test --target upload
|
||||
```
|
||||
|
||||
### Étape 5 : Projet principal
|
||||
```bash
|
||||
pio run -e main --target upload
|
||||
pio device monitor
|
||||
```
|
||||
|
||||
## 🌐 Configuration Web
|
||||
|
||||
1. **Trouvez l'IP** dans le moniteur série
|
||||
2. **Ouvrez votre navigateur** → http://IP_AFFICHEE
|
||||
3. **Utilisez la clé** : `p10rgbesp32ws`
|
||||
4. **Configurez** date, heure, couleurs, texte
|
||||
|
||||
## 🔧 Commandes Utiles
|
||||
|
||||
```bash
|
||||
# Compilation principale
|
||||
pio run -e main
|
||||
|
||||
# Upload et monitoring
|
||||
pio run -e main -t upload && pio device monitor
|
||||
|
||||
# Test des composants
|
||||
pio run -e rtc_test -t upload # Test RTC
|
||||
pio run -e p10_test -t upload # Test P10
|
||||
pio run -e nvs_erase -t upload # Reset mémoire
|
||||
|
||||
# Nettoyage
|
||||
pio run -t clean
|
||||
```
|
||||
|
||||
## ⚡ Commandes VS Code
|
||||
- **Ctrl+Shift+P** → "Tasks: Run Task"
|
||||
- Choisissez parmi :
|
||||
- PlatformIO: Build Main Project
|
||||
- PlatformIO: Upload Main Project
|
||||
- PlatformIO: Test RTC Module
|
||||
- PlatformIO: Test P10 Matrix
|
||||
- PlatformIO: Monitor Serial
|
||||
|
||||
## 🚨 Problèmes Courants
|
||||
|
||||
### L'affichage ne fonctionne pas
|
||||
- ✅ Vérifiez l'**alimentation 5V** (crucial !)
|
||||
- ✅ Vérifiez **toutes les connexions**
|
||||
- ✅ Testez avec `pio run -e p10_test -t upload`
|
||||
|
||||
### WiFi ne se connecte pas
|
||||
- ✅ Vérifiez SSID/mot de passe
|
||||
- ✅ L'ESP32 créera un point d'accès "ESP32_Clock"
|
||||
|
||||
### RTC ne fonctionne pas
|
||||
- ✅ Vérifiez connexions I2C (SDA/SCL)
|
||||
- ✅ Testez avec `pio run -e rtc_test -t upload`
|
||||
|
||||
### Paramètres perdus
|
||||
- ✅ Effacez la mémoire : `pio run -e nvs_erase -t upload`
|
||||
|
||||
## 📱 Interface Web - Fonctionnalités
|
||||
|
||||
- **Date/Heure** : Configuration complète
|
||||
- **Mode 1** : Couleurs manuelles (RGB)
|
||||
- **Mode 2** : Changement automatique de couleurs
|
||||
- **Luminosité** : 0-255
|
||||
- **Texte défilant** : Message personnalisé
|
||||
- **Vitesse** : Réglage du défilement
|
||||
- **⏱️ Countdown** : Compte à rebours vers un événement
|
||||
|
||||
## 💡 Configuration Avancée
|
||||
|
||||
### Changement des pins
|
||||
Modifiez dans `src/main.cpp` :
|
||||
```cpp
|
||||
#define P_LAT 5 // Pin Latch
|
||||
#define P_A 19 // Pin A
|
||||
#define P_B 23 // Pin B
|
||||
#define P_C 18 // Pin C
|
||||
#define P_OE 4 // Pin Output Enable
|
||||
```
|
||||
|
||||
### Réduction du bruit d'affichage
|
||||
```cpp
|
||||
#define PxMATRIX_SPI_FREQUENCY 8000000 // Réduire si bruit
|
||||
```
|
||||
|
||||
## 📋 Checklist de Test
|
||||
|
||||
- [ ] ESP32 se connecte au WiFi
|
||||
- [ ] Interface web accessible
|
||||
- [ ] Heure s'affiche correctement
|
||||
- [ ] Date défile en bas
|
||||
- [ ] Texte personnalisé fonctionne
|
||||
- [ ] Countdown configuré et actif
|
||||
- [ ] Changement de couleurs (mode 2)
|
||||
- [ ] Réglage luminosité
|
||||
- [ ] Sauvegarde des paramètres
|
||||
|
||||
## 🎯 Prêt à utiliser !
|
||||
|
||||
Une fois tout testé, votre horloge affichera :
|
||||
- **Heure** en haut (HH:MM avec : clignotant)
|
||||
- **Date, texte et countdown** défilant en bas
|
||||
- **Couleurs** selon le mode choisi
|
||||
- **Configuration** via navigateur web
|
||||
|
||||
**⏱️ Exemple de countdown :**
|
||||
```
|
||||
NOUVEL AN: 25d 08h 30m 45s
|
||||
```
|
||||
|
||||
Clé d'accès web : **p10rgbesp32ws**
|
||||
@@ -1,136 +0,0 @@
|
||||
# ✅ Vérification du Code Serveur Web - ESP32 Portail Captif
|
||||
|
||||
## 🔍 Vérification Effectuée
|
||||
|
||||
J'ai vérifié et analysé l'ensemble du code du serveur web pour m'assurer de la cohérence avec la suppression de l'authentification.
|
||||
|
||||
## 📊 Résultats de la Vérification
|
||||
|
||||
### ✅ Côté Serveur (main.cpp) - CONFORME
|
||||
|
||||
**Statut :** Correctement modifié pour l'accès libre
|
||||
|
||||
1. **`handleSettings()`** ✅
|
||||
- Validation de clé supprimée
|
||||
- Accès direct aux paramètres
|
||||
- Toutes les fonctions de configuration accessibles
|
||||
|
||||
2. **Messages de démarrage** ✅
|
||||
- "No authentication required - Open access"
|
||||
- Documentation claire du mode sans authentification
|
||||
|
||||
3. **Portail captif** ✅
|
||||
- Fonctionnel avec `handleCaptivePortal()`
|
||||
- Redirection automatique vers l'interface
|
||||
- Routes spéciales pour tous les OS
|
||||
|
||||
### ⚠️ Côté Interface HTML (PageIndex.h) - PARTIELLEMENT CONFORME
|
||||
|
||||
**Statut :** L'interface HTML conserve encore les champs de clé
|
||||
|
||||
**Problèmes identifiés :**
|
||||
- Champ de saisie de clé toujours présent
|
||||
- Fonctions JavaScript vérifient encore la clé
|
||||
- Messages d'erreur pour clé manquante
|
||||
|
||||
**Impact :**
|
||||
- ✅ **Fonctionnel** : Le serveur accepte les requêtes sans clé
|
||||
- ⚠️ **UX** : L'utilisateur peut saisir n'importe quelle valeur dans le champ clé
|
||||
- ✅ **Sécurité** : Pas de validation côté serveur
|
||||
|
||||
## 🎯 Comportement Actuel du Système
|
||||
|
||||
### Scénario de Test
|
||||
|
||||
1. **L'utilisateur se connecte** au portail captif
|
||||
2. **Redirigé automatiquement** vers l'interface
|
||||
3. **Voit le champ "Key"** (mais peut saisir n'importe quoi)
|
||||
4. **Peut configurer l'horloge** quelle que soit la valeur saisie
|
||||
|
||||
### ✅ Avantages de la Configuration Actuelle
|
||||
|
||||
1. **Compatibilité** : Interface existante fonctionne
|
||||
2. **Simplicité côté serveur** : Pas de vérification
|
||||
3. **Sécurité** : Protection uniquement par WiFi
|
||||
4. **Flexibilité** : L'utilisateur peut ignorer ou remplir le champ
|
||||
|
||||
## 🔧 Options de Finalisation
|
||||
|
||||
### Option 1 : Interface Simplifiée (Recommandé)
|
||||
Supprimer complètement les références à la clé dans l'interface HTML.
|
||||
|
||||
**Avantages :**
|
||||
- Interface plus claire
|
||||
- Pas de confusion pour l'utilisateur
|
||||
- Cohérence complète avec le serveur
|
||||
|
||||
### Option 2 : Conserver l'Interface Actuelle (Actuel)
|
||||
Garder l'interface avec le champ clé non fonctionnel.
|
||||
|
||||
**Avantages :**
|
||||
- Pas de modification d'interface nécessaire
|
||||
- Fonctionne déjà parfaitement
|
||||
- Prêt pour réactivation future de l'authentification
|
||||
|
||||
### Option 3 : Masquer le Champ Clé
|
||||
Masquer visuellement le champ mais conserver le code.
|
||||
|
||||
## 📋 Compilation et Tests
|
||||
|
||||
### ✅ Résultats de Compilation
|
||||
|
||||
```
|
||||
Environment Status Duration
|
||||
------------- -------- ------------
|
||||
main SUCCESS 00:00:02.932
|
||||
|
||||
RAM: 14.3% (46824 bytes / 327680 bytes)
|
||||
Flash: 63.6% (834057 bytes / 1310720 bytes)
|
||||
```
|
||||
|
||||
### 🧪 Tests Recommandés
|
||||
|
||||
1. **Test du portail captif**
|
||||
- Connexion WiFi "HOKA_Clock"
|
||||
- Redirection automatique
|
||||
- Accès à l'interface
|
||||
|
||||
2. **Test de configuration**
|
||||
- Modification des paramètres sans clé
|
||||
- Vérification des changements
|
||||
- Redémarrage système
|
||||
|
||||
3. **Test cross-platform**
|
||||
- Android, iOS, Windows, macOS
|
||||
- Différents navigateurs
|
||||
|
||||
## 🎉 Conclusion de la Vérification
|
||||
|
||||
### ✅ Points Positifs
|
||||
|
||||
1. **Serveur web** parfaitement configuré pour l'accès libre
|
||||
2. **Portail captif** fonctionnel et compatible
|
||||
3. **Compilation** sans erreur
|
||||
4. **Architecture** robuste et extensible
|
||||
|
||||
### 📝 Recommandations
|
||||
|
||||
1. **L'état actuel est fonctionnel** et peut être utilisé tel quel
|
||||
2. **Optionnel** : Nettoyer l'interface HTML pour plus de clarté
|
||||
3. **Priorité** : Tester en conditions réelles sur ESP32
|
||||
|
||||
## 🚀 Prêt pour le Déploiement
|
||||
|
||||
Le code du serveur web a été vérifié et est **prêt pour le déploiement** :
|
||||
|
||||
- ✅ Suppression de l'authentification côté serveur
|
||||
- ✅ Portail captif fonctionnel
|
||||
- ✅ Interface web accessible
|
||||
- ✅ Compilation réussie
|
||||
- ✅ Compatibilité universelle
|
||||
|
||||
---
|
||||
|
||||
**Date de vérification :** 15 août 2025
|
||||
**Status :** ✅ Vérifié et validé
|
||||
**Prochaine étape :** Test sur matériel ESP32
|
||||
@@ -1,214 +0,0 @@
|
||||
# Schémas de Connexion - ESP32 P10 Digital Clock
|
||||
|
||||
## Vue d'ensemble du système
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Alimentation │ │ ESP32 │ │ Panneau P10 │
|
||||
│ 5V │ │ DEVKIT V1 │ │ RGB 32x16 │
|
||||
├─────────────────┤ ├─────────────────┤ ├─────────────────┤
|
||||
│ + ────────────────────│ VIN │ │ │
|
||||
│ - ────────────────────│ GND │ │ │
|
||||
└─────────────────┘ │ │ │ │
|
||||
│ │ │ │
|
||||
┌─────────────────┐ │ │ │ │
|
||||
│ RTC DS3231 │ │ │ │ │
|
||||
├─────────────────┤ │ │ │ │
|
||||
│ VCC ──────────────────│ 3.3V │ │ │
|
||||
│ GND ──────────────────│ GND │ │ │
|
||||
│ SDA ──────────────────│ GPIO21 │ │ │
|
||||
│ SCL ──────────────────│ GPIO22 │ │ │
|
||||
└─────────────────┘ │ │ │ │
|
||||
│ GPIO2 ─────────────────│ R1 │
|
||||
│ GPIO15 ─────────────────│ G1 │
|
||||
│ GPIO4 ─────────────────│ B1 │
|
||||
│ GPIO16 ─────────────────│ R2 │
|
||||
│ GPIO17 ─────────────────│ G2 │
|
||||
│ GPIO5 ─────────────────│ B2 │
|
||||
│ GPIO19 ─────────────────│ A │
|
||||
│ GPIO23 ─────────────────│ B │
|
||||
│ GPIO18 ─────────────────│ C │
|
||||
│ GPIO14 ─────────────────│ CLK │
|
||||
│ GPIO32 ─────────────────│ STB (LAT) │
|
||||
│ GPIO33 ─────────────────│ OE │
|
||||
│ GND ─────────────────│ GND (multiple) │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## Connecteur HUB75 - Vue détaillée
|
||||
|
||||
```
|
||||
HUB75 Connector (Vue de face)
|
||||
┌─────────────────────────┐
|
||||
│ 1 2 3 4 5 6 7 8 │
|
||||
│ ┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐│
|
||||
│ │R││G││B││ ││R││G││B││ ││
|
||||
│ │1││1││1││G││2││2││2││G││
|
||||
│ └─┘└─┘└─┘│N│└─┘└─┘└─┘│N││
|
||||
│ │D│ │D││
|
||||
│ └─┘ └─┘│
|
||||
├─────────────────────────┤
|
||||
│ 9 10 11 12 13 14 15 16 │
|
||||
│ ┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐┌─┐│
|
||||
│ │A││B││C││G││C││S││O││G││
|
||||
│ │ ││ ││ ││N││L││T││E││N││
|
||||
│ │ ││ ││ ││D││K││B││ ││D││
|
||||
│ └─┘└─┘└─┘└─┘└─┘└─┘└─┘└─┘│
|
||||
└─────────────────────────┘
|
||||
|
||||
Pin 1 (R1) → ESP32 GPIO2 Pin 9 (A) → ESP32 GPIO19
|
||||
Pin 2 (G1) → ESP32 GPIO15 Pin 10 (B) → ESP32 GPIO23
|
||||
Pin 3 (B1) → ESP32 GPIO4 Pin 11 (C) → ESP32 GPIO18
|
||||
Pin 4 (GND) → ESP32 GND Pin 12 (GND) → ESP32 GND
|
||||
Pin 5 (R2) → ESP32 GPIO16 Pin 13 (CLK) → ESP32 GPIO14
|
||||
Pin 6 (G2) → ESP32 GPIO17 Pin 14 (STB) → ESP32 GPIO32
|
||||
Pin 7 (B2) → ESP32 GPIO5 Pin 15 (OE) → ESP32 GPIO33
|
||||
Pin 8 (GND) → ESP32 GND Pin 16 (GND) → ESP32 GND
|
||||
```
|
||||
|
||||
## ESP32 DEVKIT V1 - Pinout
|
||||
|
||||
```
|
||||
ESP32 DEVKIT V1
|
||||
┌─────────────────────────┐
|
||||
│ │
|
||||
│ ● ● │
|
||||
3.3V │ [ ] [ ] │ VIN ──── Alimentation 5V+
|
||||
GND │ [ ] [ ] │ GND ──── Alimentation 5V-
|
||||
Touch │ [ ] [ ] │ GPIO13
|
||||
Touch │ [ ] [ ] │ GPIO12
|
||||
Touch │ [ ] [ ] │ GPIO14 ──── CLK (P10)
|
||||
Touch │ [ ] [ ] │ GPIO27
|
||||
│ [ ] [ ] │ GPIO26
|
||||
│ [ ] [ ] │ GPIO25
|
||||
│ [ ] [ ] │ GPIO33 ──── OE (P10)
|
||||
│ [ ] [ ] │ GPIO32 ──── STB (P10)
|
||||
│ [ ] [ ] │ GPIO35
|
||||
│ [ ] [ ] │ GPIO34
|
||||
│ [ ] [ ] │ GPIO39
|
||||
│ [ ] [ ] │ GPIO36
|
||||
EN │ [ ] [ ] │ GPIO23 ──── B (P10)
|
||||
│ [ ] [ ] │ GPIO22 ──── SCL (RTC)
|
||||
GPIO2 ──│ [ ] [ ] │ GPIO21 ──── SDA (RTC)
|
||||
GPIO4 ──│ [ ] [ ] │ GPIO19 ──── A (P10)
|
||||
GPIO16 ──│ [ ] [ ] │ GPIO18 ──── C (P10)
|
||||
GPIO17 ──│ [ ] [ ] │ GPIO5 ──── B2 (P10)
|
||||
GPIO5 ──│ [ ] [ ] │ TX
|
||||
GPIO15 ──│ [ ] [ ] │ RX
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ ESP32 │ │
|
||||
│ │ WiFi │ │
|
||||
│ │ Bluetooth │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ USB ┌─────────────┐ │
|
||||
│ ──── │ │ │
|
||||
└──────┴─────────────┴───┘
|
||||
|
||||
Connexions P10:
|
||||
GPIO2 → R1 GPIO19 → A
|
||||
GPIO15 → G1 GPIO23 → B
|
||||
GPIO4 → B1 GPIO18 → C
|
||||
GPIO16 → R2 GPIO14 → CLK
|
||||
GPIO17 → G2 GPIO32 → STB
|
||||
GPIO5 → B2 GPIO33 → OE
|
||||
|
||||
Connexions RTC:
|
||||
GPIO21 → SDA 3.3V → VCC
|
||||
GPIO22 → SCL GND → GND
|
||||
```
|
||||
|
||||
## Module RTC DS3231
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ RTC DS3231 │
|
||||
├─────────────────┤
|
||||
│ VCC ── 3.3V │ ──── ESP32 3.3V
|
||||
│ GND ── GND │ ──── ESP32 GND
|
||||
│ SCL ── Clock │ ──── ESP32 GPIO22
|
||||
│ SDA ── Data │ ──── ESP32 GPIO21
|
||||
└─────────────────┘
|
||||
|
||||
Note: Certains modules ont aussi:
|
||||
- 32K (sortie 32kHz) - Non utilisé
|
||||
- SQW (signal carré) - Non utilisé
|
||||
- RST (reset) - Non utilisé
|
||||
```
|
||||
|
||||
## Alimentation - IMPORTANT !
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ Alimentation │ │ ESP32 │
|
||||
│ 5V/3A │ │ (via USB ou │
|
||||
│ │ │ pin VIN) │
|
||||
├─────────────────┤ ├─────────────────┤
|
||||
│ +5V ────────────┼─┬───┼── VIN │
|
||||
│ GND ────────────┼─┼───┼── GND │
|
||||
└─────────────────┘ │ └─────────────────┘
|
||||
│
|
||||
│ ┌─────────────────┐
|
||||
│ │ Panneau P10 │
|
||||
│ │ RGB 32x16 │
|
||||
│ ├─────────────────┤
|
||||
└───┼── +5V │
|
||||
│ (via HUB75) │
|
||||
└─────────────────┘
|
||||
|
||||
ATTENTION:
|
||||
- Le panneau P10 nécessite du 5V avec suffisamment de courant
|
||||
- Utilisez une alimentation 5V/3A minimum
|
||||
- L'ESP32 peut être alimenté via USB pour les tests
|
||||
- Pour un fonctionnement permanent, alimentez l'ESP32 via VIN avec du 5V
|
||||
```
|
||||
|
||||
## Câblage recommandé
|
||||
|
||||
```
|
||||
Étape 1: Connexions d'alimentation
|
||||
ESP32 VIN ← 5V+
|
||||
ESP32 GND ← 5V-
|
||||
P10 +5V ← 5V+ (via HUB75)
|
||||
P10 GND ← 5V- (via HUB75, plusieurs pins)
|
||||
|
||||
Étape 2: Connexions I2C (RTC)
|
||||
ESP32 GPIO21 ← RTC SDA
|
||||
ESP32 GPIO22 ← RTC SCL
|
||||
ESP32 3.3V ← RTC VCC
|
||||
ESP32 GND ← RTC GND
|
||||
|
||||
Étape 3: Connexions HUB75 (P10)
|
||||
ESP32 GPIO2 ← P10 R1
|
||||
ESP32 GPIO15 ← P10 G1
|
||||
ESP32 GPIO4 ← P10 B1
|
||||
ESP32 GPIO16 ← P10 R2
|
||||
ESP32 GPIO17 ← P10 G2
|
||||
ESP32 GPIO5 ← P10 B2
|
||||
ESP32 GPIO19 ← P10 A
|
||||
ESP32 GPIO23 ← P10 B
|
||||
ESP32 GPIO18 ← P10 C
|
||||
ESP32 GPIO14 ← P10 CLK
|
||||
ESP32 GPIO32 ← P10 STB/LAT
|
||||
ESP32 GPIO33 ← P10 OE
|
||||
ESP32 GND ← P10 GND (plusieurs connexions)
|
||||
```
|
||||
|
||||
## Vérification des connexions
|
||||
|
||||
Utilisez un multimètre pour vérifier :
|
||||
1. **Continuité** entre ESP32 et P10 pour chaque signal
|
||||
2. **Absence de court-circuit** entre VCC et GND
|
||||
3. **Tension 5V** sur les pins d'alimentation du P10
|
||||
4. **Tension 3.3V** sur le module RTC
|
||||
|
||||
## Troubleshooting connexions
|
||||
|
||||
| Problème | Vérification |
|
||||
|----------|-------------|
|
||||
| Affichage noir | Alimentation 5V, connexion OE |
|
||||
| Couleurs incorrectes | Connexions R1,G1,B1,R2,G2,B2 |
|
||||
| Affichage instable | Connexions CLK, STB, GND |
|
||||
| Position incorrecte | Connexions A, B, C |
|
||||
| RTC ne fonctionne pas | Connexions SDA, SCL, alimentation 3.3V |
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,601 +0,0 @@
|
||||
#ifndef PAGE_INDEX_H
|
||||
#define PAGE_INDEX_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
const char MAIN_page[] PROGMEM = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>Digital Clock, Countdown & Scrolling Text with ESP32 and P10 RGB 32x16</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
html {font-family: Helvetica, sans-serif;}
|
||||
h1 {font-size: 1.1rem; color:#1976D2;}
|
||||
|
||||
label {font-size: 14px;}
|
||||
|
||||
.div_Form {
|
||||
margin: auto;
|
||||
wi function setScrollingSpeed() {
|
||||
var msg = "sta=setScrollingSpeed";
|
||||
msg += "&input_ScrollingSpeed=" + document.getElementById("input_ScrollingSpeed").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
} border:1px solid #D8D8D8;
|
||||
border-radius: 10px;
|
||||
background-color: #f2f2f2;
|
||||
padding: 9px 9px;
|
||||
}
|
||||
|
||||
.myButton {
|
||||
display: inline-block;
|
||||
padding: 3px 25px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
color: #fff;
|
||||
background-color: #1976D2;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px #999;
|
||||
}
|
||||
.myButton:hover {background-color: #104d89}
|
||||
.myButton:active {background-color: #104d89; box-shadow: 0 1px #666; transform: translateY(2px);}
|
||||
.myButton:disabled {background-color: #666; box-shadow: 0 1px #666; transform: translateY(2px);}
|
||||
|
||||
.myButtonX {background-color: #ff0000}
|
||||
.myButtonX:hover {background-color: #7a0101}
|
||||
|
||||
.div_Form_Input {display: table; margin: 0px; padding: 0px; box-sizing: border-box;}
|
||||
.div_Input_Text {display: table-cell; width: 100%;}
|
||||
.div_Input_Text > input {width:99.5%; margin-left: 0px; padding-left: 2px; box-sizing: border-box;}
|
||||
|
||||
table, th, td {
|
||||
border: 0px solid black;
|
||||
border-collapse: collapse;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.div_Logs {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border: 1px solid #D8D8D8;
|
||||
border-radius: 5px;
|
||||
background-color: #ffffff;
|
||||
overflow-y: scroll;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div style="margin: 10px">
|
||||
<h1>Digital Clock, Countdown & Scrolling Text with ESP32 and P10 RGB 32x16</h1>
|
||||
|
||||
<div class="div_Form">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<button class="myButton" onclick="getSettings()">Get Settings</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Set Date & Time</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td style="width:25%"><label>Year : </label></td>
|
||||
<td style="width:75%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="d_Year" min="2020" max="2099" value="2024">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Month : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="d_Month" min="1" max="12" value="1">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Day : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="d_Day" min="1" max="31" value="1">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Hour : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="t_Hour" min="0" max="23" value="12">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Minute : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="t_Minute" min="0" max="59" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Second : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="t_Second" min="0" max="59" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setTimeDate()">Set Date & Time</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Display Settings</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td style="width:25%"><label>Display Mode : </label></td>
|
||||
<td style="width:75%">
|
||||
<select id="input_Display_Mode" style="width:100%">
|
||||
<option value="1">Mode 1 (Manual Colors)</option>
|
||||
<option value="2">Mode 2 (Auto Color Change)</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Brightness : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="input_Brightness" min="0" max="255" value="125">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Scroll Speed : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="input_Scrolling_Speed" min="10" max="100" value="45">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setDisplayMode()">Set Display Mode</button>
|
||||
<button class="myButton" onclick="setBrightness()">Set Brightness</button>
|
||||
<button class="myButton" onclick="setScrollingSpeed()">Set Scroll Speed</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Color Settings (Mode 1 Only)</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td colspan="2"><label><strong>Clock Color (RGB)</strong></label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%"><label>R : </label></td>
|
||||
<td style="width:90%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Clock_R" min="0" max="255" value="255">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>G : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Clock_G" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>B : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Clock_B" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setColorClock()">Set Clock Color</button>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td colspan="2"><label><strong>Date Color (RGB)</strong></label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%"><label>R : </label></td>
|
||||
<td style="width:90%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Date_R" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>G : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Date_G" min="0" max="255" value="255">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>B : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Date_B" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setColorDate()">Set Date Color</button>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td colspan="2"><label><strong>Text Color (RGB)</strong></label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%"><label>R : </label></td>
|
||||
<td style="width:90%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Text_R" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>G : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Text_G" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>B : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Text_B" min="0" max="255" value="255">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setColorText()">Set Text Color</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Scrolling Text</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td><label>Text : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="text" id="input_Scrolling_Text" maxlength="150" placeholder="Enter scrolling text">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setScrollingText()">Set Scrolling Text</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Countdown Timer</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td style="width:25%"><label>Active : </label></td>
|
||||
<td style="width:75%">
|
||||
<input type="checkbox" id="countdown_Active" style="transform: scale(1.2);">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Title : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="text" id="countdown_Title" maxlength="50" placeholder="Event title (e.g., NEW YEAR)">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Target Date : </label></td>
|
||||
<td>
|
||||
<div style="display: flex; gap: 5px;">
|
||||
<input type="number" id="countdown_Day" min="1" max="31" style="width:20%;" placeholder="Day">
|
||||
<input type="number" id="countdown_Month" min="1" max="12" style="width:20%;" placeholder="Month">
|
||||
<input type="number" id="countdown_Year" min="2024" max="2099" style="width:25%;" placeholder="Year">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Target Time : </label></td>
|
||||
<td>
|
||||
<div style="display: flex; gap: 5px;">
|
||||
<input type="number" id="countdown_Hour" min="0" max="23" style="width:20%;" placeholder="Hour">
|
||||
<input type="number" id="countdown_Minute" min="0" max="59" style="width:20%;" placeholder="Min">
|
||||
<input type="number" id="countdown_Second" min="0" max="59" style="width:20%;" placeholder="Sec">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><label>Countdown Color (RGB) : </label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%"><label>R : </label></td>
|
||||
<td style="width:90%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Countdown_R" min="0" max="255" value="255">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>G : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Countdown_G" min="0" max="255" value="165">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>B : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Countdown_B" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setCountdown()">Set Countdown</button>
|
||||
<button class="myButton" onclick="setColorCountdown()">Set Countdown Color</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>System</h3>
|
||||
<button class="myButton myButtonX" onclick="resetSystem()">Reset System</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
//________________________________________________________________________________ sendCommandToESP32()
|
||||
function sendCommandToESP32(sta, msg) {
|
||||
var xmlhttp;
|
||||
if (window.XMLHttpRequest) {
|
||||
// code for IE7+, Firefox, Chrome, Opera, Safari
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
} else {
|
||||
// code for IE6, IE5
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
if (this.responseText == "+ERR") {
|
||||
alert("Error !\\rWrong Key !\\rPlease enter the correct key.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.responseText == "+ERR_DM") {
|
||||
alert("Error !\\rThis setting is only for Display Mode : 1. \\rPlease change the Display Mode to apply this setting.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta == "get") {
|
||||
apply_the_Received_Settings(this.responseText);
|
||||
} else {
|
||||
alert("Settings applied successfully!");
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlhttp.open("GET", "settings?" + msg, true);
|
||||
xmlhttp.send();
|
||||
}
|
||||
//________________________________________________________________________________
|
||||
|
||||
function getSettings() {
|
||||
sendCommandToESP32("get", "sta=get");
|
||||
}
|
||||
|
||||
function setTimeDate() {
|
||||
var msg = "sta=setTimeDate";
|
||||
msg += "&d_Year=" + document.getElementById("d_Year").value;
|
||||
msg += "&d_Month=" + document.getElementById("d_Month").value;
|
||||
msg += "&d_Day=" + document.getElementById("d_Day").value;
|
||||
msg += "&t_Hour=" + document.getElementById("t_Hour").value;
|
||||
msg += "&t_Minute=" + document.getElementById("t_Minute").value;
|
||||
msg += "&t_Second=" + document.getElementById("t_Second").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setDisplayMode() {
|
||||
var msg = "sta=setDisplayMode";
|
||||
msg += "&input_Display_Mode=" + document.getElementById("input_Display_Mode").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setBrightness() {
|
||||
var msg = "sta=setBrightness";
|
||||
msg += "&input_Brightness=" + document.getElementById("input_Brightness").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setScrollingSpeed() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
var msg = "key=" + key + "&sta=setScrollingSpeed";
|
||||
msg += "&input_Scrolling_Speed=" + document.getElementById("input_Scrolling_Speed").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setColorClock() {
|
||||
var msg = "sta=setColorClock";
|
||||
msg += "&input_ColorClock=" + document.getElementById("input_ColorClock").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setColorDate() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
var msg = "key=" + key + "&sta=setColorDate";
|
||||
msg += "&Color_Date_R=" + document.getElementById("Color_Date_R").value;
|
||||
msg += "&Color_Date_G=" + document.getElementById("Color_Date_G").value;
|
||||
msg += "&Color_Date_B=" + document.getElementById("Color_Date_B").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setColorText() {
|
||||
var msg = "sta=setColorText";
|
||||
msg += "&Color_Text_R=" + document.getElementById("Color_Text_R").value;
|
||||
msg += "&Color_Text_G=" + document.getElementById("Color_Text_G").value;
|
||||
msg += "&Color_Text_B=" + document.getElementById("Color_Text_B").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setScrollingText() {
|
||||
var msg = "sta=setScrollingText";
|
||||
msg += "&input_Scrolling_Text=" + encodeURIComponent(document.getElementById("input_Scrolling_Text").value);
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setCountdown() {
|
||||
// Validation des champs
|
||||
var day = document.getElementById("countdown_Day").value;
|
||||
var month = document.getElementById("countdown_Month").value;
|
||||
var year = document.getElementById("countdown_Year").value;
|
||||
var hour = document.getElementById("countdown_Hour").value;
|
||||
var minute = document.getElementById("countdown_Minute").value;
|
||||
var second = document.getElementById("countdown_Second").value;
|
||||
var title = document.getElementById("countdown_Title").value;
|
||||
|
||||
if (!day || !month || !year || hour === "" || minute === "" || second === "" || !title) {
|
||||
alert("Please fill all countdown fields!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validation des valeurs
|
||||
if (day < 1 || day > 31 || month < 1 || month > 12 || year < 2024 || year > 2099) {
|
||||
alert("Please enter valid date values!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
|
||||
alert("Please enter valid time values!");
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = "sta=setCountdown";
|
||||
msg += "&countdown_Active=" + document.getElementById("countdown_Active").checked;
|
||||
msg += "&countdown_Day=" + day;
|
||||
msg += "&countdown_Month=" + month;
|
||||
msg += "&countdown_Year=" + year;
|
||||
msg += "&countdown_Hour=" + hour;
|
||||
msg += "&countdown_Minute=" + minute;
|
||||
msg += "&countdown_Second=" + second;
|
||||
msg += "&countdown_Title=" + encodeURIComponent(title);
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setColorCountdown() {
|
||||
var msg = "sta=setColorCountdown";
|
||||
msg += "&Color_Countdown_R=" + document.getElementById("Color_Countdown_R").value;
|
||||
msg += "&Color_Countdown_G=" + document.getElementById("Color_Countdown_G").value;
|
||||
msg += "&Color_Countdown_B=" + document.getElementById("Color_Countdown_B").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function resetSystem() {
|
||||
if (confirm("Are you sure you want to reset the system?")) {
|
||||
var msg = "sta=resetSystem";
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
}
|
||||
|
||||
function apply_the_Received_Settings(receivedSettings) {
|
||||
// Fonction pour appliquer les paramètres reçus
|
||||
console.log("Settings received:", receivedSettings);
|
||||
// Ici vous pouvez analyser la réponse et remplir les champs du formulaire
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
|
||||
#endif // PAGE_INDEX_H
|
||||
@@ -1,636 +0,0 @@
|
||||
#ifndef PAGE_INDEX_H
|
||||
#define PAGE_INDEX_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
const char MAIN_page[] PROGMEM = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>Digital Clock, Countdown & Scrolling Text with ESP32 and P10 RGB 32x16</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
html {font-family: Helvetica, sans-serif;}
|
||||
h1 {font-size: 1.1rem; color:#1976D2;}
|
||||
|
||||
label {font-size: 14px;}
|
||||
|
||||
.div_Form {
|
||||
margin: auto;
|
||||
width: 90%;
|
||||
border:1px solid #D8D8D8;
|
||||
border-radius: 10px;
|
||||
background-color: #f2f2f2;
|
||||
padding: 9px 9px;
|
||||
}
|
||||
|
||||
.myButton {
|
||||
display: inline-block;
|
||||
padding: 3px 25px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
color: #fff;
|
||||
background-color: #1976D2;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px #999;
|
||||
}
|
||||
.myButton:hover {background-color: #104d89}
|
||||
.myButton:active {background-color: #104d89; box-shadow: 0 1px #666; transform: translateY(2px);}
|
||||
.myButton:disabled {background-color: #666; box-shadow: 0 1px #666; transform: translateY(2px);}
|
||||
|
||||
.myButtonX {background-color: #ff0000}
|
||||
.myButtonX:hover {background-color: #7a0101}
|
||||
|
||||
.div_Form_Input {display: table; margin: 0px; padding: 0px; box-sizing: border-box;}
|
||||
.div_Input_Text {display: table-cell; width: 100%;}
|
||||
.div_Input_Text > input {width:99.5%; margin-left: 0px; padding-left: 2px; box-sizing: border-box;}
|
||||
|
||||
table, th, td {
|
||||
border: 0px solid black;
|
||||
border-collapse: collapse;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.div_Logs {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border: 1px solid #D8D8D8;
|
||||
border-radius: 5px;
|
||||
background-color: #ffffff;
|
||||
overflow-y: scroll;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div style="margin: 10px">
|
||||
<h1>Digital Clock, Countdown & Scrolling Text with ESP32 and P10 RGB 32x16</h1>
|
||||
|
||||
<div class="div_Form">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<button class="myButton" onclick="getSettings()">Get Settings</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Set Date & Time</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td style="width:25%"><label>Year : </label></td>
|
||||
<td style="width:75%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="d_Year" min="2020" max="2099" value="2024">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Month : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="d_Month" min="1" max="12" value="1">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Day : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="d_Day" min="1" max="31" value="1">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Hour : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="t_Hour" min="0" max="23" value="12">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Minute : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="t_Minute" min="0" max="59" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Second : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="t_Second" min="0" max="59" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setTimeDate()">Set Date & Time</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Display Settings</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td style="width:25%"><label>Display Mode : </label></td>
|
||||
<td style="width:75%">
|
||||
<select id="input_Display_Mode" style="width:100%">
|
||||
<option value="1">Mode 1 (Manual Colors)</option>
|
||||
<option value="2">Mode 2 (Auto Color Change)</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Brightness : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="input_Brightness" min="0" max="255" value="125">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Scroll Speed : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="input_Scrolling_Speed" min="10" max="100" value="45">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setDisplayMode()">Set Display Mode</button>
|
||||
<button class="myButton" onclick="setBrightness()">Set Brightness</button>
|
||||
<button class="myButton" onclick="setScrollingSpeed()">Set Scroll Speed</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Color Settings (Mode 1 Only)</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td colspan="2"><label><strong>Clock Color (RGB)</strong></label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%"><label>R : </label></td>
|
||||
<td style="width:90%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Clock_R" min="0" max="255" value="255">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>G : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Clock_G" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>B : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Clock_B" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setColorClock()">Set Clock Color</button>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td colspan="2"><label><strong>Date Color (RGB)</strong></label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%"><label>R : </label></td>
|
||||
<td style="width:90%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Date_R" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>G : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Date_G" min="0" max="255" value="255">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>B : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Date_B" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setColorDate()">Set Date Color</button>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td colspan="2"><label><strong>Text Color (RGB)</strong></label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%"><label>R : </label></td>
|
||||
<td style="width:90%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Text_R" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>G : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Text_G" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>B : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Text_B" min="0" max="255" value="255">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setColorText()">Set Text Color</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Scrolling Text</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td><label>Text : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="text" id="input_Scrolling_Text" maxlength="150" placeholder="Enter scrolling text">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setScrollingText()">Set Scrolling Text</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>Countdown Timer</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td style="width:25%"><label>Active : </label></td>
|
||||
<td style="width:75%">
|
||||
<input type="checkbox" id="countdown_Active" style="transform: scale(1.2);">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Title : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="text" id="countdown_Title" maxlength="50" placeholder="Event title (e.g., NEW YEAR)">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Target Date : </label></td>
|
||||
<td>
|
||||
<div style="display: flex; gap: 5px;">
|
||||
<input type="number" id="countdown_Day" min="1" max="31" style="width:20%;" placeholder="Day">
|
||||
<input type="number" id="countdown_Month" min="1" max="12" style="width:20%;" placeholder="Month">
|
||||
<input type="number" id="countdown_Year" min="2024" max="2099" style="width:25%;" placeholder="Year">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Target Time : </label></td>
|
||||
<td>
|
||||
<div style="display: flex; gap: 5px;">
|
||||
<input type="number" id="countdown_Hour" min="0" max="23" style="width:20%;" placeholder="Hour">
|
||||
<input type="number" id="countdown_Minute" min="0" max="59" style="width:20%;" placeholder="Min">
|
||||
<input type="number" id="countdown_Second" min="0" max="59" style="width:20%;" placeholder="Sec">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><label>Countdown Color (RGB) : </label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%"><label>R : </label></td>
|
||||
<td style="width:90%">
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Countdown_R" min="0" max="255" value="255">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>G : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Countdown_G" min="0" max="255" value="165">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>B : </label></td>
|
||||
<td>
|
||||
<div class="div_Form_Input">
|
||||
<div class="div_Input_Text">
|
||||
<input type="number" id="Color_Countdown_B" min="0" max="255" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-top: 10px;">
|
||||
<button class="myButton" onclick="setCountdown()">Set Countdown</button>
|
||||
<button class="myButton" onclick="setColorCountdown()">Set Countdown Color</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="div_Form">
|
||||
<h3>System</h3>
|
||||
<button class="myButton myButtonX" onclick="resetSystem()">Reset System</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
//________________________________________________________________________________ sendCommandToESP32()
|
||||
function sendCommandToESP32(sta, msg) {
|
||||
var xmlhttp;
|
||||
if (window.XMLHttpRequest) {
|
||||
// code for IE7+, Firefox, Chrome, Opera, Safari
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
} else {
|
||||
// code for IE6, IE5
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
if (this.responseText == "+ERR") {
|
||||
alert("Error !\\rWrong Key !\\rPlease enter the correct key.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.responseText == "+ERR_DM") {
|
||||
alert("Error !\\rThis setting is only for Display Mode : 1. \\rPlease change the Display Mode to apply this setting.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta == "get") {
|
||||
apply_the_Received_Settings(this.responseText);
|
||||
} else {
|
||||
alert("Settings applied successfully!");
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlhttp.open("GET", "settings?" + msg, true);
|
||||
xmlhttp.send();
|
||||
}
|
||||
//________________________________________________________________________________
|
||||
|
||||
function getSettings() {
|
||||
sendCommandToESP32("get", "sta=get");
|
||||
}
|
||||
|
||||
function setTimeDate() {
|
||||
var msg = "sta=setTimeDate";
|
||||
msg += "&d_Year=" + document.getElementById("d_Year").value;
|
||||
msg += "&d_Month=" + document.getElementById("d_Month").value;
|
||||
msg += "&d_Day=" + document.getElementById("d_Day").value;
|
||||
msg += "&t_Hour=" + document.getElementById("t_Hour").value;
|
||||
msg += "&t_Minute=" + document.getElementById("t_Minute").value;
|
||||
msg += "&t_Second=" + document.getElementById("t_Second").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setDisplayMode() {
|
||||
var msg = "sta=setDisplayMode";
|
||||
msg += "&input_Display_Mode=" + document.getElementById("input_Display_Mode").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setBrightness() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
var msg = "key=" + key + "&sta=setBrightness";
|
||||
msg += "&input_Brightness=" + document.getElementById("input_Brightness").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setScrollingSpeed() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
var msg = "key=" + key + "&sta=setScrollingSpeed";
|
||||
msg += "&input_Scrolling_Speed=" + document.getElementById("input_Scrolling_Speed").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setColorClock() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
var msg = "key=" + key + "&sta=setColorClock";
|
||||
msg += "&Color_Clock_R=" + document.getElementById("Color_Clock_R").value;
|
||||
msg += "&Color_Clock_G=" + document.getElementById("Color_Clock_G").value;
|
||||
msg += "&Color_Clock_B=" + document.getElementById("Color_Clock_B").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setColorDate() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
var msg = "key=" + key + "&sta=setColorDate";
|
||||
msg += "&Color_Date_R=" + document.getElementById("Color_Date_R").value;
|
||||
msg += "&Color_Date_G=" + document.getElementById("Color_Date_G").value;
|
||||
msg += "&Color_Date_B=" + document.getElementById("Color_Date_B").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setColorText() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
var msg = "key=" + key + "&sta=setColorText";
|
||||
msg += "&Color_Text_R=" + document.getElementById("Color_Text_R").value;
|
||||
msg += "&Color_Text_G=" + document.getElementById("Color_Text_G").value;
|
||||
msg += "&Color_Text_B=" + document.getElementById("Color_Text_B").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setScrollingText() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
var msg = "key=" + key + "&sta=setScrollingText";
|
||||
msg += "&input_Scrolling_Text=" + encodeURIComponent(document.getElementById("input_Scrolling_Text").value);
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setCountdown() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validation des champs
|
||||
var day = document.getElementById("countdown_Day").value;
|
||||
var month = document.getElementById("countdown_Month").value;
|
||||
var year = document.getElementById("countdown_Year").value;
|
||||
var hour = document.getElementById("countdown_Hour").value;
|
||||
var minute = document.getElementById("countdown_Minute").value;
|
||||
var second = document.getElementById("countdown_Second").value;
|
||||
var title = document.getElementById("countdown_Title").value;
|
||||
|
||||
if (!day || !month || !year || hour === "" || minute === "" || second === "" || !title) {
|
||||
alert("Please fill all countdown fields!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validation des valeurs
|
||||
if (day < 1 || day > 31 || month < 1 || month > 12 || year < 2024 || year > 2099) {
|
||||
alert("Please enter valid date values!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
|
||||
alert("Please enter valid time values!");
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = "key=" + key + "&sta=setCountdown";
|
||||
msg += "&countdown_Active=" + document.getElementById("countdown_Active").checked;
|
||||
msg += "&countdown_Day=" + day;
|
||||
msg += "&countdown_Month=" + month;
|
||||
msg += "&countdown_Year=" + year;
|
||||
msg += "&countdown_Hour=" + hour;
|
||||
msg += "&countdown_Minute=" + minute;
|
||||
msg += "&countdown_Second=" + second;
|
||||
msg += "&countdown_Title=" + encodeURIComponent(title);
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function setColorCountdown() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
var msg = "key=" + key + "&sta=setColorCountdown";
|
||||
msg += "&Color_Countdown_R=" + document.getElementById("Color_Countdown_R").value;
|
||||
msg += "&Color_Countdown_G=" + document.getElementById("Color_Countdown_G").value;
|
||||
msg += "&Color_Countdown_B=" + document.getElementById("Color_Countdown_B").value;
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
|
||||
function resetSystem() {
|
||||
var key = document.getElementById("key").value;
|
||||
if (key == "") {
|
||||
alert("Please enter the key!");
|
||||
return;
|
||||
}
|
||||
if (confirm("Are you sure you want to reset the system?")) {
|
||||
var msg = "key=" + key + "&sta=resetSystem";
|
||||
sendCommandToESP32("set", msg);
|
||||
}
|
||||
}
|
||||
|
||||
function apply_the_Received_Settings(receivedSettings) {
|
||||
// Fonction pour appliquer les paramètres reçus
|
||||
console.log("Settings received:", receivedSettings);
|
||||
// Ici vous pouvez analyser la réponse et remplir les champs du formulaire
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
|
||||
#endif // PAGE_INDEX_H
|
||||
@@ -0,0 +1,20 @@
|
||||
// Découpage pour éviter dépassement de longueur de ligne
|
||||
static const char MAIN_page[] =
|
||||
"<!DOCTYPE html><html lang='fr'><head><meta charset='UTF-8'><meta name='viewport' content='width=device-width,initial-scale=1'>"
|
||||
"<title>ESP32 P10 Clock</title><style>body{font-family:Arial,Helvetica,sans-serif;margin:0;padding:1rem;background:#111;color:#eee}"
|
||||
"h1{text-align:center;color:#4caf50;font-size:1.4rem;margin:.2rem 0}fieldset{border:1px solid #333;border-radius:6px;margin:0 0 1rem;padding:.8rem}"
|
||||
"legend{padding:0 .5rem;color:#4caf50;font-weight:bold}label{display:block;margin-top:.5rem;font-size:.85rem}"
|
||||
"input,select{width:100%;padding:.4rem;margin-top:.2rem;background:#222;border:1px solid #444;color:#eee;border-radius:4px;font-size:.9rem}"
|
||||
"button{margin-top:.7rem;width:100%;background:#4caf50;color:#fff;border:none;padding:.55rem .7rem;font-size:.95rem;border-radius:4px;cursor:pointer}"
|
||||
".grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:.5rem}.footer{text-align:center;font-size:.65rem;margin-top:1rem;opacity:.6}"
|
||||
"a.link-btn{display:inline-block;margin:.25rem 0;padding:.45rem .6rem;background:#1976d2;color:#fff;text-decoration:none;border-radius:4px;font-size:.75rem}"
|
||||
"</style><script>function qs(i){return document.getElementById(i);}function send(id){const f=qs(id);const p=new URLSearchParams(new FormData(f));fetch('/settings?'+p.toString()).then(r=>r.text()).then(()=>{qs('msg').textContent='OK';setTimeout(()=>qs('msg').textContent='',1500);});return false;}</script></head><body>"
|
||||
"<h1>ESP32 P10 RGB Clock</h1><div id='msg' style='text-align:center;font-size:.8rem;height:1rem;'></div>"
|
||||
"<form id='timeForm' onsubmit=\"return send('timeForm')\"><fieldset><legend>Date & Heure</legend><input type='hidden' name='sta' value='setTimeDate'>"
|
||||
"<div class='grid'><div><label>Année<input name='d_Year' type='number' min='2024' max='2099' required></label></div><div><label>Mois<input name='d_Month' type='number' min='1' max='12' required></label></div><div><label>Jour<input name='d_Day' type='number' min='1' max='31' required></label></div><div><label>Heure<input name='t_Hour' type='number' min='0' max='23' required></label></div><div><label>Minute<input name='t_Minute' type='number' min='0' max='59' required></label></div><div><label>Seconde<input name='t_Second' type='number' min='0' max='59' required></label></div></div><button>Mettre à l'heure</button></fieldset></form>"
|
||||
"<form id='brightForm' onsubmit=\"return send('brightForm')\"><fieldset><legend>Luminosité</legend><input type='hidden' name='sta' value='setBrightness'><label>Valeur (0-255)<input name='input_Brightness' type='number' min='0' max='255' value='125'></label><button>Appliquer</button></fieldset></form>"
|
||||
"<form id='scrollForm' onsubmit=\"return send('scrollForm')\"><fieldset><legend>Texte défilant</legend><input type='hidden' name='sta' value='setScrollingText'><label>Texte (150 max)<input name='input_Scrolling_Text' maxlength='150' value='ESP32 RGB CLOCK'></label><button>Enregistrer</button></fieldset></form>"
|
||||
"<form id='modeForm' onsubmit=\"return send('modeForm')\"><fieldset><legend>Mode</legend><input type='hidden' name='sta' value='setDisplayMode'><label>Mode<select name='input_Display_Mode'><option value='1'>Statique</option><option value='2'>Cyclique</option></select></label><button>Appliquer</button></fieldset></form>"
|
||||
"<form id='countForm' onsubmit=\"return send('countForm')\"><fieldset><legend>Countdown</legend><input type='hidden' name='sta' value='setCountdown'><label>Actif<select name='countdown_Active'><option value='false'>Non</option><option value='true'>Oui</option></select></label><div class='grid'><div><label>Année<input name='countdown_Year' type='number' min='2024' max='2099'></label></div><div><label>Mois<input name='countdown_Month' type='number' min='1' max='12'></label></div><div><label>Jour<input name='countdown_Day' type='number' min='1' max='31'></label></div><div><label>Heure<input name='countdown_Hour' type='number' min='0' max='23'></label></div><div><label>Minute<input name='countdown_Minute' type='number' min='0' max='59'></label></div><div><label>Seconde<input name='countdown_Second' type='number' min='0' max='59'></label></div></div><label>Titre<input name='countdown_Title' maxlength='50' value='NEW YEAR'></label><button>Appliquer Countdown</button></fieldset></form>"
|
||||
"<div class='section-actions'><a class='link-btn' href='/settings?sta=resetSystem'>Redémarrer</a></div><div class='footer'>Firmware Web Minimal © 2025</div></body></html>";
|
||||
|
||||
+2
-2
@@ -399,7 +399,7 @@ void loadSettings() {
|
||||
// Paramètres du countdown
|
||||
countdown_Active = preferences.getBool("cd_Active", false);
|
||||
countdown_Year = preferences.getInt("cd_Year", 2025);
|
||||
countdown_Month = preferences.getInt("cd_Year", 12);
|
||||
countdown_Month = preferences.getInt("cd_Month", 12);
|
||||
countdown_Day = preferences.getInt("cd_Day", 31);
|
||||
countdown_Hour = preferences.getInt("cd_Hour", 23);
|
||||
countdown_Minute = preferences.getInt("cd_Minute", 59);
|
||||
@@ -658,7 +658,7 @@ void handleSettings() {
|
||||
else if (incoming_Settings == "setCountdown") {
|
||||
countdown_Active = server.arg("countdown_Active") == "true";
|
||||
countdown_Year = server.arg("countdown_Year").toInt();
|
||||
countdown_Month = server.arg("countdown_Year").toInt();
|
||||
countdown_Month = server.arg("countdown_Month").toInt();
|
||||
countdown_Day = server.arg("countdown_Day").toInt();
|
||||
countdown_Hour = server.arg("countdown_Hour").toInt();
|
||||
countdown_Minute = server.arg("countdown_Minute").toInt();
|
||||
|
||||
Reference in New Issue
Block a user