Browse Source

Réactualisation interface reload

master
scayac 2 days ago
parent
commit
3c70f2c0a1
  1. 76
      data/app.js
  2. 6
      data/index.html
  3. 39
      src/main.cpp

76
data/app.js

@ -18,6 +18,34 @@ function connectWS() { @@ -18,6 +18,34 @@ function connectWS() {
powerBar.value = pct;
powerBarValue.textContent = pct + '%';
}
// Mettre à jour l'état des boutons selon le mode (manuel/auto)
if (typeof data.auto !== 'undefined' || typeof data.manual !== 'undefined') {
try {
updateButton(btnPreheat, !!data.manual);
updateButton(btnProfil, !!data.auto);
} catch (e) {
// ignore si les boutons ne sont pas encore disponibles
}
}
// Si mode automatique, appliquer la classe 'active' sur la row correspondante
if (typeof data.step !== 'undefined') {
const mapping = {0: 'row-preheat', 1: 'row-soak', 2: 'row-reflow'};
// Retirer la classe active de toutes
Object.values(mapping).forEach(id => {
const el = document.getElementById(id);
if (el) el.classList.remove('active');
});
// Si auto activé, ajouter la classe sur la step active
if (data.auto) {
const target = mapping[data.step];
if (target) {
const el = document.getElementById(target);
if (el) el.classList.add('active');
}
}
}
} catch {
if (tempDiv) tempDiv.textContent = e.data;
}
@ -26,6 +54,47 @@ function connectWS() { @@ -26,6 +54,47 @@ function connectWS() {
connectWS();
// Récupérer l'état initial depuis le serveur (après reload de la page)
function refreshState() {
fetch('/state').then(r => {
if (!r.ok) throw new Error('no state');
return r.json();
}).then(data => {
const btnPreheatEl = document.getElementById('validateChauffeManuelle');
const btnProfilEl = document.getElementById('validateChauffeAuto');
if (btnPreheatEl) updateButton(btnPreheatEl, !!data.manual);
if (btnProfilEl) updateButton(btnProfilEl, !!data.auto);
const powerBar = document.getElementById('power-bar');
const powerBarValue = document.getElementById('power-bar-value');
if (powerBar && typeof data.power !== 'undefined') {
let pct = Math.max(0, Math.min(100, Math.round(data.power)));
powerBar.value = pct;
if (powerBarValue) powerBarValue.textContent = pct + '%';
}
// Ajuster la jauge de préchauffage sur la valeur de setpoint si présente
const gauge = document.getElementById('preheat-gauge');
const gaugeValue = document.getElementById('preheat-gauge-value');
if (gauge && gaugeValue && typeof data.setpoint !== 'undefined') {
gauge.value = Math.round(data.setpoint);
gaugeValue.textContent = gauge.value + '°C';
}
// Gérer la classe 'active' sur les lignes (si mode auto)
const mapping = {0: 'row-preheat', 1: 'row-soak', 2: 'row-reflow'};
Object.values(mapping).forEach(id => {
const el = document.getElementById(id);
if (el) el.classList.remove('active');
});
if (data.auto && typeof data.step !== 'undefined') {
const target = mapping[data.step];
if (target) {
const el = document.getElementById(target);
if (el) el.classList.add('active');
}
}
}).catch(err => console.log('refreshState failed', err));
}
// Fonction utilitaire pour modifier l'aspect d'un bouton
function updateButton(btn, isActive) {
if (isActive) {
@ -37,9 +106,8 @@ function updateButton(btn, isActive) { @@ -37,9 +106,8 @@ function updateButton(btn, isActive) {
}
}
// Initialisation : aucun mode actif
updateButton(btnPreheat, false);
updateButton(btnProfil, false);
// L'état initial est chargé depuis le serveur
btnPreheat.onclick = function() {
if (btnPreheat.className === 'stop') {
@ -124,4 +192,6 @@ document.addEventListener('DOMContentLoaded', () => { @@ -124,4 +192,6 @@ document.addEventListener('DOMContentLoaded', () => {
}
};
}
// Après que le DOM est prêt, récupérer et appliquer l'état initial
refreshState();
});

6
data/index.html

@ -26,17 +26,17 @@ @@ -26,17 +26,17 @@
</div>
<div class="phase" id="chauffe-auto">
<h4>Chauffe automatique : <span id="auto-time"></span></h4>
<div class="row active">
<div class="row" id="row-preheat">
<label style="width: 65px; display: inline-block;">Preheat : </label>
<input type="number" id="preheat-temp" value="150" min="0" max="300">°C
<input type="number" id="preheat-time" value="180" min="1" max="600">s
</div>
<div class="row">
<div class="row" id="row-soak">
<label style="width: 65px; display: inline-block;">Soak :</label>
<input type="number" id="soak-temp" value="180" min="0" max="300">°C
<input type="number" id="soak-time" value="120" min="1" max="600">s
</div>
<div class="row">
<div class="row" id="row-reflow">
<label style="width: 65px; display: inline-block;">Reflow : </label>
<input type="number" id="reflow-temp" value="230" min="0" max="300">°C
<input type="number" id="reflow-time" value="60" min="1" max="600">s

39
src/main.cpp

@ -28,6 +28,7 @@ int preheatTemp = 0, preheatTime = 0; @@ -28,6 +28,7 @@ int preheatTemp = 0, preheatTime = 0;
int soakTemp = 0, soakTime = 0;
int reflowTemp = 0, reflowTime = 0;
bool autoProfileActive = false;
bool manualPreheatActive = false;
unsigned long profileStartTime = 0;
int profileStep = 0;
@ -134,6 +135,7 @@ void setup() { @@ -134,6 +135,7 @@ void setup() {
server.on("/action/stop", HTTP_POST, [](AsyncWebServerRequest *request){
setpoint = 0;
autoProfileActive = false;
manualPreheatActive = false;
profileStep = 0;
Serial.println("Arrêt demandé : setpoint PID à 0°C");
request->send(200, "text/plain", "OK");
@ -152,6 +154,7 @@ void setup() { @@ -152,6 +154,7 @@ void setup() {
Serial.println("Mode automatique désactivé (chauffe manuelle)");
}
setpoint = request->arg("temp").toDouble();
manualPreheatActive = true;
Serial.printf("Chauffe manuelle demandée : %.1f°C (setpoint PID fixé)\n", setpoint);
request->send(200, "text/plain", "OK");
});
@ -172,6 +175,7 @@ void setup() { @@ -172,6 +175,7 @@ void setup() {
reflowTime = request->arg("reflowTime").toInt();
// Démarrage du profil automatique
autoProfileActive = true;
manualPreheatActive = false;
profileStep = 0;
profileStartTime = millis();
setpoint = preheatTemp;
@ -180,6 +184,32 @@ void setup() { @@ -180,6 +184,32 @@ void setup() {
request->send(200, "text/plain", "OK");
});
// Endpoint pour renvoyer l'état actuel (utile pour réactualiser l'UI après reload)
server.on("/state", HTTP_GET, [](AsyncWebServerRequest *request){
int pct = 0;
if (output > 0) {
pct = (int)round((output * 100) / PWM_PERIOD);
if (pct > 100) pct = 100;
if (pct < 0) pct = 0;
}
int preheatProgress = 0;
if (autoProfileActive && profileStep == 0 && preheatTime > 0) {
unsigned long elapsed = (millis() - profileStartTime) / 1000;
unsigned long prog = (elapsed * 100UL) / (unsigned long)preheatTime;
if (prog > 100) prog = 100;
preheatProgress = (int)prog;
}
String json = String("{")
+ "\"manual\":" + (manualPreheatActive ? "true" : "false")
+ ",\"auto\":" + (autoProfileActive ? "true" : "false")
+ ",\"power\":" + String(pct)
+ ",\"setpoint\":" + String(setpoint, 1)
+ ",\"preheatProgress\":" + String(preheatProgress)
+ ",\"step\":" + String(profileStep)
+ "}";
request->send(200, "application/json", json);
});
// Connexion WiFi ou démarrage AP si ssid/pwd vides
if (strlen(ssid) == 0 || strlen(password) == 0) {
Serial.println("SSID ou mot de passe vide, démarrage en mode AP");
@ -299,6 +329,7 @@ void loop() { @@ -299,6 +329,7 @@ void loop() {
if (elapsed >= (unsigned long)reflowTime) {
profileStep = 3;
autoProfileActive = false;
setpoint = 0; // Reflow terminé -> couper la chauffe
Serial.println("Profil terminé");
}
}
@ -328,7 +359,13 @@ void loop() { @@ -328,7 +359,13 @@ void loop() {
pct = (int)round((output * 100) / PWM_PERIOD);
if (pct > 100) pct = 100;
}
String json = String("{\"temp\":") + String(input, 1) + ",\"setpoint\":" + String(setpoint, 1) + ",\"output\":" + String(pct) + "}";
String json = String("{\"temp\":") + String(input, 1)
+ ",\"setpoint\":" + String(setpoint, 1)
+ ",\"output\":" + String(pct)
+ ",\"manual\":" + (manualPreheatActive ? "true" : "false")
+ ",\"auto\":" + (autoProfileActive ? "true" : "false")
+ ",\"step\":" + String(profileStep)
+ "}";
Serial.println("Température: " + String(input, 1) + " °C | Setpoint: " + String(setpoint, 1) + " | Output PID: " + String(output) + " | Puissance: " + String(pct) + "%");
ws.textAll(json);
}

Loading…
Cancel
Save