From 0b8034a3d65bede57e629ec32861b62f356d0e6b Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 18:52:36 +0200 Subject: [PATCH 01/24] package update --- interface/package.json | 2 +- interface/yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/interface/package.json b/interface/package.json index ba8e0301b..45b98a2fb 100644 --- a/interface/package.json +++ b/interface/package.json @@ -47,7 +47,7 @@ "react-router-dom": "^6.25.1", "react-toastify": "^10.0.5", "typesafe-i18n": "^5.26.2", - "typescript": "^5.5.3" + "typescript": "^5.5.4" }, "devDependencies": { "@babel/core": "^7.24.9", diff --git a/interface/yarn.lock b/interface/yarn.lock index d82e9f326..fc0d16864 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -2109,7 +2109,7 @@ __metadata: rollup-plugin-visualizer: "npm:^5.12.0" terser: "npm:^5.31.3" typesafe-i18n: "npm:^5.26.2" - typescript: "npm:^5.5.3" + typescript: "npm:^5.5.4" typescript-eslint: "npm:8.0.0-alpha.10" vite: "npm:^5.3.4" vite-plugin-imagemin: "npm:^0.6.1" @@ -7297,23 +7297,23 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.5.3": - version: 5.5.3 - resolution: "typescript@npm:5.5.3" +"typescript@npm:^5.5.4": + version: 5.5.4 + resolution: "typescript@npm:5.5.4" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/f52c71ccbc7080b034b9d3b72051d563601a4815bf3e39ded188e6ce60813f75dbedf11ad15dd4d32a12996a9ed8c7155b46c93a9b9c9bad1049766fe614bbdd + checksum: 10c0/422be60f89e661eab29ac488c974b6cc0a660fb2228003b297c3d10c32c90f3bcffc1009b43876a082515a3c376b1eefcce823d6e78982e6878408b9a923199c languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.5.3#optional!builtin": - version: 5.5.3 - resolution: "typescript@patch:typescript@npm%3A5.5.3#optional!builtin::version=5.5.3&hash=b45daf" +"typescript@patch:typescript@npm%3A^5.5.4#optional!builtin": + version: 5.5.4 + resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin::version=5.5.4&hash=b45daf" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/5a437c416251334deeaf29897157032311f3f126547cfdc4b133768b606cb0e62bcee733bb97cf74c42fe7268801aea1392d8e40988cdef112e9546eba4c03c5 + checksum: 10c0/10dd9881baba22763de859e8050d6cb6e2db854197495c6f1929b08d1eb2b2b00d0b5d9b0bcee8472f1c3f4a7ef6a5d7ebe0cfd703f853aa5ae465b8404bc1ba languageName: node linkType: hard From ad561129a2e30aeedf24a703e176ba0b4d29a4f7 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 18:52:46 +0200 Subject: [PATCH 02/24] remove unused imports --- interface/src/app/status/Status.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/app/status/Status.tsx b/interface/src/app/status/Status.tsx index e3e1f679a..9e8d97327 100644 --- a/interface/src/app/status/Status.tsx +++ b/interface/src/app/status/Status.tsx @@ -9,7 +9,6 @@ import DeviceHubIcon from '@mui/icons-material/DeviceHub'; import DirectionsBusIcon from '@mui/icons-material/DirectionsBus'; import LogoDevIcon from '@mui/icons-material/LogoDev'; import MemoryIcon from '@mui/icons-material/Memory'; -import PermScanWifiIcon from '@mui/icons-material/PermScanWifi'; import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew'; import RefreshIcon from '@mui/icons-material/Refresh'; import RouterIcon from '@mui/icons-material/Router'; @@ -34,7 +33,6 @@ import { import * as SystemApi from 'api/system'; -import * as EMSESP from 'app/main/api'; import { dialogStyle } from 'CustomTheme'; import { useRequest } from 'alova'; import { busConnectionStatus } from 'app/main/types'; From 49ca42d683eea457e1476a67516d207a28ae9718 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 18:53:03 +0200 Subject: [PATCH 03/24] updated tesst with system commands like send --- src/test/test.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index c79aea1a5..6a3d53ad5 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -968,13 +968,35 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (single) { // run dedicated tests only - // 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 + 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 - // request.url("/api/thermostat/commands"); - // EMSESP::webAPIService.webAPIService(&request); + request.method(HTTP_POST); + + char data[] = "{\"cmd\":\"send\",\"data\":\"0B 90 FF 13 01 01 B9 01\"}"; + deserializeJson(doc, data); + json = doc.as(); + request.url("/api/system"); + EMSESP::webAPIService.webAPIService(&request, json); + + char data2[] = "{\"device\":\"system\", \"cmd\":\"send\",\"value\":\"0B 90 FF 13 01 01 B9 02\"}"; + deserializeJson(doc, data2); + json = doc.as(); + request.url("/api"); + EMSESP::webAPIService.webAPIService(&request, json); + + char data4[] = "{\"value\":\"0B 90 FF 13 01 01 B9 03\"}"; + deserializeJson(doc, data4); + json = doc.as(); + request.url("/api/system/send"); + EMSESP::webAPIService.webAPIService(&request, json); + + request.method(HTTP_GET); + + request.url("/api/thermostat/commands"); + EMSESP::webAPIService.webAPIService(&request); request.url("/api/thermostat/hc1/mode2"); EMSESP::webAPIService.webAPIService(&request); @@ -991,6 +1013,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const EMSESP::temperaturesensor_.test(); // add temperature sensors EMSESP::webSchedulerService.test(); // run scheduler tests, and conditions + request.method(HTTP_GET); + // boiler request.url("/api/boiler"); EMSESP::webAPIService.webAPIService(&request); @@ -1049,6 +1073,32 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const request.url("/api/analogsensor/test_analog1/offset"); EMSESP::webAPIService.webAPIService(&request); + // system calls with POST + request.method(HTTP_POST); + + // these next 3 should return empty JSON in their response + char data[] = "{\"cmd\":\"send\",\"data\":\"0B 90 FF 13 01 01 B9 01\"}"; + deserializeJson(doc, data); + json = doc.as(); + request.url("/api/system"); + EMSESP::webAPIService.webAPIService(&request, json); + + char data2[] = "{\"device\":\"system\", \"cmd\":\"send\",\"value\":\"0B 90 FF 13 01 01 B9 02\"}"; + deserializeJson(doc, data2); + json = doc.as(); + request.url("/api"); + EMSESP::webAPIService.webAPIService(&request, json); + + char data4[] = "{\"value\":\"0B 90 FF 13 01 01 B9 03\"}"; + deserializeJson(doc, data4); + json = doc.as(); + request.url("/api/system/send"); + EMSESP::webAPIService.webAPIService(&request, json); + + // console commands + shell.invoke_command("call system fetch"); + shell.invoke_command("call system send \"0B 90 FF 13 01 01 B9\""); + // // This next batch should all fail // From 0d0d0aa111a200f929f4dbe8ae4d53e6e60c765c Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 18:54:17 +0200 Subject: [PATCH 04/24] show attribute in log message --- src/analogsensor.cpp | 2 +- src/emsdevice.cpp | 5 +---- src/temperaturesensor.cpp | 2 +- src/web/WebCustomEntityService.cpp | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 39902f7f1..c07135672 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -705,7 +705,7 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int output["api_data"] = data; // always as a string return true; } - return EMSESP::return_not_found(output, "attribute", sensor_name); // not found + return EMSESP::return_not_found(output, attribute_s, sensor_name); // not found } return true; // found a match, exit } diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index d2f255ef2..b3d65fdd5 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -1598,16 +1598,13 @@ bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t // if we're filtering on an attribute, go find it if (attribute_s) { -#if defined(EMSESP_DEBUG) - EMSESP::logger().debug("[DEBUG] fetching single attribute %s", attribute_s); -#endif if (json.containsKey(attribute_s)) { std::string data = json[attribute_s].as(); output.clear(); output["api_data"] = data; // always as string return true; } - return EMSESP::return_not_found(output, "attribute", command_s); // not found + return EMSESP::return_not_found(output, attribute_s, command_s); // not found } return true; diff --git a/src/temperaturesensor.cpp b/src/temperaturesensor.cpp index 6919cc054..d94ce1255 100644 --- a/src/temperaturesensor.cpp +++ b/src/temperaturesensor.cpp @@ -402,7 +402,7 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons output["api_data"] = data; // always as string return true; } - return EMSESP::return_not_found(output, "attribute", sensor_name); // not found + return EMSESP::return_not_found(output, attribute_s, sensor_name); // not found } return true; // found a match, exit } diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index 612f86b64..94f538861 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -325,7 +325,7 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) output["api_data"] = data; // always as string return true; } - return EMSESP::return_not_found(output, "attribute", command_s); // not found + return EMSESP::return_not_found(output, attribute_s, command_s); // not found } } From 48b5970d2810216f8c0c5e61f39c74b9025c2601 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 18:55:26 +0200 Subject: [PATCH 05/24] text changes --- src/command.cpp | 12 ++++++------ src/console.cpp | 3 ++- src/emsesp.cpp | 4 ++-- src/web/WebAPIService.cpp | 3 ++- src/web/WebDataService.cpp | 2 +- src/web/WebSchedulerService.cpp | 1 - 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index d6d12fb88..16d9b1126 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -172,7 +172,7 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec } uint8_t device_type = EMSdevice::device_name_2_device_type(device_p); - if (CommandRet::OK != Command::call(device_type, data_s, "", true, id_d, output)) { + if (Command::call(device_type, data_s, "", true, id_d, output) != CommandRet::OK) { return CommandRet::INVALID; } @@ -334,7 +334,7 @@ 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 + // see if there is a command registered and it's valid auto cf = find_command(device_type, device_id, cmd, flag); if (!cf) { std::string err = std::string("unknown command ") + cmd; @@ -376,7 +376,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * 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... + // call the command... return_code = ((cf->cmdfunction_)(value, id)) ? CommandRet::OK : CommandRet::ERROR; } } @@ -394,12 +394,12 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * LOG_WARNING(error); } else { if (single_command) { - LOG_DEBUG(("%sCalling command %s"), ro.c_str(), info_s); + LOG_DEBUG(("%sCalled 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); + LOG_INFO(("%sCalled 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); + LOG_INFO(("%sCalled command %s with value %s"), ro.c_str(), info_s, value); } } } diff --git a/src/console.cpp b/src/console.cpp index 1067f592f..6d3eb7387 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -575,11 +575,12 @@ static void setup_commands(std::shared_ptr & commands) { return; } else { // show message if no data returned (e.g. for analogsensor, temperaturesensor, custom) - shell.println("No data."); + shell.println("No data returned."); return; } } + if (return_code == CommandRet::NOT_FOUND) { shell.println("Unknown command"); shell.print("Available commands are: "); diff --git a/src/emsesp.cpp b/src/emsesp.cpp index ba181a051..d085f8490 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -742,8 +742,8 @@ void EMSESP::publish_response(std::shared_ptr telegram) { buffer = nullptr; } -// builds json with the detail of each value, for a given EMS device -// for other types like sensors, scheduler, custom entities it will process single commands like 'info', 'values', 'commands', 'entities'... +// builds json with the detail of each value, for a given device type +// device type can be EMS devices looking for entities, or a sensor/scheduler/custom entity etc looking for values extracted from the info command 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; diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index af835df54..e9c4d5608 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -55,8 +55,9 @@ void WebAPIService::webAPIService(AsyncWebServerRequest * request, JsonVariant j // HTTP GET JsonDocument input_doc; // has no body JSON so create dummy as empty input object input = input_doc.to(); + } else { - // HTTP_POST | HTTP_PUT | HTTP_PATCH + // HTTP_POST input = json.as(); // extract values from the json. these will be used as default values } parse(request, input); diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 7cfb6b2f0..a423e5d0b 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -245,7 +245,7 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar return_code = Command::call(device_type, cmd, data.as() ? "true" : "false", true, id, output); } - // write debug + // write log if (return_code != CommandRet::OK) { EMSESP::logger().err("Write command failed %s (%s)", (const char *)output["message"], Command::return_code_string(return_code)); } else { diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index c52613cf5..bc56d6f7a 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -604,7 +604,6 @@ void WebSchedulerService::test() { test_value = "(custom/seltemp - boiler/flowtempoffset) * 2.8 + 5"; command("test10", test_cmd.c_str(), compute(test_value).c_str()); - // TODO add some more HTTP/URI tests test_cmd = "{\"method\":\"POST\",\"url\":\"http://192.168.1.42:8123/api/services/script/test_notify2\", \"header\":{\"authorization\":\"Bearer " "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhMmNlYWI5NDgzMmI0ODE2YWQ2NzU4MjkzZDE2YWMxZSIsImlhdCI6MTcyMTM5MTI0NCwiZXhwIjoyMDM2NzUxMjQ0fQ." "S5sago1tEI6lNhrDCO0dM_WsVQHkD_laAjcks8tWAqo\"}}"; From baf381461f9741dbb4e9b45442cc74309a2274e7 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 18:57:50 +0200 Subject: [PATCH 06/24] fix system commands - #1886 --- src/system.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/system.cpp b/src/system.cpp index 25ffdc458..34a55a525 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -144,24 +144,20 @@ bool System::command_fetch(const char * value, const int8_t id) { if (value_s == "all") { LOG_INFO("Requesting data from EMS devices"); EMSESP::fetch_device_values(); - return true; } else if (value_s == (F_(boiler))) { EMSESP::fetch_device_values_type(EMSdevice::DeviceType::BOILER); - return true; } else if (value_s == (F_(thermostat))) { EMSESP::fetch_device_values_type(EMSdevice::DeviceType::THERMOSTAT); - return true; } else if (value_s == (F_(solar))) { EMSESP::fetch_device_values_type(EMSdevice::DeviceType::SOLAR); - return true; } else if (value_s == (F_(mixer))) { EMSESP::fetch_device_values_type(EMSdevice::DeviceType::MIXER); - return true; } + } else { + EMSESP::fetch_device_values(); // default if no name or id is given } - EMSESP::fetch_device_values(); // default if no name or id is given - return true; + return true; // always true } // mqtt publish @@ -1295,6 +1291,7 @@ bool System::saveSettings(const char * filename, const char * section, JsonObjec return false; // not found } +// return back a system value bool System::get_value_info(JsonObject root, const char * command) { if (command == nullptr || strlen(command) == 0) { LOG_ERROR("empty system command"); @@ -1344,8 +1341,9 @@ bool System::get_value_info(JsonObject root, const char * command) { } } + root.clear(); // empty json output, as it may have the default output from an info command earlier + if (!s.empty()) { - root.clear(); if (val) { root["api_data"] = s; } else { @@ -1354,7 +1352,7 @@ bool System::get_value_info(JsonObject root, const char * command) { return true; // found } - return EMSESP::return_not_found(root, "data", command); // not found + return false; // not found } // export status information including the device information From e30c2b673e43a82b6dc2148404a428e775b80e8c Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 20:47:49 +0200 Subject: [PATCH 07/24] more tests --- src/test/test.cpp | 55 ++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index 6a3d53ad5..5ddbf879a 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -973,38 +973,13 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const EMSESP::temperaturesensor_.test(); // add temperature sensors EMSESP::webSchedulerService.test(); // run scheduler tests, and conditions - request.method(HTTP_POST); - - char data[] = "{\"cmd\":\"send\",\"data\":\"0B 90 FF 13 01 01 B9 01\"}"; - deserializeJson(doc, data); - json = doc.as(); - request.url("/api/system"); - EMSESP::webAPIService.webAPIService(&request, json); - - char data2[] = "{\"device\":\"system\", \"cmd\":\"send\",\"value\":\"0B 90 FF 13 01 01 B9 02\"}"; - deserializeJson(doc, data2); - json = doc.as(); - request.url("/api"); - EMSESP::webAPIService.webAPIService(&request, json); - - char data4[] = "{\"value\":\"0B 90 FF 13 01 01 B9 03\"}"; - deserializeJson(doc, data4); - json = doc.as(); - request.url("/api/system/send"); - EMSESP::webAPIService.webAPIService(&request, json); - request.method(HTTP_GET); - request.url("/api/thermostat/commands"); + request.url("/api/boiler/bad"); EMSESP::webAPIService.webAPIService(&request); - - request.url("/api/thermostat/hc1/mode2"); + request.url("/api/boiler/bad/value"); EMSESP::webAPIService.webAPIService(&request); - - request.url("/api/thermostat/hc2/mode"); - EMSESP::webAPIService.webAPIService(&request); - - request.url("/api/thermostat/hc1/mode"); + request.url("/api/boiler/bad/valu"); EMSESP::webAPIService.webAPIService(&request); } else { @@ -1042,22 +1017,32 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // custom request.url("/api/custom"); EMSESP::webAPIService.webAPIService(&request); + request.url("/api/custom/info"); + EMSESP::webAPIService.webAPIService(&request); request.url("/api/custom/seltemp"); EMSESP::webAPIService.webAPIService(&request); // system request.url("/api/system"); EMSESP::webAPIService.webAPIService(&request); + request.url("/api/system/info"); + EMSESP::webAPIService.webAPIService(&request); request.url("/api/system/settings/locale"); EMSESP::webAPIService.webAPIService(&request); // scheduler + request.url("/api/scheduler"); + EMSESP::webAPIService.webAPIService(&request); request.url("/api/scheduler/info"); EMSESP::webAPIService.webAPIService(&request); request.url("/api/scheduler/test_scheduler"); EMSESP::webAPIService.webAPIService(&request); // temperaturesensor + request.url("/api/temperaturesensor"); + EMSESP::webAPIService.webAPIService(&request); + request.url("/api/temperaturesensor/info"); + EMSESP::webAPIService.webAPIService(&request); request.url("/api/temperaturesensor/test_sensor2"); EMSESP::webAPIService.webAPIService(&request); request.url("/api/temperaturesensor/0B_0C0D_0E0F_1011"); @@ -1068,6 +1053,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // analogsensor request.url("/api/analogsensor"); EMSESP::webAPIService.webAPIService(&request); + request.url("/api/analogsensor/info"); + EMSESP::webAPIService.webAPIService(&request); request.url("/api/analogsensor/test_analog1"); EMSESP::webAPIService.webAPIService(&request); request.url("/api/analogsensor/test_analog1/offset"); @@ -1120,14 +1107,24 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // system request.url("/api/system/settings/locale2"); EMSESP::webAPIService.webAPIService(&request); + request.url("/api/system/settings2"); + EMSESP::webAPIService.webAPIService(&request); + request.url("/api/system/settings2/locale2"); + EMSESP::webAPIService.webAPIService(&request); // scheduler request.url("/api/scheduler/test_scheduler2"); EMSESP::webAPIService.webAPIService(&request); + request.url("/api/scheduler/test_scheduler/val"); + EMSESP::webAPIService.webAPIService(&request); + request.url("/api/scheduler/test_scheduler2/val2"); + EMSESP::webAPIService.webAPIService(&request); // custom request.url("/api/custom/seltemp2"); EMSESP::webAPIService.webAPIService(&request); + request.url("/api/custom/seltemp/val"); + EMSESP::webAPIService.webAPIService(&request); // temperaturesensor request.url("/api/temperaturesensor/test_sensor20"); @@ -1142,7 +1139,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const EMSESP::webAPIService.webAPIService(&request); request.url("/api/analogsensor/test_analog10"); EMSESP::webAPIService.webAPIService(&request); - request.url("/api/analogsensor/test_analog10/bad"); + request.url("/api/analogsensor/test_analog10/bad2"); EMSESP::webAPIService.webAPIService(&request); } } From 76418dd39d733a72ced1ead569f6865075df39c5 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 20:48:06 +0200 Subject: [PATCH 08/24] show message if there is no error message set --- src/command.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index 85fc28f52..1210c47e5 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -343,16 +343,20 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * // see if there is a command registered and it's valid auto cf = find_command(device_type, device_id, cmd, flag); if (!cf) { - std::string err = std::string("unknown command ") + cmd; - LOG_WARNING("Command failed: %s", err.c_str()); - - // if we don't alread have a message set, set it to invalid command - if (!output["message"]) { + // 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()); + } else { + std::string err = "no command " + std::string(cmd) + " in " + dname; output["message"] = err; + LOG_WARNING("Command failed: %s", err.c_str()); } return CommandRet::ERROR; } + // TODO here + output.clear(); // we have a command function, clear messages from device_value_info + // before calling the command, check permissions and abort if not authorized if (cf->has_flags(CommandFlag::ADMIN_ONLY) && !is_admin) { LOG_WARNING("Command failed: authentication failed"); From ae9aaf327c4aaf2a6a168a0a0c6a5f487c56db79 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 20:48:15 +0200 Subject: [PATCH 09/24] text change --- src/emsesp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index d085f8490..a5088f1af 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -794,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), "%s not found in %s", msg, cmd); output["message"] = error; return false; } From 0e40acb90fb48a5cb078c10a21cdaa70deebc53c Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 20:48:30 +0200 Subject: [PATCH 10/24] formatting for logging in debug/standalone --- src/web/WebAPIService.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index e9c4d5608..5880f4c98 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -135,7 +135,6 @@ 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); @@ -159,7 +158,6 @@ 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); From ada7b1740b024560774ac40124f496d8ffadcc71 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 20:48:52 +0200 Subject: [PATCH 11/24] handle attribute_s like we did with the other device classes --- src/web/WebSchedulerService.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index bc56d6f7a..bcc77eff8 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -196,14 +196,18 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { output["readable"] = true; output["writeable"] = true; output["visible"] = true; + break; } } - if (attribute_s && output.containsKey(attribute_s)) { - std::string data = output[attribute_s].as(); - output.clear(); - output["api_data"] = data; // always as a string - return true; + if (attribute_s) { + if (output.containsKey(attribute_s)) { + std::string data = output[attribute_s].as(); + output.clear(); + output["api_data"] = data; // always as a string + return true; + } + return EMSESP::return_not_found(output, attribute_s, command_s); // not found } if (output.size()) { From fa24a6878e0d2f521305c101fad2eb418c20a7c3 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 22:29:30 +0200 Subject: [PATCH 12/24] add values as a possible command --- src/command.cpp | 4 +++- src/web/WebCustomEntityService.cpp | 4 +++- src/web/WebSchedulerService.cpp | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index 1210c47e5..fda02bb98 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -510,10 +510,11 @@ std::string Command::tagged_cmd(const std::string & cmd, const uint8_t flag) { // list all commands for a specific device, output as json bool Command::list(const uint8_t device_type, JsonObject output) { - // force add info and commands for those non-EMS devices + // check of it a 'commands' command if (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR || device_type == EMSdevice::DeviceType::ANALOGSENSOR) { output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); + output[F_(values)] = Helpers::translated_word(FL_(values_cmd)); } else if (cmdfunctions_.empty()) { output["message"] = "no commands available"; return false; @@ -555,6 +556,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo if (!verbose && show_info) { sorted_cmds.push_back(F_(info)); sorted_cmds.push_back(F_(commands)); + sorted_cmds.push_back(F_(values)); } sorted_cmds.sort(); // sort them diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index 94f538861..f174d0885 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -256,10 +256,12 @@ void WebCustomEntityService::show_values(JsonObject output) { // process json output for info/commands and value_info bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) { - // if it's commands... + // check of it a 'commands' command if (Helpers::toLower(cmd) == F_(commands)) { output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); + output[F_(values)] = Helpers::translated_word(FL_(values_cmd)); + for (const auto & entity : *customEntityItems_) { if (entity.writeable) { output[entity.name] = "custom entity"; diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index bcc77eff8..52b44c5fa 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -136,6 +136,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { if (Helpers::toLower(cmd) == F_(commands)) { output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); + output[F_(values)] = Helpers::translated_word(FL_(values_cmd)); for (const ScheduleItem & scheduleItem : *scheduleItems_) { if (!scheduleItem.name.empty()) { From 89e9b14347b0943f8e99ab3a3e04ff059fc4d263 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 22:29:41 +0200 Subject: [PATCH 13/24] add values_cmd --- src/locale_translations.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/locale_translations.h b/src/locale_translations.h index 024c5b0cf..360d67ea4 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -74,8 +74,9 @@ MAKE_WORD_TRANSLATION(schedule_cmd, "enable schedule item", "Aktiviere Zeitplan" MAKE_WORD_TRANSLATION(entity_cmd, "set custom value on ems", "Sende eigene Entitäten zu EMS", "verstuur custom waarde naar EMS", "", "wyślij własną wartość na EMS", "", "", "emp üzerinde özel değer ayarla", "imposta valori personalizzati su EMS", "nastaviť vlastnú hodnotu na ems") // TODO translate MAKE_WORD_TRANSLATION(commands_response, "get response", "Hole Antwort", "Verzoek om antwoord", "", "uzyskaj odpowiedź", "", "", "gelen cevap", "", "získať odpoveď") // TODO translate MAKE_WORD_TRANSLATION(coldshot_cmd, "send a cold shot of water", "", "", "", "uruchom tryśnięcie zimnej wody", "", "", "soğuk su gönder", "", "pošlite studenú dávku vody") // TODO translate -MAKE_WORD_TRANSLATION(allvalues_cmd, "output all values", "", "", "", "wyświetl wszystkie wartości", "", "", "", "", "vypísať všetky hodnoty") // TODO translate +MAKE_WORD_TRANSLATION(allvalues_cmd, "output all values in system", "", "", "", "wyświetl wszystkie wartości", "", "", "", "", "vypísať všetky hodnoty") // TODO translate MAKE_WORD_TRANSLATION(message_cmd, "send a message", "", "", "", "", "", "", "", "", "") // TODO translate +MAKE_WORD_TRANSLATION(values_cmd, "list all values", "", "", "", "", "", "", "", "", "") // TODO translate // tags MAKE_WORD_TRANSLATION(tag_hc1, "hc1", "HK1", "hc1", "VK1", "OG1", "hc1", "hc1", "ID1", "hc1", "hc1") From ee87b75cf564017af8a5f3f4177851c303452197 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 22:30:40 +0200 Subject: [PATCH 14/24] prevent 'call system test' crashing --- src/system.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/system.cpp b/src/system.cpp index 34a55a525..9fd089d53 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -853,7 +853,6 @@ void System::commands_init() { Command::add(EMSdevice::DeviceType::SYSTEM, F("response"), System::command_response, FL_(commands_response)); Command::add(EMSdevice::DeviceType::SYSTEM, F("allvalues"), System::command_allvalues, FL_(allvalues_cmd)); - // MQTT subscribe "ems-esp/system/#" Mqtt::subscribe(EMSdevice::DeviceType::SYSTEM, "system/#", nullptr); // use empty function callback } @@ -1621,7 +1620,11 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output #if defined(EMSESP_TEST) // run a test, e.g. http://ems-esp/api?device=system&cmd=test&data=boiler bool System::command_test(const char * value, const int8_t id) { - return Test::test(value, id); + if (value) { + return Test::test(value, id); + } else { + return false; + } } #endif From 0028dbfb4f7d82fa8fc2dba3bd0f51162b1178ea Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 22:32:24 +0200 Subject: [PATCH 15/24] package update --- interface/package.json | 4 ++-- interface/yarn.lock | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/interface/package.json b/interface/package.json index 45b98a2fb..06a9f0717 100644 --- a/interface/package.json +++ b/interface/package.json @@ -30,7 +30,7 @@ "@mui/material": "^5.16.4", "@table-library/react-table-library": "4.1.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^20.14.11", + "@types/node": "^20.14.12", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@types/react-router-dom": "^5.3.3", @@ -59,7 +59,7 @@ "concurrently": "^8.2.2", "eslint": "^9.7.0", "eslint-config-prettier": "^9.1.0", - "preact": "^10.22.1", + "preact": "^10.23.0", "prettier": "^3.3.3", "rollup-plugin-visualizer": "^5.12.0", "terser": "^5.31.3", diff --git a/interface/yarn.lock b/interface/yarn.lock index fc0d16864..a67fdcdba 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -1839,12 +1839,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.14.11": - version: 20.14.11 - resolution: "@types/node@npm:20.14.11" +"@types/node@npm:^20.14.12": + version: 20.14.12 + resolution: "@types/node@npm:20.14.12" dependencies: undici-types: "npm:~5.26.4" - checksum: 10c0/5306becc0ff41d81b1e31524bd376e958d0741d1ce892dffd586b9ae0cb6553c62b0d62abd16da8bea6b9a2c17572d360450535d7c073794b0cef9cb4e39691e + checksum: 10c0/59bc5fa11fdd23fd517f859063118f54a1ab53d3399ef63c926f8902429d7453abc0db22ef4b0a6110026b6ab81b6472fee894e1d235c24b01a0b3e10cfae0bb languageName: node linkType: hard @@ -2085,7 +2085,7 @@ __metadata: "@trivago/prettier-plugin-sort-imports": "npm:^4.3.0" "@types/babel__core": "npm:^7" "@types/lodash-es": "npm:^4.17.12" - "@types/node": "npm:^20.14.11" + "@types/node": "npm:^20.14.12" "@types/react": "npm:^18.3.3" "@types/react-dom": "npm:^18.3.0" "@types/react-router-dom": "npm:^5.3.3" @@ -2098,7 +2098,7 @@ __metadata: jwt-decode: "npm:^4.0.0" lodash-es: "npm:^4.17.21" mime-types: "npm:^2.1.35" - preact: "npm:^10.22.1" + preact: "npm:^10.23.0" prettier: "npm:^3.3.3" react: "npm:latest" react-dom: "npm:latest" @@ -6070,10 +6070,10 @@ __metadata: languageName: node linkType: hard -"preact@npm:^10.22.1": - version: 10.22.1 - resolution: "preact@npm:10.22.1" - checksum: 10c0/9163b97d6fc0ce6b945ed77695d00c4fa07e317d0723e7b9d10c748153d30596abab8b26861ae45591e47bff25515da91406ce7f1c9e66cd9cac7e7f6c927930 +"preact@npm:^10.23.0": + version: 10.23.0 + resolution: "preact@npm:10.23.0" + checksum: 10c0/00bcf490ce13c0fd70e3d2e2418466419b31f201b28d35f173d7ddcb66b421a3f6ca569541de581cbbf4ec7b2adef3f391d631dca7a4fd86708d81ca08259c1c languageName: node linkType: hard From c4f4abf1bd7e68eafe3575b58eb3a2e0ba2dbd3b Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 23:06:16 +0200 Subject: [PATCH 16/24] remove compression --- mock-api/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/mock-api/package.json b/mock-api/package.json index 082d68200..ceb516ae8 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -12,7 +12,6 @@ "dependencies": { "@msgpack/msgpack": "^2.8.0", "@types/multer": "^1.4.11", - "compression": "^1.7.4", "express": "^4.19.2", "itty-router": "^5.0.17", "multer": "^1.4.5-lts.1" From 70344ce8326bd74bfa4895a46294ccfa43a2e18b Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 23:06:46 +0200 Subject: [PATCH 17/24] rename deviceID - removing space --- src/emsesp.cpp | 2 +- src/locale_common.h | 2 +- src/telegram.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index a5088f1af..31ac33dca 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -1312,7 +1312,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const default_name = "Cascaded Controller"; device_type = DeviceType::CONTROLLER; } else { - LOG_WARNING("Unrecognized EMS device (device ID 0x%02X, no product ID). Please report on GitHub.", device_id); + LOG_WARNING("Unrecognized EMS device (deviceID 0x%02X, no productID). Please report on GitHub.", device_id); return false; } } diff --git a/src/locale_common.h b/src/locale_common.h index 0426b05fe..0f28f5a17 100644 --- a/src/locale_common.h +++ b/src/locale_common.h @@ -151,7 +151,7 @@ MAKE_WORD_CUSTOM(nvs_optional, "[nvs]") MAKE_WORD_CUSTOM(offset_optional, "[offset]") MAKE_WORD_CUSTOM(length_optional, "[length]") MAKE_WORD_CUSTOM(typeid_mandatory, "") -MAKE_WORD_CUSTOM(deviceid_mandatory, "") +MAKE_WORD_CUSTOM(deviceid_mandatory, "") MAKE_WORD_CUSTOM(device_type_optional, "[device]") MAKE_WORD_CUSTOM(invalid_log_level, "Invalid log level") MAKE_WORD_CUSTOM(log_level_optional, "[level]") diff --git a/src/telegram.cpp b/src/telegram.cpp index 45d99d2c6..07c5f406c 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -554,7 +554,7 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt // send a Tx telegram to request data from an EMS device void TxService::read_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t length, const bool front) { - LOG_DEBUG("Tx read request to device 0x%02X for type ID 0x%02X", dest, type_id); + LOG_DEBUG("Tx read request to deviceID 0x%02X for typeID 0x%02X", dest, type_id); uint8_t message_data = (type_id > 0xFF) ? (EMS_MAX_TELEGRAM_MESSAGE_LENGTH - 2) : EMS_MAX_TELEGRAM_MESSAGE_LENGTH; if (length > 0 && length < message_data) { From 93e4e4ba0d496f2dfa586ee9ca1833d8bc292d09 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 23:07:04 +0200 Subject: [PATCH 18/24] increase rx/tx queue when running standalone --- src/telegram.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/telegram.h b/src/telegram.h index 72c4ff0de..f9e4bd966 100644 --- a/src/telegram.h +++ b/src/telegram.h @@ -32,8 +32,13 @@ #include "helpers.h" +#if defined(EMSESP_STANDALONE) +#define MAX_RX_TELEGRAMS 100 // size of Rx queue +#define MAX_TX_TELEGRAMS 200 // size of Tx queue +#else #define MAX_RX_TELEGRAMS 10 // size of Rx queue #define MAX_TX_TELEGRAMS 100 // size of Tx queue +#endif // default values for null values static constexpr uint8_t EMS_VALUE_BOOL = 0xFF; // used to mark that something is a boolean From 0cca9b7723e0ae69469524ac4297d1f2654f3ac3 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 23:07:12 +0200 Subject: [PATCH 19/24] removed comment --- src/web/WebCustomizationService.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index f016a0f5e..86239f466 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -239,8 +239,6 @@ void WebCustomizationService::writeDeviceName(AsyncWebServerRequest * request, J uint8_t device_id = emsdevice->device_id(); auto custom_name = json["name"].as(); - // emsesp::EMSESP::logger().info("Found Device ID: %d, Product ID: %d", device_id, product_id); - // updates current record or creates a new one bool entry_exists = false; update([&](WebCustomization & settings) { From 5c2aa638423a4d1bb6f9dc2738066ba7c1b4bfae Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 23 Jul 2024 23:07:52 +0200 Subject: [PATCH 20/24] bump to 3.7.0-dev.27 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 7ba5e93f1..9f72e133d 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.7.0-dev.26" +#define EMSESP_APP_VERSION "3.7.0-dev.27" From 0054a89c3889bf955ac6ebd8c4dcedc0834b07d6 Mon Sep 17 00:00:00 2001 From: proddy Date: Wed, 24 Jul 2024 09:33:39 +0200 Subject: [PATCH 21/24] add test for system commands - to see what is logged --- src/test/test.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index 5ddbf879a..187843d14 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -953,8 +953,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const bool single; - // single = true; - single = false; + single = true; + // single = false; AsyncWebServerRequest request; JsonDocument doc; @@ -968,18 +968,14 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (single) { // run dedicated tests only - 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 + // 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("call system fetch"); request.method(HTTP_GET); - - request.url("/api/boiler/bad"); - EMSESP::webAPIService.webAPIService(&request); - request.url("/api/boiler/bad/value"); - EMSESP::webAPIService.webAPIService(&request); - request.url("/api/boiler/bad/valu"); + request.url("/api/system/fetch"); EMSESP::webAPIService.webAPIService(&request); } else { @@ -1029,6 +1025,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const EMSESP::webAPIService.webAPIService(&request); request.url("/api/system/settings/locale"); EMSESP::webAPIService.webAPIService(&request); + request.url("/api/system/fetch"); + EMSESP::webAPIService.webAPIService(&request); // scheduler request.url("/api/scheduler"); From fa54cb6a48a13729135121c2c80f568816557262 Mon Sep 17 00:00:00 2001 From: proddy Date: Wed, 24 Jul 2024 13:22:34 +0200 Subject: [PATCH 22/24] more minor changes to clean up messaging --- src/analogsensor.cpp | 2 +- src/command.cpp | 27 +++++++++++----------- src/console.cpp | 13 +++++------ src/emsdevice.cpp | 30 +++++++++++++----------- src/emsesp.cpp | 10 +++----- src/locale_translations.h | 2 +- src/system.cpp | 20 ++++++++-------- src/temperaturesensor.cpp | 2 +- src/test/test.cpp | 37 ++++++++++++++++++++++-------- src/web/WebCustomEntityService.cpp | 3 ++- src/web/WebSchedulerService.cpp | 2 +- 11 files changed, 85 insertions(+), 63 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index c07135672..f36231f73 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -711,7 +711,7 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int } } - return EMSESP::return_not_found(output, cmd, F_(analogsensor)); // not found + return false; // not found } void AnalogSensor::addSensorJson(JsonObject output, const Sensor & sensor) { diff --git a/src/command.cpp b/src/command.cpp index fda02bb98..a0825de1d 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -63,7 +63,6 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec int8_t id_n = -1; // default hc // check for a device as first item in the path - // if its not a known device (thermostat, boiler etc) look for any special MQTT subscriptions const char * device_s = nullptr; if (!num_paths) { // we must look for the device in the JSON body @@ -72,7 +71,7 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec } } else { // extract it from the path - device_s = p.paths().front().c_str(); // get the device (boiler, thermostat, system etc) + device_s = p.paths().front().c_str(); // get the device type name (boiler, thermostat, system etc) } // validate the device, make sure it exists @@ -347,16 +346,13 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * if (output["message"]) { LOG_WARNING("Command failed: %s", output["message"].as()); } else { - std::string err = "no command " + std::string(cmd) + " in " + dname; + std::string err = "no " + std::string(cmd) + " in " + dname; output["message"] = err; LOG_WARNING("Command failed: %s", err.c_str()); } return CommandRet::ERROR; } - // TODO here - output.clear(); // we have a command function, clear messages from device_value_info - // before calling the command, check permissions and abort if not authorized if (cf->has_flags(CommandFlag::ADMIN_ONLY) && !is_admin) { LOG_WARNING("Command failed: authentication failed"); @@ -404,12 +400,15 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * LOG_WARNING(error); } else { if (single_command) { - LOG_DEBUG(("%sCalled command %s"), ro.c_str(), info_s); + // TODO not sure if these should go to INFO as there may be a lot of calls, e.g. ioBroker + // TODO for now using debug (regarles if compiled with EMSESP_DEBUG) + // TODO mvdp ? + logger_.debug(("%sCalled command %s"), ro.c_str(), info_s); } else { if (id > 0) { - LOG_INFO(("%sCalled command %s with value %s and id %d on device 0x%02X"), ro.c_str(), info_s, value, id, device_id); + logger_.debug(("%sCalled command %s with value %s and id %d on device 0x%02X"), ro.c_str(), info_s, value, id, device_id); } else { - LOG_INFO(("%sCalled command %s with value %s"), ro.c_str(), info_s, value); + logger_.debug(("%sCalled command %s with value %s"), ro.c_str(), info_s, value); } } } @@ -549,7 +548,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo } } - // non EMS devices always have an info and commands command + // non EMS devices always have an info, commands and values bool show_info = (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR || device_type == EMSdevice::DeviceType::ANALOGSENSOR || device_type == EMSdevice::DeviceType::SCHEDULER || device_type == EMSdevice::DeviceType::CUSTOM); @@ -576,9 +575,11 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo // we hard code 'info' and 'commands' commands so print them first if (show_info) { - shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); + shell.printf(" info:\t\t\t\t%slist all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); shell.println(COLOR_RESET); - shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); + shell.printf(" commands:\t\t\t%slist all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); + shell.println(COLOR_RESET); + shell.printf(" values:\t\t\t%slist all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); shell.println(COLOR_RESET); } @@ -618,7 +619,6 @@ bool Command::device_has_commands(const uint8_t device_type) { return true; // we always have System } - // if there are no entries to scheduler/custom/temperaturesensor/analogsensor, don't error but return a message if (device_type == EMSdevice::DeviceType::SCHEDULER) { return true; } @@ -637,6 +637,7 @@ bool Command::device_has_commands(const uint8_t device_type) { for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice && (emsdevice->device_type() == device_type)) { + // TODO will this work for info, values etc?? // device found, now see if it has any commands for (const auto & cf : cmdfunctions_) { if (cf.device_type_ == device_type) { diff --git a/src/console.cpp b/src/console.cpp index 6d3eb7387..53eb61691 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -575,18 +575,17 @@ static void setup_commands(std::shared_ptr & commands) { return; } else { // show message if no data returned (e.g. for analogsensor, temperaturesensor, custom) - shell.println("No data returned."); + shell.println("Command executed. Check log for messages."); return; } - } - - - if (return_code == CommandRet::NOT_FOUND) { + } else if (return_code == CommandRet::NOT_FOUND) { shell.println("Unknown command"); shell.print("Available commands are: "); Command::show(shell, device_type, false); // non-verbose mode - } else if (return_code != CommandRet::OK) { - shell.printfln("Bad syntax (error code %d)", return_code); + } else if ((return_code == CommandRet::ERROR) || (return_code == CommandRet::FAIL)) { + shell.printfln("Bad syntax. Check arguments."); + } else { + shell.printfln("Command failed with error code %d", return_code); } }, [](Shell & shell, const std::vector & current_arguments, const std::string & next_argument) -> std::vector { diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index b3d65fdd5..ac8902250 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -212,9 +212,6 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) { if (!strcmp(lowtopic, F_(thermostat))) { return DeviceType::THERMOSTAT; } - if (!strcmp(lowtopic, F_(system))) { - return DeviceType::SYSTEM; - } if (!strcmp(lowtopic, F_(scheduler))) { return DeviceType::SCHEDULER; } @@ -227,12 +224,6 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) { if (!strcmp(lowtopic, F_(mixer))) { return DeviceType::MIXER; } - if (!strcmp(lowtopic, F_(temperaturesensor))) { - return DeviceType::TEMPERATURESENSOR; - } - if (!strcmp(lowtopic, F_(analogsensor))) { - return DeviceType::ANALOGSENSOR; - } if (!strcmp(lowtopic, F_(switch))) { return DeviceType::SWITCH; } @@ -248,9 +239,6 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) { if (!strcmp(lowtopic, F_(heatsource))) { return DeviceType::HEATSOURCE; } - if (!strcmp(lowtopic, F_(custom))) { - return DeviceType::CUSTOM; - } if (!strcmp(lowtopic, F_(ventilation))) { return DeviceType::VENTILATION; } @@ -261,6 +249,23 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) { return DeviceType::POOL; } + // non EMS + if (!strcmp(lowtopic, F_(custom))) { + return DeviceType::CUSTOM; + } + if (!strcmp(lowtopic, F_(temperaturesensor))) { + return DeviceType::TEMPERATURESENSOR; + } + if (!strcmp(lowtopic, F_(analogsensor))) { + return DeviceType::ANALOGSENSOR; + } + if (!strcmp(lowtopic, F_(scheduler))) { + return DeviceType::SCHEDULER; + } + if (!strcmp(lowtopic, F_(system))) { + return DeviceType::SYSTEM; + } + return DeviceType::UNKNOWN; } @@ -1606,7 +1611,6 @@ bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t } return EMSESP::return_not_found(output, attribute_s, command_s); // not found } - return true; } } diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 31ac33dca..c49316807 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -794,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), "%s not found in %s", msg, cmd); + snprintf(error, sizeof(error), "no %s in %s", msg, cmd); output["message"] = error; return false; } @@ -1363,13 +1363,9 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const device_type, F_(values), [device_type](const char * value, const int8_t id, JsonObject output) { - return EMSdevice::export_values(device_type, - output, - id, - EMSdevice::OUTPUT_TARGET::API_SHORTNAMES); // HIDDEN command showing short names, used in e.g. /api/boiler + return EMSdevice::export_values(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_SHORTNAMES); }, - nullptr, - CommandFlag::HIDDEN); // this command is hidden + FL_(values_cmd)); Command::add( device_type, F_(commands), diff --git a/src/locale_translations.h b/src/locale_translations.h index 360d67ea4..baf5c6100 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -59,7 +59,7 @@ MAKE_WORD_TRANSLATION(water_device, "Water Module", "Wassermodul", "", "", "Modu MAKE_WORD_TRANSLATION(pool_device, "Pool Module", "Poolmodul", "", "", "Moduł basenu", "", "", "", "", "") // TODO translate // commands -MAKE_WORD_TRANSLATION(info_cmd, "list all values", "Liste aller Werte", "lijst van alle waardes", "", "wyświetl wszystkie wartości", "Viser alle verdier", "", "Tüm değerleri listele", "elenca tutti i valori", "zobraziť všetky hodnoty") // TODO translate +MAKE_WORD_TRANSLATION(info_cmd, "list all values (verbose)", "Liste aller Werte", "lijst van alle waardes", "", "wyświetl wszystkie wartości", "Viser alle verdier", "", "Tüm değerleri listele", "elenca tutti i valori", "zobraziť všetky hodnoty") // TODO translate MAKE_WORD_TRANSLATION(commands_cmd, "list all commands", "Liste aller Kommandos", "lijst van alle commando's", "", "wyświetl wszystkie komendy", "Viser alle kommandoer", "", "Tüm komutları listele", "elencaa tutti i comandi", "zobraziť všetky príkazy") // TODO translate MAKE_WORD_TRANSLATION(entities_cmd, "list all entities", "Liste aller Entitäten", "lijst van alle entiteiten", "", "wyświetl wszsytkie encje", "Viser alle enheter", "", "Tüm varlıkları listele", "elenca tutte le entità", "zobraziť všetky entity") // TODO translate MAKE_WORD_TRANSLATION(send_cmd, "send a telegram", "Sende EMS-Telegramm", "stuur een telegram", "", "wyślij telegram", "send et telegram", "", "Bir telegram gönder", "invia un telegramma", "poslať telegram") // TODO translate diff --git a/src/system.cpp b/src/system.cpp index 9fd089d53..98f5e8555 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1297,8 +1297,18 @@ bool System::get_value_info(JsonObject root, const char * command) { return false; } + // cmd is lower case of the command char cmd[COMMAND_MAX_LENGTH]; strlcpy(cmd, Helpers::toLower(command).c_str(), sizeof(cmd)); + + // fetch all the data from the system + (void)command_info("", 0, root); + + // check for hardcoded "info" + if (!strcmp(cmd, F_(info))) { + return true; + } + char * val = strstr(cmd, "/value"); if (val) { val[0] = '\0'; @@ -1310,14 +1320,6 @@ bool System::get_value_info(JsonObject root, const char * command) { slash++; } - // fetch all the data from the system - (void)command_info("", 0, root); - - // check for hardcoded "info" - if (Helpers::toLower(cmd) == F_(info)) { - return true; - } - std::string s; // Loop through all the key-value pairs in root to find the key, case independent if (slash) { // search the top level first @@ -1340,7 +1342,7 @@ bool System::get_value_info(JsonObject root, const char * command) { } } - root.clear(); // empty json output, as it may have the default output from an info command earlier + root.clear(); // clear json, we only one a single value if (!s.empty()) { if (val) { diff --git a/src/temperaturesensor.cpp b/src/temperaturesensor.cpp index d94ce1255..f27111c51 100644 --- a/src/temperaturesensor.cpp +++ b/src/temperaturesensor.cpp @@ -408,7 +408,7 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons } } - return EMSESP::return_not_found(output, cmd, F_(temperaturesensor)); // not found + return false; // not found } void TemperatureSensor::addSensorJson(JsonObject output, const Sensor & sensor) { diff --git a/src/test/test.cpp b/src/test/test.cpp index 187843d14..2c5e4ed73 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -953,8 +953,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const bool single; - single = true; - // single = false; + // single = true; + single = false; AsyncWebServerRequest request; JsonDocument doc; @@ -963,21 +963,39 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // load devices test("boiler"); - // test("thermostat"); - test("2thermostats"); + test("thermostat"); + // test("2thermostats"); if (single) { // run dedicated tests only - // 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 + 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("call system fetch"); - request.method(HTTP_GET); request.url("/api/system/fetch"); EMSESP::webAPIService.webAPIService(&request); + // request.url("/api/system"); + // EMSESP::webAPIService.webAPIService(&request); + // request.url("/api/system/system/version"); + // EMSESP::webAPIService.webAPIService(&request); + // request.url("/api/system/bad"); + // EMSESP::webAPIService.webAPIService(&request); + + // request.url("/api/boiler"); + // EMSESP::webAPIService.webAPIService(&request); + // request.url("/api/boiler/bad"); + // EMSESP::webAPIService.webAPIService(&request); + + // request.url("/api/custom"); + // EMSESP::webAPIService.webAPIService(&request); + // request.url("/api/custom/seltemp"); + // EMSESP::webAPIService.webAPIService(&request); + // request.url("/api/custom/bad"); + // EMSESP::webAPIService.webAPIService(&request); + } else { EMSESP::webCustomEntityService.test(); // custom entities EMSESP::webCustomizationService.test(); // set customizations - this will overwrite any settings in the FS @@ -1062,6 +1080,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const request.method(HTTP_POST); // these next 3 should return empty JSON in their response + // but there will be a log message char data[] = "{\"cmd\":\"send\",\"data\":\"0B 90 FF 13 01 01 B9 01\"}"; deserializeJson(doc, data); json = doc.as(); diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index f174d0885..9eac1425b 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -278,6 +278,7 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) } // if it's info or values... + // TODO make a function if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) { // list all names for (const CustomEntityItem & entity : *customEntityItems_) { @@ -336,7 +337,7 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) } } - return EMSESP::return_not_found(output, cmd, F_(custom)); // not found + return false; // not found } // publish single value diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index 52b44c5fa..ad3fc6cb7 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -215,7 +215,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { return true; } - return EMSESP::return_not_found(output, cmd, F_(scheduler)); // not found + return false; // not found } // publish single value From 05ff54e5e5fe606a4b9f4f09603c4d0f0a30eb49 Mon Sep 17 00:00:00 2001 From: proddy Date: Wed, 24 Jul 2024 17:57:51 +0200 Subject: [PATCH 23/24] log_info for command calls --- src/command.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index a0825de1d..15a29bace 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -400,15 +400,13 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * LOG_WARNING(error); } else { if (single_command) { - // TODO not sure if these should go to INFO as there may be a lot of calls, e.g. ioBroker - // TODO for now using debug (regarles if compiled with EMSESP_DEBUG) - // TODO mvdp ? + // log as DEBUG (TRACE) regarless if compiled with EMSESP_DEBUG logger_.debug(("%sCalled command %s"), ro.c_str(), info_s); } else { if (id > 0) { - logger_.debug(("%sCalled command %s with value %s and id %d on device 0x%02X"), ro.c_str(), info_s, value, id, device_id); + LOG_INFO(("%sCalled command %s with value %s and id %d on device 0x%02X"), ro.c_str(), info_s, value, id, device_id); } else { - logger_.debug(("%sCalled command %s with value %s"), ro.c_str(), info_s, value); + LOG_INFO(("%sCalled command %s with value %s"), ro.c_str(), info_s, value); } } } From d92f17c774325953b83a6b9f70b7239443ddf125 Mon Sep 17 00:00:00 2001 From: proddy Date: Wed, 24 Jul 2024 17:59:32 +0200 Subject: [PATCH 24/24] remove TODO --- src/command.cpp | 2 -- src/web/WebCustomEntityService.cpp | 1 - 2 files changed, 3 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index 15a29bace..b0ed8aa33 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -635,8 +635,6 @@ bool Command::device_has_commands(const uint8_t device_type) { for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice && (emsdevice->device_type() == device_type)) { - // TODO will this work for info, values etc?? - // device found, now see if it has any commands for (const auto & cf : cmdfunctions_) { if (cf.device_type_ == device_type) { return true; diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index 9eac1425b..e1706ff9a 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -278,7 +278,6 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) } // if it's info or values... - // TODO make a function if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) { // list all names for (const CustomEntityItem & entity : *customEntityItems_) {