Sortie · sept. 2026

AccueilWatt-ProxyManuel

ESP32-S3 · PSRAM · PROXY HTTPS

Manuel — Watt-Proxy

Le watt-proxy n'a presque pas d'interface : une page d'état et un assistant Wi-Fi. Ce manuel décrit chaque carte, chaque bouton, chaque endpoint — ce que ça fait et les valeurs renvoyées.

Le watt-proxy est un relais HTTPS sur ESP32-S3 : il exécute à la place des autres modules (en particulier le Guardian TTGO) le handshake TLS qui coûte ~30 KB de heap contigu, en le routant dans sa PSRAM. Il se découvre tout seul par mDNS (SolarMeshLabs._tcp, TXT fonction=proxy) ; son interface web se résume à une page d'état en lecture quasi totale et à un assistant Wi-Fi en mode point d'accès.

Conventions de lecture

Le id est soit l'identifiant HTML de l'élément affiché, soit la clé JSON renvoyée par /state (utile au support). Contrairement aux autres firmwares, le proxy n'a pas de formulaire « à sauvegarder » : la page se rafraîchit toutes les 5 s depuis /state (et en continu via un flux EventSource('/events')). La majorité des champs sont en lecture seule ; seules les cartes « Sécurité » et « Relais cloud » sont éditables et possèdent leur propre bouton d'enregistrement, à effet immédiat.

Badges utilisés dans ce manuel

Immédiat appliqué à chaud, sans redémarrage   Reboot redémarre l'appareil   opt-in fonction désactivée par défaut

Éléments communs aux deux pages

Le watt-proxy n'a ni barre latérale ni menu : juste un en-tête sobre. La page d'état et l'assistant Wi-Fi partagent l'identité de marque et le sélecteur de langue.

Élément (id)Rôle
WATT-PROXY + badge d'état — status_badgeBadge vert CONNECTÉ en Wi-Fi, rouge MODE AP en point d'accès (ap_mode), rouge OFFLINE si /state devient injoignable.
Sélecteur de langue — lang_selectFR · EN. Charge la préférence via GET /languages puis applique GET /setlanguage?lang= et recharge les libellés à chaud (i18n, sans rechargement de page). Immédiat
Repère version — header_metaAffiche FW<n> · FS<n> (clés fw_build / fs_build). Un badge jaune ⚠ attendu FS= apparaît si le filesystem chargé (fs_build_spiffs) diffère de celui attendu par le firmware — signe d'une mise à jour partielle (reflasher le FS).

Pas de credentials ? Au démarrage, sans Wi-Fi enregistré, le proxy bascule en point d'accès ouvert WATT-PROXY-xxxx et sert la page Configuration AP. Une fois connecté, c'est la page d'état qui s'affiche.

Page « État » (page principale)

Accès : la racine / en mode Wi-Fi (STA). Une grille de cartes auto-ajustées, toutes alimentées par /state. Description carte par carte.

Carte « Identité »

Lecture seule — qui est l'appareil et où il est sur le réseau.

Champ (clé /state)ExempleRôle
Nom — nameWatt-Proxy-58bcNom d'hôte mDNS (<name>.local).
MAC — macA0:B7:65:1C:33:E8Adresse matérielle de l'interface Wi-Fi.
IP — wifi_ip192.168.1.60Adresse locale courante ; (AP) en point d'accès.
SSID — wifi_ssidMaison-WifiRéseau rejoint.
RSSI — rssi−57 dBmForce du signal Wi-Fi.
Uptime — uptime_s4 j 7 h 30 mTemps depuis le dernier démarrage (formaté côté page).

Carte « Mémoire »

C'est la raison d'être du proxy : surveiller que la mémoire reste saine pendant les handshakes TLS.

Champ (clé /state)Rôle
Heap libre — heap_freeRAM interne disponible instantanément.
Heap max bloc — heap_max_blockPlus grand bloc contigu allouable — l'indicateur clé pour mbedtls.
Heap min historique — heap_min_freePlancher de heap atteint depuis le boot (détecte les pics de pression).
PSRAM libre — psram_freeRAM externe (2–8 MB) où mbedtls route ses gros buffers ; N/A si absente.

Carte « Statistiques proxy »

Compteurs du trafic proxifié depuis le démarrage. Champs sous stats dans /state.

Champ (clé)Rôle
Total requêtes — stats.totalNombre de POST /proxy traités (gros chiffre).
Réussies — stats.successfulRequêtes ayant abouti.
Échouées — stats.failedErreurs HTTPS / timeouts.
Dernière (ms) — stats.last_msTemps de la dernière requête proxifiée.
Sur 60 s — stats.recent_60sDébit récent, affiché « N/60 » (rate limit global 60 req/min).
Dernière erreur — stats.last_errorDernier message d'échec (cible / code).

Carte « Cache local (TTL 60 s) »

Cache des réponses idempotentes (ex. Open-Meteo) pour économiser le quota des API et accélérer les requêtes répétées.

Élément (id / clé)TypeRôle
Entrées valides — cache.entrieslectureAffiché « entrées / max » (cache.max_entries).
Hits / Misses / Évictions — cache.hits / misses / evictionslectureStatistiques du cache.
Hit ratio — cache.hit_ratio_pctlectureTaux de succès en %. La carte n'apparaît que si cache.enabled est vrai.
Bouton Vider le cacheboutonGET /cache/clear (après confirmation) puis rafraîchit. Immédiat

Carte « Sécurité »

État des protections (lecture) et whitelist de destinations éditable. Champs sous security dans /state.

Élément (id / clé)TypeRôle
Whitelist destinations — security.whitelist_enabledlecture« ✓ Activée » ou « Désactivée ». Si activée, le proxy refuse toute cible hors liste.
HMAC Guardian↔Proxy — security.hmac_enabledlecture« ✓ Activé » ou « Désactivé (mode compat) ». Signature partagée des requêtes.
Hosts par défaut — sec_wl_defaultsecurity.whitelist_defaultlectureListe figée (un host par ligne) compilée dans le firmware ; non modifiable ici.
Hosts custom — sec_wl_extrasecurity.whitelist_extraliste éditableVos ajouts, supprimables d'un clic sur « ✕ ».
Champ d'ajout — wl_add_in + bouton AjoutertexteValide le format ([a-z0-9.-] + au moins un point) et empile le host en mémoire client.
Bouton Enregistrer la whitelistboutonPOST /setconfig (corps whitelist_extra=<csv>). Immédiat

Suffixe accepté. « exemple.com » autorise aussi « api.exemple.com ». Les hosts par défaut restent toujours autorisés et ne se modifient pas depuis l'interface.

Carte « Relais cloud (accès distant) »

opt-in Permet de consulter l'état du proxy depuis l'app companion hors du domicile. Lecture seule, chiffré bout-en-bout (AES-256-GCM), zero-knowledge : le serveur ne stocke que des blobs opaques. Désactivé par défaut.

Élément (id / clé)TypeRôle
Activer le relais cloud — cloud_enabledcaseActive l'envoi périodique de l'instantané chiffré. Désactiver arrête tout envoi.
URL du relais — cloud_ingest_urltexte (92)Worker Cloudflare officiel par défaut ; modifiable si vous hébergez votre propre instance.
Clé E2E appairée — cl_claimedcloud_claimedlecture« Oui » une fois l'app appairée.
Envois réussis — cl_countcloud_push_countlectureCompteur de snapshots transmis.
Dernier code — cl_statuscloud_last_statuslectureCode HTTP du dernier envoi (« ✓ » si 2xx, « (en attente) » si négatif).
Bouton EnregistrerboutonGET /setcloud?enabled=&ingest_url=. Immédiat
Bouton Tester l'envoiboutonGET /cloud/test{ok, http} ; affiche le code HTTP obtenu.

Confidentialité. Aucune donnée personnelle dans le snapshot ; l'identifiant est un hash SHA-256 irréversible de la MAC. La clé de chiffrement ne quitte le réseau local qu'au profit de l'app appairée. Code du relais open-source.

Carte « Système »

Champ (clé /state)Rôle
Boot count — boot_countNombre de démarrages cumulés.
Dernière cause reset — last_resetRaison du dernier redémarrage (Power-on, WDT, panic…).
Modèle puce — chip_model (+ chip_cores)Ex. « ESP32-S3 (2 cores) ».
SDK — sdk_versionVersion ESP-IDF embarquée.

Carte « Service » & actions

Rappel du rôle (endpoint principal POST /proxy et découverte mDNS) puis les boutons d'action.

BoutonTypeAction
Voir /state JSONlienOuvre /state (le JSON brut qui alimente la page).
Voir logslienOuvre /log — ring buffer texte (128 lignes max).
Mettre à jourboutonOuvre la modale OTA (voir ci-dessous).
OTA USBlienOuvre /update — téléversement manuel d'un binaire par le navigateur.
RedémarrerboutonGET /restart après confirmation. Reboot
Factory resetboutonPOST /factoryreset après confirmation : efface la config (Wi-Fi, whitelist, cloud) et redémarre en mode AP. Reboot

Découverte mDNS. Le proxy publie le service SolarMeshLabs._tcp (port 80) avec le TXT fonction=proxy. Un Guardian dont l'option « proxy auto-discover » est active le détecte et l'utilise sans configuration.

Modale « Mise à jour firmware » (OTA)

Le bouton Mettre à jour ouvre une modale qui interroge le manifest GitHub puis pilote le téléchargement / flash.

ÉtapeEndpointRôle
PréflightGET /ota/preflightConservé pour parité d'API ; le proxy ne se proxifie pas lui-même (stub).
VérificationGET /ota/checkRenvoie state_label = available / uptodate / error, versions, changelog, tailles, need_fw / need_fs.
ApplicationPOST /ota/applyLance le pipeline (téléchargement + flash + reboot automatique).
SuiviGET /ota/status + SSE /events (ota_status)Polling 5 s + flux temps réel pendant la barre de progression (countdown 180 s).

Pendant la mise à jour. Ne pas couper l'alimentation : le redémarrage est automatique. Après coup, vider le cache du navigateur (Ctrl+F5 / Cmd+Shift+R) pour recharger la nouvelle interface.

Page « Configuration AP » (mode point d'accès)

Accès : automatique au premier démarrage (ou après un factory reset), quand aucun Wi-Fi n'est enregistré. Le proxy crée un réseau ouvert WATT-PROXY-xxxx et sert un assistant en une seule étape.

Champ (id)TypeRôle
Réseau Wi-Fi (SSID) — ssidtexte (requis)Nom du réseau domestique à rejoindre.
Mot de passe — passmot de passeLaisser vide pour un réseau ouvert.
Bouton Connecter et redémarrerboutonPOST /setwifi (FormData ssid + pass) → écrit /wifi.json et redémarre. Reboot
Sélecteur de langue — lang_selectlisteFR · EN, comme sur la page d'état.

L'en-tête affiche FW<n> · MAC (clés fw_build / mac) et le bloc d'aide rappelle le nom mDNS attendu (<name>.local) une fois la connexion établie. Un message vert confirme l'enregistrement ; un message rouge signale l'erreur (SSID manquant, réseau injoignable).

Après connexion. Le proxy quitte le mode AP, rejoint votre réseau, et se retrouve par mDNS (watt-proxy-xxxx.local) ou dans la liste des appareils du routeur. Le Guardian le redécouvre automatiquement.

Annexe — l'endpoint POST /proxy

Le cœur métier n'est pas dans l'interface mais dans cet endpoint, appelé par les autres modules. Il reçoit une requête à exécuter et renvoie la réponse de la cible.

SensChampRôle
RequêteurlCible HTTPS (obligatoire).
Requêtemethod · headers · bodyOptionnels (défaut GET) ; body utilisé pour POST/PUT.
Requêtetimeout_msOptionnel, défaut 8000, max 30000.
Réponseok · http_code · body · ms_elapsedSuccès + code HTTP cible + corps brut + durée ; en échec, ok:false + error.

Pourquoi un proxy ? Ouvrir un handshake TLS coûte ~30 KB de heap contigu — fatal sur un TTGO ESP32 ou un ESP8266. L'ESP32-S3 du proxy route ses buffers mbedtls dans sa PSRAM : le handshake devient quasi gratuit côté heap interne, et les modules « clients » restent stables.