diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b51e4d3c..6d50e258 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,6 +5,12 @@ on: tags: - '*' +env: + INCLUDE_C6_H2: true + INCLUDE_MINI_AP: false + INCLUDE_Nano_AP: false + INCLUDE_S2_Tag_Flasher: false + jobs: build: runs-on: ubuntu-22.04 @@ -41,30 +47,37 @@ jobs: run: | mkdir espbinaries - #- name: esp-idf build - # uses: espressif/esp-idf-ci-action@v1 - # with: - # esp_idf_version: latest - # target: esp32c6 - # path: 'ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/' + - name: build ESP32-C6 firmware + if: ${{ env.INCLUDE_C6_H2 == 'true' }} + uses: espressif/esp-idf-ci-action@v1 + with: + esp_idf_version: latest + target: esp32c6 + path: 'ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/' - # - name: esp-idf build - # uses: espressif/esp-idf-ci-action@v1 - # with: - # esp_idf_version: latest - # target: esp32h2 - # path: 'ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/' + - name: Add C6 files to release + if: ${{ env.INCLUDE_C6_H2 == 'true' }} + run: | + cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/OpenEPaperLink_esp32_C6.bin espbinaries/OpenEPaperLink_esp32_C6.bin + cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/bootloader/bootloader.bin espbinaries/bootloader_C6.bin + cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/partition_table/partition-table.bin espbinaries/partition-table_C6.bin + cp /home/runner/work/OpenEPaperLink/OpenEPaperLink//binaries/ESP32-C6/firmware_C6.json espbinaries - #- name: Add C6 files to release - # run: | - # cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/OpenEPaperLink_esp32_C6.bin espbinaries/OpenEPaperLink_esp32_C6.bin + - name: build ESP32-H2 firmware + if: ${{ env.INCLUDE_C6_H2 == 'true' }} + uses: espressif/esp-idf-ci-action@v1 + with: + esp_idf_version: latest + target: esp32h2 + path: 'ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/' - #- name: Add H2 files to release - # run: | - # cd ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/ - # dir build - # esptool.py --chip esp32h2 merge_bin -o merged-firmware.bin --flash_mode dio --flash_size 4MB --flash_freq 48m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/OpenEPaperLink_esp32_H2.bin - # cp merged-firmware.bin ../../espbinaries/OpenEPaperLink_esp32_H2.bin + - name: Add H2 files to release + if: ${{ env.INCLUDE_C6_H2 == 'true' }} + run: | + cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/OpenEPaperLink_esp32_H2.bin espbinaries/OpenEPaperLink_esp32_H2.bin + cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/bootloader/bootloader.bin espbinaries/bootloader_H2.bin + cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/partition_table/partition-table.bin espbinaries/partition-table_H2.bin + cp /home/runner/work/OpenEPaperLink/OpenEPaperLink//binaries/ESP32-H2/firmware_H2.json espbinaries # - name: Zip web files # run: | @@ -72,6 +85,7 @@ jobs: # python gzip_wwwfiles.py - name: Build firmware for OpenEPaperLink_Mini_AP + if: ${{ env.INCLUDE_MINI_AP == 'true' }} run: | cd ESP32_AP-Flasher export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA" @@ -90,6 +104,7 @@ jobs: cp OpenEPaperLink_Mini_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Mini_AP_full.bin - name: Build firmware for OpenEPaperLink_Nano_AP + if: ${{ env.INCLUDE_Nano_AP == 'true' }} run: | cd ESP32_AP-Flasher export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA" @@ -106,7 +121,6 @@ jobs: cd /home/runner/work/OpenEPaperLink/OpenEPaperLink cp OpenEPaperLink_Nano_AP/firmware.bin espbinaries/OpenEPaperLink_Nano_AP.bin cp OpenEPaperLink_Nano_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_AP_full.bin - # - name: move files for big APs # run: | # cp -a binaries/ESP32-C6/. ESP32_AP-Flasher/data/ @@ -128,7 +142,6 @@ jobs: cd /home/runner/work/OpenEPaperLink/OpenEPaperLink cp OpenEPaperLink_AP_and_Flasher/firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher.bin cp OpenEPaperLink_AP_and_Flasher/merged-firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher_full.bin - - name: Build firmware for ESP32_S3_16_8_YELLOW_AP run: | cd ESP32_AP-Flasher @@ -254,7 +267,6 @@ jobs: cd /home/runner/work/OpenEPaperLink/OpenEPaperLink cp BLE_ONLY_AP/firmware.bin espbinaries/BLE_ONLY_AP.bin cp BLE_ONLY_AP/merged-firmware.bin espbinaries/BLE_ONLY_AP_full.bin - - name: generate release json file run: | mkdir jsonfiles @@ -272,6 +284,7 @@ jobs: # this is down here intentionally to be able to modify the binary folder before adding it to the Tag_Flasher later (ota binaries can be removed) - name: Build firmware for Tag_Flasher + if: ${{ env.INCLUDE_S2_Tag_Flasher == 'true' }} run: | cd Tag_Flasher/ESP32_Flasher export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA" @@ -288,7 +301,6 @@ jobs: cd /home/runner/work/OpenEPaperLink/OpenEPaperLink cp S2_Tag_Flasher/firmware.bin espbinaries/S2_Tag_Flasher.bin cp S2_Tag_Flasher/merged-firmware.bin espbinaries/S2_Tag_Flasher_full.bin - - name: Add esp bins to release uses: svenstaro/upload-release-action@v2 with: diff --git a/ESP32_AP-Flasher/data/www/index.html.gz b/ESP32_AP-Flasher/data/www/index.html.gz index 2e56d843..0540a265 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 7f103aa0..9ba87224 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 307f2eb1..ce140bfd 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 3802564e..f3d27e17 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/espflasher.h b/ESP32_AP-Flasher/include/espflasher.h index 4185705f..4fb9206b 100644 --- a/ESP32_AP-Flasher/include/espflasher.h +++ b/ESP32_AP-Flasher/include/espflasher.h @@ -1,4 +1,16 @@ #include #include -bool doC6flash(uint8_t doDownload); +#if defined HAS_H2 + #define SHORT_CHIP_NAME "H2" + #define OTA_BIN_DIR "ESP32-H2" + #define ESP_CHIP_TYPE ESP32H2_CHIP +#elif defined HAS_TSLR + #define SHORT_CHIP_NAME "TSLR" +#elif defined C6_OTA_FLASHING + #define SHORT_CHIP_NAME "C6" + #define OTA_BIN_DIR "ESP32-C6" + #define ESP_CHIP_TYPE ESP32C6_CHIP +#endif + +bool FlashC6_H2(const char *Url); diff --git a/ESP32_AP-Flasher/platformio.ini b/ESP32_AP-Flasher/platformio.ini index 28ab9db5..9fe5647b 100644 --- a/ESP32_AP-Flasher/platformio.ini +++ b/ESP32_AP-Flasher/platformio.ini @@ -180,24 +180,29 @@ build_flags = -D HAS_TFT -D HAS_LILYGO_TPANEL -D CORE_DEBUG_LEVEL=1 - -D ARDUINO_USB_CDC_ON_BOOT=1 + -D ARDUINO_USB_CDC_ON_BOOT=1 -D CONFIG_ESP32S3_SPIRAM_SUPPORT=1 -D CONFIG_SPIRAM_USE_MALLOC=1 -D POWER_NO_SOFT_POWER -D BOARD_HAS_PSRAM -D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y -D HAS_BLE_WRITER - -D FLASHER_AP_SS=-1 + -D FLASHER_AP_SS=-1 -D FLASHER_AP_CLK=-1 -D FLASHER_AP_MOSI=-1 -D FLASHER_AP_MISO=-1 -D FLASHER_AP_RESET=34 -D FLASHER_AP_POWER={-1} -D FLASHER_AP_TEST=-1 +; NB: FLASHER_DEBUG_TXD and FLASHER_DEBUG_RXD use the same pins as +; FLASHER_AP_TXD and FLASHER_AP_RXD but the naming convention is different + -D FLASHER_DEBUG_SHARED + -D FLASHER_DEBUG_PORT=1 -D FLASHER_AP_TXD=48 + -D FLASHER_DEBUG_RXD=48 -D FLASHER_AP_RXD=47 - -D FLASHER_DEBUG_TXD=43 - -D FLASHER_DEBUG_RXD=44 + -D FLASHER_DEBUG_TXD=47 +; -D FLASHER_DEBUG_PROG=33 -D FLASHER_LED=-1 -D TFT_HEIGHT=480 @@ -207,6 +212,8 @@ build_flags = -D SERIAL_FLASHER_INTERFACE_UART=1 -D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=200 -D SERIAL_FLASHER_RESET_HOLD_TIME_MS=200 + -D HAS_H2 + -D C6_OTA_FLASHING -D HAS_SUBGHZ build_src_filter = +<*>--- diff --git a/ESP32_AP-Flasher/src/espflasher.cpp b/ESP32_AP-Flasher/src/espflasher.cpp index 3d55df34..a3011583 100644 --- a/ESP32_AP-Flasher/src/espflasher.cpp +++ b/ESP32_AP-Flasher/src/espflasher.cpp @@ -9,6 +9,14 @@ #include "storage.h" #include "tag_db.h" #include "web.h" +#include "espflasher.h" +#include "util.h" + +#define LOG(format, ... ) Serial.printf(format,## __VA_ARGS__) + +#ifndef FLASHER_DEBUG_PORT +#define FLASHER_DEBUG_PORT 2 +#endif esp_loader_error_t connect_to_target(uint32_t higher_transmission_rate) { esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT(); @@ -120,150 +128,197 @@ esp_loader_error_t flash_binary(String &file_path, size_t address) { bool downloadAndWriteBinary(String &filename, const char *url) { HTTPClient binaryHttp; - Serial.println(url); + bool Ret = false; + bool bHaveFsMutex = false; + + LOG("downloadAndWriteBinary: url %s\n",url); binaryHttp.begin(url); binaryHttp.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); - int binaryResponseCode = binaryHttp.GET(); - Serial.println(binaryResponseCode); - if (binaryResponseCode == HTTP_CODE_OK) { + do { + int binaryResponseCode = binaryHttp.GET(); + if(binaryResponseCode != HTTP_CODE_OK) { + wsSerial("http error " + String(binaryResponseCode) + " fetching " + String(url)); + break; + } int contentLength = binaryHttp.getSize(); - Serial.println(contentLength); + LOG("contentLength %d\r\n",contentLength); + if(contentLength < 0) { + wsSerial("Couldn't get contentLength"); + break; + } xSemaphoreTake(fsMutex, portMAX_DELAY); + bHaveFsMutex = true; File file = contentFS->open(filename, "wb"); - if (file) { - wsSerial("downloading " + String(filename)); - WiFiClient *stream = binaryHttp.getStreamPtr(); - uint8_t buffer[1024]; - size_t totalBytesRead = 0; - time_t timeOut = millis() + 5000; - // while (stream->available()) { - while (millis() < timeOut) { - size_t bytesRead = stream->readBytes(buffer, sizeof(buffer)); + if(!file) { + wsSerial("file open error " + String(filename)); + break; + } + wsSerial("downloading " + String(filename)); + WiFiClient *stream = binaryHttp.getStreamPtr(); + uint8_t buffer[1024]; + size_t totalBytesRead = 0; + // timeout if we don't average at least 1k bytes/second + unsigned long timeOut = millis() + contentLength; + while(stream->connected() && totalBytesRead < contentLength) { + size_t bytesRead; + size_t bytesToRead; + if(stream->available()) { + bytesToRead = min(sizeof(buffer), (size_t) stream->available()); + bytesRead = stream->readBytes(buffer, bytesToRead); + if(bytesRead == 0 || millis() > timeOut) { + wsSerial("Download time out"); + break; + } file.write(buffer, bytesRead); totalBytesRead += bytesRead; - if (totalBytesRead == contentLength) break; + vTaskDelay(1 / portTICK_PERIOD_MS); + } else { + vTaskDelay(10 / portTICK_PERIOD_MS); } - file.close(); - xSemaphoreGive(fsMutex); - binaryHttp.end(); - - file = contentFS->open(filename, "r"); - if (file) { - if (totalBytesRead == contentLength || (contentLength == 0 && file.size() > 0)) { - file.close(); - return true; - } - wsSerial("Download failed, " + String(file.size()) + " bytes"); - file.close(); - } - } else { - xSemaphoreGive(fsMutex); - wsSerial("file open error " + String(filename)); } - } else { - wsSerial("http error " + String(binaryResponseCode) + " fetching " + String(url)); - } + file.close(); + + if(!stream->connected()) { + wsSerial("Connection dropped during transfer"); + break; + } + file = contentFS->open(filename, "r"); + if(!file) { + wsSerial("file open error " + String(filename)); + break; + } + if(file.size() == contentLength) { + Ret = true; + } else { + wsSerial("Download failed, " + String(file.size()) + " bytes"); + } + file.close(); + } while(false); + binaryHttp.setReuse(false); binaryHttp.end(); - return false; + if(bHaveFsMutex) { + xSemaphoreGive(fsMutex); + } + + return Ret; } -bool doC6flash(uint8_t doDownload) { - String filenameFirmwareLocal = "/firmware.json"; +bool FlashC6_H2(const char *RepoUrl) { + String JsonFilename = "/firmware_" SHORT_CHIP_NAME ".json" ; + bool Ret = false; + bool bLoaderInit = false; + bool bDownload = strlen(RepoUrl) > 0; + int retry; DynamicJsonDocument jsonDoc(1024); - if (doDownload) { - const String githubUrl = "https://raw.githubusercontent.com/" + config.repo + "/master/binaries/ESP32-C6/firmware.json"; - if (downloadAndWriteBinary(filenameFirmwareLocal, githubUrl.c_str())) { - File readfile = contentFS->open(filenameFirmwareLocal, "r"); - if (!readfile) { - Serial.println("load firmware.json: Failed to open file"); - return false; - } - DeserializationError jsonError = deserializeJson(jsonDoc, readfile); - if (!jsonError) { - JsonArray jsonArray = jsonDoc.as(); - for (JsonObject obj : jsonArray) { - String filename = "/" + obj["filename"].as(); - // String binaryUrl = "https://raw.githubusercontent.com/" + config.repo + "/master/binaries/ESP32-C6" + String(filename); - String binaryUrl = "http://www.openepaperlink.eu/binaries/ESP32-C6" + String(filename); - for (int retry = 0; retry < 10; retry++) { - if (downloadAndWriteBinary(filename, binaryUrl.c_str())) { - break; - } - wsSerial("Retry " + String(retry)); - if (retry < 9) { - delay(1000); - } else { - return false; - } - } - } - } else { - wsSerial("json error fetching " + String(githubUrl)); - return false; + LOG("%s#%d: ",__FUNCTION__,__LINE__); util::printHeap(); + + do { + if(bDownload) { + String FileUrl = RepoUrl + JsonFilename; + if(!downloadAndWriteBinary(JsonFilename, FileUrl.c_str())) { + LOG("%s#%d: ",__FUNCTION__,__LINE__); util::printHeap(); + break; } - } else { - return false; } - } else { - File readfile = contentFS->open(filenameFirmwareLocal, "r"); - if (!readfile) { - Serial.println("load local firmware.json: Failed to open file"); - return false; + + File readfile = contentFS->open(JsonFilename, "r"); + if(!readfile) { + Serial.println("load " + JsonFilename + ": Failed to open file"); + break; } DeserializationError jsonError = deserializeJson(jsonDoc, readfile); - } - const loader_esp32_config_t config = { - .baud_rate = 115200, - .uart_port = 2, - .uart_rx_pin = FLASHER_DEBUG_TXD, - .uart_tx_pin = FLASHER_DEBUG_RXD, - .reset_trigger_pin = FLASHER_AP_RESET, - .gpio0_trigger_pin = FLASHER_DEBUG_PROG, - }; + if(jsonError) { + wsSerial(String("json error parsing") + JsonFilename); + break; + } - if (loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) { - wsSerial("Serial initialization failed"); - loader_port_esp32_deinit(); - return false; - } + if(!bDownload) { + Ret = true; + break; + } - if (connect_to_target(115200) == ESP_LOADER_SUCCESS) { - if (esp_loader_get_target() == ESP32C6_CHIP) { - wsSerial("Connected to ESP32-C6"); - int maxRetries = 5; - esp_loader_error_t err; + JsonArray jsonArray = jsonDoc.as(); + for(JsonObject obj : jsonArray) { + String filename = "/" + obj["filename"].as(); + String binaryUrl = RepoUrl + filename; - JsonArray jsonArray = jsonDoc.as(); - for (JsonObject obj : jsonArray) { - String filename = "/" + obj["filename"].as(); - const char *addressStr = obj["address"]; - uint32_t address = strtoul(addressStr, NULL, 16); - - for (int retry = 0; retry < maxRetries; retry++) { - err = flash_binary(filename, address); - if (err == ESP_LOADER_SUCCESS) break; - Serial.printf("Flash failed with error %d. Retrying...\n", err); + for(retry = 0; retry < 10; retry++) { + if(downloadAndWriteBinary(filename, binaryUrl.c_str())) { + break; + } + wsSerial("Retry " + String(retry)); + if(retry < 9) { delay(1000); } - if (err != ESP_LOADER_SUCCESS) { - loader_port_esp32_deinit(); - return false; - } } - - Serial.println("Done!"); - } else { - wsSerial("Connected to wrong ESP32 type"); - loader_port_esp32_deinit(); - return false; + if(retry == 10) { + break; + } } - } else { - wsSerial("Connection to the C6 failed"); + if(retry < 10) { + Ret = true; + } + } while(false); + + if(Ret == true) do { + Ret = false; + const loader_esp32_config_t config = { + .baud_rate = 115200, + .uart_port = FLASHER_DEBUG_PORT, + .uart_rx_pin = FLASHER_DEBUG_TXD, + .uart_tx_pin = FLASHER_DEBUG_RXD, + .reset_trigger_pin = FLASHER_AP_RESET, + .gpio0_trigger_pin = FLASHER_DEBUG_PROG, + }; + + bLoaderInit = true; + if(loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) { + wsSerial("Serial initialization failed"); + break; + } + + if(connect_to_target(115200) != ESP_LOADER_SUCCESS) { + wsSerial("Connection to the " SHORT_CHIP_NAME " failed"); + break; + } + + if(esp_loader_get_target() != ESP_CHIP_TYPE) { + wsSerial("Connected to wrong ESP32 type"); + break; + } + wsSerial("Connected to ESP32-" SHORT_CHIP_NAME); + int maxRetries = 5; + esp_loader_error_t err; + + JsonArray jsonArray = jsonDoc.as(); + for(JsonObject obj : jsonArray) { + String filename = "/" + obj["filename"].as(); + const char *addressStr = obj["address"]; + uint32_t address = strtoul(addressStr, NULL, 16); + + for(int retry = 0; retry < maxRetries; retry++) { + err = flash_binary(filename, address); + if(err == ESP_LOADER_SUCCESS) { + Ret = true; + break; + } + Serial.printf("Flash failed with error %d. Retrying...\n", err); + delay(1000); + } + if(err != ESP_LOADER_SUCCESS) { + break; + } + } + Serial.println("Done!"); + } while(false); + + if(bLoaderInit) { loader_port_esp32_deinit(); - return false; } - loader_port_esp32_deinit(); - return true; + + LOG("%s#%d: ",__FUNCTION__,__LINE__); util::printHeap(); + return Ret; } + diff --git a/ESP32_AP-Flasher/src/ota.cpp b/ESP32_AP-Flasher/src/ota.cpp index 96ad558e..879575e6 100644 --- a/ESP32_AP-Flasher/src/ota.cpp +++ b/ESP32_AP-Flasher/src/ota.cpp @@ -7,6 +7,7 @@ #include #include +#include "flasher.h" #include "espflasher.h" #include "leds.h" #include "serialap.h" @@ -15,6 +16,7 @@ #include "util.h" #include "web.h" + #ifndef BUILD_ENV_NAME #define BUILD_ENV_NAME unknown #endif @@ -30,6 +32,8 @@ #define STR_IMPL(x) #x #define STR(x) STR_IMPL(x) +#define LOG(format, ... ) Serial.printf(format,## __VA_ARGS__) + void handleSysinfoRequest(AsyncWebServerRequest* request) { StaticJsonDocument<250> doc; @@ -41,12 +45,20 @@ void handleSysinfoRequest(AsyncWebServerRequest* request) { doc["psramsize"] = ESP.getPsramSize(); doc["flashsize"] = ESP.getFlashChipSize(); doc["rollback"] = Update.canRollBack(); -#if defined C6_OTA_FLASHING - doc["hasC6"] = 1; - doc["C6version"] = apInfo.version; -#else + doc["ap_version"] = apInfo.version; + doc["hasC6"] = 0; + doc["hasH2"] = 0; + doc["hasTslr"] = 0; + +#if defined HAS_H2 + doc["hasH2"] = 1; +#elif defined HAS_TSLR + doc["hasTslr"] = 1; +#elif defined C6_OTA_FLASHING + doc["hasC6"] = 1; #endif + #ifdef HAS_EXT_FLASHER doc["hasFlasher"] = 1; #else @@ -290,22 +302,26 @@ void handleRollback(AsyncWebServerRequest* request) { } } +#ifdef C6_OTA_FLASHING void C6firmwareUpdateTask(void* parameter) { - uint8_t doDownload = *((uint8_t*)parameter); + String *Url = reinterpret_cast(parameter); + LOG("C6firmwareUpdateTask: url '%s'\n",Url->c_str()); wsSerial("Stopping AP service"); setAPstate(false, AP_STATE_FLASHING); config.runStatus = RUNSTATUS_STOP; +#ifndef FLASHER_DEBUG_SHARED extern bool rxSerialStopTask2; rxSerialStopTask2 = true; +#endif vTaskDelay(500 / portTICK_PERIOD_MS); Serial1.end(); - wsSerial("C6 flash starting"); + wsSerial(SHORT_CHIP_NAME " flash starting"); - bool result = doC6flash(doDownload); + bool result = FlashC6_H2(Url->c_str()); - wsSerial("C6 flash end"); + wsSerial(SHORT_CHIP_NAME " flash end"); if (result) { setAPstate(false, AP_STATE_OFFLINE); @@ -315,12 +331,13 @@ void C6firmwareUpdateTask(void* parameter) { wsSerial("starting monitor"); Serial1.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD); +#ifndef FLASHER_DEBUG_SHARED rxSerialStopTask2 = false; -#ifdef FLASHER_DEBUG_RXD xTaskCreate(rxSerialTask2, "rxSerialTask2", 1750, NULL, 2, NULL); #endif vTaskDelay(1000 / portTICK_PERIOD_MS); + apInfo.version = 0; wsSerial("resetting AP"); APTagReset(); vTaskDelay(1000 / portTICK_PERIOD_MS); @@ -328,23 +345,47 @@ void C6firmwareUpdateTask(void* parameter) { wsSerial("bringing AP online"); if (bringAPOnline()) config.runStatus = RUNSTATUS_RUN; - wsSerial("Finished!"); - } else { - wsSerial("Flashing failed. :-("); + // Wait for version info to arrive + vTaskDelay(50 / portTICK_PERIOD_MS); + if(apInfo.version == 0) { + result = false; + } + } + + if (result) { + wsSerial("Finished!"); + char buffer[50]; + snprintf(buffer,sizeof(buffer), + "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. :-("); + } + else { + wsSerial("Flashing failed. :-("); + } + delete Url; vTaskDelete(NULL); } +#endif + void handleUpdateC6(AsyncWebServerRequest* request) { #if defined C6_OTA_FLASHING - uint8_t doDownload = 1; - if (request->hasParam("download", true)) { - doDownload = atoi(request->getParam("download", true)->value().c_str()); + 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"); } - xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6144, &doDownload, 10, NULL); - request->send(200, "Ok"); + else { + LOG("Sending bad request"); + request->send(400, "Bad request"); + } +#elif defined(SHORT_CHIP_NAME) + request->send(400, SHORT_CHIP_NAME " flashing not implemented"); #else - request->send(400, "C6 flashing not implemented"); + request->send(400, "C6/H2 flashing not implemented"); #endif } diff --git a/ESP32_AP-Flasher/src/serialap.cpp b/ESP32_AP-Flasher/src/serialap.cpp index ce225e47..811e78f2 100644 --- a/ESP32_AP-Flasher/src/serialap.cpp +++ b/ESP32_AP-Flasher/src/serialap.cpp @@ -14,6 +14,8 @@ #include "web.h" #include "zbs_interface.h" +#define LOG(format, ... ) printf(format,## __VA_ARGS__) + QueueHandle_t rxCmdQueue; SemaphoreHandle_t txActive; @@ -25,7 +27,9 @@ SemaphoreHandle_t txActive; volatile uint8_t cmdReplyValue = CMD_REPLY_WAIT; #define AP_SERIAL_PORT Serial1 +#ifndef FLASHER_DEBUG_SHARED volatile bool rxSerialStopTask2 = false; +#endif uint8_t channelList[6]; struct espSetChannelPower curChannel = {0, 11, 10}; @@ -42,6 +46,17 @@ 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 { uint8_t* data; uint8_t len; @@ -156,6 +171,21 @@ void setAPstate(bool isOnline, uint8_t state) { 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); + gSerialTaskState = SERIAL_STATE_STOP; + for(int i = 0; i < 100; i++) { + vTaskDelay(1 / portTICK_RATE_MS); + if(gSerialTaskState == SERIAL_STATE_STOPPED) { + gSerialTaskState = SERIAL_STATE_NONE; + break; + } + } + LOG("gSerialTaskState %d\n",gSerialTaskState); + } +#endif } // Reset the tag @@ -435,7 +465,9 @@ void rxSerialTask(void* parameter) { static char lastchar = 0; static uint8_t charindex = 0; - while (1) { + gSerialTaskState = SERIAL_STATE_RUNNING; + LOG("rxSerialTask starting\n"); + while (gSerialTaskState == SERIAL_STATE_RUNNING) { while (AP_SERIAL_PORT.available()) { lastchar = AP_SERIAL_PORT.read(); switch (RXState) { @@ -666,9 +698,14 @@ void rxSerialTask(void* parameter) { } vTaskDelay(1 / portTICK_PERIOD_MS); } // end of while(1) + + AP_SERIAL_PORT.end(false); + gSerialTaskState = SERIAL_STATE_STOPPED; + LOG("rxSerialTask stopped\n"); + vTaskDelete(NULL); } -#ifdef FLASHER_DEBUG_RXD +#if defined(FLASHER_DEBUG_RXD) && !defined(FLASHER_DEBUG_SHARED) void rxSerialTask2(void* parameter) { char lastchar = 0; time_t startTime = millis(); @@ -747,11 +784,29 @@ void segmentedShowIp() { } bool bringAPOnline() { - #ifdef BLE_ONLY +#ifdef BLE_ONLY apInfo.state = AP_STATE_NORADIO; - #endif +#endif if (apInfo.state == AP_STATE_NORADIO) return true; if (apInfo.state == AP_STATE_FLASHING) return false; + + if(gSerialTaskState != SERIAL_STATE_INITIALIZED) { +#if (AP_PROCESS_PORT == FLASHER_AP_PORT) + 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 +#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); + } setAPstate(false, AP_STATE_OFFLINE); // try without rebooting AP_SERIAL_PORT.updateBaudRate(115200); @@ -823,25 +878,12 @@ void APTask(void* parameter) { return; } -#if (AP_PROCESS_PORT == FLASHER_AP_PORT) - AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD); -#endif -#ifdef HAS_EXT_FLASHER -#if (AP_PROCESS_PORT == FLASHER_EXT_PORT) - AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_EXT_RXD, FLASHER_EXT_TXD); -#endif -#if (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT) - AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD); -#endif -#endif xTaskCreate(rxCmdProcessor, "rxCmdProcessor", 6000, NULL, 15, NULL); - xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, 11, NULL); -#ifdef FLASHER_DEBUG_RXD +#if defined(FLASHER_DEBUG_RXD) && !defined(FLASHER_DEBUG_SHARED) xTaskCreate(rxSerialTask2, "rxSerialTask2", 1750, NULL, 2, NULL); -#endif - vTaskDelay(500 / portTICK_PERIOD_MS); +#endif bringAPOnline(); #ifndef C6_OTA_FLASHING diff --git a/ESP32_AP-Flasher/src/web.cpp b/ESP32_AP-Flasher/src/web.cpp index 5c856fc4..584baa21 100644 --- a/ESP32_AP-Flasher/src/web.cpp +++ b/ESP32_AP-Flasher/src/web.cpp @@ -514,13 +514,21 @@ void init_web() { UDPcomm udpsync; udpsync.getAPList(); AsyncResponseStream *response = request->beginResponseStream("application/json"); + String HasC6 = "0"; + String HasH2 = "0"; + String HasTSLR = "0"; response->print("{"); -#ifdef C6_OTA_FLASHING - response->print("\"C6\": \"1\", "); -#else - response->print("\"C6\": \"0\", "); +#ifdef HAS_H2 + HasH2 = "1"; +#elif defined(HAS_TSLR) + HasTSLR = "1"; +#elif defined(C6_OTA_FLASHING) + HasC6 = "1"; #endif + response->print("\"C6\": \"" + HasC6 + "\", "); + response->print("\"H2\": \"" + HasH2 + "\", "); + response->print("\"TLSR\": \"" + HasTSLR + "\", "); #ifdef SAVE_SPACE response->print("\"savespace\": \"1\", "); #else diff --git a/ESP32_AP-Flasher/wwwroot/index.html b/ESP32_AP-Flasher/wwwroot/index.html index f69af71e..6360e21b 100644 --- a/ESP32_AP-Flasher/wwwroot/index.html +++ b/ESP32_AP-Flasher/wwwroot/index.html @@ -522,7 +522,10 @@ options:

Releases

-
+
+

+
+

Other actions

Update
Remark'; + table.appendChild(tableHeader); - let rowCounter = 0; - releaseDetails.forEach(release => { - if (rowCounter < 4 && release?.html_url) { - const tableRow = document.createElement('tr'); - let tablerow = `${release.tag_name}${release.date}${release.name}`; - if (release.tag_name == currentVer) { - tablerow += "current version"; - } else if (release.date < formatEpoch(currentBuildtime)) { - tablerow += "older"; - } else { - tablerow += "newer"; - } - tableRow.innerHTML = tablerow; - table.appendChild(tableRow); - rowCounter++; - } - }); + let rowCounter = 0; + let radioFwCounter = 0; + releaseDetails.forEach(release => { + if (rowCounter < 4 && release?.html_url) { + const tableRow = document.createElement('tr'); + let tablerow = `${release.tag_name}${release.date}${release.name}`; + if (release.tag_name == currentVer) { + tablerow += "current version"; + } else if (release.date < formatEpoch(currentBuildtime)) { + tablerow += "older"; + } else { + tablerow += "newer"; + } + tableRow.innerHTML = tablerow; + table.appendChild(tableRow); + rowCounter++; + } + if (release?.firmware_url) { + radioFwCounter++; + } + }); + $('#releasetable').innerHTML = ""; + $('#releasetable').appendChild(table); - $('#releasetable').innerHTML = ""; - $('#releasetable').appendChild(table); - disableButtons(buttonState); - }) - .catch(error => { - print('Error fetching releases:' + error, "red"); - }); + if(radioFwCounter > 0) { + const table1 = document.createElement('table'); + const tableHeader1 = document.createElement('tr'); + + tableHeader1.innerHTML = 'ReleaseDateName
Update
VersionRemark'; + table1.appendChild(tableHeader1); + + rowCounter = 0; + for (const release of releaseDetails) { + if (rowCounter < 4 && release?.firmware_url) { + const tableRow = document.createElement('tr'); + var tablerow; + var firmwareVer = "unknown"; + var release_url = release.firmware_url; + + tablerow = `${release.tag_name}${release.date}${release.name}`; + tablerow += ``; + const firmwareUrl = 'http://proxy.openepaperlink.org/proxy.php?url=' + release.firmware_url; + firmwareVer = await fetch(firmwareUrl, { method: 'GET'}) + .then(function (response) { return response.json(); }) + .then(function (response) { + return response[2]['version']; }) + .catch(error => { + print('Error fetching releases:' + error, "red"); + }); + tablerow += '' + firmwareVer + ''; + if(firmwareVer != 'unknown') { + let Ver = Number('0x' + firmwareVer); + if(Ver > gCurrentRfVer) { + tablerow += 'Newer'; + } + else if (Ver < gCurrentRfVer) { + tablerow += 'Older'; + } + else if(!Number.isNaN(Ver)){ + tablerow += 'Same'; + } + } + tablerow += ''; + tableRow.innerHTML = tablerow; + table1.appendChild(tableRow); + rowCounter++; + } + }; + + $('#radio_releasetable').innerHTML = ""; + $('#radio_releasetable').appendChild(table1); + } + + const table2 = document.createElement('table'); + { + const tableHeader2 = document.createElement('tr'); + tableHeader2.innerHTML = 'Firmware
Update
'; + table2.appendChild(tableHeader2); + const tableRow = document.createElement('tr'); + tablerow = 'Last uploaded version'; + tablerow += ``; + tableRow.innerHTML = tablerow; + table2.appendChild(tableRow); + } + { + const tableRow = document.createElement('tr'); + const Url = "https://raw.githubusercontent.com/" + repo + + "/master/binaries/ESP32-" + gShortName + + "/firmware_" + gShortName + ".json"; + + tablerow = `Latest version from repo`; + tablerow += ``; + tableRow.innerHTML = tablerow; + table2.appendChild(tableRow); + } + $('#radio_releasetable1').innerHTML = ""; + $('#radio_releasetable1').appendChild(table2); + + disableButtons(buttonState); } export function updateAll(binUrl, fileUrl, tagname) { @@ -358,19 +449,18 @@ $('#rollbackBtn').onclick = function () { disableButtons(false); } -$('#updateC6Btn').onclick = function () { +export async function updateC6H2(Url) { if (running) return; disableButtons(true); running = true; errors = 0; + const ReleaseUrl = Url.substring(0,Url.lastIndexOf('/')); const consoleDiv = document.getElementById('updateconsole'); consoleDiv.scrollTop = consoleDiv.scrollHeight; - - print("Flashing ESP32-C6..."); - - const isChecked = $('#c6download').checked; const formData = new FormData(); - formData.append('download', isChecked ? '1' : '0'); + + print("Flashing " + gModuleType + " ..."); + formData.append('url', ReleaseUrl); fetch("update_c6", { method: "POST", @@ -418,7 +508,7 @@ $('#selectRepo').onclick = function (event) { if (!responseBody.trim().startsWith("[")) { throw new Error("Failed to fetch the release info file"); } - const updateData = JSON.parse(responseBody).filter(item => !item.name.endsWith('_full.bin')); + const updateData = JSON.parse(responseBody).filter(item => !item.name.endsWith('_full.bin') && !item.name.includes('_H2.') && !item.name.includes('_C6.')); const inputParent = $('#environment').parentNode; const selectElement = document.createElement('select'); diff --git a/binaries/ESP32-C6/firmware_C6.json b/binaries/ESP32-C6/firmware_C6.json index a76fa879..3fe50694 100644 --- a/binaries/ESP32-C6/firmware_C6.json +++ b/binaries/ESP32-C6/firmware_C6.json @@ -1,10 +1,10 @@ [{ - "filename": "bootloader.bin", + "filename": "bootloader_C6.bin", "address": "0x0", "version": "0001" }, { - "filename": "partition-table.bin", + "filename": "partition-table_C6.bin", "address": "0x8000", "version": "0001" }, diff --git a/binaries/ESP32-H2/firmware_H2.json b/binaries/ESP32-H2/firmware_H2.json index 8037c452..2a44a1ae 100644 --- a/binaries/ESP32-H2/firmware_H2.json +++ b/binaries/ESP32-H2/firmware_H2.json @@ -1,10 +1,10 @@ [{ - "filename": "bootloader.bin", + "filename": "bootloader_H2.bin", "address": "0x0", "version": "0001" }, { - "filename": "partition-table.bin", + "filename": "partition-table_H2.bin", "address": "0x8000", "version": "0001" },