Merge branch 'commands' of github.com:proddy/EMS-ESP32 into commands

This commit is contained in:
proddy
2026-06-13 17:16:40 +02:00
4 changed files with 20 additions and 39 deletions

View File

@@ -32,6 +32,7 @@
#include <map> #include <map>
#include "firmwareVersion.h" #include "firmwareVersion.h"
#include "shuntingYard.h" // for compute() used by the message and sendmail commands
#if defined(EMSESP_TEST) #if defined(EMSESP_TEST)
#include "../test/test.h" #include "../test/test.h"
@@ -194,15 +195,11 @@ bool System::command_sendmail(const char * value, const int8_t id) {
// msg.headers.addCustom("Importance", PRIORITY); // msg.headers.addCustom("Importance", PRIORITY);
// msg.headers.addCustom("X-MSMail-Priority", PRIORITY); // msg.headers.addCustom("X-MSMail-Priority", PRIORITY);
// msg.headers.addCustom("X-Priority", PRIORITY_NUM); // msg.headers.addCustom("X-Priority", PRIORITY_NUM);
EMSESP::webSchedulerService.computed_value.clear(); // run the body through the Shunting Yard calculator (entity substitution, expressions, optional {url} fetch)
EMSESP::webSchedulerService.raw_value = body.c_str(); // keep the original body if the calculator returns nothing
for (uint16_t wait = 0; wait < 2000 && !EMSESP::webSchedulerService.raw_value.empty(); wait++) { std::string computed_body = compute(body.c_str());
delay(1); if (!computed_body.empty()) {
} body = computed_body.c_str();
if (!EMSESP::webSchedulerService.computed_value.empty()) {
body = EMSESP::webSchedulerService.computed_value.c_str();
EMSESP::webSchedulerService.computed_value.clear();
EMSESP::webSchedulerService.computed_value.shrink_to_fit(); // free allocated memory
} }
msg.text.body(body); msg.text.body(body);
@@ -344,22 +341,16 @@ bool System::command_message(const char * value, const int8_t id, JsonObject out
return false; // must have a string value return false; // must have a string value
} }
EMSESP::webSchedulerService.computed_value.clear(); // process the message via the Shunting Yard calculator (entity substitution, expressions, optional {url} fetch)
EMSESP::webSchedulerService.raw_value = value; std::string computed_value = compute(value);
for (uint16_t wait = 0; wait < 2000 && !EMSESP::webSchedulerService.raw_value.empty(); wait++) { if (computed_value.empty()) {
delay(1);
}
if (EMSESP::webSchedulerService.computed_value.empty()) {
LOG_WARNING("Message result is empty"); LOG_WARNING("Message result is empty");
return false; return false;
} }
LOG_INFO("Message: %s", EMSESP::webSchedulerService.computed_value.c_str()); // send to log LOG_INFO("Message: %s", computed_value.c_str()); // send to log
Mqtt::queue_publish(F_(message), EMSESP::webSchedulerService.computed_value); // send to MQTT if enabled Mqtt::queue_publish(F_(message), computed_value); // send to MQTT if enabled
output["api_data"] = EMSESP::webSchedulerService.computed_value; // send to API output["api_data"] = computed_value; // send to API
EMSESP::webSchedulerService.computed_value.clear();
EMSESP::webSchedulerService.computed_value.shrink_to_fit();
return true; return true;
} }

View File

@@ -141,14 +141,12 @@ bool WebCommandService::dispatchCommand(const char * name, const char * value) {
if (isUrlCommand(ci->cmd.c_str())) { if (isUrlCommand(ci->cmd.c_str())) {
return queueCommand(name, value); return queueCommand(name, value);
} }
// system/message defers evaluation of its value (via the scheduler's raw_value), // internal command whose value embeds a {url} fetch (e.g. system/message) - the value is
// so executing it never blocks - keep it synchronous even if the value has a {url} // resolved by compute() at execution time and would block, so offload it to the worker task
if (Helpers::toLower(ci->cmd.c_str()) != "system/message") { // the effective value is the override if given, else the command's stored default
// the effective value is the override if given, else the command's stored default const std::string effective_value = value ? value : std::string(ci->value.c_str());
const std::string effective_value = value ? value : std::string(ci->value.c_str()); if (valueContainsUrl(effective_value)) {
if (valueContainsUrl(effective_value)) { return queueCommand(name, value);
return queueCommand(name, value);
}
} }
} }
} }
@@ -240,8 +238,8 @@ bool WebCommandService::executeCommand(const char * name, const std::string & co
// run the value through the shunting-yard calculator so expressions like "custom/heatcnt + 1" // run the value through the shunting-yard calculator so expressions like "custom/heatcnt + 1"
// are resolved (entity references replaced by their values, then computed). Plain values pass // are resolved (entity references replaced by their values, then computed). Plain values pass
// through unchanged. Applies to both URL and internal commands, like the old scheduler code // through unchanged. Applies to both URL and internal commands, like the old scheduler code
// which computed the value before executing. system/message evaluates its own argument later // which computed the value before executing. system/message runs the shunting-yard on its own
// (deferred via the scheduler's raw_value), so pre-computing it would run it twice - pass raw. // argument, so pre-computing it here would run it twice - pass it through raw.
std::string computed_data = data; std::string computed_data = data;
if (!data.empty() && cmd != "system/message") { if (!data.empty() && cmd != "system/message") {
computed_data = compute(data); computed_data = compute(data);

View File

@@ -367,11 +367,6 @@ void WebSchedulerService::loop() {
static uint32_t last_uptime_min = 0; static uint32_t last_uptime_min = 0;
static uint32_t last_uptime_sec = 0; static uint32_t last_uptime_sec = 0;
if (!raw_value.empty()) {
computed_value = compute(raw_value);
raw_value.clear();
}
if (scheduleItems_->empty()) { if (scheduleItems_->empty()) {
return; return;
} }

View File

@@ -75,9 +75,6 @@ class WebSchedulerService : public StatefulService<WebScheduler> {
std::string get_metrics_prometheus(); std::string get_metrics_prometheus();
std::string raw_value;
std::string computed_value;
#if defined(EMSESP_TEST) #if defined(EMSESP_TEST)
void load_test_data(); void load_test_data();
#endif #endif