mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
id to value_info, alternative prefix to command/value
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
- Mock API to simulate an ESP, for testing web
|
- Mock API to simulate an ESP, for testing web
|
||||||
- Able to write values from the Web UI
|
- Able to write values from the Web UI
|
||||||
|
- check values with `"cmd":<valuename>` and data empty or `?`
|
||||||
|
- set hc for values and commands by id or prefix `hc<x>`+separarator, separator can be any char
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
- Don't create Home Assistant MQTT discovery entries for device values that don't exists (#756 on EMS-ESP repo)
|
- Don't create Home Assistant MQTT discovery entries for device values that don't exists (#756 on EMS-ESP repo)
|
||||||
|
|||||||
@@ -30,9 +30,12 @@ std::vector<Command::CmdFunction> Command::cmdfunctions_;
|
|||||||
// id may be used to represent a heating circuit for example, it's optional
|
// id may be used to represent a heating circuit for example, it's optional
|
||||||
// returns false if error or not found
|
// returns false if error or not found
|
||||||
bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id) {
|
bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id) {
|
||||||
std::string dname = EMSdevice::device_type_2_device_name(device_type);
|
std::string dname = EMSdevice::device_type_2_device_name(device_type);
|
||||||
|
int8_t id_new = id;
|
||||||
|
char cmd_new[20];
|
||||||
|
|
||||||
auto cf = find_command(device_type, cmd);
|
check_command(cmd_new, cmd, id_new);
|
||||||
|
auto cf = find_command(device_type, cmd_new);
|
||||||
if ((cf == nullptr) || (cf->cmdfunction_json_)) {
|
if ((cf == nullptr) || (cf->cmdfunction_json_)) {
|
||||||
LOG_WARNING(F("Command %s on %s not found"), cmd, dname.c_str());
|
LOG_WARNING(F("Command %s on %s not found"), cmd, dname.c_str());
|
||||||
return false; // command not found, or requires a json
|
return false; // command not found, or requires a json
|
||||||
@@ -48,18 +51,21 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ((cf->cmdfunction_)(value, id));
|
return ((cf->cmdfunction_)(value, id_new));
|
||||||
}
|
}
|
||||||
|
|
||||||
// calls a command. Takes a json object for output.
|
// calls a command. Takes a json object for output.
|
||||||
// id may be used to represent a heating circuit for example
|
// id may be used to represent a heating circuit for example
|
||||||
// returns false if error or not found
|
// returns false if error or not found
|
||||||
bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id, JsonObject & json) {
|
bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id, JsonObject & json) {
|
||||||
std::string dname = EMSdevice::device_type_2_device_name(device_type);
|
int8_t id_new = id;
|
||||||
|
char cmd_new[20];
|
||||||
|
|
||||||
auto cf = find_command(device_type, cmd);
|
check_command(cmd_new, cmd, id_new);
|
||||||
|
auto cf = find_command(device_type, cmd_new);
|
||||||
|
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
|
std::string dname = EMSdevice::device_type_2_device_name(device_type);
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
LOG_DEBUG(F("[DEBUG] Calling %s command %s"), dname.c_str(), cmd);
|
LOG_DEBUG(F("[DEBUG] Calling %s command %s"), dname.c_str(), cmd);
|
||||||
} else if (id == -1) {
|
} else if (id == -1) {
|
||||||
@@ -76,19 +82,48 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cf == nullptr) {
|
if (cf == nullptr) {
|
||||||
return EMSESP::get_device_value_info(json, cmd, device_type);
|
return EMSESP::get_device_value_info(json, cmd_new, id_new, device_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cf->cmdfunction_json_) {
|
if (cf->cmdfunction_json_) {
|
||||||
return ((cf->cmdfunction_json_)(value, id, json));
|
return ((cf->cmdfunction_json_)(value, id_new, json));
|
||||||
} else {
|
} else {
|
||||||
if (value == nullptr || strlen(value) == 0) {
|
if (value == nullptr || strlen(value) == 0 || strcmp(value, "?") == 0 || strcmp(value, "*") == 0) {
|
||||||
return EMSESP::get_device_value_info(json, cmd, device_type);
|
return EMSESP::get_device_value_info(json, cmd_new, id_new, device_type);
|
||||||
}
|
}
|
||||||
return ((cf->cmdfunction_)(value, id));
|
return ((cf->cmdfunction_)(value, id_new));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char * Command::check_command(char * out, const char * cmd, int8_t & id) {
|
||||||
|
// convert cmd to lowercase
|
||||||
|
strlcpy(out, cmd, 20);
|
||||||
|
for (char * p = out; *p; p++) {
|
||||||
|
*p = tolower(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
//scan for prefix hc.
|
||||||
|
for (uint8_t i = DeviceValueTAG::TAG_HC1; i <= DeviceValueTAG::TAG_HC4; i++) {
|
||||||
|
if ((strncmp(out, EMSdevice::tag_to_string(i).c_str(), 3) == 0) && (strlen(out) > 4)) {
|
||||||
|
strcpy(out, &out[4]);
|
||||||
|
id = 1 + i - DeviceValueTAG::TAG_HC1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//scan for prefix wwc.
|
||||||
|
for (uint8_t i = DeviceValueTAG::TAG_WWC1; i <= DeviceValueTAG::TAG_WWC4; i++) {
|
||||||
|
if ((strncmp(out, EMSdevice::tag_to_string(i).c_str(), 4) == 0) && (strlen(out) > 5)) {
|
||||||
|
strcpy(out, &out[5]);
|
||||||
|
id = 8 + i - DeviceValueTAG::TAG_WWC1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// add a command to the list, which does not return json
|
// add a command to the list, which does not return json
|
||||||
void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_p cb, uint8_t flag) {
|
void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_p cb, uint8_t flag) {
|
||||||
// if the command already exists for that device type don't add it
|
// if the command already exists for that device type don't add it
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class Command {
|
|||||||
static void add_with_json(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_json_p cb);
|
static void add_with_json(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_json_p cb);
|
||||||
static void show_all(uuid::console::Shell & shell);
|
static void show_all(uuid::console::Shell & shell);
|
||||||
static Command::CmdFunction * find_command(const uint8_t device_type, const char * cmd);
|
static Command::CmdFunction * find_command(const uint8_t device_type, const char * cmd);
|
||||||
|
static char * check_command(char * out, const char * cmd, int8_t & id);
|
||||||
|
|
||||||
static void show(uuid::console::Shell & shell, uint8_t device_type);
|
static void show(uuid::console::Shell & shell, uint8_t device_type);
|
||||||
static void show_devices(uuid::console::Shell & shell);
|
static void show_devices(uuid::console::Shell & shell);
|
||||||
|
|||||||
@@ -620,12 +620,25 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
|
|||||||
return (num_elements != 0);
|
return (num_elements != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EMSdevice::get_value_info(JsonObject & root, const char * cmd) {
|
bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t id) {
|
||||||
JsonObject json = root;
|
JsonObject json = root;
|
||||||
|
int8_t tag = id;
|
||||||
|
|
||||||
|
// check if we have hc or wwc
|
||||||
|
if (id >= 1 && id <= 4) {
|
||||||
|
tag = DeviceValueTAG::TAG_HC1 + id - 1;
|
||||||
|
} else if (id >= 8 && id <= 11) {
|
||||||
|
tag = DeviceValueTAG::TAG_WWC1 + id - 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search device value with this tag
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
if (strcmp(cmd, uuid::read_flash_string(dv.short_name).c_str()) == 0) {
|
if (strcmp(cmd, uuid::read_flash_string(dv.short_name).c_str()) == 0 && (tag <= 0 || tag == dv.tag)) {
|
||||||
uint8_t divider = (dv.options_size == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0;
|
uint8_t divider = (dv.options_size == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0;
|
||||||
json["name"] = cmd;
|
json["name"] = dv.short_name;
|
||||||
|
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
|
json["circuit"] = tag_to_string(dv.tag);
|
||||||
|
}
|
||||||
switch (dv.type) {
|
switch (dv.type) {
|
||||||
case DeviceValueType::ENUM: {
|
case DeviceValueType::ENUM: {
|
||||||
if (Helpers::hasValue((uint8_t)(*(uint8_t *)(dv.value_p)))) {
|
if (Helpers::hasValue((uint8_t)(*(uint8_t *)(dv.value_p)))) {
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ class EMSdevice {
|
|||||||
bool handle_telegram(std::shared_ptr<const Telegram> telegram);
|
bool handle_telegram(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
std::string get_value_uom(const char * key);
|
std::string get_value_uom(const char * key);
|
||||||
bool get_value_info(JsonObject & root, const char * cmd);
|
bool get_value_info(JsonObject & root, const char * cmd, const int8_t id);
|
||||||
bool generate_values_json(JsonObject & json, const uint8_t tag_filter, const bool nested, const bool console = false);
|
bool generate_values_json(JsonObject & json, const uint8_t tag_filter, const bool nested, const bool console = false);
|
||||||
bool generate_values_json_web(JsonObject & json);
|
bool generate_values_json_web(JsonObject & json);
|
||||||
|
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ void EMSESP::publish_device_values(uint8_t device_type) {
|
|||||||
// group by device type
|
// group by device type
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
||||||
// if we're using HA, if done is checked for each sensor in devices
|
// if we're using HA, done is checked for each sensor in devices
|
||||||
if (Mqtt::ha_enabled()) {
|
if (Mqtt::ha_enabled()) {
|
||||||
emsdevice->publish_mqtt_ha_sensor(); // create the configs for each value as a sensor
|
emsdevice->publish_mqtt_ha_sensor(); // create the configs for each value as a sensor
|
||||||
}
|
}
|
||||||
@@ -547,10 +547,10 @@ void EMSESP::publish_response(std::shared_ptr<const Telegram> telegram) {
|
|||||||
Mqtt::publish(F("response"), doc.as<JsonObject>());
|
Mqtt::publish(F("response"), doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, uint8_t devicetype) {
|
bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype) {
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice->device_type() == devicetype) {
|
if (emsdevice->device_type() == devicetype) {
|
||||||
return emsdevice->get_value_info(root, cmd);
|
return emsdevice->get_value_info(root, cmd, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class EMSESP {
|
|||||||
static void actual_master_thermostat(const uint8_t device_id);
|
static void actual_master_thermostat(const uint8_t device_id);
|
||||||
static uint8_t check_master_device(const uint8_t device_id, const uint16_t type_id, const bool read);
|
static uint8_t check_master_device(const uint8_t device_id, const uint16_t type_id, const bool read);
|
||||||
|
|
||||||
static bool get_device_value_info(JsonObject & root, const char * cmd, uint8_t devicetype);
|
static bool get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype);
|
||||||
|
|
||||||
static void show_device_values(uuid::console::Shell & shell);
|
static void show_device_values(uuid::console::Shell & shell);
|
||||||
static void show_sensor_values(uuid::console::Shell & shell);
|
static void show_sensor_values(uuid::console::Shell & shell);
|
||||||
|
|||||||
12
src/mqtt.cpp
12
src/mqtt.cpp
@@ -328,11 +328,11 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len)
|
|||||||
}
|
}
|
||||||
cmd_only++; // skip the /
|
cmd_only++; // skip the /
|
||||||
int8_t id = -1;
|
int8_t id = -1;
|
||||||
// check for hcx/ prefix
|
// check for hcx/ prefix, commented out, this is now in command::call
|
||||||
if (cmd_only[0] == 'h' && cmd_only[1] == 'c' && cmd_only[3] == '/') {
|
// if (cmd_only[0] == 'h' && cmd_only[1] == 'c' && cmd_only[3] == '/') {
|
||||||
id = cmd_only[2] - '0';
|
// id = cmd_only[2] - '0';
|
||||||
cmd_only += 4;
|
// cmd_only += 4;
|
||||||
}
|
// }
|
||||||
// LOG_INFO(F("devicetype= %d, topic = %s, cmd = %s, message = %s, id = %d"), mf.device_type_, topic, cmd_only, message, id);
|
// LOG_INFO(F("devicetype= %d, topic = %s, cmd = %s, message = %s, id = %d"), mf.device_type_, topic, cmd_only, message, id);
|
||||||
if (!Command::call(mf.device_type_, cmd_only, message, id)) {
|
if (!Command::call(mf.device_type_, cmd_only, message, id)) {
|
||||||
LOG_ERROR(F("No matching cmd (%s) in topic %s, id %d, or invalid data"), cmd_only, topic, id);
|
LOG_ERROR(F("No matching cmd (%s) in topic %s, id %d, or invalid data"), cmd_only, topic, id);
|
||||||
@@ -382,7 +382,7 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len)
|
|||||||
if (cmd_known && json.size()) {
|
if (cmd_known && json.size()) {
|
||||||
Mqtt::publish(F("response"), resp.as<JsonObject>());
|
Mqtt::publish(F("response"), resp.as<JsonObject>());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cmd_known) {
|
if (!cmd_known) {
|
||||||
|
|||||||
Reference in New Issue
Block a user