diff --git a/src/mqtt.cpp b/src/mqtt.cpp index eb3478129..fb045fce6 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -64,11 +64,11 @@ void Mqtt::subscribe(const uint8_t device_type, const std::string & topic, mqtt_ if (!mqtt_subfunctions_.empty()) { for (auto & mqtt_subfunction : mqtt_subfunctions_) { if ((mqtt_subfunction.device_type_ == device_type) && (strcmp(mqtt_subfunction.topic_.c_str(), topic.c_str()) == 0)) { - // add the function, in case its not there + // add the function (in case its not there) and quit because it already exists if (cb) { mqtt_subfunction.mqtt_subfunction_ = cb; } - return; // it exists, exit + return; } } } @@ -89,8 +89,9 @@ void Mqtt::subscribe(const uint8_t device_type, const std::string & topic, mqtt_ // subscribe to the command topic if it doesn't exist yet void Mqtt::register_command(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_p cb) { - std::string cmd_topic = EMSdevice::device_type_2_device_name(device_type); + std::string cmd_topic = EMSdevice::device_type_2_device_name(device_type); // thermostat, boiler, etc... + // see if we have already a handler for the device type (boiler, thermostat). If not add it bool exists = false; if (!mqtt_subfunctions_.empty()) { for (const auto & mqtt_subfunction : mqtt_subfunctions_) { @@ -101,15 +102,21 @@ void Mqtt::register_command(const uint8_t device_type, const __FlashStringHelper } if (!exists) { - Mqtt::subscribe(device_type, cmd_topic, nullptr); // use an empty function handler to signal this is a command function + Mqtt::subscribe(device_type, cmd_topic, nullptr); // use an empty function handler to signal this is a command function only (e.g. ems-esp/boiler) + LOG_DEBUG(F("Registering MQTT cmd %s with topic %s"), uuid::read_flash_string(cmd).c_str(), EMSdevice::device_type_2_device_name(device_type).c_str()); } - LOG_DEBUG(F("Registering MQTT cmd %s with topic %s"), uuid::read_flash_string(cmd).c_str(), EMSdevice::device_type_2_device_name(device_type).c_str()); + // register the individual commands too (e.g. ems-esp/boiler/wwonetime) + // https://github.com/emsesp/EMS-ESP32/issues/31 + std::string topic(100, '\0'); + topic = cmd_topic + "/" + uuid::read_flash_string(cmd); + Mqtt::subscribe(device_type, topic, nullptr); } -// subscribe to an MQTT topic, and store the associated callback function. For generic functions not tied to a specific device +// subscribe to an MQTT topic, and store the associated callback function +// For generic functions not tied to a specific device void Mqtt::subscribe(const std::string & topic, mqtt_subfunction_p cb) { - subscribe(0, topic, cb); // no device_id needed, if generic to EMS-ESP + subscribe(0, topic, cb); // no device_id needed if generic to EMS-ESP } // resubscribe to all MQTT topics @@ -189,7 +196,7 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) { // show subscriptions shell.printfln(F("MQTT topic subscriptions:")); for (const auto & mqtt_subfunction : mqtt_subfunctions_) { - shell.printfln(F(" %s/%s"), mqtt_base_.c_str(), mqtt_subfunction.topic_.c_str()); + shell.printfln(F(" %s/%s (%s)"), mqtt_base_.c_str(), mqtt_subfunction.topic_.c_str(), EMSdevice::device_type_2_device_name(mqtt_subfunction.device_type_).c_str()); } shell.println(); @@ -266,6 +273,20 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len) return; } + // check if it's not json, then try and extract the command from the topic name + if (message[0] != '{') { + char * cmd_only = strrchr(topic, '/'); + if (cmd_only == NULL) { + return; // invalid topic name + } + cmd_only++; // skip the / + // LOG_INFO(F("devicetype= %d, topic = %s, cmd = %s, message = %s"), mf.device_type_, topic, cmd_only, message); + if (!Command::call(mf.device_type_, cmd_only, message)) { + LOG_ERROR(F("No matching cmd (%s) in topic %s, or invalid data"), cmd_only, topic); + } + return; + } + // It's a command then with the payload being JSON like {"cmd":"", "data":, "id":} // Find the command from the json and call it directly StaticJsonDocument doc; @@ -305,7 +326,7 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len) } if (!cmd_known) { - LOG_ERROR(F("No matching cmd (%s), invalid data or command failed"), command); + LOG_ERROR(F("No matching cmd (%s) or invalid data"), command); } return; diff --git a/src/test/test.cpp b/src/test/test.cpp index 17805b2c1..b53c5ea39 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -21,8 +21,6 @@ #include "test.h" -// create some fake test data - namespace emsesp { // no shell @@ -368,12 +366,22 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd) { if (command == "boiler") { shell.printfln(F("Testing boiler...")); + Mqtt::ha_enabled(false); + Mqtt::nested_format(true); + run_test("boiler"); shell.invoke_command("show devices"); shell.invoke_command("show"); - // shell.invoke_command("call boiler info"); - // shell.invoke_command("call system publish"); - // shell.invoke_command("show mqtt"); + shell.invoke_command("call boiler info"); + shell.invoke_command("call system publish"); + + EMSESP::mqtt_.incoming("ems-esp/boiler/wwonetime", "1"); + EMSESP::mqtt_.incoming("ems-esp/boiler/wwonetime", "0"); + EMSESP::mqtt_.incoming("ems-esp/boiler/heatingtemp", "24"); + EMSESP::mqtt_.incoming("ems-esp/boiler/wwonetime", "test"); // should fail + EMSESP::mqtt_.incoming("ems-esp/boiler", "{\"cmd\":\"flowtemp\",\"id\":0,\"data\":22}"); + + shell.invoke_command("show mqtt"); } if (command == "fr120") { diff --git a/src/test/test.h b/src/test/test.h index fb991cdbc..6227c8dfa 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -30,9 +30,9 @@ namespace emsesp { // #define EMSESP_TEST_DEFAULT "mixer" // #define EMSESP_TEST_DEFAULT "web" // #define EMSESP_TEST_DEFAULT "general" -// #define EMSESP_TEST_DEFAULT "boiler" +#define EMSESP_TEST_DEFAULT "boiler" // #define EMSESP_TEST_DEFAULT "mqtt2" -#define EMSESP_TEST_DEFAULT "mqtt_nested" +// #define EMSESP_TEST_DEFAULT "mqtt_nested" // #define EMSESP_TEST_DEFAULT "ha" class Test { diff --git a/src/version.h b/src/version.h index 41d49a009..7c6067f11 100644 --- a/src/version.h +++ b/src/version.h @@ -1,2 +1,2 @@ -#define EMSESP_APP_VERSION "3.0.1b0" +#define EMSESP_APP_VERSION "3.0.1b1" #define EMSESP_PLATFORM "ESP32"