mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
allow number and string for MQTT json commands - #445
This commit is contained in:
@@ -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*
|
||||
|
||||
1
makefile
1
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
25
src/mqtt.cpp
25
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<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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user