From 70d8b6824c03653f26d9e3b788a073d422b02fbe Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sat, 24 Apr 2021 10:39:17 +0200 Subject: [PATCH] id to value_info, alternative prefix to command/value --- CHANGELOG_LATEST.md | 2 ++ src/command.cpp | 55 ++++++++++++++++++++++++++++++++++++--------- src/command.h | 1 + src/emsdevice.cpp | 19 +++++++++++++--- src/emsdevice.h | 2 +- src/emsesp.cpp | 6 ++--- src/emsesp.h | 2 +- src/mqtt.cpp | 12 +++++----- 8 files changed, 75 insertions(+), 24 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 13234a685..45a7de9b9 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -4,6 +4,8 @@ - Mock API to simulate an ESP, for testing web - Able to write values from the Web UI +- check values with `"cmd":` and data empty or `?` +- set hc for values and commands by id or prefix `hc`+separarator, separator can be any char ## Fixed - Don't create Home Assistant MQTT discovery entries for device values that don't exists (#756 on EMS-ESP repo) diff --git a/src/command.cpp b/src/command.cpp index 2d8ec80dd..4abdd4d64 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -30,9 +30,12 @@ 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); + std::string dname = EMSdevice::device_type_2_device_name(device_type); + int8_t id_new = id; + char cmd_new[20]; - auto cf = find_command(device_type, cmd); + check_command(cmd_new, cmd, id_new); + auto cf = find_command(device_type, cmd_new); if ((cf == nullptr) || (cf->cmdfunction_json_)) { LOG_WARNING(F("Command %s on %s not found"), cmd, dname.c_str()); return false; // command not found, or requires a json @@ -48,18 +51,21 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val } #endif - return ((cf->cmdfunction_)(value, id)); + return ((cf->cmdfunction_)(value, id_new)); } // calls a command. Takes a json object for output. // 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) { - std::string dname = EMSdevice::device_type_2_device_name(device_type); + int8_t id_new = id; + char cmd_new[20]; - auto cf = find_command(device_type, cmd); + check_command(cmd_new, cmd, id_new); + auto cf = find_command(device_type, cmd_new); #ifdef EMSESP_DEBUG + std::string dname = EMSdevice::device_type_2_device_name(device_type); if (value == nullptr) { LOG_DEBUG(F("[DEBUG] Calling %s command %s"), dname.c_str(), cmd); } else if (id == -1) { @@ -76,19 +82,48 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val } if (cf == nullptr) { - return EMSESP::get_device_value_info(json, cmd, device_type); + return EMSESP::get_device_value_info(json, cmd_new, id_new, device_type); } if (cf->cmdfunction_json_) { - return ((cf->cmdfunction_json_)(value, id, json)); + return ((cf->cmdfunction_json_)(value, id_new, json)); } else { - if (value == nullptr || strlen(value) == 0) { - return EMSESP::get_device_value_info(json, cmd, device_type); + if (value == nullptr || strlen(value) == 0 || strcmp(value, "?") == 0 || strcmp(value, "*") == 0) { + return EMSESP::get_device_value_info(json, cmd_new, id_new, device_type); } - return ((cf->cmdfunction_)(value, id)); + return ((cf->cmdfunction_)(value, id_new)); } } +char * Command::check_command(char * out, const char * cmd, int8_t & id) { + // convert cmd to lowercase + strlcpy(out, cmd, 20); + for (char * p = out; *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]); + id = 1 + i - DeviceValueTAG::TAG_HC1; + break; + } + } + + //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]); + id = 8 + i - DeviceValueTAG::TAG_WWC1; + break; + } + } + + return out; +} + + // add a command to the list, which does not return json void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_p cb, uint8_t flag) { // if the command already exists for that device type don't add it diff --git a/src/command.h b/src/command.h index 50d36cdc6..c6e7da5d6 100644 --- a/src/command.h +++ b/src/command.h @@ -65,6 +65,7 @@ class Command { static void add_with_json(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_json_p cb); 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 void show(uuid::console::Shell & shell, uint8_t device_type); static void show_devices(uuid::console::Shell & shell); diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 0e532bd18..5cf200c57 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -620,12 +620,25 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) { return (num_elements != 0); } -bool EMSdevice::get_value_info(JsonObject & root, const char * cmd) { +bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t id) { JsonObject json = root; + int8_t tag = id; + + // check if we have hc or wwc + if (id >= 1 && id <= 4) { + tag = DeviceValueTAG::TAG_HC1 + id - 1; + } else if (id >= 8 && id <= 11) { + tag = DeviceValueTAG::TAG_WWC1 + id - 8; + } + + // search device value with this tag for (auto & dv : devicevalues_) { - if (strcmp(cmd, uuid::read_flash_string(dv.short_name).c_str()) == 0) { + if (strcmp(cmd, uuid::read_flash_string(dv.short_name).c_str()) == 0 && (tag <= 0 || tag == dv.tag)) { uint8_t divider = (dv.options_size == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0; - json["name"] = cmd; + json["name"] = dv.short_name; + if (dv.tag >= DeviceValueTAG::TAG_HC1) { + json["circuit"] = tag_to_string(dv.tag); + } switch (dv.type) { case DeviceValueType::ENUM: { if (Helpers::hasValue((uint8_t)(*(uint8_t *)(dv.value_p)))) { diff --git a/src/emsdevice.h b/src/emsdevice.h index 5ea14ab17..c00c792bf 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -263,7 +263,7 @@ class EMSdevice { bool handle_telegram(std::shared_ptr telegram); std::string get_value_uom(const char * key); - bool get_value_info(JsonObject & root, const char * cmd); + bool get_value_info(JsonObject & root, const char * cmd, const int8_t id); bool generate_values_json(JsonObject & json, const uint8_t tag_filter, const bool nested, const bool console = false); bool generate_values_json_web(JsonObject & json); diff --git a/src/emsesp.cpp b/src/emsesp.cpp index a38f5ad59..97b62cf4c 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -440,7 +440,7 @@ void EMSESP::publish_device_values(uint8_t device_type) { // group by device type for (const auto & emsdevice : emsdevices) { if (emsdevice && (emsdevice->device_type() == device_type)) { - // if we're using HA, if done is checked for each sensor in devices + // if we're using HA, done is checked for each sensor in devices if (Mqtt::ha_enabled()) { emsdevice->publish_mqtt_ha_sensor(); // create the configs for each value as a sensor } @@ -547,10 +547,10 @@ void EMSESP::publish_response(std::shared_ptr telegram) { Mqtt::publish(F("response"), doc.as()); } -bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, uint8_t devicetype) { +bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype) { for (const auto & emsdevice : emsdevices) { if (emsdevice->device_type() == devicetype) { - return emsdevice->get_value_info(root, cmd); + return emsdevice->get_value_info(root, cmd, id); } } return false; diff --git a/src/emsesp.h b/src/emsesp.h index 982c6b1af..b49872c4d 100644 --- a/src/emsesp.h +++ b/src/emsesp.h @@ -106,7 +106,7 @@ class EMSESP { static void actual_master_thermostat(const uint8_t device_id); static uint8_t check_master_device(const uint8_t device_id, const uint16_t type_id, const bool read); - static bool get_device_value_info(JsonObject & root, const char * cmd, uint8_t devicetype); + static bool get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype); static void show_device_values(uuid::console::Shell & shell); static void show_sensor_values(uuid::console::Shell & shell); diff --git a/src/mqtt.cpp b/src/mqtt.cpp index f6294d3e2..470a8d04c 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -328,11 +328,11 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len) } cmd_only++; // skip the / int8_t id = -1; - // check for hcx/ prefix - if (cmd_only[0] == 'h' && cmd_only[1] == 'c' && cmd_only[3] == '/') { - id = cmd_only[2] - '0'; - cmd_only += 4; - } + // check for hcx/ prefix, commented out, this is now in command::call + // if (cmd_only[0] == 'h' && cmd_only[1] == 'c' && cmd_only[3] == '/') { + // id = cmd_only[2] - '0'; + // cmd_only += 4; + // } // LOG_INFO(F("devicetype= %d, topic = %s, cmd = %s, message = %s, id = %d"), mf.device_type_, topic, cmd_only, message, id); if (!Command::call(mf.device_type_, cmd_only, message, id)) { LOG_ERROR(F("No matching cmd (%s) in topic %s, id %d, or invalid data"), cmd_only, topic, id); @@ -382,7 +382,7 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len) if (cmd_known && json.size()) { Mqtt::publish(F("response"), resp.as()); return; - } + } } if (!cmd_known) {