diff --git a/lib/SvelteUi/app/src/App.svelte b/lib/SvelteUi/app/src/App.svelte index 2a42dde0..71d9bf08 100644 --- a/lib/SvelteUi/app/src/App.svelte +++ b/lib/SvelteUi/app/src/App.svelte @@ -34,9 +34,19 @@ - {#if sysinfo.vndcfg === false} + {#if sysinfo.upgrading} + + {:else if sysinfo.vndcfg === false} + {#if sysinfo.booting} + + {:else} + {/if} {:else if sysinfo.usrcfg === false} + {#if sysinfo.booting} + + {:else} {/if} + {/if} diff --git a/lib/SvelteUi/app/src/lib/BoardTypeSelectOptions.svelte b/lib/SvelteUi/app/src/lib/BoardTypeSelectOptions.svelte index 3cc48c34..d0d51c39 100644 --- a/lib/SvelteUi/app/src/lib/BoardTypeSelectOptions.svelte +++ b/lib/SvelteUi/app/src/lib/BoardTypeSelectOptions.svelte @@ -4,7 +4,7 @@ export let chip; - + {#if chip == 'esp8266'} diff --git a/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte b/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte index 688a8069..7d660484 100644 --- a/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte +++ b/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte @@ -518,6 +518,7 @@ {/if} {#if configuration.i.v.p > 0 || sysinfo.chip == 'esp8266'} +
Vcc offset
diff --git a/lib/SvelteUi/app/src/lib/DataStores.js b/lib/SvelteUi/app/src/lib/DataStores.js index 7f9c1c03..0a50f2a2 100644 --- a/lib/SvelteUi/app/src/lib/DataStores.js +++ b/lib/SvelteUi/app/src/lib/DataStores.js @@ -7,7 +7,8 @@ let sysinfo = { vndcfg: null, usrcfg: null, fwconsent: null, - booting: false + booting: true, + upgrading: false }; export const sysinfoStore = writable(sysinfo); @@ -17,20 +18,38 @@ export async function getSysinfo() { sysinfoStore.set(sysinfo); }; +let lastTemp = -127; let data = {}; export const dataStore = readable(data, (set) => { - async function getData(){ - const response = await fetch("/data.json"); - data = (await response.json()) - set(data); - if(sysinfo.booting) { - getSysinfo(); - } + let timeout; + async function getData() { + fetch("/data.json") + .then((res) => res.json()) + .then((data) => { + set(data); + if(lastTemp != data.t) { + lastTemp = data.t; + getTemperatures(); + } + if(sysinfo.upgrading) { + window.location.reload(); + } else if(sysinfo.booting) { + getSysinfo(); + } + timeout = setTimeout(getData, 5000); + }) + .catch((err) => { + data.em = 3; + data.hm = 0; + data.wm = 0; + data.mm = 0; + set(data); + timeout = setTimeout(getData, 15000); + }); } - const interval = setInterval(getData, 5000); getData(); return function stop() { - clearInterval(interval); + clearTimeout(timeout); } }); @@ -40,13 +59,12 @@ export const pricesStore = readable(prices, (set) => { const response = await fetch("/energyprice.json"); prices = (await response.json()) set(prices); + + let date = new Date(); + setTimeout(getPrices, (61-date.getMinutes())*60000) } - const date = new Date(); - const timeout = setTimeout(getPrices, (61-date.getMinutes())*60000) getPrices(); - return function stop() { - clearTimeout(timeout); - } + return function stop() {} }); let dayPlot = {}; @@ -55,13 +73,12 @@ export const dayPlotStore = readable(dayPlot, (set) => { const response = await fetch("/dayplot.json"); dayPlot = (await response.json()) set(dayPlot); + + let date = new Date(); + setTimeout(getDayPlot, (61-date.getMinutes())*60000) } - const date = new Date(); - const timeout = setTimeout(getDayPlot, (61-date.getMinutes())*60000) getDayPlot(); - return function stop() { - clearTimeout(timeout); - } + return function stop() {} }); let monthPlot = {}; @@ -70,25 +87,31 @@ export const monthPlotStore = readable(monthPlot, (set) => { const response = await fetch("/monthplot.json"); monthPlot = (await response.json()) set(monthPlot); + + let date = new Date(); + setTimeout(getmonthPlot, (24-date.getHours())*3600000) } - const date = new Date(); - const timeout = setTimeout(getmonthPlot, (24-date.getHours())*3600000) getmonthPlot(); - return function stop() { - clearTimeout(timeout); - } + return function stop() {} }); let temperatures = {}; -export const temperaturesStore = readable(temperatures, (set) => { - async function getTemperatures(){ - const response = await fetch("/temperature.json"); - temperatures = (await response.json()) - set(temperatures); - } - const interval = setInterval(getTemperatures, 60000); +export async function getTemperatures() { + const response = await fetch("/temperature.json"); + temperatures = (await response.json()) + temperaturesStore.set(temperatures); +} + +export const temperaturesStore = writable(temperatures, (set) => { getTemperatures(); - return function stop() { - clearTimeout(interval); - } + return function stop() {} }); + +let releases = []; +export const gitHubReleaseStore = writable(releases); + +export async function getGitHubReleases() { + const response = await fetch("https://api.github.com/repos/gskjold/AmsToMqttBridge/releases"); + releases = (await response.json()) + gitHubReleaseStore.set(releases); +}; diff --git a/lib/SvelteUi/app/src/lib/DownloadIcon.svelte b/lib/SvelteUi/app/src/lib/DownloadIcon.svelte new file mode 100644 index 00000000..ea9993ba --- /dev/null +++ b/lib/SvelteUi/app/src/lib/DownloadIcon.svelte @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/lib/SvelteUi/app/src/lib/Header.svelte b/lib/SvelteUi/app/src/lib/Header.svelte index 56e31ce6..8f813a02 100644 --- a/lib/SvelteUi/app/src/lib/Header.svelte +++ b/lib/SvelteUi/app/src/lib/Header.svelte @@ -1,6 +1,8 @@
-
{ data.t ? data.t.toFixed(1) : '-' }°C
+ {#if data.t > -50} +
{ data.t > -50 ? data.t.toFixed(1) : '-' }°C
+ {/if}
Free mem: {data.m ? (data.m/1000).toFixed(1) : '-'}kb
- 0 ? data.v.toFixed(2)+"V" : "ESP"} color={sysinfo.booting ? 'yellow' : data.em === 1 ? 'green' : data.em === 2 ? 'yellow' : data.em === 3 ? 'red' : 'gray'}/> - - - + 1.0 ? data.v.toFixed(2)+"V" : "ESP"} color={sysinfo.booting ? 'yellow' : data.em === 1 ? 'green' : data.em === 2 ? 'yellow' : data.em === 3 ? 'red' : 'gray'}/> + + +
@@ -57,15 +81,20 @@
-
+
-
+
+ {#if sysinfo.fwconsent && nextVersion} +
+ +
+ {/if}
\ No newline at end of file diff --git a/lib/SvelteUi/app/src/lib/PowerGauge.svelte b/lib/SvelteUi/app/src/lib/PowerGauge.svelte index 38d83be9..83eaf644 100644 --- a/lib/SvelteUi/app/src/lib/PowerGauge.svelte +++ b/lib/SvelteUi/app/src/lib/PowerGauge.svelte @@ -31,7 +31,7 @@ } .plot-value { font-size: 1.7rem; - cursor: pointer; + //cursor: pointer; } .plot-unit { font-size: 1.0rem; diff --git a/lib/SvelteUi/app/src/lib/SetupModal.svelte b/lib/SvelteUi/app/src/lib/SetupModal.svelte index 90b611bb..7cef5852 100644 --- a/lib/SvelteUi/app/src/lib/SetupModal.svelte +++ b/lib/SvelteUi/app/src/lib/SetupModal.svelte @@ -5,9 +5,40 @@ export let sysinfo = {} let staticIp = false; - let ntpDhcp = true; - let loadingOrSaving = false; + + let tries = 0; + function scanForDevice() { + var url = ""; + tries++; + + if(sysinfo.net.ip && tries%3 == 0) { + url = "http://" + sysinfo.net.ip; + } else if(sysinfo.hostname && tries%3 == 1) { + url = "http://" + sysinfo.hostname; + } else if(sysinfo.hostname && tries%3 == 2) { + url = "http://" + sysinfo.hostname + ".local"; + } else { + url = ""; + } + if(console) console.log("Trying url " + url); + + var retry = function() { + setTimeout(scanForDevice, 1000); + }; + + var xhr = new XMLHttpRequest(); + xhr.timeout = 5000; + xhr.addEventListener('abort', retry); + xhr.addEventListener('error', retry); + xhr.addEventListener('timeout', retry); + xhr.addEventListener('load', function(e) { + window.location.href = url ? url : "/"; + }); + xhr.open("GET", url + "/is-alive", true); + xhr.send(); + }; + async function handleSubmit(e) { loadingOrSaving = true; const formData = new FormData(e.target) @@ -27,6 +58,7 @@ sysinfoStore.update(s => { s.usrcfg = res.success; s.booting = res.reboot; + setTimeout(scanForDevice, 5000); return s; }); } @@ -49,7 +81,7 @@
Hostname: - +
diff --git a/lib/SvelteUi/app/src/lib/StatusPage.svelte b/lib/SvelteUi/app/src/lib/StatusPage.svelte index de881e62..53ed06cb 100644 --- a/lib/SvelteUi/app/src/lib/StatusPage.svelte +++ b/lib/SvelteUi/app/src/lib/StatusPage.svelte @@ -1,36 +1,58 @@
Device information -
+
Chip: {sysinfo.chip}
-
+
Device: {boardtype(sysinfo.chip, sysinfo.board)}
-
- Firmware version: {sysinfo.version} -
{#if sysinfo.meter}
Meter -
+
Manufacturer: {metertype(sysinfo.meter.mfg)}
-
+
Model: {sysinfo.meter.model}
-
+
ID: {sysinfo.meter.id}
@@ -38,18 +60,49 @@ {#if sysinfo.net}
Network -
+
IP: {sysinfo.net.ip}
-
+
Mask: {sysinfo.net.mask}
-
+
Gateway: {sysinfo.net.gw}
-
+
DNS: {sysinfo.net.dns1} {#if sysinfo.net.dns2 != '0.0.0.0'}/ {sysinfo.net.dns2}{/if}
{/if} +
+ Firmware +
+ Installed version: {sysinfo.version} +
+
+ Latest version: + {#if sysinfo.fwconsent && nextVersion && nextVersion.tag_name} + {nextVersion.tag_name} +
+ +
+ {/if} +
+ {#if sysinfo.board == 2 || sysinfo.board == 4 || sysinfo.board == 7 } +
+ {boardtype(sysinfo.chip, sysinfo.board)} must be connected to an external power supply during firmware upgrade. Failure to do so may cause power-down during upload resulting in non-functioning unit. +
+ {/if} +
+
+ + {#if fileinput && fileinput.files.length == 0} + + {:else if fileinput} + {fileinput.files[0].name} + + {/if} +
+
+
diff --git a/lib/SvelteUi/app/src/lib/UpgradeHelper.js b/lib/SvelteUi/app/src/lib/UpgradeHelper.js new file mode 100644 index 00000000..31ab6ca3 --- /dev/null +++ b/lib/SvelteUi/app/src/lib/UpgradeHelper.js @@ -0,0 +1,65 @@ + + +export async function upgrade(version) { + const data = new URLSearchParams() + data.append('version', version.tag_name); + const response = await fetch('/upgrade', { + method: 'POST', + body: data + }); + let res = (await response.json()) +} + +export function getNextVersion(currentVersion, releases) { + if(/^v\d{1,2}\.\d{1,2}\.\d{1,2}$/.test(currentVersion)) { + var v = currentVersion.substring(1).split('.'); + var v_major = parseInt(v[0]); + var v_minor = parseInt(v[1]); + var v_patch = parseInt(v[2]); + + releases.reverse(); + var next_patch; + var next_minor; + var next_major; + for(var i = 0; i < releases.length; i++) { + var release = releases[i]; + var ver2 = release.tag_name; + var v2 = ver2.substring(1).split('.'); + var v2_major = parseInt(v2[0]); + var v2_minor = parseInt(v2[1]); + var v2_patch = parseInt(v2[2]); + + if(v2_major == v_major) { + if(v2_minor == v_minor) { + if(v2_patch > v_patch) { + next_patch = release; + } + } else if(v2_minor == v_minor+1) { + next_minor = release; + } + } else if(v2_major == v_major+1) { + if(next_major) { + var mv = next_major.tag_name.substring(1).split('.'); + var mv_major = parseInt(mv[0]); + var mv_minor = parseInt(mv[1]); + var mv_patch = parseInt(mv[2]); + if(v2_minor == mv_minor) { + next_major = release; + } + } else { + next_major = release; + } + } + }; + if(next_minor) { + return next_minor; + } else if(next_major) { + return next_major; + } else if(next_patch) { + return next_patch; + } + return false; + } else { + return releases[0]; + } +} diff --git a/lib/SvelteUi/app/src/lib/UploadIcon.svelte b/lib/SvelteUi/app/src/lib/UploadIcon.svelte new file mode 100644 index 00000000..4aefd39e --- /dev/null +++ b/lib/SvelteUi/app/src/lib/UploadIcon.svelte @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/lib/SvelteUi/app/src/lib/VendorModal.svelte b/lib/SvelteUi/app/src/lib/VendorModal.svelte index a6607c20..58b49dd5 100644 --- a/lib/SvelteUi/app/src/lib/VendorModal.svelte +++ b/lib/SvelteUi/app/src/lib/VendorModal.svelte @@ -39,14 +39,14 @@ Vendor configuration
Board type
-
{#if sysinfo.board && sysinfo.board > 20}
HAN GPIO
-
diff --git a/lib/SvelteUi/app/vite.config.js b/lib/SvelteUi/app/vite.config.js index 762b5719..9e1ad30c 100644 --- a/lib/SvelteUi/app/vite.config.js +++ b/lib/SvelteUi/app/vite.config.js @@ -17,15 +17,17 @@ export default defineConfig({ plugins: [svelte()], server: { proxy: { - "/data.json": "http://192.168.233.244", + "/data.json": "http://192.168.233.229", "/energyprice.json": "http://192.168.233.235", "/dayplot.json": "http://192.168.233.235", "/monthplot.json": "http://192.168.233.235", "/temperature.json": "http://192.168.233.235", - "/sysinfo.json": "http://192.168.233.244", - "/configuration.json": "http://192.168.233.244", - "/save": "http://192.168.233.244", - "/reboot": "http://192.168.233.244" + "/sysinfo.json": "http://192.168.233.229", + "/configuration.json": "http://192.168.233.229", + "/save": "http://192.168.233.229", + "/reboot": "http://192.168.233.229", + "/firmware": "http://192.168.233.229", + "/upgrade": "http://192.168.233.229" } } }) diff --git a/lib/SvelteUi/include/AmsWebServer.h b/lib/SvelteUi/include/AmsWebServer.h index a42630fb..bcec5b29 100644 --- a/lib/SvelteUi/include/AmsWebServer.h +++ b/lib/SvelteUi/include/AmsWebServer.h @@ -87,6 +87,12 @@ private: void configurationJson(); void handleSave(); void reboot(); + void upgrade(); + void firmwarePost(); + void firmwareUpload(); + void isAliveCheck(); + + HTTPUpload& uploadFile(const char* path); void notFound(); }; diff --git a/lib/SvelteUi/src/AmsWebServer.cpp b/lib/SvelteUi/src/AmsWebServer.cpp index 8810ee17..e6c558fb 100644 --- a/lib/SvelteUi/src/AmsWebServer.cpp +++ b/lib/SvelteUi/src/AmsWebServer.cpp @@ -17,6 +17,10 @@ #include "version.h" +#if defined(ESP32) +#include +#endif + AmsWebServer::AmsWebServer(uint8_t* buf, RemoteDebug* Debug, HwTools* hw) { this->debugger = Debug; @@ -51,6 +55,9 @@ void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, Meter server.on(F("/configuration.json"), HTTP_GET, std::bind(&AmsWebServer::configurationJson, this)); server.on(F("/save"), HTTP_POST, std::bind(&AmsWebServer::handleSave, this)); server.on(F("/reboot"), HTTP_POST, std::bind(&AmsWebServer::reboot, this)); + server.on(F("/upgrade"), HTTP_POST, std::bind(&AmsWebServer::upgrade, this)); + server.on(F("/firmware"), HTTP_POST, std::bind(&AmsWebServer::firmwarePost, this), std::bind(&AmsWebServer::firmwareUpload, this)); + server.on(F("/is-alive"), HTTP_GET, std::bind(&AmsWebServer::isAliveCheck, this)); server.onNotFound(std::bind(&AmsWebServer::notFound, this)); @@ -154,7 +161,8 @@ void AmsWebServer::sysinfoJson() { #else chipId = ESP.getChipId(); #endif - doc["chipId"] = String(chipId, HEX); + String chipIdStr = String(chipId, HEX);; + doc["chipId"] = chipIdStr; SystemConfig sys; config->getSystemConfig(sys); @@ -164,6 +172,17 @@ void AmsWebServer::sysinfoJson() { doc["fwconsent"] = sys.dataCollectionConsent; doc["country"] = sys.country; + if(sys.userConfigured) { + WiFiConfig wifiConfig; + config->getWiFiConfig(wifiConfig); + doc["hostname"] = wifiConfig.hostname; + } else { + doc["hostname"] = "ams-"+chipIdStr; + } + + doc["booting"] = performRestart; + doc["upgrading"] = rebootForUpgrade; + doc["net"]["ip"] = WiFi.localIP().toString(); doc["net"]["mask"] = WiFi.subnetMask().toString(); doc["net"]["gw"] = WiFi.gatewayIP().toString(); @@ -176,6 +195,23 @@ void AmsWebServer::sysinfoJson() { serializeJson(doc, buf, BufferSize); server.send(200, MIME_JSON, buf); + + server.handleClient(); + delay(250); + + if(performRestart || rebootForUpgrade) { + if(ds != NULL) { + ds->save(); + } + if(debugger->isActive(RemoteDebug::INFO)) debugger->printf(PSTR("Rebooting")); + delay(1000); + #if defined(ESP8266) + ESP.reset(); + #elif defined(ESP32) + ESP.restart(); + #endif + performRestart = false; + } } void AmsWebServer::dataJson() { @@ -802,8 +838,9 @@ void AmsWebServer::handleSave() { bool success = true; if(server.hasArg(F("v")) && server.arg(F("v")) == F("true")) { - int boardType = server.arg(F("b")).toInt(); - int hanPin = server.arg(F("h")).toInt(); + int boardType = server.arg(F("vb")).toInt(); + int hanPin = server.arg(F("vh")).toInt(); + config->clear(); #if defined(CONFIG_IDF_TARGET_ESP32S2) switch(boardType) { @@ -854,7 +891,14 @@ void AmsWebServer::handleSave() { case 2: // spenceme config->clearGpio(*gpioConfig); gpioConfig->vccBootLimit = 33; + gpioConfig->hanPin = 3; + gpioConfig->apPin = 0; + gpioConfig->ledPin = 2; + gpioConfig->ledInverted = true; + gpioConfig->tempSensorPin = 5; + break; case 0: // roarfred + config->clearGpio(*gpioConfig); gpioConfig->hanPin = 3; gpioConfig->apPin = 0; gpioConfig->ledPin = 2; @@ -900,6 +944,7 @@ void AmsWebServer::handleSave() { success = false; } #endif + config->setGpioConfig(*gpioConfig); SystemConfig sys; config->getSystemConfig(sys); @@ -1119,11 +1164,16 @@ void AmsWebServer::handleSave() { gpioConfig->tempSensorPin = server.hasArg(F("itd")) && !server.arg(F("itd")).isEmpty() ?server.arg(F("itd")).toInt() : 0xFF; gpioConfig->tempAnalogSensorPin = server.hasArg(F("ita")) && !server.arg(F("ita")).isEmpty() ?server.arg(F("ita")).toInt() : 0xFF; gpioConfig->vccPin = server.hasArg(F("ivp")) && !server.arg(F("ivp")).isEmpty() ? server.arg(F("ivp")).toInt() : 0xFF; + gpioConfig->vccResistorGnd = server.hasArg(F("ivdg")) && !server.arg(F("ivdg")).isEmpty() ? server.arg(F("ivdg")).toInt() : 0; + gpioConfig->vccResistorVcc = server.hasArg(F("ivdv")) && !server.arg(F("ivdv")).isEmpty() ? server.arg(F("ivdv")).toInt() : 0; + config->setGpioConfig(*gpioConfig); + } + + if(server.hasArg(F("iv")) && server.arg(F("iv")) == F("true")) { + if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf(PSTR("Received Vcc config")); gpioConfig->vccOffset = server.hasArg(F("ivo")) && !server.arg(F("ivo")).isEmpty() ? server.arg(F("ivo")).toFloat() * 100 : 0; gpioConfig->vccMultiplier = server.hasArg(F("ivm")) && !server.arg(F("ivm")).isEmpty() ? server.arg(F("ivm")).toFloat() * 1000 : 1000; gpioConfig->vccBootLimit = server.hasArg(F("ivb")) && !server.arg(F("ivb")).isEmpty() ? server.arg(F("ivb")).toFloat() * 10 : 0; - gpioConfig->vccResistorGnd = server.hasArg(F("ivdg")) && !server.arg(F("ivdg")).isEmpty() ? server.arg(F("ivdg")).toInt() : 0; - gpioConfig->vccResistorVcc = server.hasArg(F("ivdv")) && !server.arg(F("ivdv")).isEmpty() ? server.arg(F("ivdv")).toInt() : 0; config->setGpioConfig(*gpioConfig); } @@ -1250,4 +1300,160 @@ void AmsWebServer::reboot() { ESP.restart(); #endif performRestart = false; -} \ No newline at end of file +} + +void AmsWebServer::upgrade() { + if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("Serving /upgrade over http...\n"); + + DynamicJsonDocument doc(128); + doc["reboot"] = true; + + serializeJson(doc, buf, BufferSize); + server.send(200, MIME_JSON, buf); + + server.handleClient(); + delay(250); + + String customFirmwareUrl = ""; + if(server.hasArg(F("url"))) { + customFirmwareUrl = server.arg(F("url")); + } + + String url = customFirmwareUrl.isEmpty() || !customFirmwareUrl.startsWith(F("http")) ? F("http://ams2mqtt.rewiredinvent.no/hub/firmware/update") : customFirmwareUrl; + + if(server.hasArg(F("version"))) { + url += "/" + server.arg(F("version")); + } + + WiFiClient client; + #if defined(ESP8266) + String chipType = F("esp8266"); + #elif defined(CONFIG_IDF_TARGET_ESP32S2) + String chipType = F("esp32s2"); + #elif defined(ESP32) + #if defined(CONFIG_FREERTOS_UNICORE) + String chipType = F("esp32solo"); + #else + String chipType = F("esp32"); + #endif + #endif + + #if defined(ESP8266) + ESPhttpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + t_httpUpdate_return ret = ESPhttpUpdate.update(client, url, VERSION); + #elif defined(ESP32) + HTTPUpdate httpUpdate; + httpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + HTTPUpdateResult ret = httpUpdate.update(client, url, String(VERSION) + "-" + chipType); + #endif + + switch(ret) { + case HTTP_UPDATE_FAILED: + debugger->printf(PSTR("Update failed")); + break; + case HTTP_UPDATE_NO_UPDATES: + debugger->printf(PSTR("No Update")); + break; + case HTTP_UPDATE_OK: + debugger->printf(PSTR("Update OK")); + break; + } +} + +void AmsWebServer::firmwarePost() { + if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf(PSTR("Handling firmware post...")); + if(!checkSecurity(1)) + return; + + server.send(200); +} + + +void AmsWebServer::firmwareUpload() { + if(!checkSecurity(1)) + return; + + HTTPUpload& upload = server.upload(); + if(upload.status == UPLOAD_FILE_START) { + String filename = upload.filename; + if(!filename.endsWith(".bin")) { + server.send(500, MIME_PLAIN, "500: couldn't create file"); + } else { + #if defined(ESP32) + esp_task_wdt_delete(NULL); + esp_task_wdt_deinit(); + #elif defined(ESP8266) + ESP.wdtDisable(); + #endif + } + } + uploadFile(FILE_FIRMWARE); + if(upload.status == UPLOAD_FILE_END) { + rebootForUpgrade = true; + server.sendHeader("Location","/"); + server.send(302); + } +} + +HTTPUpload& AmsWebServer::uploadFile(const char* path) { + HTTPUpload& upload = server.upload(); + if(upload.status == UPLOAD_FILE_START){ + if(uploading) { + if(debugger->isActive(RemoteDebug::ERROR)) debugger->printf(PSTR("Upload already in progress")); + server.send_P(500, MIME_HTML, PSTR("

Upload already in progress!

")); + } else if (!LittleFS.begin()) { + if(debugger->isActive(RemoteDebug::ERROR)) debugger->printf(PSTR("An Error has occurred while mounting LittleFS")); + server.send_P(500, MIME_HTML, PSTR("

Unable to mount LittleFS!

")); + } else { + uploading = true; + if(debugger->isActive(RemoteDebug::DEBUG)) { + debugger->printf_P(PSTR("handleFileUpload file: %s\n"), path); + } + if(LittleFS.exists(path)) { + LittleFS.remove(path); + } + file = LittleFS.open(path, "w"); + if(debugger->isActive(RemoteDebug::DEBUG)) { + debugger->printf_P(PSTR("handleFileUpload Open file and write: %u\n"), upload.currentSize); + } + size_t written = file.write(upload.buf, upload.currentSize); + if(debugger->isActive(RemoteDebug::DEBUG)) { + debugger->printf_P(PSTR("handleFileUpload Written: %u\n"), written); + } + } + } else if(upload.status == UPLOAD_FILE_WRITE) { + if(debugger->isActive(RemoteDebug::DEBUG)) { + debugger->printf_P(PSTR("handleFileUpload Writing: %u\n"), upload.currentSize); + } + if(file) { + size_t written = file.write(upload.buf, upload.currentSize); + if(debugger->isActive(RemoteDebug::DEBUG)) { + debugger->printf_P(PSTR("handleFileUpload Written: %u\n"), written); + } + delay(1); + if(written != upload.currentSize) { + file.flush(); + file.close(); + LittleFS.remove(path); + LittleFS.end(); + + if(debugger->isActive(RemoteDebug::ERROR)) debugger->printf(PSTR("An Error has occurred while writing file")); + server.send_P(500, MIME_JSON, PSTR("{ \"success\": false, \"message\": \"Unable to upload\" }")); + } + } + } else if(upload.status == UPLOAD_FILE_END) { + if(file) { + file.flush(); + file.close(); +// LittleFS.end(); + } else { + server.send_P(500, MIME_JSON, PSTR("{ \"success\": false, \"message\": \"Unable to upload\" }")); + } + } + return upload; +} + +void AmsWebServer::isAliveCheck() { + server.sendHeader(F("Access-Control-Allow-Origin"), F("*")); + server.send(200); +}