From fc1cb00523e6aa6a56be1abda0cdab7c3d3acd33 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Thu, 22 Jul 2021 12:54:02 +0200 Subject: [PATCH 1/2] reload values after write and update --- interface/src/project/EMSESPDataForm.tsx | 7 ++++--- interface/src/project/SensorForm.tsx | 1 + src/emsesp.cpp | 4 ++++ src/emsesp.h | 7 +++++++ src/telegram.cpp | 7 +++++++ src/web/WebDataService.cpp | 7 ++++++- 6 files changed, 29 insertions(+), 4 deletions(-) diff --git a/interface/src/project/EMSESPDataForm.tsx b/interface/src/project/EMSESPDataForm.tsx index c7376fda3..afd1c61d8 100644 --- a/interface/src/project/EMSESPDataForm.tsx +++ b/interface/src/project/EMSESPDataForm.tsx @@ -192,6 +192,7 @@ class EMSESPDataForm extends Component< this.props.enqueueSnackbar('Write command sent to device', { variant: 'success' }); + this.handleRowClick(selectedDevice); } else if (response.status === 204) { this.props.enqueueSnackbar('Write command failed', { variant: 'error' @@ -315,7 +316,7 @@ class EMSESPDataForm extends Component< this.handleRowClick(device)} + onClick={() => this.handleRowClick(device.id)} > { - this.setState({ selectedDevice: device.id, deviceData: undefined }); + this.setState({ selectedDevice: device, deviceData: undefined }); redirectingAuthorizedFetch(DEVICE_DATA_ENDPOINT, { method: 'POST', - body: JSON.stringify({ id: device.id }), + body: JSON.stringify({ id: device }), headers: { 'Content-Type': 'application/json' } diff --git a/interface/src/project/SensorForm.tsx b/interface/src/project/SensorForm.tsx index ce7825090..e981007ef 100644 --- a/interface/src/project/SensorForm.tsx +++ b/interface/src/project/SensorForm.tsx @@ -66,6 +66,7 @@ class SensorForm extends React.Component { ]} label="Custom Offset (°C)" name="offset" + type="number" value={sensor.offset} fullWidth variant="outlined" diff --git a/src/emsesp.cpp b/src/emsesp.cpp index b856d1d8e..fd9d6e419 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -77,6 +77,7 @@ bool EMSESP::trace_raw_ = false; uint64_t EMSESP::tx_delay_ = 0; uint8_t EMSESP::bool_format_ = 1; uint8_t EMSESP::enum_format_ = 1; +uint16_t EMSESP::wait_validate_ = 0; // for a specific EMS device go and request data values // or if device_id is 0 it will fetch from all our known and active devices @@ -839,6 +840,9 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too } } + if (wait_validate_ == telegram->type_id) { + wait_validate_ = 0; + } break; } } diff --git a/src/emsesp.h b/src/emsesp.h index 791652a8f..b8c336e0d 100644 --- a/src/emsesp.h +++ b/src/emsesp.h @@ -178,6 +178,12 @@ class EMSESP { static void set_read_id(uint16_t id) { read_id_ = id; } + static bool wait_validate() { + return (wait_validate_ != 0); + } + static void wait_validate(uint16_t wait) { + wait_validate_ = wait; + } enum Bus_status : uint8_t { BUS_STATUS_CONNECTED = 0, BUS_STATUS_TX_ERRORS, BUS_STATUS_OFFLINE }; static uint8_t bus_status(); @@ -264,6 +270,7 @@ class EMSESP { static uint64_t tx_delay_; static uint8_t bool_format_; static uint8_t enum_format_; + static uint16_t wait_validate_; }; } // namespace emsesp diff --git a/src/telegram.cpp b/src/telegram.cpp index b5ce8b0ca..450a0740e 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -431,6 +431,9 @@ void TxService::add(const uint8_t operation, } else { tx_telegrams_.emplace_back(tx_telegram_id_++, std::move(telegram), false, validateid); // add to back of queue } + if (validateid != 0) { + EMSESP::wait_validate(validateid); + } } // builds a Tx telegram and adds to queue @@ -507,6 +510,9 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt // tx_telegrams_.push_back(qtxt); // add to back of queue tx_telegrams_.emplace_back(tx_telegram_id_++, std::move(telegram), false, validate_id); // add to back of queue } + if (validate_id != 0) { + EMSESP::wait_validate(validate_id); + } } // send a Tx telegram to request data from an EMS device @@ -570,6 +576,7 @@ void TxService::retry_tx(const uint8_t operation, const uint8_t * data, const ui if (++retry_count_ > MAXIMUM_TX_RETRIES) { reset_retry_count(); // give up increment_telegram_fail_count(); // another Tx fail + EMSESP::wait_validate(0); // do not wait for validation LOG_ERROR(F("Last Tx %s operation failed after %d retries. Ignoring request: %s"), (operation == Telegram::Operation::TX_WRITE) ? F("Write") : F("Read"), diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 86c5f142f..1bf492944 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -100,6 +100,11 @@ void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant & for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice) { if (emsdevice->unique_id() == json["id"]) { + // wait max 2.5 sec for updated data (post_send_delay is 2 sec) + for (uint16_t i = 0; i < 2500 && EMSESP::wait_validate(); i++) { + delay(1); + } + EMSESP::wait_validate(0); // reset in case of timeout #ifndef EMSESP_STANDALONE JsonObject root = response->getRoot(); emsdevice->generate_values_json_web(root); @@ -166,7 +171,7 @@ void WebDataService::write_sensor(AsyncWebServerRequest * request, JsonVariant & // if valid add. uint8_t no = sensor["no"]; if (no > 0 && no < 100) { - char name[25]; + char name[20]; std::string id = sensor["id"]; strlcpy(name, id.c_str(), sizeof(name)); float offset = sensor["offset"]; // this will be a float value. We'll convert it to int and * 10 it From 694f647a2cc5938373a67091ced293d9a553ac7a Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Thu, 22 Jul 2021 13:00:16 +0200 Subject: [PATCH 2/2] Command returns as enum --- src/command.h | 10 ++++++++++ src/console.cpp | 8 ++++---- src/mqtt.cpp | 10 +++++----- src/web/WebAPIService.cpp | 6 +++--- src/web/WebDataService.cpp | 4 ++-- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/command.h b/src/command.h index daee30e80..c68a6fd7b 100644 --- a/src/command.h +++ b/src/command.h @@ -45,6 +45,16 @@ enum CommandFlag : uint8_t { }; +// returns 0 if the command errored, 1 (TRUE) if ok, 2 if not found, 3 if error or 4 if not allowed +enum CommandRet: uint8_t { + ERRORED = 0, + OK, + NOT_FOUND, + ERROR, + NOT_ALLOWED + +}; + using cmdfunction_p = std::function; using cmdfunction_json_p = std::function; diff --git a/src/console.cpp b/src/console.cpp index cc654e63e..cd35f8aa7 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -385,7 +385,7 @@ void EMSESPShell::add_console_commands() { const char * cmd = arguments[1].c_str(); - uint8_t cmd_return = 1; // OK + uint8_t cmd_return = CommandRet::OK; if (arguments.size() == 2) { // no value specified, just the cmd @@ -403,17 +403,17 @@ void EMSESPShell::add_console_commands() { cmd_return = Command::call(device_type, cmd, arguments[2].c_str(), true, atoi(arguments[3].c_str()), json); } - if (cmd_return == 1 && json.size()) { + if (cmd_return == CommandRet::OK && json.size()) { serializeJsonPretty(doc, shell); shell.println(); return; } - if (cmd_return == 2) { + if (cmd_return == CommandRet::NOT_FOUND) { shell.println(F("Unknown command")); shell.print(F("Available commands are: ")); Command::show(shell, device_type, false); // non-verbose mode - } else if (cmd_return == 3) { + } else if (cmd_return == CommandRet::ERROR) { shell.println(F("Bad syntax")); } }, diff --git a/src/mqtt.cpp b/src/mqtt.cpp index da307095f..238b6f1ac 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -348,10 +348,10 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len) // LOG_INFO(F("devicetype= %d, topic = %s, cmd = %s, message = %s), mf.device_type_, topic, cmd_only, message); // call command, assume admin authentication is allowed uint8_t cmd_return = Command::call(mf.device_type_, cmd_only, message, true); - if (cmd_return == 2) { + if (cmd_return == CommandRet::NOT_FOUND) { LOG_ERROR(F("No matching cmd (%s) in topic %s"), cmd_only, topic); Mqtt::publish(F_(response), "unknown"); - } else if (cmd_return == 3) { + } else if (cmd_return == CommandRet::ERROR) { LOG_ERROR(F("Invalid data with cmd (%s) in topic %s"), cmd_only, topic); Mqtt::publish(F_(response), "unknown"); } @@ -381,7 +381,7 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len) n = doc["id"]; } - uint8_t cmd_return = 1; // OK + uint8_t cmd_return = CommandRet::OK; JsonVariant data = doc["data"]; if (data.is()) { @@ -402,10 +402,10 @@ void Mqtt::on_message(const char * fulltopic, const char * payload, size_t len) } } - if (cmd_return == 2) { + if (cmd_return == CommandRet::NOT_FOUND) { LOG_ERROR(F("No matching cmd (%s)"), command); Mqtt::publish(F_(response), "unknown"); - } else if (cmd_return == 3) { + } else if (cmd_return == CommandRet::ERROR) { LOG_ERROR(F("Invalid data for cmd (%s)"), command); Mqtt::publish(F_(response), "unknown"); } diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index 20f06110f..8fd60f05b 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -182,15 +182,15 @@ void WebAPIService::parse(AsyncWebServerRequest * request, std::string & device_ uint8_t cmd_reply = Command::call(device_type, cmd_s.c_str(), (have_data ? value_s.c_str() : nullptr), authenticated, id_n, json); // check for errors - if (cmd_reply == 2) { + if (cmd_reply == CommandRet::NOT_FOUND) { delete response; send_message_response(request, 400, "Command not found"); // Bad Request return; - } else if (cmd_reply == 3) { + } else if (cmd_reply == CommandRet::ERROR) { delete response; send_message_response(request, 400, "Problems parsing elements"); // Bad Request return; - } else if (cmd_reply == 4) { + } else if (cmd_reply == CommandRet::NOT_ALLOWED) { delete response; send_message_response(request, 401, "Bad credentials"); // Unauthorized return; diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 1bf492944..631bc8984 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -135,7 +135,7 @@ void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant & if (emsdevice->unique_id() == id) { const char * cmd = dv["c"]; uint8_t device_type = emsdevice->device_type(); - uint8_t cmd_return = 1; // OK + uint8_t cmd_return = CommandRet::OK; char s[10]; // the data could be in any format, but we need string JsonVariant data = dv["v"]; @@ -150,7 +150,7 @@ void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant & } // send "Write command sent to device" or "Write command failed" - AsyncWebServerResponse * response = request->beginResponse((cmd_return == 1) ? 200 : 204); + AsyncWebServerResponse * response = request->beginResponse((cmd_return == CommandRet::OK) ? 200 : 204); request->send(response); return; }