Browse Source

Ajout doc pour la chauffe + corrections qq bugs

master
scayac 2 months ago
parent
commit
423bb6beff
  1. 205
      data/index.html
  2. 56
      src/main.cpp

205
data/index.html

@ -148,6 +148,17 @@ @@ -148,6 +148,17 @@
color: white;
}
.mode-btn.secondary {
background: #95a5a6;
border-color: #95a5a6;
color: white;
}
.mode-btn.secondary:hover {
background: #7f8c8d;
border-color: #7f8c8d;
}
.data-card.solar {
background: linear-gradient(135deg, #ffeaa7 0%, #fdcb6e 100%);
}
@ -233,6 +244,92 @@ @@ -233,6 +244,92 @@
flex-wrap: wrap;
margin-top: 20px;
}
.help-icon {
display: inline-block;
width: 24px;
height: 24px;
border-radius: 50%;
background: #667eea;
color: white;
text-align: center;
line-height: 24px;
cursor: pointer;
font-size: 16px;
font-weight: bold;
margin-left: 10px;
transition: background 0.3s;
}
.help-icon:hover {
background: #764ba2;
}
.help-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
z-index: 1000;
justify-content: center;
align-items: center;
}
.help-modal.show {
display: flex;
}
.help-content {
background: white;
padding: 30px;
border-radius: 10px;
max-width: 600px;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
}
.help-content h3 {
color: #667eea;
margin-top: 0;
margin-bottom: 20px;
}
.help-content .mode-item {
margin-bottom: 20px;
padding: 15px;
background: #f5f7fa;
border-radius: 5px;
border-left: 4px solid #667eea;
}
.help-content .mode-title {
font-weight: bold;
font-size: 16px;
color: #333;
margin-bottom: 8px;
}
.help-content .mode-desc {
color: #555;
line-height: 1.6;
}
.close-help {
float: right;
font-size: 28px;
font-weight: bold;
color: #aaa;
cursor: pointer;
line-height: 20px;
}
.close-help:hover {
color: #333;
}
</style>
</head>
<body>
@ -291,7 +388,7 @@ @@ -291,7 +388,7 @@
</div>
</div>
<h2>🎛 Mode de Fonctionnement</h2>
<h2>🎛 Mode de Fonctionnement <span class="help-icon" onclick="toggleHelp()">?</span></h2>
<div class="mode-selector">
<button class="mode-btn" data-bit="16" onclick="toggleMode(16)">🟢 ON</button>
<button class="mode-btn" data-bit="8" onclick="toggleMode(8)">🌙 NUIT</button>
@ -307,9 +404,92 @@ @@ -307,9 +404,92 @@
</div>
</div>
<!-- Modal d'aide -->
<div id="helpModal" class="help-modal" onclick="closeHelp(event)">
<div class="help-content" onclick="event.stopPropagation()">
<span class="close-help" onclick="toggleHelp()">&times;</span>
<h3>📖 Guide des Modes de Chauffe</h3>
<div class="mode-item">
<div class="mode-title">🟢 Mode ON</div>
<div class="mode-desc">
Le chauffe-eau fonctionne à pleine puissance en permanence, indépendamment de la production solaire.
</div>
</div>
<div class="mode-item">
<div class="mode-title">🔴 Mode OFF</div>
<div class="mode-desc">
Le chauffe-eau est complètement désactivé. Aucune chauffe n'est effectuée.
</div>
</div>
<div class="mode-item">
<div class="mode-title">🌙 Mode NUIT</div>
<div class="mode-desc">
Active le chauffage entre <span id="nightHoursHelp">0h - 4h</span> pour atteindre
la température minimale configurée de <span id="minTempHelp">40°C</span>.<br/>(Ces valeurs peuvent être modifiées dans les paramètres)
</div>
</div>
<div class="mode-item">
<div class="mode-title"> Mode SOLEIL</div>
<div class="mode-desc">
Utilise uniquement l'excédent de production solaire pour chauffer l'eau. La puissance de chauffe
s'ajuste automatiquement en fonction de la production solaire disponible. Optimise l'autoconsommation.
</div>
</div>
<div class="mode-item">
<div class="mode-title">☼ Mode JOUR</div>
<div class="mode-desc">
Chauffe intelligemment pendant les heures d'ensoleillement (lever à coucher du soleil) pour atteindre
la température maximale configurée de<span id="maxTempHelp">60°C</span> à l'heure cible. La puissance est calculée en fonction du temps
restant et de l'écart de température. Le chauffage s'arrête automatiquement une fois la température
maximale atteinte jusqu'au lendemain. <em>(Le bouton devient gris quand la température max est atteinte)</em>
</div>
</div>
<div class="mode-item">
<div class="mode-title">🔄 Combinaisons</div>
<div class="mode-desc">
Vous pouvez combiner les modes NUIT, SOLEIL et JOUR pour une gestion optimale :
<ul style="margin: 10px 0 0 20px;">
<li><strong>NUIT + SOLEIL</strong> : Maintien nocturne + optimisation solaire diurne</li>
<li><strong>NUIT + JOUR</strong> : Maintien nocturne + chauffe intelligente diurne</li>
<li><strong>SOLEIL + JOUR</strong> : Utilise l'excédent + planifie la chauffe</li>
<li><strong>NUIT + SOLEIL + JOUR</strong> : Combinaison complète pour un fonctionnement 24h/24</li>
</ul>
</div>
</div>
</div>
</div>
<script>
let refreshInterval;
let currentMode = 0; // Mode par défaut (OFF)
let configNightStart = 0;
let configNightEnd = 4;
let configMinTemp = 40;
let configMaxTemp = 60;
function toggleHelp() {
const modal = document.getElementById('helpModal');
modal.classList.toggle('show');
// Mettre à jour les heures affichées dans le modal
if (modal.classList.contains('show')) {
document.getElementById('nightHoursHelp').textContent =
configNightStart + 'h - ' + configNightEnd + 'h';
document.getElementById('minTempHelp').textContent = configMinTemp + '°C';
document.getElementById('maxTempHelp').textContent = configMaxTemp + '°C';
}
}
function closeHelp(event) {
if (event.target.id === 'helpModal') {
toggleHelp();
}
}
function showError(message) {
const statusDot = document.getElementById('statusDot');
@ -456,6 +636,29 @@ @@ -456,6 +636,29 @@
// Mettre à jour le flag global d'erreur Enphase
window.enphaseConnectionError = !!data.enphase_connection_error;
updateStatusBar();
// Mettre à jour les heures de configuration
if (data.night_start_hour !== undefined) {
configNightStart = data.night_start_hour;
}
if (data.night_end_hour !== undefined) {
configNightEnd = data.night_end_hour;
}
if (data.min_water_temp !== undefined) {
configMinTemp = data.min_water_temp;
}
if (data.max_water_temp !== undefined) {
configMaxTemp = data.max_water_temp;
}
// Mettre à jour le style du bouton JOUR si maxTempReachedToday
const jourBtn = document.querySelector('[data-bit="2"]');
if (data.max_temp_reached_today && jourBtn.classList.contains('active')) {
jourBtn.classList.add('secondary');
} else {
jourBtn.classList.remove('secondary');
}
document.getElementById('dataDisplay').style.display = 'block';
// Mettre à jour la production solaire

56
src/main.cpp

@ -217,6 +217,10 @@ bool loadAuthConfig() { @@ -217,6 +217,10 @@ bool loadAuthConfig() {
if (doc["system"]["night_end_hour"]) {
nightEndHour = doc["system"]["night_end_hour"].as<int>();
}
if (doc["system"]["operating_mode"]) {
operatingMode = doc["system"]["operating_mode"].as<int>();
Serial.printf("[CONFIG] Mode de fonctionnement chargé: %d\n", operatingMode);
}
}
// Charger les paramètres Enphase si disponibles
@ -496,8 +500,9 @@ void calculateHeaterPower() { @@ -496,8 +500,9 @@ void calculateHeaterPower() {
}
// Calculer l'excédent solaire et ajuster le pourcentage de chauffe
float solarExcess = solarProduction - powerConsumption;
int calculatedHeaterPowerJour, calculatedHeaterPowerSoleil = 0;
float solarExcess = 0;
int calculatedHeaterPowerJour = 0;
int calculatedHeaterPowerSoleil = 0;
int calculatedHeaterPower = heaterPower;
// Extraire les bits du mode
@ -572,6 +577,10 @@ void calculateHeaterPower() { @@ -572,6 +577,10 @@ void calculateHeaterPower() {
}
if (modeSOLEIL) {
//Calculer l'excédent solaire
solarExcess = solarProduction - powerConsumption;
// Mode SOLEIL: ajuster selon l'excédent solaire
if (solarExcess > 0) {
// Convertir l'excédent solaire en pourcentage (max = puissance max du chauffe-eau)
@ -785,6 +794,7 @@ void setup() { @@ -785,6 +794,7 @@ void setup() {
doc["system"]["longitude"] = longitude;
doc["system"]["night_start_hour"] = nightStartHour;
doc["system"]["night_end_hour"] = nightEndHour;
doc["system"]["operating_mode"] = operatingMode;
doc["enphase"]["gateway_ip"] = enphaseGatewayIP;
doc["enphase"]["token"] = enphaseToken;
doc["enphase"]["update_interval"] = enphaseUpdateInterval;
@ -1088,6 +1098,11 @@ void setup() { @@ -1088,6 +1098,11 @@ void setup() {
doc["sunset_time"] = sunsetTime;
doc["timestamp"] = millis();
doc["enphase_connection_error"] = enphaseConnectionError;
doc["max_temp_reached_today"] = maxTempReachedToday;
doc["night_start_hour"] = nightStartHour;
doc["night_end_hour"] = nightEndHour;
doc["min_water_temp"] = minWaterTemp;
doc["max_water_temp"] = maxWaterTemp;
String response;
serializeJson(doc, response);
request->send(200, "application/json", response);
@ -1220,6 +1235,25 @@ void setup() { @@ -1220,6 +1235,25 @@ void setup() {
if (newMode >= 0 && newMode <= 31) {
operatingMode = newMode;
Serial.printf("[MODE] Mode changé via GET: %d\n", operatingMode);
// Sauvegarder le mode dans la configuration
File configFile = LittleFS.open("/config.json", "r");
if (configFile) {
JsonDocument configDoc;
DeserializationError error = deserializeJson(configDoc, configFile);
configFile.close();
if (!error) {
configDoc["system"]["operating_mode"] = operatingMode;
configFile = LittleFS.open("/config.json", "w");
if (configFile) {
serializeJsonPretty(configDoc, configFile);
configFile.close();
Serial.println("[MODE] Mode sauvegardé dans la configuration");
}
}
}
request->send(200, "text/plain", "OK");
} else {
request->send(400, "text/plain", "Mode invalide (0-31)");
@ -1275,6 +1309,24 @@ void setup() { @@ -1275,6 +1309,24 @@ void setup() {
operatingMode = newMode;
Serial.printf("[MODE] Mode changé: %d\n", operatingMode);
// Sauvegarder le mode dans la configuration
File configFile = LittleFS.open("/config.json", "r");
if (configFile) {
JsonDocument configDoc;
DeserializationError error = deserializeJson(configDoc, configFile);
configFile.close();
if (!error) {
configDoc["system"]["operating_mode"] = operatingMode;
configFile = LittleFS.open("/config.json", "w");
if (configFile) {
serializeJsonPretty(configDoc, configFile);
configFile.close();
Serial.println("[MODE] Mode sauvegardé dans la configuration");
}
}
}
JsonDocument responseDoc;
responseDoc["success"] = true;
responseDoc["mode"] = operatingMode;

Loading…
Cancel
Save