diff --git a/ESP32_AP-Flasher/data/www/index.html.gz b/ESP32_AP-Flasher/data/www/index.html.gz index 8ae02dee..e90b9180 100644 Binary files a/ESP32_AP-Flasher/data/www/index.html.gz and b/ESP32_AP-Flasher/data/www/index.html.gz differ diff --git a/ESP32_AP-Flasher/data/www/main.css.gz b/ESP32_AP-Flasher/data/www/main.css.gz index 45a4fddc..b445e024 100644 Binary files a/ESP32_AP-Flasher/data/www/main.css.gz and b/ESP32_AP-Flasher/data/www/main.css.gz differ diff --git a/ESP32_AP-Flasher/data/www/main.js.gz b/ESP32_AP-Flasher/data/www/main.js.gz index 289da7c1..8f861700 100644 Binary files a/ESP32_AP-Flasher/data/www/main.js.gz and b/ESP32_AP-Flasher/data/www/main.js.gz differ diff --git a/ESP32_AP-Flasher/data/www/ota.js.gz b/ESP32_AP-Flasher/data/www/ota.js.gz index b3894736..c25b6050 100644 Binary files a/ESP32_AP-Flasher/data/www/ota.js.gz and b/ESP32_AP-Flasher/data/www/ota.js.gz differ diff --git a/ESP32_AP-Flasher/include/serialap.h b/ESP32_AP-Flasher/include/serialap.h index 5b0ef378..6254de29 100644 --- a/ESP32_AP-Flasher/include/serialap.h +++ b/ESP32_AP-Flasher/include/serialap.h @@ -12,8 +12,8 @@ extern struct espSetChannelPower curChannel; #define AP_STATE_NORADIO 7 struct APInfoS { - bool isOnline = false; - uint8_t state = AP_STATE_OFFLINE; + volatile bool isOnline = false; + volatile uint8_t state = AP_STATE_OFFLINE; uint8_t type; uint16_t version = 0; uint8_t channel; @@ -29,6 +29,17 @@ struct APInfoS { extern struct APInfoS apInfo; +enum ApSerialState { + SERIAL_STATE_NONE, + SERIAL_STATE_INITIALIZED, + SERIAL_STATE_STARTING, + SERIAL_STATE_RUNNING, + SERIAL_STATE_STOP, + SERIAL_STATE_STOPPED +}; + +extern volatile ApSerialState gSerialTaskState; + void APTask(void* parameter); bool sendCancelPending(struct pendingData* pending); @@ -38,5 +49,5 @@ void APEnterEarlyReset(); bool sendChannelPower(struct espSetChannelPower* scp); void rxSerialTask2(void* parameter); void APTagReset(); -bool bringAPOnline(); +bool bringAPOnline(uint8_t newState = AP_STATE_ONLINE); void setAPstate(bool isOnline, uint8_t state); diff --git a/ESP32_AP-Flasher/include/tag_db.h b/ESP32_AP-Flasher/include/tag_db.h index 7465429d..c47b0b9c 100644 --- a/ESP32_AP-Flasher/include/tag_db.h +++ b/ESP32_AP-Flasher/include/tag_db.h @@ -63,7 +63,7 @@ struct Config { uint8_t language; uint8_t maxsleep; uint8_t stopsleep; - uint8_t runStatus; + volatile uint8_t runStatus; uint8_t preview; uint8_t nightlyreboot; uint8_t lock; diff --git a/ESP32_AP-Flasher/src/espflasher.cpp b/ESP32_AP-Flasher/src/espflasher.cpp index 11f28b46..afb70b35 100644 --- a/ESP32_AP-Flasher/src/espflasher.cpp +++ b/ESP32_AP-Flasher/src/espflasher.cpp @@ -224,8 +224,8 @@ bool FlashC6_H2(const char *RepoUrl) { File readfile = contentFS->open(JsonFilename, "r"); if(!readfile) { - Serial.println("load " + JsonFilename + ": Failed to open file"); - break; + wsSerial("load " + JsonFilename + ": Failed to open file"); + return true; } DeserializationError jsonError = deserializeJson(jsonDoc, readfile); diff --git a/ESP32_AP-Flasher/src/ota.cpp b/ESP32_AP-Flasher/src/ota.cpp index 18f629e7..431efae8 100644 --- a/ESP32_AP-Flasher/src/ota.cpp +++ b/ESP32_AP-Flasher/src/ota.cpp @@ -306,22 +306,25 @@ void handleRollback(AsyncWebServerRequest* request) { #ifdef C6_OTA_FLASHING void C6firmwareUpdateTask(void* parameter) { - String *Url = reinterpret_cast(parameter); - LOG("C6firmwareUpdateTask: url '%s'\n",Url->c_str()); + char* urlPtr = reinterpret_cast(parameter); + + LOG("C6firmwareUpdateTask: url '%s'\n", urlPtr); wsSerial("Stopping AP service"); - setAPstate(false, AP_STATE_FLASHING); + gSerialTaskState = SERIAL_STATE_STOP; config.runStatus = RUNSTATUS_STOP; + setAPstate(false, AP_STATE_FLASHING); #ifndef FLASHER_DEBUG_SHARED extern bool rxSerialStopTask2; rxSerialStopTask2 = true; #endif vTaskDelay(500 / portTICK_PERIOD_MS); Serial1.end(); + setAPstate(false, AP_STATE_FLASHING); wsSerial(SHORT_CHIP_NAME " flash starting"); - bool result = FlashC6_H2(Url->c_str()); + bool result = FlashC6_H2(urlPtr); wsSerial(SHORT_CHIP_NAME " flash end"); @@ -340,15 +343,15 @@ void C6firmwareUpdateTask(void* parameter) { vTaskDelay(1000 / portTICK_PERIOD_MS); apInfo.version = 0; - wsSerial("resetting AP"); - APTagReset(); - vTaskDelay(1000 / portTICK_PERIOD_MS); - wsSerial("bringing AP online"); - if (bringAPOnline()) config.runStatus = RUNSTATUS_RUN; + // if (bringAPOnline(AP_STATE_REQUIRED_POWER_CYCLE)) config.runStatus = RUNSTATUS_STOP; + if (bringAPOnline(AP_STATE_ONLINE)) { + config.runStatus = RUNSTATUS_RUN; + setAPstate(true, AP_STATE_ONLINE); + } - // Wait for version info to arrive - vTaskDelay(50 / portTICK_PERIOD_MS); + // Wait for version info to arrive + vTaskDelay(500 / portTICK_PERIOD_MS); if(apInfo.version == 0) { result = false; } @@ -358,16 +361,19 @@ void C6firmwareUpdateTask(void* parameter) { wsSerial("Finished!"); char buffer[50]; snprintf(buffer,sizeof(buffer), - "ESP32-" SHORT_CHIP_NAME " version is now %04x",apInfo.version); + "ESP32-" SHORT_CHIP_NAME " version is now %04x", apInfo.version); wsSerial(String(buffer)); } else if(apInfo.version == 0) { - wsSerial("AP failed failed to come online. :-("); + wsSerial("AP failed to come online. :-("); } else { wsSerial("Flashing failed. :-("); } - delete Url; + // wsSerial("Reboot system now"); + // wsSerial("[reboot]"); + free(urlPtr); + vTaskDelay(30000 / portTICK_PERIOD_MS); vTaskDelete(NULL); } #endif @@ -376,9 +382,10 @@ void C6firmwareUpdateTask(void* parameter) { void handleUpdateC6(AsyncWebServerRequest* request) { #if defined C6_OTA_FLASHING if (request->hasParam("url",true)) { - String *Url = new String(request->getParam("url",true)->value()); - xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6400, Url, 10, NULL); - request->send(200, "Ok"); + const char* urlStr = request->getParam("url", true)->value().c_str(); + char* urlCopy = strdup(urlStr); + xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6400, urlCopy, 10, NULL); + request->send(200, "Ok"); } else { LOG("Sending bad request"); diff --git a/ESP32_AP-Flasher/src/serialap.cpp b/ESP32_AP-Flasher/src/serialap.cpp index 4e63e8a3..b564ddee 100644 --- a/ESP32_AP-Flasher/src/serialap.cpp +++ b/ESP32_AP-Flasher/src/serialap.cpp @@ -15,7 +15,7 @@ #include "web.h" #include "zbs_interface.h" -#define LOG(format, ... ) printf(format,## __VA_ARGS__) +#define LOG(format, ...) printf(format, ##__VA_ARGS__) QueueHandle_t rxCmdQueue; SemaphoreHandle_t txActive; @@ -47,15 +47,6 @@ struct espSetChannelPower curChannel = {0, 11, 10}; volatile uint32_t lastAPActivity = 0; struct APInfoS apInfo; -enum ApSerialState { - SERIAL_STATE_NONE, - SERIAL_STATE_INITIALIZED, - SERIAL_STATE_STARTING, - SERIAL_STATE_RUNNING, - SERIAL_STATE_STOP, - SERIAL_STATE_STOPPED -}; - volatile ApSerialState gSerialTaskState; struct rxCmd { @@ -166,27 +157,28 @@ void setAPstate(bool isOnline, uint8_t state) { CRGB::Red, CRGB::YellowGreen}; rgbIdleColor = colorMap[state]; - #ifdef BLE_ONLY - rgbIdleColor = CRGB::Green; - #endif +#ifdef BLE_ONLY + rgbIdleColor = CRGB::Green; +#endif rgbIdlePeriod = (isOnline ? 767 : 255); if (isOnline) rgbIdle(); #endif #ifdef FLASHER_DEBUG_SHARED -// Flasher shares port with AP comms - if(state == AP_STATE_FLASHING) { - LOG("Shared COM port, gSerialTaskState %d\n",gSerialTaskState); + // Flasher shares port with AP comms + if (state == AP_STATE_FLASHING) { + LOG("Shared COM port, gSerialTaskState %d\n", gSerialTaskState); gSerialTaskState = SERIAL_STATE_STOP; - for(int i = 0; i < 100; i++) { + for (int i = 0; i < 100; i++) { vTaskDelay(1 / portTICK_RATE_MS); - if(gSerialTaskState == SERIAL_STATE_STOPPED) { + if (gSerialTaskState == SERIAL_STATE_STOPPED) { gSerialTaskState = SERIAL_STATE_NONE; break; } } - LOG("gSerialTaskState %d\n",gSerialTaskState); + LOG("gSerialTaskState %d\n", gSerialTaskState); } #endif + wsSendSysteminfo(); } // Reset the tag @@ -415,46 +407,49 @@ void rxCmdProcessor(void* parameter) { txActive = xSemaphoreCreateBinary(); xSemaphoreGive(txActive); while (1) { - struct rxCmd* rxcmd = nullptr; - BaseType_t q = xQueueReceive(rxCmdQueue, &rxcmd, 10); - if (q == pdTRUE) { - switch (rxcmd->type) { - case RX_CMD_RQB: - processBlockRequest((struct espBlockRequest*)rxcmd->data); + if (apInfo.isOnline) { + struct rxCmd* rxcmd = nullptr; + BaseType_t q = xQueueReceive(rxCmdQueue, &rxcmd, 10); + if (q == pdTRUE) { + switch (rxcmd->type) { + case RX_CMD_RQB: + processBlockRequest((struct espBlockRequest*)rxcmd->data); #ifdef HAS_RGB_LED - // shortBlink(CRGB::Blue); + // shortBlink(CRGB::Blue); #endif - quickBlink(3); - break; - case RX_CMD_ADR: - processDataReq((struct espAvailDataReq*)rxcmd->data, true); + quickBlink(3); + break; + case RX_CMD_ADR: + processDataReq((struct espAvailDataReq*)rxcmd->data, true); #ifdef HAS_RGB_LED - // shortBlink(CRGB::Aqua); + // shortBlink(CRGB::Aqua); #endif - quickBlink(1); - break; - case RX_CMD_XFC: - processXferComplete((struct espXferComplete*)rxcmd->data, true); + quickBlink(1); + break; + case RX_CMD_XFC: + processXferComplete((struct espXferComplete*)rxcmd->data, true); #ifdef HAS_RGB_LED - // shortBlink(CRGB::Purple); + // shortBlink(CRGB::Purple); #endif - break; - case RX_CMD_XTO: - processXferTimeout((struct espXferComplete*)rxcmd->data, true); - break; - case RX_CMD_RSET: - Serial.println("AP did reset, resending pending\r\n"); - refreshAllPending(); - sendChannelPower(&curChannel); - break; - case RX_CMD_TRD: - // received tag return data - processTagReturnData((struct espTagReturnData*)rxcmd->data, rxcmd->len, true); - break; + break; + case RX_CMD_XTO: + processXferTimeout((struct espXferComplete*)rxcmd->data, true); + break; + case RX_CMD_RSET: + Serial.println("AP did reset, resending pending\r\n"); + refreshAllPending(); + sendChannelPower(&curChannel); + break; + case RX_CMD_TRD: + // received tag return data + processTagReturnData((struct espTagReturnData*)rxcmd->data, rxcmd->len, true); + break; + } + if (rxcmd->data) free(rxcmd->data); + if (rxcmd) free(rxcmd); } - if (rxcmd->data) free(rxcmd->data); - if (rxcmd) free(rxcmd); } + vTaskDelay(1 / portTICK_PERIOD_MS); } } void rxSerialTask(void* parameter) { @@ -539,8 +534,8 @@ void rxSerialTask(void* parameter) { packetp = (uint8_t*)calloc(sizeof(struct espBlockRequest) + 8, 1); memset(cmdbuffer, 0x00, 4); lastAPActivity = millis(); - if (apInfo.isOnline == false) - setAPstate(true, AP_STATE_ONLINE); + // don't set APstate heree, as it interferes with the flashing process + // if (apInfo.isOnline == false && config.runStatus == RUNSTATUS_RUN) setAPstate(true, AP_STATE_ONLINE); } if (strncmp(cmdbuffer, "ADR>", 4) == 0) { RXState = ZBS_RX_WAIT_DATA_REQ; @@ -549,8 +544,8 @@ void rxSerialTask(void* parameter) { packetp = (uint8_t*)calloc(sizeof(struct espAvailDataReq) + 8, 1); memset(cmdbuffer, 0x00, 4); lastAPActivity = millis(); - if (apInfo.isOnline == false) - setAPstate(true, AP_STATE_ONLINE); + // don't set APstate heree, as it interferes with the flashing process + // if (apInfo.isOnline == false && config.runStatus == RUNSTATUS_RUN) setAPstate(true, AP_STATE_ONLINE); } if (strncmp(cmdbuffer, "XFC>", 4) == 0) { RXState = ZBS_RX_WAIT_XFERCOMPLETE; @@ -573,8 +568,6 @@ void rxSerialTask(void* parameter) { packetp = (uint8_t*)calloc(sizeof(struct espTagReturnData) + 8, 1); memset(cmdbuffer, 0x00, 4); lastAPActivity = millis(); - if (apInfo.isOnline == false) - setAPstate(true, AP_STATE_ONLINE); } break; case ZBS_RX_BLOCK_REQUEST: @@ -747,11 +740,11 @@ void rxSerialTask2(void* parameter) { } else { Serial.println("Failed!"); } - logLine("IEEE802.15.4 modem reset " + (config.runStatus == RUNSTATUS_RUN)?("ok"):("failed")); + logLine("IEEE802.15.4 modem reset " + (config.runStatus == RUNSTATUS_RUN) ? ("ok") : ("failed")); } rxStrCount = 0; memset(rxStr, 0, sizeof(rxStr)); - } else if(rxStrCount < sizeof(rxStr) - 2) { + } else if (rxStrCount < sizeof(rxStr) - 2) { rxStrCount++; } else { rxStrCount = 0; @@ -764,7 +757,7 @@ void rxSerialTask2(void* parameter) { if (currentTime - startTime >= 1000) { if (charCount > 6000) { rxSerialStopTask2 = true; - Serial.println("Serial monitor stopped because of flooding (" + String(charCount) + " characters per second"); + Serial.println("Serial monitor stopped because of flooding (" + String(charCount) + " characters per second)"); } startTime = currentTime; charCount = 0; @@ -822,35 +815,35 @@ void segmentedShowIp() { vTaskDelay(2000 / portTICK_PERIOD_MS); } -bool bringAPOnline() { +bool bringAPOnline(uint8_t newState) { #ifdef BLE_ONLY apInfo.state = AP_STATE_NORADIO; #endif if (apInfo.state == AP_STATE_NORADIO) return true; if (apInfo.state == AP_STATE_FLASHING) return false; - if(gSerialTaskState != SERIAL_STATE_INITIALIZED) { + if (gSerialTaskState != SERIAL_STATE_INITIALIZED) { #ifdef HAS_ELECROW_ADV_2_8 - // Set GPIO45 low to connect the wireless interface to the multiplexed pins - pinMode(45, OUTPUT); - digitalWrite(45, LOW); + // Set GPIO45 low to connect the wireless interface to the multiplexed pins + pinMode(45, OUTPUT); + digitalWrite(45, LOW); #endif #if (AP_PROCESS_PORT == FLASHER_AP_PORT) - AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD); + AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD); #elif defined(HAS_EXT_FLASHER) - #if (AP_PROCESS_PORT == FLASHER_EXT_PORT) - AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_EXT_RXD, FLASHER_EXT_TXD); - #elif (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT) - AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD); - #endif +#if (AP_PROCESS_PORT == FLASHER_EXT_PORT) + AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_EXT_RXD, FLASHER_EXT_TXD); +#elif (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT) + AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD); #endif - gSerialTaskState = SERIAL_STATE_INITIALIZED; +#endif + gSerialTaskState = SERIAL_STATE_INITIALIZED; } - if(gSerialTaskState != SERIAL_STATE_RUNNING) { - gSerialTaskState = SERIAL_STATE_STARTING; - xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, 11, NULL); - vTaskDelay(500 / portTICK_PERIOD_MS); + if (gSerialTaskState != SERIAL_STATE_RUNNING) { + gSerialTaskState = SERIAL_STATE_STARTING; + xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, 11, NULL); + vTaskDelay(500 / portTICK_PERIOD_MS); } setAPstate(false, AP_STATE_OFFLINE); // try without rebooting @@ -888,18 +881,18 @@ bool bringAPOnline() { } vTaskDelay(200 / portTICK_PERIOD_MS); - setAPstate(true, AP_STATE_ONLINE); + setAPstate(newState == AP_STATE_ONLINE ? true : false, newState); return true; } } bool checkRadio() { - #ifdef BLE_ONLY +#ifdef BLE_ONLY return false; - #endif - #ifndef C6_OTA_FLASHING +#endif +#ifndef C6_OTA_FLASHING return true; - #endif +#endif // make a short between FLASHER_AP_TXD and FLASHER_AP_RXD to indicate that no radio is present // e.g. for flasher only, or just to use the S3 to generate images for smaller AP's pinMode(FLASHER_AP_TXD, OUTPUT); @@ -923,7 +916,6 @@ void APTask(void* parameter) { return; } - xTaskCreate(rxCmdProcessor, "rxCmdProcessor", 6000, NULL, 15, NULL); #if defined(FLASHER_DEBUG_RXD) && !defined(FLASHER_DEBUG_SHARED) xTaskCreate(rxSerialTask2, "rxSerialTask2", 1850, NULL, 2, NULL); diff --git a/ESP32_AP-Flasher/wwwroot/index.html b/ESP32_AP-Flasher/wwwroot/index.html index 8f5438b3..c92e86a6 100644 --- a/ESP32_AP-Flasher/wwwroot/index.html +++ b/ESP32_AP-Flasher/wwwroot/index.html @@ -182,6 +182,7 @@
+
diff --git a/ESP32_AP-Flasher/wwwroot/main.css b/ESP32_AP-Flasher/wwwroot/main.css index 314a50d9..306f2efd 100644 --- a/ESP32_AP-Flasher/wwwroot/main.css +++ b/ESP32_AP-Flasher/wwwroot/main.css @@ -651,6 +651,16 @@ select { text-align: center; } +.waitingicon { + display: none; + font-size: 1.2em; + background-color: lightgreen; + color: black; + height: 20px; + width: 20px; + vertical-align: top; + text-align: center; +} ul.messages { padding: 5px; } diff --git a/ESP32_AP-Flasher/wwwroot/main.js b/ESP32_AP-Flasher/wwwroot/main.js index 9d2d942d..803e9298 100644 --- a/ESP32_AP-Flasher/wwwroot/main.js +++ b/ESP32_AP-Flasher/wwwroot/main.js @@ -21,7 +21,7 @@ const apstate = [ { state: "online", color: "green", icon: "check_circle" }, { state: "flashing", color: "orange", icon: "flash_on" }, { state: "wait for reset", color: "blue", icon: "hourglass" }, - { state: "AP requires power cycle", color: "purple", icon: "refresh" }, + { state: "AP requires reboot", color: "purple", icon: "refresh" }, { state: "failed", color: "red", icon: "error" }, { state: "coming online...", color: "orange", icon: "hourglass" }, { state: "AP without radio", color: "green", icon: "wifi_off" } @@ -371,6 +371,11 @@ function processTags(tagArray) { } else { $('#tag' + tagmac + ' .nextupdate').innerHTML = ""; } + if (element.nextupdate < (Date.now() / 1000) - servertimediff) { + $('#tag' + tagmac + ' .waitingicon').style.display = 'inline-block'; + } else { + $('#tag' + tagmac + ' .waitingicon').style.display = 'none'; + } if (element.nextcheckin > 1672531200) { div.dataset.nextcheckin = element.nextcheckin; diff --git a/ESP32_AP-Flasher/wwwroot/ota.js b/ESP32_AP-Flasher/wwwroot/ota.js index 459bf91f..4ecfde0c 100644 --- a/ESP32_AP-Flasher/wwwroot/ota.js +++ b/ESP32_AP-Flasher/wwwroot/ota.js @@ -185,13 +185,13 @@ export async function initUpdate() { if(firmwareVer != 'unknown') { let Ver = Number('0x' + firmwareVer); if(Ver > gCurrentRfVer) { - tablerow += 'Newer'; + tablerow += 'newer'; } else if (Ver < gCurrentRfVer) { - tablerow += 'Older'; + tablerow += 'older'; } else if(!Number.isNaN(Ver)){ - tablerow += 'Same'; + tablerow += 'current version'; } } tablerow += ''; @@ -211,7 +211,7 @@ export async function initUpdate() { tableHeader2.innerHTML = 'Firmware
Update
'; table2.appendChild(tableHeader2); const tableRow = document.createElement('tr'); - tablerow = 'Last uploaded version'; + tablerow = 'Binaries from file system'; tablerow += ``; tableRow.innerHTML = tablerow; table2.appendChild(tableRow); @@ -222,7 +222,7 @@ export async function initUpdate() { "/master/binaries/ESP32-" + gShortName + "/firmware_" + gShortName + ".json"; - tablerow = `Latest version from repo`; + tablerow = `Latest version from repo`; tablerow += ``; tableRow.innerHTML = tablerow; table2.appendChild(tableRow);