566 lines
24 KiB
Arduino
566 lines
24 KiB
Arduino
|
|
||
|
void handleRoot() {
|
||
|
String html = "<html><head><script src='https://code.jquery.com/jquery-3.6.4.min.js'></script>";
|
||
|
html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"/css\">";
|
||
|
html += "<link rel='stylesheet' href='https://unpkg.com/purecss@0.6.2/build/pure-min.css'>";
|
||
|
html += "<title>powerMC (ESP32) "+String(FIRMWARE_VERSION)+"</title></head>";
|
||
|
html += "<body><h1>powerMC (ESP32) "+String(FIRMWARE_VERSION)+"</h1>";
|
||
|
|
||
|
html += "<table><tr><td>";
|
||
|
|
||
|
html += "<p><a href='"+cs_jsonPath+"'>JSON Daten</a></p><br>";
|
||
|
html += "<p><a href='"+cs_demoMode1Path+"'>Start demo mode charge and discharge</a></p>";
|
||
|
html += "<p><a href='"+cs_demoMode2Path+"'>Start demo mode charge to max</a></p>";
|
||
|
html += "<p><a href='"+cs_demoMode3Path+"'>Start demo mode discharge to zero</a></p><br>";
|
||
|
html += "<p><a href='"+cs_resetESPPath+"'>Reset ESP32</a></p>";
|
||
|
html += "<p><a href='"+cs_resetWifiPath+"'>Reset Wifi settings</a></p><br>";
|
||
|
html += "<p><a href='"+cs_checkUpdatePath+"'>Firmware update</a></p><br>";
|
||
|
html += "<p><a href='"+cs_configPath+"'>Config</a></p>";
|
||
|
|
||
|
html += "</td><td> </td><td>";
|
||
|
|
||
|
html += "<p id='busVoltage'>Busvoltage: <span id='busVoltageValue'>0</span> V</p>";
|
||
|
html += "<p id='shuntVoltage'>Shuntvoltage: <span id='shuntVoltageValue'>0</span> V</p>";
|
||
|
html += "<p id='current'>Strom: <span id='currentValue'>0</span> A</p>";
|
||
|
html += "<p id='power'>Leistung: <span id='powerValue'>0</span> W</p>";
|
||
|
html += "<p id='energy'>Energie: <span id='energyValue'>0</span> Wh</p>";
|
||
|
html += "<p id='temp'>Temp: <span id='tempValue'>0</span> °C</p>";
|
||
|
html += "<p id='humidity'>Humidity: <span id='humidityValue'>0</span> %</p>";
|
||
|
html += "<p>Shunt max voltage drop: <span>"+String(globalConfigData.shunt_voltage_drop,0)+"</span> mV</p>";
|
||
|
html += "<p>Shunt max current: <span>"+String(globalConfigData.shunt_max_current,0)+"</span> A</p>";
|
||
|
html += "<p>Current factor: <span>"+String(globalConfigData.current_fact/100,2)+" (div. by 100)</span></p>";
|
||
|
html += "<p>Max capacity: <span>"+String(globalConfigData.max_capacity,0)+"</span> Wh</p>";
|
||
|
html += "<p>Ina226 refresh period: <span>"+String(globalConfigData.time_ina226_refresh,0)+"</span> s</p>";
|
||
|
html += "<p id='errorCode'>Error code: <span id='error'>0</span></p>";
|
||
|
|
||
|
html += "</td></tr></table>";
|
||
|
|
||
|
html += "<script>";
|
||
|
|
||
|
html += "function showNotification(message, isSuccess) {";
|
||
|
html += " var notification = document.createElement('div');";
|
||
|
html += " notification.className = isSuccess ? 'success-notification' : 'error-notification';";
|
||
|
html += " notification.innerHTML = message;";
|
||
|
html += " document.body.appendChild(notification);";
|
||
|
html += " setTimeout(function() {";
|
||
|
html += " document.body.removeChild(notification);";
|
||
|
html += " }, 3000);";
|
||
|
html += "}";
|
||
|
|
||
|
html += "function updateValues() {";
|
||
|
html += "$.ajax({";
|
||
|
html += "url: '/json',";
|
||
|
html += "type: 'GET',";
|
||
|
html += "dataType: 'json',";
|
||
|
html += "success: function(data) {";
|
||
|
html += "$('#currentValue').text(data.current);";
|
||
|
html += "$('#powerValue').text(data.power);";
|
||
|
html += "$('#energyValue').text(data.energy);";
|
||
|
html += "$('#busVoltageValue').text(data.busVoltage);";
|
||
|
html += "$('#shuntVoltageValue').text(data.shuntVoltage);";
|
||
|
html += "$('#tempValue').text(data.temp.toFixed(2));";
|
||
|
html += "$('#humidityValue').text(data.humidity.toFixed(2));";
|
||
|
html += "$('#error').text('0b' + data.errorCode.toString(2).padStart(16, '0'));"; // Hier wird der errorCode als Binärzahl dargestellt
|
||
|
html += "},";
|
||
|
html += "error: function() {";
|
||
|
html += "console.log('Fehler beim Abrufen der Daten.');";
|
||
|
html += "}";
|
||
|
html += "});";
|
||
|
html += "}";
|
||
|
html += "updateValues();";
|
||
|
html += "setInterval(updateValues, " + String(LOOP_DISPLAY_DELAY_MS) + ");";
|
||
|
html += "</script></body></html>";
|
||
|
|
||
|
server.send(200, cs_textHtml, html);
|
||
|
}
|
||
|
|
||
|
void handleJson() {
|
||
|
// JSON-Daten aus globalen Variablen erstellen
|
||
|
DynamicJsonDocument doc(200);
|
||
|
doc[cs_busVoltageID] = globalBusVoltage;
|
||
|
doc[cs_shuntVoltageID] = globalShuntVoltage;
|
||
|
doc[cs_currentID] = globalCurrent;
|
||
|
doc[cs_powerID] = globalPower;
|
||
|
doc[cs_energyID] = globalEnergy;
|
||
|
doc[cs_tempID] = globalTemp;
|
||
|
doc[cs_humidityID] = globalHumidity;
|
||
|
doc[cs_errorCodeID] = globalErrorCode;
|
||
|
doc["shuntValue"] = globalShuntValue;
|
||
|
doc["ina226Status"] = ina226Status;
|
||
|
doc["ina226ShuntValue"] = ina226.getShunt();
|
||
|
doc["ina226AlertFlag"] = ina226.getAlertFlag();
|
||
|
doc["ina226AlertLimit"] = ina226.getAlertLimit();
|
||
|
doc["ina226CurrentLSB"] = ina226.getCurrentLSB();
|
||
|
|
||
|
String jsonData;
|
||
|
serializeJson(doc, jsonData);
|
||
|
|
||
|
server.send(200, cs_applicationJson, jsonData);
|
||
|
}
|
||
|
|
||
|
void handleConfig() {
|
||
|
String html = "<html><head>";
|
||
|
html += "<title>powerMC (ESP32) "+String(FIRMWARE_VERSION)+" - configuration</title>";
|
||
|
html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"/css\">";
|
||
|
html += "<link rel='stylesheet' href='https://unpkg.com/purecss@0.6.2/build/pure-min.css'>";
|
||
|
html += "</head>";
|
||
|
|
||
|
html += "<body><h1>powerMC (ESP32) "+String(FIRMWARE_VERSION)+" - configuration</h1>";
|
||
|
|
||
|
html += "<p><a href='"+cs_rootPath+"'>Main</a></p><br>";
|
||
|
|
||
|
html += "<form id=\"configForm\" action=\"/saveConfig\" method=\"post\">";
|
||
|
|
||
|
html += "<table>";
|
||
|
|
||
|
html += "<tr><td><label for=\"temp_min\">Max capacity:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"max_capacity\" name=\"max_capacity\" value=\"" + String(globalConfigData.max_capacity) + "\" min=\"2000\" max=\"10000\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"max_capacity_value\">" + String(globalConfigData.max_capacity, 0) + "</span>Wh</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"temp_min\">Shunt voltage drop:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"shunt_voltage_drop\" name=\"shunt_voltage_drop\" value=\"" + String(globalConfigData.shunt_voltage_drop) + "\" min=\"10\" max=\"85\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"shunt_voltage_drop_value\">" + String(globalConfigData.shunt_voltage_drop, 0) + "</span>mV</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"shunt_max_current\">Shunt current Max:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"shunt_max_current\" name=\"shunt_max_current\" value=\"" + String(globalConfigData.shunt_max_current) + "\" min=\"10\" max=\"200\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"shunt_max_current_value\">" + String(globalConfigData.shunt_max_current, 0) + "</span>A</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"temp_min\">Temperature Min:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"temp_min\" name=\"temp_min\" value=\"" + String(globalConfigData.temp_min) + "\" min=\"0\" max=\"100\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"temp_min_value\">" + String(globalConfigData.temp_min, 0) + "</span>°C</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"temp_max\">Temperature Max:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"temp_max\" name=\"temp_max\" value=\"" + String(globalConfigData.temp_max) + "\" min=\"0\" max=\"100\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"temp_max_value\">" + String(globalConfigData.temp_max, 0) + "</span>°C</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"humidity_min\">Himidity Min:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"humi_min\" name=\"humi_min\" value=\"" + String(globalConfigData.humi_min) + "\" min=\"0\" max=\"100\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"humi_min_value\">" + String(globalConfigData.humi_min, 0) + "</span>%</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"humidity_max\">Humidity Max:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"humi_max\" name=\"humi_max\" value=\"" + String(globalConfigData.humi_max) + "\" min=\"0\" max=\"100\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"humi_max_value\">" + String(globalConfigData.humi_max, 0) + "</span>%</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"current_min\">Current Min:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"current_min\" name=\"current_min\" value=\"" + String(globalConfigData.current_min) + "\" min=\"-100\" max=\"100\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"current_min_value\">" + String(globalConfigData.current_min, 0) + "</span>A</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"current_max\">Current Max:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"current_max\" name=\"current_max\" value=\"" + String(globalConfigData.current_max) + "\" min=\"-100\" max=\"100\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"current_max_value\">" + String(globalConfigData.current_max, 0) + "</span>A</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"current_fact\">Current correction factor:</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"current_fact\" name=\"current_fact\" value=\"" + String(globalConfigData.current_fact,0) + "\" min=\"1\" max=\"3000\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"current_fact_value\">" + String(globalConfigData.current_fact/100,2) + "</span>(div. by 100)</td></tr>";
|
||
|
|
||
|
html += "<tr><td><label for=\"time_ina226_refresh\">Ina226 update interval (s):</label></td><td> </td>";
|
||
|
html += "<td class=\"slider-container\"><input type=\"range\" id=\"time_ina226_refresh\" name=\"time_ina226_refresh\" value=\"" + String(globalConfigData.time_ina226_refresh,0) + "\" min=\"10\" max=\"120\" step=\"1\">";
|
||
|
html += "<span class=\"slider-value\" id=\"time_ina226_refresh_value\">" + String(globalConfigData.time_ina226_refresh,0) + "</span>sek.</td></tr>";
|
||
|
|
||
|
html += "</table><br>";
|
||
|
|
||
|
html += "<button type=\"button\" onclick=\"saveConfig()\">Save Config</button></form>";
|
||
|
html += "<button onclick=\"location.reload()\">Reset</button>";
|
||
|
|
||
|
html += "<div id=\"responseMessage\" style=\"display: none;\"></div>";
|
||
|
|
||
|
html += "<script>";
|
||
|
|
||
|
html += "function showNotification(message, isSuccess) {";
|
||
|
html += " var notification = document.createElement('div');";
|
||
|
html += " notification.className = isSuccess ? 'success-notification' : 'error-notification';";
|
||
|
html += " notification.innerHTML = message;";
|
||
|
html += " document.body.appendChild(notification);";
|
||
|
html += " setTimeout(function() {";
|
||
|
html += " document.body.removeChild(notification);";
|
||
|
html += " }, 3000);";
|
||
|
html += "}";
|
||
|
|
||
|
html += "function saveConfig() {var form = document.getElementById('configForm');";
|
||
|
html += "var formData = new FormData(form);";
|
||
|
html += "var jsonData = {};";
|
||
|
html += "formData.forEach(function(value, key){jsonData[key] = value;});";
|
||
|
html += "fetch('/saveConfig', {method: 'PUT',headers: {'Content-Type': 'application/json'},body: JSON.stringify(jsonData)})";
|
||
|
html += ".then(response => response.json())";
|
||
|
html += ".then(data => { showNotification('Successful saved config', data.message.toLowerCase() === 'ok'); })";
|
||
|
html += ".catch(error => { console.error('Error:', error); });}";
|
||
|
|
||
|
html += "document.getElementById('temp_min').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('temp_min_value').innerText = this.value;});";
|
||
|
html += "document.getElementById('temp_max').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('temp_max_value').innerText = this.value;});";
|
||
|
html += "document.getElementById('humi_min').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('humi_min_value').innerText = this.value;});";
|
||
|
html += "document.getElementById('humi_max').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('humi_max_value').innerText = this.value;});";
|
||
|
html += "document.getElementById('current_min').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('current_min_value').innerText = this.value;});";
|
||
|
html += "document.getElementById('current_max').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('current_max_value').innerText = this.value;});";
|
||
|
html += "document.getElementById('current_fact').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('current_fact_value').innerText = this.value / 100.0;});";
|
||
|
html += "document.getElementById('shunt_voltage_drop').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('shunt_voltage_drop_value').innerText = this.value;});";
|
||
|
html += "document.getElementById('shunt_max_current').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('shunt_max_current_value').innerText = this.value;});";
|
||
|
html += "document.getElementById('max_capacity').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('max_capacity_value').innerText = this.value;});";
|
||
|
html += "document.getElementById('time_ina226_refresh').addEventListener('input', function() {";
|
||
|
html += "document.getElementById('time_ina226_refresh_value').innerText = this.value;});";
|
||
|
|
||
|
html += "</script></body></html>";
|
||
|
|
||
|
server.send(200, cs_textHtml, html);
|
||
|
}
|
||
|
|
||
|
|
||
|
void handleSaveConfig() {
|
||
|
if (server.hasArg("plain")) {
|
||
|
|
||
|
Serial.println("Received new config data:");
|
||
|
Serial.println(server.arg("plain"));
|
||
|
|
||
|
// JSON-Payload analysieren
|
||
|
DynamicJsonDocument jsonDoc(1024);
|
||
|
deserializeJson(jsonDoc, server.arg("plain"));
|
||
|
|
||
|
// Parameter überprüfen und in die Konfiguration übertragen
|
||
|
if (jsonDoc.containsKey("temp_min")) {
|
||
|
float temp_min = jsonDoc["temp_min"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.temp_min = temp_min;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("temp_max")) {
|
||
|
float temp_max = jsonDoc["temp_max"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.temp_max = temp_max;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("humi_min")) {
|
||
|
float humi_min = jsonDoc["humi_min"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.humi_min = humi_min;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("humi_max")) {
|
||
|
float humi_max = jsonDoc["humi_max"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.humi_max = humi_max;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("current_min")) {
|
||
|
float current_min = jsonDoc["current_min"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.current_min = current_min;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("current_max")) {
|
||
|
float current_max = jsonDoc["current_max"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.current_max = current_max;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("shunt_voltage_drop")) {
|
||
|
float shunt_voltage_drop = jsonDoc["shunt_voltage_drop"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.shunt_voltage_drop = shunt_voltage_drop;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("shunt_max_current")) {
|
||
|
float shunt_max_current = jsonDoc["shunt_max_current"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.shunt_max_current = shunt_max_current;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("max_capacity")) {
|
||
|
float max_capacity = jsonDoc["max_capacity"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.max_capacity = max_capacity;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("time_ina226_refresh")) {
|
||
|
float time_ina226_refresh = jsonDoc["time_ina226_refresh"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.time_ina226_refresh = time_ina226_refresh;
|
||
|
}
|
||
|
|
||
|
if (jsonDoc.containsKey("current_fact")) {
|
||
|
float current_fact = jsonDoc["current_fact"];
|
||
|
// Hier prüfen und in die globale Konfiguration übertragen
|
||
|
globalConfigData.current_fact = current_fact;
|
||
|
}
|
||
|
|
||
|
writeConfigToEEPROM();
|
||
|
|
||
|
if (ina226.reset())
|
||
|
{
|
||
|
Serial.println("Ina226 reset");
|
||
|
configureIna226();
|
||
|
checkError();
|
||
|
} else {
|
||
|
Serial.println("Ina226 error: can't reset and reconfigure.");
|
||
|
}
|
||
|
|
||
|
// Schicke eine Bestätigung zurück
|
||
|
server.send(200, "application/json", "{\"message\": \"ok\"}");
|
||
|
} else {
|
||
|
// Ungültige Anfrage
|
||
|
server.send(400, "text/plain", "Invalid request");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void handleDemoMode1() {
|
||
|
demoMode1 = true;
|
||
|
demoMode2 = false;
|
||
|
demoMode3 = false;
|
||
|
globalBusVoltage = 25.6;
|
||
|
globalEnergy = globalConfigData.max_capacity / 2;
|
||
|
handleRoot();
|
||
|
}
|
||
|
|
||
|
void handleDemoMode2() {
|
||
|
demoMode1 = false;
|
||
|
demoMode2 = true;
|
||
|
demoMode3 = false;
|
||
|
globalBusVoltage = 25.6;
|
||
|
globalEnergy = globalConfigData.max_capacity * 0.97;
|
||
|
handleRoot();
|
||
|
}
|
||
|
|
||
|
void handleDemoMode3() {
|
||
|
demoMode1 = false;
|
||
|
demoMode2 = false;
|
||
|
demoMode3 = true;
|
||
|
globalBusVoltage = 25.6;
|
||
|
globalEnergy = globalConfigData.max_capacity * 0.03;
|
||
|
handleRoot();
|
||
|
}
|
||
|
|
||
|
void handleResetESP() {
|
||
|
|
||
|
String message = "<html><head><title>powerMC (ESP32) "+String(FIRMWARE_VERSION)+" - reset</title>"
|
||
|
"<script>setTimeout(function() { window.location.href = '/'; }, 10000);</script>"
|
||
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css\">"
|
||
|
"<link rel='stylesheet' href='https://unpkg.com/purecss@0.6.2/build/pure-min.css'>"
|
||
|
"</head><body><h1>powerMC (ESP32) "+String(FIRMWARE_VERSION)+" - reset</h1>"
|
||
|
"Rebooting...<br>"
|
||
|
"</body></html>";
|
||
|
|
||
|
server.send(200, cs_textHtml, message);
|
||
|
|
||
|
delay(5000);
|
||
|
|
||
|
// manual reset after restart is required
|
||
|
ESP.restart();
|
||
|
}
|
||
|
|
||
|
void handleResetWifi() {
|
||
|
|
||
|
String message = "<html><head><title>powerMC (ESP32) "+String(FIRMWARE_VERSION)+" - reset WiFi configuration</title>"
|
||
|
"<script>setTimeout(function() { window.location.href = '/'; }, 10000);</script>"
|
||
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css\">"
|
||
|
"<link rel='stylesheet' href='https://unpkg.com/purecss@0.6.2/build/pure-min.css'>"
|
||
|
"</head><body><h1>owerMC (ESP32) "+String(FIRMWARE_VERSION)+" - reset WiFi configuration</h1>"
|
||
|
"Reset WifiManager config, rebooting...<br>"
|
||
|
"</body></html>";
|
||
|
|
||
|
server.send(200, cs_textHtml, message);
|
||
|
|
||
|
// Erase WiFi Credentials, enable, compile, flash, disable and reflash.
|
||
|
wifiManager.resetSettings();
|
||
|
|
||
|
delay(5000);
|
||
|
|
||
|
// manual reset after restart is required
|
||
|
ESP.restart();
|
||
|
}
|
||
|
|
||
|
void handleUpdateFirmware() {
|
||
|
String message = "<html><head><title>powerMC (ESP32) " + String(FIRMWARE_VERSION) + " - firmware update</title>"
|
||
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css\">"
|
||
|
"<link rel='stylesheet' href='https://unpkg.com/purecss@0.6.2/build/pure-min.css'>"
|
||
|
"</head><body><h1>powerMC (ESP32) " + String(FIRMWARE_VERSION) + " - firmware update</h1>"
|
||
|
"<p><a href='"+cs_rootPath+"'>Main</a></p><br>"
|
||
|
"<button onclick='window.location.href=\"/updateFirmwareAction\";'>Update Firmware</button>"
|
||
|
"</body></html>";
|
||
|
|
||
|
server.send(200, cs_textHtml, message);
|
||
|
}
|
||
|
|
||
|
void handleUpdateFirmwareAction() {
|
||
|
|
||
|
if (fwUpdate_isRunning)
|
||
|
{
|
||
|
Serial.println("Firmware-Update is running...");
|
||
|
if (updateStatus == "") {
|
||
|
updateStatus = "Firmware-Update is running...<br>";
|
||
|
}
|
||
|
server.send(200, cs_textHtml, updateStatus);
|
||
|
} else {
|
||
|
|
||
|
String message = "<html><head><title>powerMC (ESP32) " + String(FIRMWARE_VERSION) + " - firmware update</title>"
|
||
|
"<script>"
|
||
|
"function readUpdateFirmwareStatus() {"
|
||
|
" var xhr = new XMLHttpRequest();"
|
||
|
" xhr.onreadystatechange = function() {"
|
||
|
" if (xhr.readyState == 4) {"
|
||
|
" document.getElementById('updateStatus').innerHTML = xhr.responseText;"
|
||
|
" if (xhr.responseText.includes('Firmware update successful')) { "
|
||
|
" setTimeout(function() { "
|
||
|
" window.location.href = '" + cs_resetESPPath + "'; "
|
||
|
" }, 5000); }"
|
||
|
" }"
|
||
|
" };"
|
||
|
" xhr.timeout = 1000;"
|
||
|
" xhr.open('GET', '/readUpdateFirmwareStatus', true);"
|
||
|
" xhr.send();"
|
||
|
"}"
|
||
|
"setInterval(readUpdateFirmwareStatus, 2000);"
|
||
|
"</script>"
|
||
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css\">"
|
||
|
"<link rel='stylesheet' href='https://unpkg.com/purecss@0.6.2/build/pure-min.css'>"
|
||
|
"</head><body><h1>powerMC (ESP32) " + String(FIRMWARE_VERSION) + " - firmware update</h1><br>"
|
||
|
"<p>Updating...</p>"
|
||
|
"<div id='updateStatus'></div>"
|
||
|
"</body></html>";
|
||
|
|
||
|
server.send(200, cs_textHtml, message);
|
||
|
|
||
|
disableWatchdog();
|
||
|
|
||
|
updateStatus = "";
|
||
|
|
||
|
Serial.print(cs_startingFirmwareUpdate);
|
||
|
ESPhttpUpdate.rebootOnUpdate(false);
|
||
|
t_httpUpdate_return ret = ESPhttpUpdate.update(String(FIRMWARE_UPDATE_URL));
|
||
|
fwUpdate_isRunning = true;
|
||
|
|
||
|
Serial.println(cs_finish);
|
||
|
|
||
|
switch (ret) {
|
||
|
case HTTP_UPDATE_FAILED:
|
||
|
Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
|
||
|
updateStatus = "<b>Firmware-Update failed.</b><br>";
|
||
|
updateStatus += "<b>Last error: "+String(ESPhttpUpdate.getLastError())+"</b><br>";
|
||
|
updateStatus += "<b>Last error message: "+ESPhttpUpdate.getLastErrorString()+"</b><br>";
|
||
|
fwUpdate_isRunning = false;
|
||
|
enableWatchdog();
|
||
|
break;
|
||
|
|
||
|
case HTTP_UPDATE_NO_UPDATES:
|
||
|
Serial.println(cs_noUpdatesAvailable);
|
||
|
updateStatus = "<b>No Updates available.</b><br>";
|
||
|
fwUpdate_isRunning = false;
|
||
|
enableWatchdog();
|
||
|
break;
|
||
|
|
||
|
case HTTP_UPDATE_OK:
|
||
|
Serial.println(cs_fwUpdSuccess);
|
||
|
updateStatus = "<b>Firmware update successful, resetting in a few seconds.</b><br>";
|
||
|
fwUpdate_isRunning = false;
|
||
|
break;
|
||
|
|
||
|
default: // other
|
||
|
Serial.println(cs_unknownStatus);
|
||
|
updateStatus = "<b>Unknown status.</b><br>";
|
||
|
fwUpdate_isRunning = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void handleReadUpdateFirmwareStatus() {
|
||
|
if (fwUpdate_isRunning)
|
||
|
{
|
||
|
Serial.println(cs_fwUpdRunning);
|
||
|
if (updateStatus == "") {
|
||
|
updateStatus = "Firmware-Update is running...<br>";
|
||
|
}
|
||
|
}
|
||
|
server.send(200, cs_textHtml, updateStatus);
|
||
|
}
|
||
|
|
||
|
void handleCSS() {
|
||
|
// "<link rel="stylesheet" type="text/css" href="/css">"
|
||
|
String customCSS = R"(
|
||
|
body {
|
||
|
font-family: Arial, sans-serif;
|
||
|
margin: 20px;
|
||
|
}
|
||
|
|
||
|
h1 {
|
||
|
color: #333;
|
||
|
}
|
||
|
|
||
|
p {
|
||
|
margin: 5px 0;
|
||
|
}
|
||
|
|
||
|
a {
|
||
|
color: #0066cc;
|
||
|
text-decoration: none;
|
||
|
}
|
||
|
|
||
|
#busVoltage,
|
||
|
#current,
|
||
|
#power,
|
||
|
#energy,
|
||
|
#temp,
|
||
|
#humidity,
|
||
|
#errorCode {
|
||
|
margin-bottom: 10px;
|
||
|
}
|
||
|
|
||
|
span {
|
||
|
font-weight: bold;
|
||
|
}
|
||
|
|
||
|
td {
|
||
|
vertical-align: top;
|
||
|
padding: 10px;
|
||
|
}
|
||
|
|
||
|
.success-notification {
|
||
|
position: fixed;
|
||
|
bottom: 0;
|
||
|
left: 0;
|
||
|
width: 100%;
|
||
|
background-color: #4CAF50;
|
||
|
color: #fff;
|
||
|
text-align: center;
|
||
|
padding: 10px;
|
||
|
}
|
||
|
|
||
|
.error-notification {
|
||
|
position: fixed;
|
||
|
bottom: 0;
|
||
|
left: 0;
|
||
|
width: 100%;
|
||
|
background-color: #f44336;
|
||
|
color: #fff;
|
||
|
text-align: center;
|
||
|
padding: 10px;
|
||
|
}
|
||
|
|
||
|
button {
|
||
|
font-family: Arial, sans-serif;
|
||
|
background-color: #d3d3d3;
|
||
|
color: #000;
|
||
|
padding: 10px 20px;
|
||
|
text-align: center;
|
||
|
text-decoration: none;
|
||
|
display: inline-block;
|
||
|
font-size: 16px;
|
||
|
margin: 4px 2px;
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
|
||
|
button:active {
|
||
|
background-color: #a9a9a9; /* Dunkleres Grau beim Drücken */
|
||
|
}
|
||
|
)";
|
||
|
|
||
|
server.send(200, cs_textCSS, customCSS);
|
||
|
}
|