mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
feat: expose cmd's via MQTT directly #31
This commit is contained in:
41
src/mqtt.cpp
41
src/mqtt.cpp
@@ -64,11 +64,11 @@ void Mqtt::subscribe(const uint8_t device_type, const std::string & topic, mqtt_
|
|||||||
if (!mqtt_subfunctions_.empty()) {
|
if (!mqtt_subfunctions_.empty()) {
|
||||||
for (auto & mqtt_subfunction : mqtt_subfunctions_) {
|
for (auto & mqtt_subfunction : mqtt_subfunctions_) {
|
||||||
if ((mqtt_subfunction.device_type_ == device_type) && (strcmp(mqtt_subfunction.topic_.c_str(), topic.c_str()) == 0)) {
|
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) {
|
if (cb) {
|
||||||
mqtt_subfunction.mqtt_subfunction_ = 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
|
// 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) {
|
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;
|
bool exists = false;
|
||||||
if (!mqtt_subfunctions_.empty()) {
|
if (!mqtt_subfunctions_.empty()) {
|
||||||
for (const auto & mqtt_subfunction : mqtt_subfunctions_) {
|
for (const auto & mqtt_subfunction : mqtt_subfunctions_) {
|
||||||
@@ -101,15 +102,21 @@ void Mqtt::register_command(const uint8_t device_type, const __FlashStringHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!exists) {
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
// subscribe to an MQTT topic, and store the associated callback function. For generic functions not tied to a specific device
|
// 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
|
||||||
void Mqtt::subscribe(const std::string & topic, mqtt_subfunction_p cb) {
|
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
|
// resubscribe to all MQTT topics
|
||||||
@@ -189,7 +196,7 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) {
|
|||||||
// show subscriptions
|
// show subscriptions
|
||||||
shell.printfln(F("MQTT topic subscriptions:"));
|
shell.printfln(F("MQTT topic subscriptions:"));
|
||||||
for (const auto & mqtt_subfunction : mqtt_subfunctions_) {
|
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();
|
shell.println();
|
||||||
|
|
||||||
@@ -266,6 +273,20 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len)
|
|||||||
return;
|
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":"<cmd>", "data":<data>, "id":<n>}
|
// It's a command then with the payload being JSON like {"cmd":"<cmd>", "data":<data>, "id":<n>}
|
||||||
// Find the command from the json and call it directly
|
// Find the command from the json and call it directly
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_SMALL> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_SMALL> doc;
|
||||||
@@ -305,7 +326,7 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!cmd_known) {
|
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;
|
return;
|
||||||
|
|||||||
@@ -21,8 +21,6 @@
|
|||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
// create some fake test data
|
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
// no shell
|
// no shell
|
||||||
@@ -368,12 +366,22 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd) {
|
|||||||
|
|
||||||
if (command == "boiler") {
|
if (command == "boiler") {
|
||||||
shell.printfln(F("Testing boiler..."));
|
shell.printfln(F("Testing boiler..."));
|
||||||
|
Mqtt::ha_enabled(false);
|
||||||
|
Mqtt::nested_format(true);
|
||||||
|
|
||||||
run_test("boiler");
|
run_test("boiler");
|
||||||
shell.invoke_command("show devices");
|
shell.invoke_command("show devices");
|
||||||
shell.invoke_command("show");
|
shell.invoke_command("show");
|
||||||
// shell.invoke_command("call boiler info");
|
shell.invoke_command("call boiler info");
|
||||||
// shell.invoke_command("call system publish");
|
shell.invoke_command("call system publish");
|
||||||
// shell.invoke_command("show mqtt");
|
|
||||||
|
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") {
|
if (command == "fr120") {
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ namespace emsesp {
|
|||||||
// #define EMSESP_TEST_DEFAULT "mixer"
|
// #define EMSESP_TEST_DEFAULT "mixer"
|
||||||
// #define EMSESP_TEST_DEFAULT "web"
|
// #define EMSESP_TEST_DEFAULT "web"
|
||||||
// #define EMSESP_TEST_DEFAULT "general"
|
// #define EMSESP_TEST_DEFAULT "general"
|
||||||
// #define EMSESP_TEST_DEFAULT "boiler"
|
#define EMSESP_TEST_DEFAULT "boiler"
|
||||||
// #define EMSESP_TEST_DEFAULT "mqtt2"
|
// #define EMSESP_TEST_DEFAULT "mqtt2"
|
||||||
#define EMSESP_TEST_DEFAULT "mqtt_nested"
|
// #define EMSESP_TEST_DEFAULT "mqtt_nested"
|
||||||
// #define EMSESP_TEST_DEFAULT "ha"
|
// #define EMSESP_TEST_DEFAULT "ha"
|
||||||
|
|
||||||
class Test {
|
class Test {
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#define EMSESP_APP_VERSION "3.0.1b0"
|
#define EMSESP_APP_VERSION "3.0.1b1"
|
||||||
#define EMSESP_PLATFORM "ESP32"
|
#define EMSESP_PLATFORM "ESP32"
|
||||||
|
|||||||
Reference in New Issue
Block a user