From a9fca73f2d211603c0c8e0bf3dfd78ddd0c5c4cc Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 10 May 2021 15:30:10 +0200 Subject: [PATCH] command default id=-1, command_check, add "warm water" to long names --- src/WebAPIService.cpp | 12 +++---- src/command.cpp | 75 ++++++++++++++++++++++++++++++------------- src/command.h | 4 +-- src/console.cpp | 14 +++++--- src/console.h | 2 -- src/dallassensor.cpp | 19 ++++++++--- src/dallassensor.h | 5 +++ src/emsdevice.cpp | 10 +++++- src/emsdevice.h | 2 +- src/emsesp.cpp | 4 +-- 10 files changed, 101 insertions(+), 46 deletions(-) diff --git a/src/WebAPIService.cpp b/src/WebAPIService.cpp index ad7f49737..64be97391 100644 --- a/src/WebAPIService.cpp +++ b/src/WebAPIService.cpp @@ -69,7 +69,7 @@ void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVari } // make sure we have a value. There must always be a value - if (!body.containsKey("value")) { + if (!body.containsKey(F_(value))) { send_message_response(request, 400, "Problems parsing JSON"); // Bad Request return; } @@ -114,8 +114,8 @@ void WebAPIService::parse(AsyncWebServerRequest * request, std::string & device_ if (request->hasParam(F_(data))) { value_s = request->getParam(F_(data))->value().c_str(); } - if (request->hasParam("value")) { - value_s = request->getParam("value")->value().c_str(); + if (request->hasParam(F_(value))) { + value_s = request->getParam(F_(value))->value().c_str(); } // get id (or hc), which is optional @@ -134,15 +134,15 @@ void WebAPIService::parse(AsyncWebServerRequest * request, std::string & device_ auto num_paths = p.paths().size(); if (num_paths == 1) { // if there are no more paths parameters, default to 'info' - cmd_s = "info_short"; + // cmd_s = "info_short"; + // check empty command in Command::find_command and set the default there! } else if (num_paths == 2) { cmd_s = p.paths()[1]; } else if (num_paths > 2) { - // command-check makes prefix to TAG + // check in Command::find_command makes prefix to TAG cmd_s = p.paths()[1] + "/" + p.paths()[2]; } } - // now go and validate everything // device check diff --git a/src/command.cpp b/src/command.cpp index 150193fc0..013f93e35 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -30,14 +30,13 @@ std::vector Command::cmdfunctions_; // id may be used to represent a heating circuit for example, it's optional // returns false if error or not found bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id) { - std::string dname = EMSdevice::device_type_2_device_name(device_type); - int8_t id_new = id; - char cmd_new[20]; + int8_t id_new = id; + char cmd_new[20] = {'\0'}; + strlcpy(cmd_new, cmd, 20); - check_command(cmd_new, cmd, id_new); - auto cf = find_command(device_type, cmd_new); + auto cf = find_command(device_type, cmd_new, id_new); if ((cf == nullptr) || (cf->cmdfunction_json_)) { - LOG_WARNING(F("Command %s on %s not found"), cmd, dname.c_str()); + LOG_WARNING(F("Command %s on %s not found"), cmd, EMSdevice::device_type_2_device_name(device_type).c_str()); return false; // command not found, or requires a json } @@ -58,11 +57,11 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val // id may be used to represent a heating circuit for example // returns false if error or not found bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id, JsonObject & json) { - int8_t id_new = id; - char cmd_new[20]; + int8_t id_new = id; + char cmd_new[20] = {'\0'}; + strlcpy(cmd_new, cmd, 20); - check_command(cmd_new, cmd, id_new); - auto cf = find_command(device_type, cmd_new); + auto cf = find_command(device_type, cmd_new, id_new); #ifdef EMSESP_DEBUG std::string dname = EMSdevice::device_type_2_device_name(device_type); @@ -95,18 +94,27 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val } } -// set the id if there are prefixes -char * Command::check_command(char * out, const char * cmd, int8_t & id) { +// strip prefixes, check, and find command +Command::CmdFunction * Command::find_command(const uint8_t device_type, char * cmd, int8_t & id) { + // no command for id0 + if (id == 0) { + return nullptr; + } + // empty command is info with id0 or info_short + if (cmd[0] == '\0') { + // strcpy(cmd, "info_short"); + strcpy(cmd, "info"); + id = 0; + } // convert cmd to lowercase - strlcpy(out, cmd, 20); - for (char * p = out; *p; p++) { + for (char * p = cmd; *p; p++) { *p = tolower(*p); } // scan for prefix hc. for (uint8_t i = DeviceValueTAG::TAG_HC1; i <= DeviceValueTAG::TAG_HC4; i++) { - if ((strncmp(out, EMSdevice::tag_to_string(i).c_str(), 3) == 0) && (strlen(out) > 4)) { - strcpy(out, &out[4]); + if ((strncmp(cmd, EMSdevice::tag_to_string(i).c_str(), 3) == 0) && (strlen(cmd) > 3)) { + strcpy(cmd, &cmd[4]); id = 1 + i - DeviceValueTAG::TAG_HC1; break; } @@ -114,14 +122,19 @@ char * Command::check_command(char * out, const char * cmd, int8_t & id) { // scan for prefix wwc. for (uint8_t i = DeviceValueTAG::TAG_WWC1; i <= DeviceValueTAG::TAG_WWC4; i++) { - if ((strncmp(out, EMSdevice::tag_to_string(i).c_str(), 4) == 0) && (strlen(out) > 5)) { - strcpy(out, &out[5]); + if ((strncmp(cmd, EMSdevice::tag_to_string(i).c_str(), 4) == 0) && (strlen(cmd) > 4)) { + strcpy(cmd, &cmd[5]); id = 8 + i - DeviceValueTAG::TAG_WWC1; break; } } - return out; + // empty command after processing prefix is info + if (cmd[0] == '\0') { + strlcpy(cmd, "info", 20); + } + + return find_command(device_type ,cmd); } // add a command to the list, which does not return json @@ -196,7 +209,11 @@ bool Command::list(const uint8_t device_type, JsonObject & json) { for (auto & cl : sorted_cmds) { for (const auto & cf : cmdfunctions_) { if ((cf.device_type_ == device_type) && !cf.hidden_ && cf.description_ && (cl == uuid::read_flash_string(cf.cmd_))) { - json[cl] = cf.description_; + if (cf.flag_ == FLAG_WW) { + json[cl] = EMSdevice::tag_to_string(TAG_DEVICE_DATA_WW) + " " + uuid::read_flash_string(cf.description_); + } else { + json[cl] = cf.description_; + } } } } @@ -233,16 +250,28 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo // verbose mode shell.println(); for (auto & cl : sorted_cmds) { - shell.print(" "); - shell.print(cl); // find and print the description for (const auto & cf : cmdfunctions_) { if ((cf.device_type_ == device_type) && !cf.hidden_ && cf.description_ && (cl == uuid::read_flash_string(cf.cmd_))) { + uint8_t i = cl.length(); + shell.print(" "); + if (cf.flag_ == FLAG_HC) { + shell.print("[hc] "); + i += 5; + } else if (cf.flag_ == FLAG_WWC) { + shell.print("[wwc] "); + i += 6; + } + shell.print(cl); // pad with spaces - for (uint8_t i = cl.length(); i++ < 22;) { + while (i++ < 22) { shell.print(' '); } shell.print(COLOR_BRIGHT_CYAN); + if (cf.flag_ == FLAG_WW) { + shell.print(EMSdevice::tag_to_string(TAG_DEVICE_DATA_WW)); + shell.print(' '); + } shell.print(uuid::read_flash_string(cf.description_)); shell.print(COLOR_RESET); } diff --git a/src/command.h b/src/command.h index fcad91214..08ec8b5b3 100644 --- a/src/command.h +++ b/src/command.h @@ -70,13 +70,13 @@ class Command { } static bool call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id, JsonObject & json); - static bool call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id = 0); + static bool call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id = -1); static void add(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_p cb, const __FlashStringHelper * description, uint8_t flag = 0); static void add_with_json(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_json_p cb, const __FlashStringHelper * description, bool hidden = false); static void show_all(uuid::console::Shell & shell); static Command::CmdFunction * find_command(const uint8_t device_type, const char * cmd); - static char * check_command(char * out, const char * cmd, int8_t & id); + static Command::CmdFunction * find_command(const uint8_t device_type, char * cmd, int8_t & id); static void show(uuid::console::Shell & shell, uint8_t device_type, bool verbose); static void show_devices(uuid::console::Shell & shell); diff --git a/src/console.cpp b/src/console.cpp index d521286ad..dc11cd403 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -373,8 +373,18 @@ void EMSESPShell::add_console_commands() { return; } + DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN); + JsonObject json = doc.to(); + + bool ok = false; // validate the command if (arguments.size() < 2) { + // no cmd specified, default to empty command + if (Command::call(device_type, "", "", -1, json)) { + serializeJsonPretty(doc, shell); + shell.println(); + return; + } shell.print(F("Missing command. Available commands are: ")); Command::show(shell, device_type, false); // non-verbose mode return; @@ -382,10 +392,6 @@ void EMSESPShell::add_console_commands() { const char * cmd = arguments[1].c_str(); - DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN); - JsonObject json = doc.to(); - - bool ok = false; if (arguments.size() == 2) { // no value specified, just the cmd ok = Command::call(device_type, cmd, nullptr, -1, json); diff --git a/src/console.h b/src/console.h index 58c04e6e8..686332342 100644 --- a/src/console.h +++ b/src/console.h @@ -44,8 +44,6 @@ using uuid::log::Level; #define LOG_WARNING(...) logger_.warning(__VA_ARGS__) #define LOG_ERROR(...) logger_.err(__VA_ARGS__) -#define MQTT_TOPIC(list_name) (__pstr__##list_name[0]) - // clang-format off // strings stored 32 bit aligned on ESP8266/ESP32 #define MAKE_PSTR(string_name, string_literal) static const char __pstr__##string_name[] __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = string_literal; diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index 39403a783..1bade3efe 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -134,6 +134,7 @@ void DallasSensor::loop() { int16_t t; t = get_temperature_c(addr); if ((t >= -550) && (t <= 1250)) { + sensorreads_++; // check if we have this sensor already bool found = false; for (auto & sensor : sensors_) { @@ -322,7 +323,7 @@ bool DallasSensor::command_commands(const char * value, const int8_t id, JsonObj // returns false if empty // e.g. dallassensor_data = {"sensor1":{"id":"28-EA41-9497-0E03-5F","temp":23.30},"sensor2":{"id":"28-233D-9497-0C03-8B","temp":24.0}} bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject & json) { - if (sensors_.size() == 0 || id != -1) { + if (sensors_.size() == 0) { return false; } @@ -330,10 +331,18 @@ bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject for (const auto & sensor : sensors_) { char sensorID[10]; // sensor{1-n} snprintf_P(sensorID, 10, PSTR("sensor%d"), i++); - if (Mqtt::dallas_format() == Mqtt::Dallas_Format::SENSORID && Helpers::hasValue(sensor.temperature_c)) { - json[sensor.to_string()] = (float)(sensor.temperature_c) / 10; - } else if (Helpers::hasValue(sensor.temperature_c)) { - json[sensorID] = (float)(sensor.temperature_c) / 10; + if (id == -1) { // show number and id + JsonObject dataSensor = json.createNestedObject(sensorID); + dataSensor["id"] = sensor.to_string(); + if (Helpers::hasValue(sensor.temperature_c)) { + dataSensor["temp"] = (float)(sensor.temperature_c) / 10; + } + } else { // show according to format + if (Mqtt::dallas_format() == Mqtt::Dallas_Format::SENSORID && Helpers::hasValue(sensor.temperature_c)) { + json[sensor.to_string()] = (float)(sensor.temperature_c) / 10; + } else if (Helpers::hasValue(sensor.temperature_c)) { + json[sensorID] = (float)(sensor.temperature_c) / 10; + } } } diff --git a/src/dallassensor.h b/src/dallassensor.h index 8a0175534..c5b75a926 100644 --- a/src/dallassensor.h +++ b/src/dallassensor.h @@ -64,6 +64,10 @@ class DallasSensor { const std::vector sensors() const; + uint32_t reads() { + return sensorreads_; + } + uint32_t fails() { return sensorfails_; } @@ -128,6 +132,7 @@ class DallasSensor { bool parasite_ = false; bool changed_ = false; uint32_t sensorfails_ = 0; + uint32_t sensorreads_ = 0; int8_t scanretry_ = 0; }; diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 6452baa8f..806434b34 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -492,6 +492,10 @@ void EMSdevice::register_device_value(uint8_t tag, if (f != nullptr) { if (tag >= TAG_HC1 && tag <= TAG_HC4) { Command::add(device_type_, name[0], f, name[1], FLAG_HC); + } else if (tag >= TAG_WWC1 && tag <= TAG_WWC4) { + Command::add(device_type_, name[0], f, name[1], FLAG_WWC); + } else if (tag == TAG_DEVICE_DATA_WW) { + Command::add(device_type_, name[0], f, name[1], FLAG_WW); } else { Command::add(device_type_, name[0], f, name[1], 0); } @@ -687,7 +691,11 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t json["name"] = dv.short_name; if (dv.full_name != nullptr) { - json["fullname"] = dv.full_name; + if (dv.tag == TAG_DEVICE_DATA_WW) { + json["fullname"] = tag_to_string(dv.tag) + " " + uuid::read_flash_string(dv.full_name); + } else { + json["fullname"] = dv.full_name; + } } if (!tag_to_mqtt(dv.tag).empty()) { json["circuit"] = tag_to_mqtt(dv.tag); diff --git a/src/emsdevice.h b/src/emsdevice.h index f27761672..bf103fe01 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -94,7 +94,7 @@ enum DeviceValueTAG : uint8_t { }; // mqtt flags for command subscriptions -enum MqttSubFlag : uint8_t { FLAG_NORMAL = 0, FLAG_HC, FLAG_WWC, FLAG_NOSUB }; +enum MqttSubFlag : uint8_t { FLAG_NORMAL = 0, FLAG_HC, FLAG_WWC, FLAG_WW, FLAG_NOSUB }; // mqtt-HA flags enum DeviceValueHA : uint8_t { HA_NONE = 0, HA_VALUE, HA_DONE }; diff --git a/src/emsesp.cpp b/src/emsesp.cpp index d854dd8a1..0c7a0f705 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -1008,7 +1008,7 @@ bool EMSESP::command_info(uint8_t device_type, JsonObject & json, const int8_t i tag = DeviceValueTAG::TAG_HC1 + id - 1; } else if (id >= 9 && id <= 10) { tag = DeviceValueTAG::TAG_WWC1 + id - 9; - } else if (id == -1) { + } else if (id == -1 || id == 0) { tag = DeviceValueTAG::TAG_NONE; } else { return false; @@ -1017,7 +1017,7 @@ bool EMSESP::command_info(uint8_t device_type, JsonObject & json, const int8_t i for (const auto & emsdevice : emsdevices) { if (emsdevice && (emsdevice->device_type() == device_type) && ((device_type != DeviceType::THERMOSTAT) || (emsdevice->device_id() == EMSESP::actual_master_thermostat()))) { - has_value |= emsdevice->generate_values_json(json, tag, (id == -1), verbose); // nested for id -1,0 & console for id -1 + has_value |= emsdevice->generate_values_json(json, tag, (id < 1), verbose && (id == -1)); // nested for id -1,0 & console for id -1 } }