diff --git a/src/command.cpp b/src/command.cpp index 643fbb8ae..416dbab15 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -334,10 +334,10 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * // first see if there is a command registered and it's valid auto cf = find_command(device_type, device_id, cmd, flag); if (!cf) { - LOG_WARNING("Command failed: invalid command '%s'", cmd ? cmd : ""); + LOG_WARNING("Command failed: unknown command '%s'", cmd ? cmd : ""); // if we don't alread have a message set, set it to invalid command if (!output["message"]) { - output["message"] = "invalid command"; + output["message"] = "unknown command"; } return CommandRet::ERROR; } @@ -360,39 +360,45 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * snprintf(info_s, sizeof(info_s), "'%s/%s'", dname, cmd); } - if (single_command) { - LOG_DEBUG(("%sCalling command %s"), ro.c_str(), info_s); - } else { - if (id > 0) { - LOG_INFO(("%sCalling command %s with value %s and id %d on device 0x%02X"), ro.c_str(), info_s, value, id, device_id); - } else { - LOG_INFO(("%sCalling command %s with value %s"), ro.c_str(), info_s, value); - } - } - - // call the function based on type, either with a json package or no parameters + // call the function based on command function type + // commands return true or false only (bool) uint8_t return_code = CommandRet::OK; if (cf->cmdfunction_json_) { - // JSON + // handle commands that report back a JSON body return_code = ((cf->cmdfunction_json_)(value, id, output)) ? CommandRet::OK : CommandRet::ERROR; } else if (cf->cmdfunction_) { - // Normal command + // if it's a read only command and we're trying to set a value, return an error if (!single_command && EMSESP::cmd_is_readonly(device_type, device_id, cmd, id)) { return_code = CommandRet::INVALID; // error on readonly or invalid hc } else { + // call it... return_code = ((cf->cmdfunction_)(value, id)) ? CommandRet::OK : CommandRet::ERROR; } } - // report back. If not OK show output from error, other return the HTTP code + // report back. If not OK show output from error, otherwise return the HTTP code if (return_code != CommandRet::OK) { + char error[100]; if (single_command) { - LOG_ERROR("Command '%s' failed with error '%s'", cmd, FL_(cmdRet)[return_code]); + snprintf(error, sizeof(error), "Command '%s' failed (%s)", cmd, FL_(cmdRet)[return_code]); } else { - LOG_ERROR("Command '%s: %s' failed with error '%s'", cmd, value, FL_(cmdRet)[return_code]); + snprintf(error, sizeof(error), "Command '%s: %s' failed (%s)", cmd, value, FL_(cmdRet)[return_code]); + } + output.clear(); + output["message"] = error; + LOG_WARNING(error); + } else { + if (single_command) { + LOG_DEBUG(("%sCalling command %s"), ro.c_str(), info_s); + } else { + if (id > 0) { + LOG_INFO(("%sCalling command %s with value %s and id %d on device 0x%02X"), ro.c_str(), info_s, value, id, device_id); + } else { + LOG_INFO(("%sCalling command %s with value %s"), ro.c_str(), info_s, value); + } } - return message(return_code, "callback function failed", output); } + return return_code; } @@ -523,7 +529,13 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo std::list sorted_cmds; for (const auto & cf : cmdfunctions_) { if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) { - sorted_cmds.push_back(tagged_cmd(cf.cmd_, cf.flags_)); + // remove duplicates + auto line = tagged_cmd(cf.cmd_, cf.flags_); + // only add if not already in list + // removes duplicates if having more than one device (e.g. 2 thermostats) + if (std::find(sorted_cmds.begin(), sorted_cmds.end(), line) == sorted_cmds.end()) { + sorted_cmds.push_back(line); + } } } diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 328ef02a3..93997a555 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -746,11 +746,19 @@ void EMSESP::publish_response(std::shared_ptr telegram) { // for other types like sensors, scheduler, custom entities it will process single commands like 'info', 'values', 'commands'... bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8_t id, const uint8_t devicetype) { // check first for EMS devices + bool found_device = false; for (const auto & emsdevice : emsdevices) { if (emsdevice->device_type() == devicetype) { - return emsdevice->get_value_info(root, cmd, id); + found_device = true; + if (emsdevice->get_value_info(root, cmd, id)) { + return true; + } } } + // if the EMS device was valid, but the cmd not found show an error + if (found_device) { + // return EMSESP::return_not_found(root, "poep", cmd); // not found + } // check for other devices... @@ -786,7 +794,7 @@ bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8 bool EMSESP::return_not_found(JsonObject output, const char * msg, const char * cmd) { output.clear(); char error[100]; - snprintf(error, sizeof(error), "cannot find %s in '%s'", msg, cmd); + snprintf(error, sizeof(error), "cannot find %s in %s", msg, cmd); output["message"] = error; return false; } diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index cdb323d31..af835df54 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -124,15 +124,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject input) { // call command uint8_t return_code = Command::process(request->url().c_str(), is_admin, input, output); - if (return_code != CommandRet::OK) { - char error[100]; - if (output.size()) { - snprintf(error, sizeof(error), "API call failed. %s (%s)", (const char *)output["message"], Command::return_code_string(return_code).c_str()); - } else { - snprintf(error, sizeof(error), "API call failed (%s)", Command::return_code_string(return_code).c_str()); - } - emsesp::EMSESP::logger().err(error); api_fails_++; } @@ -142,10 +134,10 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject input) { if (api_data) { request->send(200, "text/plain; charset=utf-8", api_data); #if defined(EMSESP_STANDALONE) + Serial.println(); Serial.printf("%sweb output: %s[%s] %s(200)%s ", COLOR_WHITE, COLOR_BRIGHT_CYAN, request->url().c_str(), COLOR_BRIGHT_GREEN, COLOR_MAGENTA); serializeJson(output, Serial); Serial.println(COLOR_RESET); - Serial.println(); #endif api_count_++; delete response; @@ -166,11 +158,11 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject input) { api_count_++; #if defined(EMSESP_STANDALONE) + Serial.println(); Serial.printf("%sweb output: %s[%s]", COLOR_WHITE, COLOR_BRIGHT_CYAN, request->url().c_str()); Serial.printf(" %s(%d)%s ", ret_codes[return_code] == 200 ? COLOR_BRIGHT_GREEN : COLOR_BRIGHT_RED, ret_codes[return_code], COLOR_YELLOW); serializeJson(output, Serial); Serial.println(COLOR_RESET); - Serial.println(); #endif }