From 67877d07c51b5e456e86bc55ec334151e3c827b1 Mon Sep 17 00:00:00 2001 From: proddy Date: Sat, 15 Aug 2020 19:53:55 +0200 Subject: [PATCH] allow number and string for MQTT json commands - #445 --- README.md | 2 +- makefile | 1 - src/console.cpp | 5 --- src/helpers.cpp | 4 +-- src/mqtt.cpp | 25 +++++++++---- src/mqtt.h | 6 ++-- src/test/test.cpp | 91 ++++++++++++++--------------------------------- 7 files changed, 53 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 99081c65a..34f0c6355 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ Breaking change: The MQTT base has been removed in version 2. The hostname is on All commands must be written as `{"cmd": ,"data":, "id":}`. -The `id` can be replaced with `hc` for some devices. `cmd` and `data` must be enclose in quotes as a string. +The `id` can be replaced with `hc` for some devices and represented as a string or a number. `cmd` is a string, `data` can be a string or number. ``` *boiler_cmd* diff --git a/makefile b/makefile index 575648548..06928a441 100644 --- a/makefile +++ b/makefile @@ -27,7 +27,6 @@ CXX_STANDARD := -std=c++11 # Defined Symbols #---------------------------------------------------------------------- DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_NO_LED -DEFINES += -DRUN_TEST #---------------------------------------------------------------------- # Sources & Files diff --git a/src/console.cpp b/src/console.cpp index b71b59427..9fb8a3118 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -92,11 +92,6 @@ void EMSESPShell::display_banner() { emsesp::EMSESP::watch_id(WATCH_ID_NONE); emsesp::EMSESP::watch(EMSESP::WATCH_OFF); -#if defined(EMSESP_STANDALONE) -#ifdef RUN_TEST - invoke_command("test"); // same as "test default" -#endif -#endif } // pre-loads all the console commands into the MAIN context diff --git a/src/helpers.cpp b/src/helpers.cpp index 1319bc0a5..4ca778590 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -186,7 +186,7 @@ char * Helpers::render_value(char * result, const int16_t value, const uint8_t f return nullptr; } - // just print it if mo conversion required (format = 0) + // just print it if no conversion required (format = 0) if (!format) { itoa(result, value, 10); return result; @@ -406,7 +406,7 @@ bool Helpers::value2bool(const char * v, bool & value) { if ((bool_str == "off") || (bool_str == "0") or (bool_str == "false")) { value = false; - return true; // is a bool + return true; // is a bool } return false; // not a bool diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 11a703603..3cc0f4df9 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -192,10 +192,12 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) { shell.println(); } // namespace emsesp +#if defined(EMSESP_DEBUG) // simulate receiving a MQTT message, used only for testing -void Mqtt::incoming(char * topic, char * payload) { +void Mqtt::incoming(const char * topic, const char * payload) { on_message(topic, payload, strlen(payload)); } +#endif // calls a command, context is the device_type // id may be used to represent a heating circuit for example @@ -223,7 +225,7 @@ bool Mqtt::call_command(const uint8_t device_type, const char * cmd, const char } // received an MQTT message that we subscribed too -void Mqtt::on_message(char * topic, char * payload, size_t len) { +void Mqtt::on_message(const char * topic, const char * payload, size_t len) { if (len == 0) { return; } @@ -257,7 +259,7 @@ void Mqtt::on_message(char * topic, char * payload, size_t len) { return; } - // check for hc and id + // check for hc and id, and convert to int int8_t n = -1; // no value if (doc.containsKey("hc")) { n = doc["hc"]; @@ -265,9 +267,20 @@ void Mqtt::on_message(char * topic, char * payload, size_t len) { n = doc["id"]; } - if (!call_command(mf.device_type_, command, doc["data"], n)) { - // if we got here we didn't find a matching command - LOG_ERROR(F("MQTT error: no matching cmd: %s"), command); + bool cmd_known = false; + JsonVariant data = doc["data"]; + if (data.is()) { + cmd_known = call_command(mf.device_type_, command, data.as(), n); + } else if (data.is()) { + char data_str[10]; + cmd_known = call_command(mf.device_type_, command, Helpers::itoa(data_str, (int16_t)data.as()), n); + } else if (data.is()) { + char data_str[10]; + cmd_known = call_command(mf.device_type_, command, Helpers::render_value(data_str, (float)data.as(), 2), n); + } + + if (!cmd_known) { + LOG_ERROR(F("MQTT: no matching cmd or invalid data: %s"), command); } return; diff --git a/src/mqtt.h b/src/mqtt.h index 8c9e36faf..a5afbe3c0 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -96,7 +96,9 @@ class Mqtt { mqttClient_->disconnect(); } - void incoming(char * topic, char * payload); // for testing +#if defined(EMSESP_DEBUG) + void incoming(const char * topic, const char * payload); // for testing only +#endif static bool connected() { return mqttClient_->connected(); @@ -163,7 +165,7 @@ class Mqtt { static std::shared_ptr queue_subscribe_message(const std::string & topic); void on_publish(uint16_t packetId); - void on_message(char * topic, char * payload, size_t len); + void on_message(const char * topic, const char * payload, size_t len); void process_queue(); void process_all_queue(); diff --git a/src/test/test.cpp b/src/test/test.cpp index 6b951ba93..5c3cf5012 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -28,7 +28,7 @@ namespace emsesp { // used with the 'test' command, under su/admin void Test::run_test(uuid::console::Shell & shell, const std::string & command) { if (command == "default") { - run_test(shell, "general"); // add the default test case here + run_test(shell, "mqtt"); // add the default test case here } if (command.empty()) { @@ -553,78 +553,40 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) { shell.loop_all(); - char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; - char payload[100]; + char boiler_topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; + char thermostat_topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; + char system_topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; // test publish and adding to queue EMSESP::txservice_.flush_tx_queue(); EMSESP::EMSESP::mqtt_.publish("boiler_cmd", "test me"); Mqtt::show_mqtt(shell); // show queue - strcpy(topic, "ems-esp/boiler_cmd"); - strcpy(payload, "12345"); - EMSESP::mqtt_.incoming(topic, payload); // invalid format - EMSESP::mqtt_.incoming(payload, payload); // no matching topic + strcpy(boiler_topic, "ems-esp/boiler_cmd"); + strcpy(thermostat_topic, "ems-esp/thermostat_cmd"); + strcpy(system_topic, "ems-esp/saystem_cmd"); - strcpy(topic, "ems-esp/boiler_cmd"); - strcpy(payload, "{\"cmd\":\"garbage\",\"data\":22.52}"); - EMSESP::mqtt_.incoming(topic, payload); // should report error + EMSESP::mqtt_.incoming(boiler_topic, "12345"); // invalid format + EMSESP::mqtt_.incoming("bad_topic", "12345"); // no matching topic + EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"garbage\",\"data\":22.52}"); // should report error + EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"comfort\",\"data\":\"eco\"}"); + EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"wwactivated\",\"data\":\"1\"}"); + EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"wwactivated\",\"data\":1}"); + EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"flowtemp\",\"data\":55}"); - strcpy(topic, "ems-esp/boiler_cmd"); - strcpy(payload, "{\"cmd\":\"comfort\",\"data\":\"eco\"}"); - EMSESP::mqtt_.incoming(topic, payload); + EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"send\",\"data\":\"01 02 03 04 05\"}"); + EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"pin\",\"id\":12,\"data\":\"1\"}"); - strcpy(topic, "ems-esp/boiler_cmd"); - strcpy(payload, "{\"cmd\":\"wwactivated\",\"data\":\"1\"}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/boiler_cmd"); - strcpy(payload, "{\"cmd\":\"wwactivated\",\"data\":1}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/boiler_cmd"); - strcpy(payload, "{\"cmd\":\"flowtemp\",\"data\":55}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/system_cmd"); - strcpy(payload, "{\"cmd\":\"send\",\"data\":\"01 02 03 04 05\"}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/system_cmd"); - strcpy(payload, "{\"cmd\":\"pin\",\"id\":12,\"data\":\"1\"}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/thermostat_cmd"); - strcpy(payload, "{\"cmd\":\"wwmode\",\"data\":\"auto\"}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/thermostat_cmd"); - strcpy(payload, "{\"cmd\":\"control\",\"data\":\"1\"}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/thermostat_cmd"); - strcpy(payload, "{\"cmd\":\"control\",\"data\":1}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/thermostat_cmd"); - strcpy(payload, "{\"cmd\":\"mode\",\"data\":\"auto\",\"id\":2}"); // with id - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/thermostat_cmd"); - strcpy(payload, "{\"cmd\":\"mode\",\"data\":\"auto\",\"hc\":2}"); // with hc - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/thermostat_cmd"); - strcpy(payload, "{\"cmd\":\"temp\",\"data\":22.52}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/thermostat_cmd"); - strcpy(payload, "{\"cmd\":\"temp\",\"data\":22.52}"); - EMSESP::mqtt_.incoming(topic, payload); - - strcpy(topic, "ems-esp/thermostat_cmd"); - strcpy(payload, "{\"cmd\":\"temp\",\"id\":2,\"data\":22}"); - EMSESP::mqtt_.incoming(topic, payload); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"wwmode\",\"data\":\"auto\"}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"control\",\"data\":\"1\"}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"control\",\"data\":1}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"id\":2}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"hc\":2}"); // hc as number + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"hc\":\"2\"}"); // hc as string + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":22.56}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":22}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":\"22.56\"}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"id\":2,\"data\":22}"); // EMSESP::txservice_.show_tx_queue(); // EMSESP::publish_all_values(); @@ -636,6 +598,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) { shell.invoke_command("call"); shell.invoke_command("call wwmode"); shell.invoke_command("call mode auto 2"); + shell.invoke_command("call temp 22.56"); Mqtt::resubscribe(); Mqtt::show_mqtt(shell); // show queue