schedulder enhancement url json #1806

This commit is contained in:
MichaelDvP
2024-07-19 12:45:27 +02:00
parent b857eedab8
commit 559caeb30f
2 changed files with 95 additions and 6 deletions

View File

@@ -18,6 +18,7 @@
#include "emsesp.h"
#include "WebSchedulerService.h"
#include <HTTPClient.h>
namespace emsesp {
@@ -330,6 +331,33 @@ bool WebSchedulerService::has_commands() {
// execute scheduled command
bool WebSchedulerService::command(const char * name, const char * cmd, const char * data) {
// check http commands. e.g.
// tasmota(get): http://<tasmotsIP>/cm?cmnd=power%20ON
// shelly(get): http://<shellyIP>/relais/0?turn=on
const char * c = strchr(cmd, '{');
if (c) { // parse json
JsonDocument doc;
int httpResult = 0;
if (DeserializationError::Ok == deserializeJson(doc, c)) {
HTTPClient http;
String url = doc["url"];
if (http.begin(url)) {
for (JsonPair p : doc["header"].as<JsonObject>()) {
http.addHeader(p.key().c_str(), p.value().as<String>().c_str());
}
String value = doc["value"] | "";
if (value.length()) {
httpResult = http.POST(value);
} else if (data && data[0] != '\0') { // post
httpResult = http.POST(String(data));
} else {
httpResult = http.GET();
}
http.end();
}
}
return httpResult > 0;
}
JsonDocument doc_input;
JsonObject input = doc_input.to<JsonObject>();
if (strlen(data)) { // empty data queries a value
@@ -390,12 +418,12 @@ void WebSchedulerService::condition() {
#ifdef EMESESP_DEBUG
// emsesp::EMSESP::logger().debug("condition match: %s", match.c_str());
#endif
if (!match.empty() && match[0] == '1') {
if (scheduleItem.retry_cnt == 0xFF) { // default unswitched
if (match.length() == 1 && match[0] == '1' && scheduleItem.retry_cnt == 0xFF) {
scheduleItem.retry_cnt = command(scheduleItem.name.c_str(), scheduleItem.cmd.c_str(), compute(scheduleItem.value).c_str()) ? 1 : 0xFF;
}
} else if (scheduleItem.retry_cnt == 1) {
} else if (match.length() == 1 && match[0] == '0' && scheduleItem.retry_cnt == 1) {
scheduleItem.retry_cnt = 0xFF;
} else if (match.length() != 1) { // the match is not boolean
emsesp::EMSESP::logger().debug("condition result: %s", match.c_str());
}
}
}

View File

@@ -63,6 +63,22 @@ std::deque<Token> exprToTokens(const std::string & expr) {
for (const auto * p = expr.c_str(); *p; ++p) {
if (isblank(*p)) {
// do nothing
} else if (*p == '{') { // json is stored as string including {}
const auto * b = p;
++p;
uint8_t i = 1;
while (*p && i > 0) {
i += (*p == '{') ? 1 : (*p == '}') ? -1 : 0;
++p;
}
if (*p) {
++p;
}
const auto s = std::string(b, p);
tokens.push_back(Token{Token::Type::String, s, -3});
if (*p == '\0') {
--p;
}
} else if (*p >= 'a' && *p <= 'z') {
const auto * b = p;
while ((*p >= 'a' && *p <= 'z') || (*p == '_')) {
@@ -579,7 +595,52 @@ std::string calculate(const std::string & expr) {
// check for multiple instances of <cond> ? <expr1> : <expr2>
std::string compute(const std::string & expr) {
auto expr_new = expr;
auto expr_new = emsesp::Helpers::toLower(expr);
// search json with url:
auto f = expr_new.find_first_of("{");
while (f != std::string::npos) {
auto e = f + 1;
for (uint8_t i = 1; i > 0; e++) {
if (e >= expr_new.length()) {
return "";
} else if (expr_new[e] == '}') {
i--;
} else if (expr_new[e] == '{') {
i++;
}
}
std::string cmd = expr_new.substr(f, e - f).c_str();
JsonDocument doc;
if (DeserializationError::Ok == deserializeJson(doc, cmd)) {
HTTPClient http;
String url = doc["url"];
if (http.begin(url)) {
int httpResult = 0;
for (JsonPair p : doc["header"].as<JsonObject>()) {
http.addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
}
String data = doc["value"] | "";
if (data.length()) {
httpResult = http.POST(data);
} else {
httpResult = http.GET();
}
if (httpResult > 0) {
std::string result = emsesp::Helpers::toLower(http.getString().c_str());
String key = doc["key"] | "";
doc.clear();
if (key.length() && DeserializationError::Ok == deserializeJson(doc, result)) {
result = doc[key.c_str()].as<std::string>();
}
expr_new.replace(f, e - f, result.c_str());
}
http.end();
}
}
f = expr_new.find_first_of("{", e);
}
// positions: q-questionmark, c-colon
auto q = expr_new.find_first_of("?");
while (q != std::string::npos) {