allow number and string for MQTT json commands - #445

This commit is contained in:
proddy
2020-08-15 19:53:55 +02:00
parent 64063fa6cd
commit 67877d07c5
7 changed files with 53 additions and 81 deletions

View File

@@ -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":<cmd> ,"data":<data>, "id":<n>}`.
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*

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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<char *>()) {
cmd_known = call_command(mf.device_type_, command, data.as<char *>(), n);
} else if (data.is<int>()) {
char data_str[10];
cmd_known = call_command(mf.device_type_, command, Helpers::itoa(data_str, (int16_t)data.as<int>()), n);
} else if (data.is<float>()) {
char data_str[10];
cmd_known = call_command(mf.device_type_, command, Helpers::render_value(data_str, (float)data.as<float>(), 2), n);
}
if (!cmd_known) {
LOG_ERROR(F("MQTT: no matching cmd or invalid data: %s"), command);
}
return;

View File

@@ -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<const MqttMessage> 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();

View File

@@ -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