mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-10-28 19:24:59 +00:00
crashmode
This commit is contained in:
@@ -8,7 +8,8 @@ UploadFileService::UploadFileService(AsyncWebServer * server, SecurityManager *
|
||||
: _securityManager(securityManager)
|
||||
, _is_firmware(false)
|
||||
, _is_filesystem(false)
|
||||
, _is_recovery(false) {
|
||||
, _is_recovery(false)
|
||||
, _response_sent(false) {
|
||||
server->on(
|
||||
UPLOAD_FILE_PATH,
|
||||
HTTP_POST,
|
||||
@@ -31,9 +32,10 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
||||
// check details of the file, to see if its a valid bin or json file
|
||||
const std::size_t filesize = request->contentLength();
|
||||
|
||||
_is_firmware = false;
|
||||
_is_filesystem = false;
|
||||
_is_recovery = false;
|
||||
_is_firmware = false;
|
||||
_is_filesystem = false;
|
||||
_is_recovery = false;
|
||||
_response_sent = false;
|
||||
|
||||
switch (OtaUpdater::classify(filename, filesize, emsesp::System::MIN_FIRMWARE_SIZE)) {
|
||||
case OtaUpdater::FileType::FILESYSTEM:
|
||||
@@ -96,6 +98,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
||||
}
|
||||
request->onDisconnect([this] { handleDisconnect(); }); // success, let's make sure we end the update if the client hangs up
|
||||
} else {
|
||||
emsesp::EMSESP::logger().err("OTA begin failed: %s", _ota.errorString());
|
||||
handleError(request, 507); // failed to begin, send an error response Insufficient Storage
|
||||
return;
|
||||
}
|
||||
@@ -147,6 +150,19 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
||||
}
|
||||
|
||||
void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
|
||||
if (request->_tempObject) {
|
||||
const int code = static_cast<int>(reinterpret_cast<intptr_t>(request->_tempObject));
|
||||
if (!_response_sent && code >= 400) {
|
||||
request->send(request->beginResponse(code));
|
||||
_response_sent = true;
|
||||
}
|
||||
_is_firmware = false;
|
||||
_is_filesystem = false;
|
||||
_is_recovery = false;
|
||||
emsesp::EMSESP::system_.systemStatus(emsesp::SYSTEM_STATUS::SYSTEM_STATUS_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
emsesp::EMSESP::logger().info("Upload successful");
|
||||
|
||||
// did we just complete uploading a json file?
|
||||
@@ -217,26 +233,25 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
|
||||
}
|
||||
|
||||
void UploadFileService::handleError(AsyncWebServerRequest * request, int code) {
|
||||
emsesp::EMSESP::logger().info("Upload error: %d", code);
|
||||
emsesp::EMSESP::system_.uart_init(); // re-enable UART
|
||||
|
||||
// if we have had an error already, do nothing
|
||||
if (request->_tempObject) {
|
||||
return;
|
||||
}
|
||||
request->_tempObject = reinterpret_cast<void *>(static_cast<intptr_t>(code)); // stop later chunks from retrying the write
|
||||
|
||||
// send the error code to the client and record the error code in the temp object
|
||||
AsyncWebServerResponse * response = request->beginResponse(code);
|
||||
request->send(response);
|
||||
emsesp::EMSESP::logger().info("Upload error: %d", code);
|
||||
emsesp::EMSESP::system_.uart_init(); // re-enable UART
|
||||
_ota.abort();
|
||||
|
||||
// check for invalid extension and immediately kill the connection, which will throw an error
|
||||
// that is caught by the web code. Unfortunately the http error code is not sent to the client on fast network connections
|
||||
// 406: the client sent a file we won't accept. Close now so the browser fails fast.
|
||||
// Other codes wait for uploadComplete() to send, so we don't destroy the request mid-stream.
|
||||
if (code == 406) {
|
||||
request->send(request->beginResponse(code));
|
||||
_response_sent = true;
|
||||
request->client()->close();
|
||||
_is_firmware = false;
|
||||
_is_filesystem = false;
|
||||
_is_recovery = false;
|
||||
_ota.abort();
|
||||
}
|
||||
|
||||
// if we aborted a filesystem upload, remount LittleFS so the device keeps working
|
||||
@@ -249,13 +264,10 @@ void UploadFileService::handleDisconnect() {
|
||||
emsesp::EMSESP::logger().info("Upload finished");
|
||||
emsesp::EMSESP::system_.uart_init(); // re-enable UART
|
||||
|
||||
#ifdef EMSESP_HAS_RECOVERY
|
||||
if (_is_recovery) {
|
||||
// the client hung up before the upload completed
|
||||
_ota.abort();
|
||||
_ota.abort();
|
||||
if (_is_recovery || _is_firmware || _is_filesystem) {
|
||||
emsesp::EMSESP::system_.systemStatus(emsesp::SYSTEM_STATUS::SYSTEM_STATUS_NORMAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
_is_firmware = false;
|
||||
_is_filesystem = false;
|
||||
|
||||
@@ -22,6 +22,7 @@ class UploadFileService {
|
||||
bool _is_firmware;
|
||||
bool _is_filesystem;
|
||||
bool _is_recovery; // firmware for the factory partition, which doesn't change the boot partition
|
||||
bool _response_sent;
|
||||
OtaUpdater _ota;
|
||||
|
||||
void handleUpload(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final);
|
||||
|
||||
+57
-8
@@ -573,8 +573,12 @@ void System::recovery_installed() {
|
||||
if (factory != nullptr) {
|
||||
char c[20];
|
||||
snprintf(c, sizeof(c), "d_%s", factory->label);
|
||||
EMSESP::nvs_.remove(factory->label);
|
||||
EMSESP::nvs_.remove(c);
|
||||
if (EMSESP::nvs_.isKey(factory->label)) {
|
||||
EMSESP::nvs_.remove(factory->label);
|
||||
}
|
||||
if (EMSESP::nvs_.isKey(c)) {
|
||||
EMSESP::nvs_.remove(c);
|
||||
}
|
||||
partition_info_.erase(factory->label); // on the AsyncTCP task, same as the web handlers reading it
|
||||
}
|
||||
LOG_INFO("Recovery firmware v%s installed", recovery_version().c_str());
|
||||
@@ -639,6 +643,12 @@ bool System::set_partition([[maybe_unused]] const char * partitionname) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef EMSESP_HAS_RECOVERY
|
||||
if (partition->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) {
|
||||
EMSESP::nvs_.putString(EMSESP_NVS_RECOVERY_REASON, "request");
|
||||
}
|
||||
#endif
|
||||
|
||||
// initiate the restart
|
||||
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
|
||||
return true;
|
||||
@@ -1323,6 +1333,16 @@ void System::show_system(uuid::console::Shell & shell) {
|
||||
shell.printfln(" [total %d]", available.size());
|
||||
// List all partitions and their version info
|
||||
shell.println(" Partitions:");
|
||||
#ifndef EMSESP_STANDALONE
|
||||
const esp_partition_t * running = esp_ota_get_running_partition();
|
||||
const esp_partition_t * boot = esp_ota_get_boot_partition();
|
||||
const char * running_label = running ? running->label : "";
|
||||
const char * boot_label = boot ? boot->label : "";
|
||||
#else
|
||||
const char * running_label = "";
|
||||
const char * boot_label = "";
|
||||
#endif
|
||||
bool boot_listed = false;
|
||||
for (const auto & partition : partition_info_) {
|
||||
if (partition.second.version.empty()) {
|
||||
continue; // no version, empty string
|
||||
@@ -1334,13 +1354,42 @@ void System::show_system(uuid::console::Shell & shell) {
|
||||
strftime(time_string, sizeof(time_string), "%FT%T", localtime(&d));
|
||||
installed = std::string(", installed on ") + time_string;
|
||||
}
|
||||
shell.printfln(" %s: v%s (%d KB%s) %s",
|
||||
partition.first.c_str(),
|
||||
partition.second.version.c_str(),
|
||||
partition.second.size,
|
||||
installed.c_str(),
|
||||
(strcmp(esp_ota_get_running_partition()->label, partition.first.c_str()) == 0) ? "** active **" : "");
|
||||
const bool is_running = strcmp(running_label, partition.first.c_str()) == 0;
|
||||
const bool is_boot = strcmp(boot_label, partition.first.c_str()) == 0;
|
||||
if (is_boot) {
|
||||
boot_listed = true;
|
||||
}
|
||||
const char * mark = is_running && is_boot ? "** active, boot **" : is_running ? "** active **" : is_boot ? "** boot **" : "";
|
||||
shell.printfln(" %s: v%s (%d KB%s) %s", partition.first.c_str(), partition.second.version.c_str(), partition.second.size, installed.c_str(), mark);
|
||||
}
|
||||
#ifndef EMSESP_STANDALONE
|
||||
#ifdef EMSESP_HAS_RECOVERY
|
||||
// 16MB boards: factory ("boot") holds the recovery app and is omitted from partition_info_
|
||||
{
|
||||
const esp_partition_t * factory = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr);
|
||||
esp_app_desc_t desc;
|
||||
if (OtaUpdater::isRecoveryPartition(factory, &desc)) {
|
||||
const bool is_running = running && factory == running;
|
||||
const bool is_boot = boot && factory == boot;
|
||||
if (is_boot) {
|
||||
boot_listed = true;
|
||||
}
|
||||
int size_kb = 0;
|
||||
esp_image_metadata_t meta = {};
|
||||
esp_partition_pos_t part_pos = {.offset = factory->address, .size = factory->size};
|
||||
if (esp_image_verify(ESP_IMAGE_VERIFY_SILENT, &part_pos, &meta) == ESP_OK) {
|
||||
size_kb = static_cast<int>(meta.image_len / 1024);
|
||||
}
|
||||
const char * mark = is_running && is_boot ? "** active, boot **" : is_running ? "** active **" : is_boot ? "** boot **" : "";
|
||||
shell.printfln(" %s: Recovery v%s (%d KB) %s", factory->label, desc.version, size_kb, mark);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// recovery/factory is omitted from partition_info_, still show it if it's the boot target
|
||||
if (!boot_listed && boot_label[0] != '\0') {
|
||||
shell.printfln(" %s: ** boot **", boot_label);
|
||||
}
|
||||
#endif
|
||||
// List all NVS values
|
||||
#ifndef EMSESP_STANDALONE
|
||||
shell.println(" NVS values:");
|
||||
|
||||
+2
-1
@@ -375,7 +375,8 @@ class System {
|
||||
static constexpr uint8_t HEALTHCHECK_NO_NETWORK = (1 << 1); // 2
|
||||
static constexpr uint8_t HEALTHCHECK_RESET = (1 << 7); // 128
|
||||
|
||||
// smallest .bin accepted as a firmware image, for both URL and web uploads - 1.6 MB
|
||||
// smallest .bin accepted as a main firmware image, for both URL and web uploads - 1.6 MB
|
||||
// recovery firmware uses OtaUpdater::MIN_RECOVERY_FIRMWARE_SIZE when the filename contains "recovery"
|
||||
static constexpr size_t MIN_FIRMWARE_SIZE = 1677721;
|
||||
|
||||
private:
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "3.9.0-dev.16"
|
||||
#define EMSESP_APP_VERSION "3.9.0-dev.17"
|
||||
|
||||
@@ -134,13 +134,12 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
|
||||
root["temperature"] = (int)Helpers::transformNumFloat(EMSESP::system_.temperature(), 0, EMSESP::system_.fahrenheit() ? 2 : 0); // only 2 decimal places
|
||||
#endif
|
||||
|
||||
// check for a factory partition first
|
||||
// factory partition is only on 16MB boards; recovery_version is empty until a recovery .bin is installed
|
||||
const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr);
|
||||
root["has_loader"] = partition != NULL && partition != esp_ota_get_running_partition();
|
||||
if (partition != NULL) {
|
||||
root["recovery_version"] = EMSESP::system_.recovery_version(); // empty if not installed
|
||||
root["recovery_version"] = EMSESP::system_.recovery_version();
|
||||
}
|
||||
partition = esp_ota_get_next_update_partition(nullptr);
|
||||
partition = esp_ota_get_next_update_partition(nullptr);
|
||||
if (partition) {
|
||||
uint64_t buffer;
|
||||
esp_partition_read(partition, 0, &buffer, 8);
|
||||
|
||||
Reference in New Issue
Block a user