mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-09 01:09:51 +03:00
Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev
This commit is contained in:
@@ -184,7 +184,8 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec
|
||||
}
|
||||
|
||||
// call the command based on the type
|
||||
uint8_t return_code = CommandRet::ERROR;
|
||||
uint8_t return_code = CommandRet::OK;
|
||||
|
||||
if (data.is<const char *>()) {
|
||||
return_code = Command::call(device_type, command_p, data.as<const char *>(), is_admin, id_n, output);
|
||||
} else if (data.is<int>()) {
|
||||
@@ -312,11 +313,17 @@ bool Command::set_attribute(JsonObject output, const char * cmd, const char * at
|
||||
return true;
|
||||
}
|
||||
|
||||
// not found
|
||||
output.clear();
|
||||
|
||||
// attribute isn't found
|
||||
// it could be a value command, but the value doesn't exist?
|
||||
if (strcmp(attribute, "value") == 0) {
|
||||
LOG_DEBUG("%s has no value set", cmd);
|
||||
return false; // fail
|
||||
}
|
||||
|
||||
char error[100];
|
||||
snprintf(error, sizeof(error), "no %s in %s", attribute, cmd);
|
||||
snprintf(error, sizeof(error), "no attribute '%s' in %s", attribute, cmd);
|
||||
output["message"] = error;
|
||||
return false;
|
||||
}
|
||||
@@ -356,7 +363,7 @@ uint8_t Command::call(const uint8_t device_type, const char * command, const cha
|
||||
return CommandRet::OK;
|
||||
}
|
||||
} else if (device_type == EMSdevice::DeviceType::SYSTEM && strchr(cmd, '/')) {
|
||||
// check service commands, if not found continue with commandsfunctions
|
||||
// check service commands, if not found continue with command functions
|
||||
if (EMSESP::system_.command_service(cmd, value)) {
|
||||
return CommandRet::OK;
|
||||
}
|
||||
@@ -376,14 +383,23 @@ uint8_t Command::call(const uint8_t device_type, const char * command, const cha
|
||||
flag = CommandFlag::CMD_FLAG_AHS;
|
||||
}
|
||||
|
||||
// see if there is a command registered and it's valid
|
||||
// see if there is a command registered for this EMS device
|
||||
auto cf = find_command(device_type, device_id, cmd, flag);
|
||||
if (!cf) {
|
||||
// if we don't already have a message set, set it to invalid command
|
||||
if (output["message"]) {
|
||||
LOG_WARNING("Command failed: %s", output["message"].as<const char *>());
|
||||
return CommandRet::ERROR;
|
||||
} else {
|
||||
std::string err = "no " + std::string(cmd) + " in " + dname;
|
||||
// not an error, no test if we're fetching a value, but the value is not set
|
||||
auto attribute_s = Command::get_attribute(cmd);
|
||||
if (attribute_s) {
|
||||
if (strcmp(attribute_s, "value") == 0) {
|
||||
return CommandRet::NO_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
std::string err = "no entity '" + std::string(cmd) + "' in " + dname;
|
||||
output["message"] = err;
|
||||
LOG_WARNING("Command failed: %s", err.c_str());
|
||||
}
|
||||
@@ -496,7 +512,7 @@ Command::CmdFunction * Command::find_command(const uint8_t device_type, const ui
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr; // command not found
|
||||
return nullptr; // command not found, could be an attribute?
|
||||
}
|
||||
|
||||
void Command::erase_device_commands(const uint8_t device_type) {
|
||||
|
||||
@@ -48,7 +48,8 @@ enum CommandRet : uint8_t {
|
||||
NOT_FOUND, // 2
|
||||
ERROR, // 3
|
||||
NOT_ALLOWED, // 4 - needs authentication
|
||||
INVALID // 5 - invalid (tag)
|
||||
INVALID, // 5 - invalid (tag)
|
||||
NO_VALUE // 6 - no value
|
||||
};
|
||||
|
||||
using cmd_function_p = std::function<bool(const char * data, const int8_t id)>;
|
||||
|
||||
@@ -1528,6 +1528,7 @@ bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t
|
||||
if (cmd_s == Helpers::toLower(dv.short_name) && (tag <= 0 || tag == dv.tag)) {
|
||||
get_value_json(output, dv);
|
||||
// if we're filtering on an attribute, go find it
|
||||
// if we can't find it, maybe it exists but doesn't not have a value assigned yet
|
||||
return Command::set_attribute(output, cmd_s, attribute_s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -780,6 +780,7 @@ bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the EMS device was valid, but the cmd not found exit. it will be handled upstream.
|
||||
if (found_device) {
|
||||
return false;
|
||||
|
||||
@@ -380,7 +380,13 @@ std::string commands(std::string & expr, bool quotes = true) {
|
||||
JsonObject output = doc_out.to<JsonObject>();
|
||||
JsonObject input = doc_in.to<JsonObject>();
|
||||
std::string cmd_s = "api/" + std::string(cmd);
|
||||
emsesp::Command::process(cmd_s.c_str(), true, input, output);
|
||||
|
||||
auto return_code = emsesp::Command::process(cmd_s.c_str(), true, input, output);
|
||||
// check for no value (entity is valid but has no value set)
|
||||
if (return_code != emsesp::CommandRet::OK && return_code != emsesp::CommandRet::NO_VALUE) {
|
||||
return expr = "";
|
||||
}
|
||||
|
||||
std::string data = output["api_data"] | "";
|
||||
if (!isnum(data) && quotes) {
|
||||
data.insert(data.begin(), '"');
|
||||
|
||||
@@ -324,20 +324,15 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
if (command == "general") {
|
||||
shell.printfln("Testing adding a boiler, thermostat, all sensors, scheduler and custom entities...");
|
||||
|
||||
// setup fake data
|
||||
// EMSESP::webCustomizationService.test(); // set customizations - this will overwrite any settings in the FS
|
||||
|
||||
// add devices
|
||||
test("general");
|
||||
|
||||
// EMSESP::webCustomEntityService.test(); // add custom entities
|
||||
// EMSESP::temperaturesensor_.test(); // add temperature sensors
|
||||
// EMSESP::webSchedulerService.test(); // add scheduler items
|
||||
EMSESP::webCustomEntityService.test(); // custom entities
|
||||
EMSESP::webCustomizationService.test(); // set customizations - this will overwrite any settings in the FS
|
||||
EMSESP::temperaturesensor_.test(); // add temperature sensors
|
||||
EMSESP::webSchedulerService.test(); // run scheduler tests, and conditions
|
||||
|
||||
// shell.invoke_command("show devices");
|
||||
// shell.invoke_command("show values");
|
||||
// shell.invoke_command("call system publish");
|
||||
// shell.invoke_command("show mqtt");
|
||||
shell.invoke_command("show values");
|
||||
ok = true;
|
||||
}
|
||||
|
||||
@@ -1089,6 +1084,10 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
// request.url("/api/boiler/comfort/value");
|
||||
// EMSESP::webAPIService.webAPIService(&request);
|
||||
|
||||
// this should fail but it doesn't
|
||||
// request.url("/api/boiler/bad/value");
|
||||
// EMSESP::webAPIService.webAPIService(&request);
|
||||
|
||||
// POST COMMANDS
|
||||
request.method(HTTP_POST);
|
||||
|
||||
|
||||
@@ -134,12 +134,13 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject input) {
|
||||
}
|
||||
|
||||
// send the json that came back from the command call
|
||||
// sequence is FAIL, OK, NOT_FOUND, ERROR, NOT_ALLOWED, INVALID
|
||||
// sequence matches CommandRet in command.h (FAIL, OK, NOT_FOUND, ERROR, NOT_ALLOWED, INVALID, NO_VALUE)
|
||||
// 400 (bad request)
|
||||
// 200 (OK)
|
||||
// 404 (not found)
|
||||
// 401 (unauthorized)
|
||||
int ret_codes[6] = {400, 200, 404, 400, 401, 400};
|
||||
// 400 (invalid)
|
||||
int ret_codes[7] = {400, 200, 404, 400, 401, 400, 404};
|
||||
response->setCode(ret_codes[return_code]);
|
||||
response->setLength();
|
||||
response->setContentType("application/json; charset=utf-8");
|
||||
|
||||
@@ -105,7 +105,7 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web
|
||||
if (entityItem.ram == 0 && entityItem.value_type == DeviceValueType::STRING) {
|
||||
entityItem.raw = new uint8_t[(size_t)entityItem.factor + 1];
|
||||
entityItem.data = "";
|
||||
entityItem.uom = 0;
|
||||
entityItem.uom = 0;
|
||||
} else if (entityItem.value_type == DeviceValueType::BOOL) {
|
||||
entityItem.value = EMS_VALUE_DEFAULT_BOOL;
|
||||
entityItem.uom = 0;
|
||||
|
||||
@@ -165,6 +165,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
||||
if (Helpers::toLower(scheduleItem.name) == cmd) {
|
||||
get_value_json(output, scheduleItem);
|
||||
@@ -385,7 +386,6 @@ bool WebSchedulerService::command(const char * name, const std::string & command
|
||||
snprintf(command_str, sizeof(command_str), "/api/%s", cmd.c_str());
|
||||
|
||||
uint8_t return_code = Command::process(command_str, true, input, output); // admin set
|
||||
|
||||
if (return_code == CommandRet::OK) {
|
||||
#if defined(EMSESP_DEBUG)
|
||||
EMSESP::logger().debug("Schedule command '%s' with data '%s' was successful", cmd.c_str(), data.c_str());
|
||||
@@ -596,10 +596,6 @@ void WebSchedulerService::test() {
|
||||
test_value = "(custom/seltemp)";
|
||||
command("test5", test_cmd.c_str(), compute(test_value).c_str());
|
||||
|
||||
// note: this will fail unless test("boiler") is loaded before hand
|
||||
test_value = "(boiler/outdoortemp)";
|
||||
command("test6", test_cmd.c_str(), compute(test_value).c_str());
|
||||
|
||||
test_value = "boiler/flowtempoffset";
|
||||
command("test7", test_cmd.c_str(), compute(test_value).c_str());
|
||||
|
||||
@@ -613,10 +609,35 @@ void WebSchedulerService::test() {
|
||||
test_value = "(custom/seltemp - boiler/flowtempoffset) * 2.8 + 5";
|
||||
command("test10", test_cmd.c_str(), compute(test_value).c_str());
|
||||
|
||||
test_cmd = "{\"method\":\"POST\",\"url\":\"http://192.168.1.42:8123/api/services/script/test_notify2\", \"header\":{\"authorization\":\"Bearer "
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhMmNlYWI5NDgzMmI0ODE2YWQ2NzU4MjkzZDE2YWMxZSIsImlhdCI6MTcyMTM5MTI0NCwiZXhwIjoyMDM2NzUxMjQ0fQ."
|
||||
"S5sago1tEI6lNhrDCO0dM_WsVQHkD_laAjcks8tWAqo\"}}";
|
||||
command("test11", test_cmd.c_str(), "");
|
||||
// test case conversion
|
||||
test_value = "(thermostat/hc1/modetype == \"comfort\")";
|
||||
command("test11a", test_cmd.c_str(), compute(test_value).c_str()); // should be 1 true
|
||||
test_value = "(thermostat/hc1/modetype == \"Comfort\")";
|
||||
command("test11b", test_cmd.c_str(), compute(test_value).c_str()); // should be 1 true
|
||||
test_value = "(thermostat/hc1/modetype == \"unknown\")";
|
||||
command("test11c", test_cmd.c_str(), compute(test_value).c_str()); // should be 0 false
|
||||
|
||||
// can't find entity, should fail
|
||||
test_value = "(boiler/storagetemp/value1)";
|
||||
command("test12", test_cmd.c_str(), compute(test_value).c_str());
|
||||
|
||||
// can't find attribute, should fail
|
||||
test_value = "(boiler/storagetemp1/value1)";
|
||||
command("test13", test_cmd.c_str(), compute(test_value).c_str());
|
||||
|
||||
// check when entity has no value, should pass
|
||||
test_value = "(boiler/storagetemp2/value)";
|
||||
command("test14", test_cmd.c_str(), compute(test_value).c_str());
|
||||
|
||||
// should pass
|
||||
test_value = "(boiler/storagetemp1/value)";
|
||||
command("test15", test_cmd.c_str(), compute(test_value).c_str());
|
||||
|
||||
// test HTTP POST to call HA script
|
||||
// test_cmd = "{\"method\":\"POST\",\"url\":\"http://192.168.1.42:8123/api/services/script/test_notify2\", \"header\":{\"authorization\":\"Bearer "
|
||||
// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhMmNlYWI5NDgzMmI0ODE2YWQ2NzU4MjkzZDE2YWMxZSIsImlhdCI6MTcyMTM5MTI0NCwiZXhwIjoyMDM2NzUxMjQ0fQ."
|
||||
// "S5sago1tEI6lNhrDCO0dM_WsVQHkD_laAjcks8tWAqo\"}}";
|
||||
// command("test99", test_cmd.c_str(), "");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user