diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 18d5a64d3..23e6d0ac1 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -710,17 +710,31 @@ void EMSESP::publish_sensor_values(const bool time, const bool force) { // MQTT publish a telegram as raw data to the topic 'response' void EMSESP::publish_response(std::shared_ptr telegram) { - static char * buffer = nullptr; - static uint8_t offset; - if (buffer == nullptr) { - offset = telegram->offset; // store offset from first part - buffer = new char[768]; // max 256 hex-codes, 255 spaces, 1 termination - buffer[0] = '\0'; + static char * buffer = nullptr; + static uint8_t offset = 0; + static uint16_t type = 0; + // restart on mismatch while collecting telegram + if (buffer && (telegram->offset < offset || telegram->type_id != type)) { + delete[] buffer; + buffer = nullptr; + } + if (buffer == nullptr) { + offset = telegram->offset; // store offset from first part + type = telegram->type_id; + buffer = new char[768]; // max 256 hex-codes, 255 spaces, 1 termination + for (uint16_t i = 0; i < 256; i++) { + buffer[i * 3] = '0'; + buffer[i * 3 + 1] = '0'; + buffer[i * 3 + 2] = ' '; + } + buffer[267] = '\0'; + } + if (telegram->message_length > 0) { + strlcpy(&buffer[(telegram->offset - offset) * 3], Helpers::data_to_hex(telegram->message_data, telegram->message_length).c_str(), 768); } - strlcat(buffer, Helpers::data_to_hex(telegram->message_data, telegram->message_length).c_str(), 768); if (response_id_ != 0) { - strlcat(buffer, " ", 768); - return; // do not delete buffer + buffer[strlen(buffer)] = ' '; // overwrite termination \0 + return; // do not delete buffer } JsonDocument doc; char s[10]; @@ -1179,31 +1193,16 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const } // first check to see if we already have it, if so update the record + auto it = emsdevices.begin(); for (const auto & emsdevice : emsdevices) { if (emsdevice && emsdevice->is_device_id(device_id)) { if (product_id == 0 || emsdevice->product_id() != 0) { // update only with valid product_id return true; } - - LOG_DEBUG("Updating details for already active deviceID 0x%02X", device_id); - emsdevice->product_id(product_id); - emsdevice->version(version); - - // only set brand if it doesn't already exist - if (emsdevice->brand() == EMSdevice::Brand::NO_BRAND) { - emsdevice->brand(brand); - } - - // find the name and flags in our device library database - for (const auto & device : device_library_) { - if (device.product_id == product_id && device.device_type == emsdevice->device_type()) { - emsdevice->default_name(device.default_name); // custom name is set later - emsdevice->add_flags(device.flags); - } - } - - return true; // finish up + emsdevices.erase(it); // erase the old device without product_id and re detect + break; } + it++; } // look up the rest of the details using the product_id and create the new device object diff --git a/src/emsesp.h b/src/emsesp.h index 77c0246ce..ac6592765 100644 --- a/src/emsesp.h +++ b/src/emsesp.h @@ -178,6 +178,10 @@ class EMSESP { response_id_ = id; } + static uint16_t response_id() { + return response_id_; + } + static bool wait_validate() { return (wait_validate_ != 0); } diff --git a/src/mqtt.h b/src/mqtt.h index 054a39aef..c4acca9de 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -208,6 +208,10 @@ class Mqtt { return lastresponse_; } + static void clear_response() { + lastresponse_.clear(); + } + void set_qos(uint8_t mqtt_qos) const { mqtt_qos_ = mqtt_qos; } diff --git a/src/telegram.cpp b/src/telegram.cpp index e5cdf4ee7..7f0dba3c6 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -336,7 +336,7 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) { telegram_raw[3] = telegram->offset; // EMS+ has different format for read and write - if (telegram->operation != Telegram::Operation::TX_READ) { + if (telegram->operation != Telegram::Operation::TX_READ && telegram->operation != Telegram::Operation::TX_RAW) { // WRITE/NONE telegram_raw[4] = (telegram->type_id >> 8) - 1; // type, 1st byte, high-byte, subtract 0x100 telegram_raw[5] = telegram->type_id & 0xFF; // type, 2nd byte, low-byte @@ -404,6 +404,17 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) { return; } + if (telegram->operation == Telegram::Operation::TX_RAW) { + tx_state(Telegram::Operation::TX_READ); + if (EMSESP::response_id() == 0) { + Mqtt::clear_response(); + EMSESP::set_response_id(telegram->type_id); + if (telegram->message_data[0] >= (telegram->type_id > 0xFF ? 25 : 27)) { + EMSESP::set_read_id(telegram->type_id); + } + } + return; + } tx_state(telegram->operation); // tx now in a wait state } @@ -512,14 +523,7 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt if (src != ems_bus_id() || dest == 0) { operation = Telegram::Operation::NONE; // do not check reply/ack for other ids and broadcasts } else if (dest & 0x80) { - operation = Telegram::Operation::TX_READ; - EMSESP::set_response_id(type_id); - // trigger read of all parts of telegram if requested length is more than 32 - // compatibility to earlier versions - const uint8_t part_length = type_id > 0xFF ? 25 : 27; - if (message_data[0] >= part_length) { - EMSESP::set_read_id(type_id); - } + // keep RAW to set the response when sending } else { operation = Telegram::Operation::TX_WRITE; validate_id = type_id; @@ -541,7 +545,7 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt LOG_DEBUG("New Tx [#%d] telegram, length %d", tx_telegram_id_, message_length); - if (front) { + if (front && (operation != Telegram::Operation::TX_RAW || EMSESP::response_id() == 0)) { // tx_telegrams_.push_front(qtxt); // add to front of queue tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram), false, validate_id); // add to front of queue } else { @@ -674,8 +678,8 @@ uint16_t TxService::post_send_query() { if (post_typeid) { uint8_t dest = (this->telegram_last_->dest & 0x7F); // when set a value with large offset before and validate on same type and offset, or complete telegram - uint8_t length = (this->telegram_last_->type_id == post_typeid) ? this->telegram_last_->message_length : 0xFF; - uint8_t offset = (this->telegram_last_->type_id == post_typeid) ? this->telegram_last_->offset : 0; + uint8_t length = (this->telegram_last_->type_id == post_typeid) ? this->telegram_last_->message_length : 0xFF; + uint8_t offset = (this->telegram_last_->type_id == post_typeid) ? this->telegram_last_->offset : 0; this->add(Telegram::Operation::TX_READ, dest, post_typeid, offset, &length, 1, 0, true); // add to top/front of queue // read_request(telegram_last_post_send_query_, dest, 0); // no offset LOG_DEBUG("Sending post validate read, type ID 0x%02X to dest 0x%02X", post_typeid, dest);