From 30fca2a190f8c06692b19a4a63bf62ea5033b1b4 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Thu, 28 Nov 2024 15:40:42 +0100 Subject: [PATCH] system commands withing command (api/mqtt/console), alternative to #2182 --- src/command.cpp | 46 +++++++++++++++++++- src/console.cpp | 32 -------------- src/locale_translations.h | 6 +++ src/shower.cpp | 42 ------------------ src/shower.h | 8 ++++ src/system.cpp | 90 ++++++++++++++++++++++++++++++++++++++- src/system.h | 9 ++++ 7 files changed, 155 insertions(+), 78 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index 4b92d61ca..0e655a3a4 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -326,7 +326,7 @@ uint8_t Command::call(const uint8_t device_type, const char * command, const cha return CommandRet::NOT_FOUND; } char cmd[COMMAND_MAX_LENGTH]; - strcpy(cmd, Helpers::toLower(command).c_str()); + strlcpy(cmd, Helpers::toLower(command).c_str(), sizeof(cmd)); auto dname = EMSdevice::device_type_2_device_name(device_type); // device name, not translated @@ -342,6 +342,11 @@ uint8_t Command::call(const uint8_t device_type, const char * command, const cha LOG_DEBUG("Fetched device entity/attributes for %s/%s", dname, cmd); return CommandRet::OK; } + } else if (device_type == EMSdevice::DeviceType::SYSTEM && strchr(cmd, '/')) { + // check service commands, if not found continue with commandsfunctions + if (EMSESP::system_.command_service(cmd, value)) { + return CommandRet::OK; + } } uint8_t device_id = EMSESP::device_id_from_cmd(device_type, cmd, id); @@ -531,6 +536,17 @@ bool Command::list(const uint8_t device_type, JsonObject output) { output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); output[F_(entities)] = Helpers::translated_word(FL_(entities_cmd)); + if (device_type == EMSdevice::DeviceType::SYSTEM) { + output["settings/showertimer"] = Helpers::translated_word(FL_(system_cmd)); + output["settings/showeralert"] = Helpers::translated_word(FL_(system_cmd)); + output["settings/hideled"] = Helpers::translated_word(FL_(system_cmd)); + output["settings/txmode"] = Helpers::translated_word(FL_(system_cmd)); + output["settings/analogenabled"] = Helpers::translated_word(FL_(system_cmd)); + output["mqtt/enabled"] = Helpers::translated_word(FL_(system_cmd)); + output["ntp/enabled"] = Helpers::translated_word(FL_(system_cmd)); + output["ap/enabled"] = Helpers::translated_word(FL_(system_cmd)); + output["syslog/enabled"] = Helpers::translated_word(FL_(system_cmd)); + } // create a list of commands we have registered, and sort them std::list sorted_cmds; for (const auto & cf : cmdfunctions_) { @@ -559,7 +575,17 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo sorted_cmds.push_back(tagged_cmd(cf.cmd_, cf.flags_)); } } - + if (device_type == EMSdevice::DeviceType::SYSTEM) { + sorted_cmds.emplace_back("settings/showertimer"); + sorted_cmds.emplace_back("settings/showeralert"); + sorted_cmds.emplace_back("settings/hideled"); + sorted_cmds.emplace_back("settings/txmode"); + sorted_cmds.emplace_back("settings/analogenabled"); + sorted_cmds.emplace_back("mqtt/enabled"); + sorted_cmds.emplace_back("ntp/enabled"); + sorted_cmds.emplace_back("ap/enabled"); + sorted_cmds.emplace_back("syslog/enabled"); + } sorted_cmds.sort(); // sort them // if not in verbose mode, just print them on a single line and exit @@ -567,6 +593,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo sorted_cmds.emplace_front(F_(info)); sorted_cmds.emplace_front(F_(commands)); sorted_cmds.emplace_front(F_(values)); + sorted_cmds.emplace_front(F_(entities)); for (const auto & cl : sorted_cmds) { shell.print(cl); shell.print(" "); @@ -590,6 +617,19 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo shell.print(' '); } shell.print(COLOR_BRIGHT_CYAN); + if (cf.has_flags(CommandFlag::CMD_FLAG_HC)) { + shell.print(Helpers::translated_word(FL_(tag_hcx))); + shell.print(' '); + } else if (cf.has_flags(CommandFlag::CMD_FLAG_DHW)) { + shell.print(Helpers::translated_word(FL_(tag_dhwx))); + shell.print(' '); + } else if (cf.has_flags(CommandFlag::CMD_FLAG_AHS)) { + shell.print(Helpers::translated_word(FL_(tag_ahsx))); + shell.print(' '); + } else if (cf.has_flags(CommandFlag::CMD_FLAG_HS)) { + shell.print(Helpers::translated_word(FL_(tag_hsx))); + shell.print(' '); + } shell.print(Helpers::translated_word(cf.description_)); if (!cf.has_flags(CommandFlag::ADMIN_ONLY)) { shell.print(' '); @@ -677,6 +717,8 @@ void Command::show_all(uuid::console::Shell & shell) { shell.println(COLOR_RESET); shell.printf(" values \t\t\t%slist all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); shell.println(COLOR_RESET); + shell.printf(" entities \t\t\t%slist all entities %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); + shell.println(COLOR_RESET); // show system ones first show(shell, EMSdevice::DeviceType::SYSTEM, true); diff --git a/src/console.cpp b/src/console.cpp index 262f02632..f45c165b3 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -327,38 +327,6 @@ static void setup_commands(std::shared_ptr const & commands) { EMSESP::uart_init(); }); - commands->add_command(ShellContext::MAIN, - CommandFlags::ADMIN, - string_vector{F_(set), F_(service)}, - string_vector{F_(service_mandatory), F_(enable_mandatory)}, - [](Shell & shell, const std::vector & arguments) { - if (arguments.back() == "enable" || arguments.back() == "disable") { - bool enable = arguments.back() == "enable"; - if (arguments.front() == "mqtt") { - EMSESP::esp8266React.getMqttSettingsService()->update([&](MqttSettings & Settings) { - Settings.enabled = enable; - return StateUpdateResult::CHANGED; - }); - } else if (arguments.front() == "ntp") { - EMSESP::esp8266React.getNTPSettingsService()->update([&](NTPSettings & Settings) { - Settings.enabled = enable; - return StateUpdateResult::CHANGED; - }); - } else if (arguments.front() == "ap") { - EMSESP::esp8266React.getAPSettingsService()->update([&](APSettings & Settings) { - Settings.provisionMode = enable ? 0 : 2; - return StateUpdateResult::CHANGED; - }); - } else { - shell.printfln("unknown service: %s", arguments.front().c_str()); - return; - } - shell.printfln("service '%s' %sd", arguments.front().c_str(), arguments.back().c_str()); - } else { - shell.println("Must be `enable` or `disable`"); - } - }); - // // EMS device commands // diff --git a/src/locale_translations.h b/src/locale_translations.h index 5c9f68c83..153409ee4 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -79,6 +79,7 @@ MAKE_WORD_TRANSLATION(commands_response, "get response", "Hole Antwort", "Verzoe MAKE_WORD_TRANSLATION(coldshot_cmd, "send a cold shot of water", "Zugabe einer Menge kalten Wassers", "", "", "uruchom tryśnięcie zimnej wody", "", "", "soğuk su gönder", "", "pošlite studenú dávku vody", "poslat studenou vodu") // TODO translate MAKE_WORD_TRANSLATION(message_cmd, "send a message", "Eine Nachricht senden", "", "", "", "", "", "", "", "poslať správu", "odeslat zprávu") // TODO translate MAKE_WORD_TRANSLATION(values_cmd, "list all values", "Liste alle Werte auf", "", "", "", "", "", "", "", "vypísať všetky hodnoty", "vypsat všechny hodnoty") // TODO translate +MAKE_WORD_TRANSLATION(system_cmd, "system setting", "System Einstellung", "", "", "", "", "", "", "", "vypísať všetky hodnoty", "vypsat všechny hodnoty") // TODO translate MAKE_WORD_TRANSLATION(showertimer_cmd, "enable shower timer", "aktiviere Duschzeitmessung", "", "", "", "", "", "", "", "povoliť časovač sprchovania", "") // TODO translate MAKE_WORD_TRANSLATION(showeralert_cmd, "enable shower alert", "aktiviere Duschzeitwarnung", "", "", "", "", "", "", "", "povoliť upozornenie na sprchu", "") // TODO translate @@ -120,6 +121,11 @@ MAKE_WORD_TRANSLATION(tag_hs14, "hs14", "hs14", "hs14", "VK14", "ŹC14", "hs14", MAKE_WORD_TRANSLATION(tag_hs15, "hs15", "hs15", "hs15", "VK15", "ŹC15", "hs15", "hs15", "hs15", "hs15", "hs15", "hs15") MAKE_WORD_TRANSLATION(tag_hs16, "hs16", "hs16", "hs16", "VK16", "ŹC16", "hs16", "hs16", "hs16", "hs16", "hs16", "hs16") +MAKE_WORD_TRANSLATION(tag_hcx, "hc", "HK", "hc", "VK", "OG", "hc", "hc", "ID", "hc", "hc", "hc") +MAKE_WORD_TRANSLATION(tag_dhwx, "dhw[n]", "WWK[n]", "dhw[n]", "VVK[n]", "CWU[n]", "dhw[n]", "ecs[n]", "SKS[n]", "dhw[n]", "TÚV[n]", "TUV[n]") +MAKE_WORD_TRANSLATION(tag_ahsx, "ahs", "AHQ", "ahs", "ahs", "AŹC", "ahs", "ahs", "ahs", "ahs", "ahs", "ahs") +MAKE_WORD_TRANSLATION(tag_hsx, "hs", "HQ", "hs", "hs", "ŹC", "hs", "hs", "hs", "hs", "hs", "hs") + // General MAKE_WORD_TRANSLATION(on, "on", "an", "aan", "på", "włączono", "på", "on", "açık", "on", "zap", "zap") MAKE_WORD_TRANSLATION(off, "off", "aus", "uit", "av", "wyłączono", "av", "off", "kapalı", "off", "vyp", "vyp") diff --git a/src/shower.cpp b/src/shower.cpp index b88f86266..88226cd79 100644 --- a/src/shower.cpp +++ b/src/shower.cpp @@ -51,48 +51,6 @@ void Shower::start() { FL_(coldshot_cmd), CommandFlag::ADMIN_ONLY); - Command::add( - EMSdevice::DeviceType::SYSTEM, - F_(showertimer), - [&](const char * value, const int8_t id, JsonObject output) { - bool b; - if (!Helpers::value2bool(value, b)) { - return false; - } - shower_timer_ = b; - EMSESP::webSettingsService.update([&](WebSettings & settings) { - if (settings.shower_timer != b) { - settings.shower_timer = b; - return StateUpdateResult::CHANGED; - } - return StateUpdateResult::UNCHANGED; - }); - return true; - }, - FL_(showertimer_cmd), - CommandFlag::ADMIN_ONLY); - - Command::add( - EMSdevice::DeviceType::SYSTEM, - F_(showeralert), - [&](const char * value, const int8_t id, JsonObject output) { - bool b; - if (!Helpers::value2bool(value, b)) { - return false; - } - shower_alert_ = b; - EMSESP::webSettingsService.update([&](WebSettings & settings) { - if (settings.shower_alert != b) { - settings.shower_alert = b; - return StateUpdateResult::CHANGED; - } - return StateUpdateResult::UNCHANGED; - }); - return true; - }, - FL_(showeralert_cmd), - CommandFlag::ADMIN_ONLY); - if (shower_timer_) { set_shower_state(false, true); // turns shower to off and creates HA topic if not already done } diff --git a/src/shower.h b/src/shower.h index 6711f0af3..2876a80cb 100644 --- a/src/shower.h +++ b/src/shower.h @@ -33,6 +33,14 @@ class Shower { // commands static bool command_coldshot(const char * value, const int8_t id); + void shower_timer(bool enable) { + shower_timer_ = enable; + } + + void shower_alert(bool enable) { + shower_alert_ = enable; + } + private: static uuid::log::Logger logger_; diff --git a/src/system.cpp b/src/system.cpp index 96565589e..78e767887 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1347,6 +1347,91 @@ bool System::saveSettings(const char * filename, const char * section, JsonObjec return false; // not found } +// set a entity of services 'network', 'settings', 'mqtt', etc. +bool System::command_service(const char * cmd, const char * value) { + bool ok = false; + bool b; + if (Helpers::value2bool(value, b)) { + if (!strcmp(cmd, "settings/showertimer")) { + EMSESP::webSettingsService.update([&](WebSettings & settings) { + settings.shower_timer = b; + return StateUpdateResult::CHANGED; + }); + EMSESP::shower_.shower_timer(b); + ok = true; + } else if (!strcmp(cmd, "settings/showeralert")) { + EMSESP::webSettingsService.update([&](WebSettings & settings) { + settings.shower_alert = b; + return StateUpdateResult::CHANGED; + }); + EMSESP::shower_.shower_alert(b); + ok = true; + } else if (!strcmp(cmd, "settings/hideled")) { + EMSESP::webSettingsService.update([&](WebSettings & settings) { + settings.hide_led = b; + return StateUpdateResult::CHANGED; + }); + EMSESP::system_.hide_led(b); + ok = true; + } else if (!strcmp(cmd, "settings/analogenabled")) { + EMSESP::webSettingsService.update([&](WebSettings & settings) { + settings.analog_enabled = b; + return StateUpdateResult::CHANGED; + }); + EMSESP::system_.analog_enabled(b); + ok = true; + } else if (!strcmp(cmd, "mqtt/enabled")) { + EMSESP::esp8266React.getMqttSettingsService()->update([&](MqttSettings & Settings) { + Settings.enabled = b; + return StateUpdateResult::CHANGED; + }); + ok = true; + } else if (!strcmp(cmd, "ap/enabled")) { + EMSESP::esp8266React.getAPSettingsService()->update([&](APSettings & Settings) { + Settings.provisionMode = b ? 0 : 2; + return StateUpdateResult::CHANGED; + }); + ok = true; + } else if (!strcmp(cmd, "ntp/enabled")) { + EMSESP::esp8266React.getNTPSettingsService()->update([&](NTPSettings & Settings) { + Settings.enabled = b; + return StateUpdateResult::CHANGED; + }); + ok = true; + } else if (!strcmp(cmd, "ap/enabled")) { + EMSESP::esp8266React.getAPSettingsService()->update([&](APSettings & Settings) { + Settings.provisionMode = b ? 0 : 2; + return StateUpdateResult::CHANGED; + }); + ok = true; + } else if (!strcmp(cmd, "syslog/enabled")) { + EMSESP::webSettingsService.update([&](WebSettings & settings) { + settings.syslog_enabled = b; + return StateUpdateResult::CHANGED; + }); + EMSESP::system_.syslog_enabled_ = b; + EMSESP::system_.syslog_init(); + ok = true; + } + } + int n; + if (!ok && Helpers::value2number(value, n)) { + if (!strcmp(cmd, "settings/txmode") && n >= 0 && n <= 4) { + EMSESP::webSettingsService.update([&](WebSettings & settings) { + settings.tx_mode = n; + return StateUpdateResult::CHANGED; + }); + EMSESP::uart_init(); + ok = true; + } + } + + if (ok) { + LOG_INFO("System command '%s' with value '%s'", cmd, value); + } + return ok; +} + // return back a system value bool System::get_value_info(JsonObject output, const char * cmd) { if (cmd == nullptr || strlen(cmd) == 0) { @@ -1428,8 +1513,9 @@ void System::get_value_json(JsonObject output, const std::string & circuit, cons output["circuit"] = circuit; } output["readable"] = true; - output["writable"] = false; - output["visible"] = true; + output["writeable"] = + (name == "txmode" || name == "showertimer" || name == "showeralert" || name == "enabled" || name == "hideled" || name == "analogenabled"); + output["visible"] = true; if (val.is()) { output["value"] = val.as(); output["type"] = "boolean"; diff --git a/src/system.h b/src/system.h index ffc620a3f..35db0cd83 100644 --- a/src/system.h +++ b/src/system.h @@ -73,6 +73,7 @@ class System { static bool command_message(const char * value, const int8_t id); static bool command_info(const char * value, const int8_t id, JsonObject output); static bool command_response(const char * value, const int8_t id, JsonObject output); + static bool command_service(const char * cmd, const char * value); static bool get_value_info(JsonObject root, const char * cmd); static void get_value_json(JsonObject output, const std::string & circuit, const std::string & name, JsonVariant val); @@ -165,6 +166,14 @@ class System { return analog_enabled_; } + void analog_enabled(bool b) { + analog_enabled_ = b; + } + + void hide_led(bool b) { + hide_led_ = b; + } + bool readonly_mode() { return readonly_mode_; }