introduce system status in WebUI for easier monitoring of tasks

This commit is contained in:
proddy
2025-01-19 18:18:04 +01:00
parent 6e29de4463
commit 006eae5862
21 changed files with 264 additions and 191 deletions

View File

@@ -1734,29 +1734,34 @@ void EMSESP::loop() {
esp32React.loop(); // web services
system_.loop(); // does LED and checks system health, and syslog service
// if we're doing an OTA upload, skip everything except from console refresh
static bool upload_status = true; // ready for any OTA uploads
if (!system_.upload_isrunning()) {
// run the loop, unless we're in the middle of an OTA upload
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_NORMAL) {
// service loops
webLogService.loop(); // log in Web UI
rxservice_.loop(); // process any incoming Rx telegrams
shower_.loop(); // check for shower on/off
temperaturesensor_.loop(); // read sensor temperatures
analogsensor_.loop(); // read analog sensor values
publish_all_loop(); // with HA messages in parts to avoid flooding the mqtt queue
publish_all_loop(); // with HA messages in parts to avoid flooding the MQTT queue
mqtt_.loop(); // sends out anything in the MQTT queue
webModulesService.loop(); // loop through the external library modules
if (system_.PSram() == 0) { // run non-async if there is no PSRAM available
webSchedulerService.loop();
}
scheduled_fetch_values(); // force a query on the EMS devices to fetch latest data at a set interval (1 min)
}
} else if (upload_status) {
// start an upload from a URL, if it exists. This is blocking.
if (!system_.uploadFirmwareURL()) {
upload_status = false; // abort all other attempts, until reset (after a restart normally)
system_.upload_isrunning(false);
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_PENDING_UPLOAD) {
// start an upload from a URL, assuming if the URL exists from a previous pass.
// Note this function is synchronous and blocking.
if (system_.uploadFirmwareURL()) {
// firmware has been uploaded, set status to uploading
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_UPLOADING);
} else {
// if it fails to pass, reset
Shell::loop_all(); // flush log buffers so latest error message are shown in console
system_.uploadFirmwareURL("reset");
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_ERROR_UPLOAD);
}
}

View File

@@ -83,8 +83,6 @@ uuid::log::Logger System::logger_{F_(system), uuid::log::Facility::KERN};
// init statics
PButton System::myPButton_;
bool System::restart_requested_ = false;
bool System::restart_pending_ = false;
bool System::test_set_all_active_ = false;
uint32_t System::max_alloc_mem_;
uint32_t System::heap_mem_;
@@ -298,8 +296,7 @@ void System::system_restart(const char * partitionname) {
}
// make sure it's only executed once
restart_requested(false);
restart_pending(false);
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_NORMAL);
store_nvs_values(); // save any NVS values
Shell::loop_all(); // flush log to output
@@ -565,27 +562,10 @@ void System::led_init(bool refresh) {
}
}
// returns true if OTA is uploading
bool System::upload_isrunning() {
#if defined(EMSESP_STANDALONE)
return false;
#else
return upload_isrunning_ || Update.isRunning();
#endif
}
void System::upload_isrunning(bool in_progress) {
// if we've just started an upload
if (!upload_isrunning_ && in_progress) {
EMSuart::stop();
}
upload_isrunning_ = in_progress;
}
// checks system health and handles LED flashing wizardry
void System::loop() {
// check if we're supposed to do a reset/restart
if (restart_requested()) {
if (systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED) {
system_restart();
}
@@ -706,7 +686,7 @@ void System::heartbeat_json(JsonObject output) {
#ifndef EMSESP_STANDALONE
output["freemem"] = getHeapMem();
output["max_alloc"] = getMaxAllocMem();
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
output["temperature"] = temperature_;
#endif
#endif
@@ -790,8 +770,8 @@ void System::system_check() {
#ifndef EMSESP_STANDALONE
#if defined(CONFIG_IDF_TARGET_ESP32)
uint8_t raw = temprature_sens_read();
temperature_ = (raw - 32) / 1.8f; // convert to Celsius
uint8_t raw = temprature_sens_read();
temperature_ = (raw - 32) / 1.8f; // convert to Celsius
#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
#if ESP_IDF_VERSION_MAJOR < 5
temp_sensor_read_celsius(&temperature_);
@@ -1901,7 +1881,7 @@ bool System::load_board_profile(std::vector<int8_t> & data, const std::string &
return true;
}
// format command - factory reset, removing all config files
// format command - factory reset, removing all config fi`les
bool System::command_format(const char * value, const int8_t id) {
LOG_INFO("Removing all config files");
#ifndef EMSESP_STANDALONE
@@ -1915,8 +1895,8 @@ bool System::command_format(const char * value, const int8_t id) {
}
#endif
EMSESP::system_.restart_requested(true); // will be handled by the main loop
// restart will be handled by the main loop
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
return true;
}
@@ -1926,11 +1906,13 @@ bool System::command_restart(const char * value, const int8_t id) {
// if it has an id then it's a web call and we need to queue the restart
// default id is -1 when calling /api/system/restart directly for example
LOG_INFO("Preparing to restart system");
EMSESP::system_.restart_pending(true);
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_PENDING_RESTART);
return true;
}
LOG_INFO("Restarting system immediately");
EMSESP::system_.restart_requested(true); // will be handled by the main loop
// restart will be handled by the main loop
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
return true;
}
@@ -2022,25 +2004,38 @@ String System::getBBQKeesGatewayDetails() {
// Stream from an URL and send straight to OTA uploader service.
//
// This function needs to be called twice, once with a url to persist it, and second with no arguments to start the upload
// This function needs to be called twice, 1st pass once with a url to persist it, 2nd pass with no arguments to start the upload
// This is to avoid timeouts in callback functions, like calling from a web hook.
bool System::uploadFirmwareURL(const char * url) {
#ifndef EMSESP_STANDALONE
static String saved_url;
// if the URL is not empty, store the URL for the 2nd pass
// if the URL is not empty, store the URL for the 2nd pass and exit
if (url && strlen(url) > 0) {
// if the passed URL is "reset" abort the current upload. This is called when an error happens during OTA
if (strncmp(url, "reset", 5) == 0) {
LOG_DEBUG("Firmware upload - resetting");
saved_url.clear();
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_NORMAL);
return true;
}
// given a URL to download from, save it
saved_url = url;
EMSESP::system_.upload_isrunning(true); // tell EMS-ESP we're ready to start the uploading process
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_PENDING_UPLOAD); // we're ready to start the upload
return true;
}
// make sure we have a valid URL
// assumed we have a valid URL from the 1st pass
if (saved_url.isEmpty()) {
LOG_ERROR("Firmware upload failed - invalid URL");
return false; // error
}
LOG_INFO("Firmware downloading from %s", saved_url.c_str());
Shell::loop_all(); // flush log buffers so latest messages are shown in console
// Configure temporary client
HTTPClient http;
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); // important for GitHub 302's
@@ -2051,42 +2046,46 @@ bool System::uploadFirmwareURL(const char * url) {
// start a connection, returns -1 if fails
int httpCode = http.GET();
if (httpCode != HTTP_CODE_OK) {
LOG_ERROR("Firmware upload failed. URL %s, HTTP code %d", saved_url.c_str(), httpCode);
LOG_ERROR("Firmware upload failed - HTTP code %d", httpCode);
http.end();
return false; // error
}
// check we have enough space for the upload in the ota partition
int firmware_size = http.getSize();
LOG_INFO("Firmware uploading (file: %s, size: %d bytes). Please wait...", saved_url.c_str(), firmware_size);
LOG_INFO("Firmware uploading (size: %d bytes). Please wait...", firmware_size);
if (!Update.begin(firmware_size)) {
LOG_ERROR("Firmware upload failed - no space");
http.end();
return false; // error
}
// flush log buffers so latest messages are shown
Shell::loop_all();
Shell::loop_all(); // flush log buffers so latest messages are shown in console
// TODO do we need to stop the UART with EMSuart::stop() ?
// get tcp stream and send it to Updater
WiFiClient * stream = http.getStreamPtr();
if (Update.writeStream(*stream) != firmware_size) {
LOG_ERROR("Firmware upload failed - size differences");
http.end();
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_ERROR_UPLOAD);
return false; // error
}
if (!Update.end(true)) {
LOG_ERROR("Firmware upload failed - general error");
http.end();
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_ERROR_UPLOAD);
return false; // error
}
// finished with upload
http.end();
EMSESP::system_.upload_isrunning(false);
saved_url.clear(); // prevent from downloading again
LOG_INFO("Firmware uploaded successfully. Restarting...");
restart_pending(true);
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
#endif
return true; // OK
@@ -2148,4 +2147,14 @@ bool System::command_read(const char * value, const int8_t id) {
return readCommand(value);
}
// set the system status code - SYSTEM_STATUS in system.h
void System::systemStatus(uint8_t status_code) {
systemStatus_ = status_code;
LOG_DEBUG("Setting System status code %d", status_code);
}
uint8_t System::systemStatus() {
return systemStatus_;
}
} // namespace emsesp

View File

@@ -59,6 +59,17 @@ namespace emsesp {
enum PHY_type : uint8_t { PHY_TYPE_NONE = 0, PHY_TYPE_LAN8720, PHY_TYPE_TLK110 };
enum SYSTEM_STATUS : uint8_t {
SYSTEM_STATUS_NORMAL = 0,
SYSTEM_STATUS_PENDING_UPLOAD = 1,
SYSTEM_STATUS_UPLOADING = 2,
SYSTEM_STATUS_ERROR_UPLOAD = 3,
SYSTEM_STATUS_RESTARTING = 4,
SYSTEM_STATUS_ERROR = 5,
SYSTEM_STATUS_PENDING_RESTART = 6,
SYSTEM_STATUS_RESTART_REQUESTED = 7
};
class System {
public:
void start();
@@ -88,8 +99,7 @@ class System {
void store_nvs_values();
void system_restart(const char * partition = nullptr);
void upload_isrunning(bool in_progress);
bool upload_isrunning();
void show_mem(const char * note);
void reload_settings();
void syslog_init();
@@ -122,6 +132,9 @@ class System {
void button_init(bool refresh);
void commands_init();
void systemStatus(uint8_t status_code);
uint8_t systemStatus();
static void extractSettings(const char * filename, const char * section, JsonObject output);
static bool saveSettings(const char * filename, const char * section, JsonObject input);
@@ -130,20 +143,6 @@ class System {
static bool readCommand(const char * data);
static void restart_requested(bool restart_requested) {
restart_requested_ = restart_requested;
}
static bool restart_requested() {
return restart_requested_;
}
static void restart_pending(bool restart_pending) {
restart_pending_ = restart_pending;
}
static bool restart_pending() {
return restart_pending_;
}
bool telnet_enabled() {
return telnet_enabled_;
}
@@ -341,11 +340,12 @@ class System {
private:
static uuid::log::Logger logger_;
static bool restart_requested_;
static bool restart_pending_; // used in 2-stage process to call restart from Web API
static bool test_set_all_active_; // force all entities in a device to have a value
static uint32_t max_alloc_mem_;
static uint32_t heap_mem_;
static bool test_set_all_active_; // force all entities in a device to have a value
static uint32_t max_alloc_mem_;
static uint32_t heap_mem_;
uint8_t systemStatus_; // uses SYSTEM_STATUS enum
// button
static PButton myPButton_; // PButton instance