mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
Add value_info
This commit is contained in:
@@ -45,12 +45,6 @@ void WebAPIService::webAPIService(AsyncWebServerRequest * request) {
|
|||||||
// get cmd, we know we have one
|
// get cmd, we know we have one
|
||||||
String cmd = request->getParam(F_(cmd))->value();
|
String cmd = request->getParam(F_(cmd))->value();
|
||||||
|
|
||||||
// look up command in our list
|
|
||||||
if (Command::find_command(device_type, cmd.c_str()) == nullptr) {
|
|
||||||
request->send(400, "text/plain", F("Invalid cmd"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String data;
|
String data;
|
||||||
if (request->hasParam(F_(data))) {
|
if (request->hasParam(F_(data))) {
|
||||||
data = request->getParam(F_(data))->value();
|
data = request->getParam(F_(data))->value();
|
||||||
|
|||||||
@@ -58,10 +58,6 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val
|
|||||||
std::string dname = EMSdevice::device_type_2_device_name(device_type);
|
std::string dname = EMSdevice::device_type_2_device_name(device_type);
|
||||||
|
|
||||||
auto cf = find_command(device_type, cmd);
|
auto cf = find_command(device_type, cmd);
|
||||||
if (cf == nullptr) {
|
|
||||||
LOG_WARNING(F("Command %s on %s not found"), cmd, dname.c_str());
|
|
||||||
return false; // command not found or not json
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
@@ -79,10 +75,17 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cf->cmdfunction_json_) {
|
if (cf == nullptr) {
|
||||||
return ((cf->cmdfunction_)(value, id));
|
return EMSESP::get_device_value_info(json, cmd, device_type);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (cf->cmdfunction_json_) {
|
||||||
return ((cf->cmdfunction_json_)(value, id, json));
|
return ((cf->cmdfunction_json_)(value, id, json));
|
||||||
|
} else {
|
||||||
|
if (value == nullptr || strlen(value) == 0) {
|
||||||
|
return EMSESP::get_device_value_info(json, cmd, device_type);
|
||||||
|
}
|
||||||
|
return ((cf->cmdfunction_)(value, id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -349,11 +349,6 @@ void EMSESPShell::add_console_commands() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char * cmd = arguments[1].c_str();
|
const char * cmd = arguments[1].c_str();
|
||||||
if (Command::find_command(device_type, cmd) == nullptr) {
|
|
||||||
shell.print(F("Unknown command. Available commands are: "));
|
|
||||||
Command::show(shell, device_type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN);
|
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN);
|
||||||
JsonObject json = doc.to<JsonObject>();
|
JsonObject json = doc.to<JsonObject>();
|
||||||
@@ -379,7 +374,10 @@ void EMSESPShell::add_console_commands() {
|
|||||||
doc.shrinkToFit();
|
doc.shrinkToFit();
|
||||||
serializeJsonPretty(doc, shell);
|
serializeJsonPretty(doc, shell);
|
||||||
shell.println();
|
shell.println();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
shell.print(F("Unknown command. Available commands are: "));
|
||||||
|
Command::show(shell, device_type);
|
||||||
},
|
},
|
||||||
[&](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) -> std::vector<std::string> {
|
[&](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) -> std::vector<std::string> {
|
||||||
if (arguments.size() == 0) {
|
if (arguments.size() == 0) {
|
||||||
@@ -416,6 +414,7 @@ std::string EMSESPShell::hostname_text() {
|
|||||||
return console_hostname_;
|
return console_hostname_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// remove commands from the current context to save memory before exiting
|
// remove commands from the current context to save memory before exiting
|
||||||
bool EMSESPShell::exit_context() {
|
bool EMSESPShell::exit_context() {
|
||||||
unsigned int current_context = context();
|
unsigned int current_context = context();
|
||||||
@@ -429,7 +428,6 @@ bool EMSESPShell::exit_context() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// enter a custom context (sub-menu)
|
// enter a custom context (sub-menu)
|
||||||
void Console::enter_custom_context(Shell & shell, unsigned int context) {
|
void Console::enter_custom_context(Shell & shell, unsigned int context) {
|
||||||
// load_standard_commands(context);
|
// load_standard_commands(context);
|
||||||
@@ -500,7 +498,8 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EMSESPShell::commands->add_command(context, CommandFlags::USER, flash_string_vector{F_(exit)}, [=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
EMSESPShell::commands->add_command(context, CommandFlags::USER, flash_string_vector{F_(exit)}, [=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
shell.exit_context();
|
shell.stop();
|
||||||
|
// shell.exit_context();
|
||||||
});
|
});
|
||||||
|
|
||||||
EMSESPShell::commands->add_command(context, CommandFlags::USER, flash_string_vector{F_(su)}, [=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
EMSESPShell::commands->add_command(context, CommandFlags::USER, flash_string_vector{F_(su)}, [=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
@@ -664,7 +663,7 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// prompt, change per context
|
// prompt, change per context
|
||||||
std::string EMSESPShell::context_text() {
|
std::string EMSESPShell::context_text() {
|
||||||
switch (static_cast<ShellContext>(context())) {
|
switch (static_cast<ShellContext>(context())) {
|
||||||
@@ -678,6 +677,7 @@ std::string EMSESPShell::context_text() {
|
|||||||
return std::string{};
|
return std::string{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// when in su (admin) show # as the prompt suffix
|
// when in su (admin) show # as the prompt suffix
|
||||||
std::string EMSESPShell::prompt_suffix() {
|
std::string EMSESPShell::prompt_suffix() {
|
||||||
|
|||||||
@@ -101,10 +101,10 @@ class EMSESPShell : virtual public uuid::console::Shell {
|
|||||||
void stopped() override;
|
void stopped() override;
|
||||||
void display_banner() override;
|
void display_banner() override;
|
||||||
std::string hostname_text() override;
|
std::string hostname_text() override;
|
||||||
std::string context_text() override;
|
// std::string context_text() override;
|
||||||
std::string prompt_suffix() override;
|
std::string prompt_suffix() override;
|
||||||
void end_of_transmission() override;
|
void end_of_transmission() override;
|
||||||
bool exit_context() override;
|
// bool exit_context() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void add_console_commands();
|
void add_console_commands();
|
||||||
|
|||||||
@@ -613,6 +613,105 @@ 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) {
|
||||||
|
JsonObject json = root;
|
||||||
|
for (auto & dv : devicevalues_) {
|
||||||
|
if (strcmp(cmd, uuid::read_flash_string(dv.short_name).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;
|
||||||
|
switch (dv.type) {
|
||||||
|
case DeviceValueType::ENUM:
|
||||||
|
// json["value"] = dv.options[*(uint8_t *)(dv.value_p)]; // text
|
||||||
|
if (Helpers::hasValue((uint8_t)(*(uint8_t *)(dv.value_p)))) {
|
||||||
|
json["value"] = (uint8_t)(*(uint8_t *)(dv.value_p));
|
||||||
|
}
|
||||||
|
json["type"] = "enum";
|
||||||
|
json["min"] = 0;
|
||||||
|
json["max"] = dv.options_size - 1;
|
||||||
|
break;
|
||||||
|
case DeviceValueType::USHORT:
|
||||||
|
if (Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
|
||||||
|
json["value"] = Helpers::round2(*(uint16_t *)(dv.value_p), divider);
|
||||||
|
}
|
||||||
|
json["type"] = "number";
|
||||||
|
json["min"] = 0;
|
||||||
|
json["max"] = divider ? EMS_VALUE_USHORT_NOTSET / divider : EMS_VALUE_USHORT_NOTSET;
|
||||||
|
break;
|
||||||
|
case DeviceValueType::UINT:
|
||||||
|
if (Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
|
||||||
|
json["value"] = Helpers::round2(*(uint8_t *)(dv.value_p), divider);
|
||||||
|
}
|
||||||
|
json["type"] = "number";
|
||||||
|
json["min"] = 0;
|
||||||
|
if (dv.uom == DeviceValueUOM::PERCENT) {
|
||||||
|
json["max"] = 100;
|
||||||
|
} else {
|
||||||
|
json["max"] = divider ? EMS_VALUE_UINT_NOTSET / divider : EMS_VALUE_UINT_NOTSET;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DeviceValueType::SHORT:
|
||||||
|
if (Helpers::hasValue(*(int16_t *)(dv.value_p))) {
|
||||||
|
json["value"] = Helpers::round2(*(int16_t *)(dv.value_p), divider);
|
||||||
|
}
|
||||||
|
json["type"] = "number";
|
||||||
|
json["min"] = divider ? -EMS_VALUE_SHORT_NOTSET / divider : -EMS_VALUE_SHORT_NOTSET;
|
||||||
|
json["max"] = divider ? EMS_VALUE_SHORT_NOTSET / divider : EMS_VALUE_SHORT_NOTSET;
|
||||||
|
break;
|
||||||
|
case DeviceValueType::INT:
|
||||||
|
if (Helpers::hasValue(*(int8_t *)(dv.value_p))) {
|
||||||
|
json["value"] = Helpers::round2(*(int8_t *)(dv.value_p), divider);
|
||||||
|
}
|
||||||
|
json["type"] = "number";
|
||||||
|
if (dv.uom == DeviceValueUOM::PERCENT) {
|
||||||
|
json["min"] = -100;
|
||||||
|
json["max"] = 100;
|
||||||
|
} else {
|
||||||
|
json["min"] = divider ? -EMS_VALUE_INT_NOTSET / divider : -EMS_VALUE_INT_NOTSET;
|
||||||
|
json["max"] = divider ? EMS_VALUE_INT_NOTSET / divider : EMS_VALUE_INT_NOTSET;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DeviceValueType::ULONG:
|
||||||
|
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
|
json["value"] = Helpers::round2(*(uint32_t *)(dv.value_p), divider);
|
||||||
|
}
|
||||||
|
json["type"] = "number";
|
||||||
|
json["min"] = 0;
|
||||||
|
json["max"] = divider ? EMS_VALUE_ULONG_NOTSET / divider : EMS_VALUE_ULONG_NOTSET;
|
||||||
|
break;
|
||||||
|
case DeviceValueType::BOOL:
|
||||||
|
if (Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
||||||
|
json["value"] = (bool)(*(uint8_t *)(dv.value_p)) ? true : false;
|
||||||
|
}
|
||||||
|
json["type"] = "boolean";
|
||||||
|
break;
|
||||||
|
case DeviceValueType::TIME:
|
||||||
|
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
|
json["value"] = (divider) ? *(uint32_t *)(dv.value_p) / divider : *(uint32_t *)(dv.value_p);
|
||||||
|
}
|
||||||
|
json["type"] = "number";
|
||||||
|
json["min"] = 0;
|
||||||
|
json["max"] = divider ? EMS_VALUE_ULONG_NOTSET / divider : EMS_VALUE_ULONG_NOTSET;
|
||||||
|
break;
|
||||||
|
case DeviceValueType::TEXT:
|
||||||
|
if (Helpers::hasValue((char *)(dv.value_p))) {
|
||||||
|
json["value"] = (char *)(dv.value_p);
|
||||||
|
}
|
||||||
|
json["type"] = "text";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
json["type"] = "unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dv.uom != DeviceValueUOM::NONE) {
|
||||||
|
json["unit"] = EMSdevice::uom_to_string(dv.uom);
|
||||||
|
}
|
||||||
|
json["writeable"] = dv.has_cmd;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// For each value in the device create the json object pair and add it to given json
|
// For each value in the device create the json object pair and add it to given json
|
||||||
// return false if empty
|
// return false if empty
|
||||||
// this is used to create both the MQTT payloads and Console messages (console = true)
|
// this is used to create both the MQTT payloads and Console messages (console = true)
|
||||||
@@ -778,7 +877,8 @@ void EMSdevice::publish_mqtt_ha_sensor() {
|
|||||||
|
|
||||||
void EMSdevice::ha_config_clear() {
|
void EMSdevice::ha_config_clear() {
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
dv.ha &= ~DeviceValueHA::HA_DONE;
|
// dv.ha &= ~DeviceValueHA::HA_DONE; // repubish all with values
|
||||||
|
dv.ha = DeviceValueHA::HA_NONE; // also wait for new value
|
||||||
}
|
}
|
||||||
ha_config_done(false);
|
ha_config_done(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,6 +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 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);
|
||||||
|
|
||||||
|
|||||||
@@ -547,6 +547,15 @@ 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) {
|
||||||
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
if (emsdevice->device_type() == devicetype) {
|
||||||
|
return emsdevice->get_value_info(root, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// search for recognized device_ids : Me, All, otherwise print hex value
|
// search for recognized device_ids : Me, All, otherwise print hex value
|
||||||
std::string EMSESP::device_tostring(const uint8_t device_id) {
|
std::string EMSESP::device_tostring(const uint8_t device_id) {
|
||||||
if ((device_id & 0x7F) == rxservice_.ems_bus_id()) {
|
if ((device_id & 0x7F) == rxservice_.ems_bus_id()) {
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ 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 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);
|
||||||
|
|
||||||
|
|||||||
@@ -313,6 +313,7 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len)
|
|||||||
if (mf.mqtt_subfunction_) {
|
if (mf.mqtt_subfunction_) {
|
||||||
if (!(mf.mqtt_subfunction_)(message)) {
|
if (!(mf.mqtt_subfunction_)(message)) {
|
||||||
LOG_ERROR(F("MQTT error: invalid payload %s for this topic %s"), message, topic);
|
LOG_ERROR(F("MQTT error: invalid payload %s for this topic %s"), message, topic);
|
||||||
|
Mqtt::publish(F("response"), "invalid");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -335,6 +336,7 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len)
|
|||||||
// 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);
|
||||||
|
Mqtt::publish(F("response"), "unknown");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -379,11 +381,13 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len)
|
|||||||
cmd_known = Command::call(mf.device_type_, command, "", n, json);
|
cmd_known = Command::call(mf.device_type_, command, "", n, json);
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cmd_known) {
|
if (!cmd_known) {
|
||||||
LOG_ERROR(F("No matching cmd (%s) or invalid data"), command);
|
LOG_ERROR(F("No matching cmd (%s) or invalid data"), command);
|
||||||
|
Mqtt::publish(F("response"), "unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user