From b0db054e1131a7ba6d94e690f96aae6fa599115c Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 19 Apr 2026 14:17:31 +0200 Subject: [PATCH] fix firmware install date (was using UTC as TZ not initialised) --- src/core/system.cpp | 27 ++++++++++++++++----------- src/core/system.h | 2 +- src/web/WebStatusService.cpp | 21 +++++++++++++++------ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/core/system.cpp b/src/core/system.cpp index b2acd2c50..b39ce5e15 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -407,11 +407,11 @@ void System::get_partition_info() { partition_info_.clear(); // clear existing data #ifdef EMSESP_STANDALONE - // dummy data for standalone mode - version, size, install_date - partition_info_["app0"] = {EMSESP_APP_VERSION, 0, ""}; - partition_info_["app1"] = {"", 0, ""}; - partition_info_["factory"] = {"", 0, ""}; - partition_info_["boot"] = {"", 0, ""}; + // dummy data for standalone mode - version, size, install_date in UTC epoch + partition_info_["app0"] = {EMSESP_APP_VERSION, 0, 0}; + partition_info_["app1"] = {"", 0, 0}; + partition_info_["factory"] = {"", 0, 0}; + partition_info_["boot"] = {"", 0, 0}; #else auto current_partition = (const char *)esp_ota_get_running_partition()->label; @@ -451,10 +451,8 @@ void System::get_partition_info() { p_info.version = EMSESP::nvs_.getString(part->label, "").c_str(); char c[20]; snprintf(c, sizeof(c), "d_%s", (const char *)part->label); - time_t d = EMSESP::nvs_.getULong(c, 0); - char time_string[25]; - strftime(time_string, sizeof(time_string), "%FT%T", localtime(&d)); - p_info.install_date = d > 1500000000L ? time_string : ""; + time_t d = EMSESP::nvs_.getULong(c, 0); + p_info.install_date = d > 1500000000L ? d : 0; // store UTC epoch; formatted to local time at render if (!p_info.version.empty()) { esp_image_metadata_t meta = {}; @@ -474,7 +472,7 @@ void System::get_partition_info() { #endif } -// set NTP install time/date for the current partition +// set install time/date for the current partition, in UTC // assumes NTP is connected and working void System::set_partition_install_date() { #ifndef EMSESP_STANDALONE @@ -1337,11 +1335,18 @@ void System::show_system(uuid::console::Shell & shell) { if (partition.second.version.empty()) { continue; // no version, empty string } + std::string installed; + if (partition.second.install_date > 0) { + char time_string[25]; + time_t d = partition.second.install_date; + 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, - partition.second.install_date.empty() ? "" : (std::string(", installed on ") + partition.second.install_date).c_str(), + installed.c_str(), (strcmp(esp_ota_get_running_partition()->label, partition.first.c_str()) == 0) ? "** active **" : ""); } diff --git a/src/core/system.h b/src/core/system.h index e869faf4b..52f6b0e5c 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -75,7 +75,7 @@ enum FUSE_VALUE : uint8_t { ALL = 0, MFG = 1, MODEL = 2, BOARD = 3, REV = 4, BAT struct PartitionInfo { std::string version; size_t size; - std::string install_date; // optional, only available if NTP is connected + time_t install_date; // UTC epoch seconds; 0 if unknown. Format with localtime() at render time so it honors the current TZ. }; class System { diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index f360ff99e..aa66292b1 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -146,18 +146,27 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) { } // get the partition info for each partition, including the running one - // the partition data is done once in System::start() and stored in partition_info_ + // the partition data is gathered once in System::start() and stored in partition_info_ + // install_date is stored as a UTC epoch and formatted to local time here so it honors + // the current TZ (which may not have been set yet when System::start() ran). JsonArray partitions = root["partitions"].to(); for (const auto & partition : EMSESP::system_.partition_info_) { // Skip partition if it has no version, or it's size is 0 if (partition.second.version.empty() || partition.second.size == 0) { continue; } - JsonObject part = partitions.add(); - part["partition"] = partition.first; - part["version"] = partition.second.version; - part["size"] = partition.second.size; - part["install_date"] = partition.second.install_date; + JsonObject part = partitions.add(); + part["partition"] = partition.first; + part["version"] = partition.second.version; + part["size"] = partition.second.size; + if (partition.second.install_date > 0) { + char time_string[25]; + time_t d = partition.second.install_date; + strftime(time_string, sizeof(time_string), "%FT%T", localtime(&d)); + part["install_date"] = time_string; + } else { + part["install_date"] = ""; + } } root["developer_mode"] = EMSESP::system_.developer_mode();