[opentherm] Fix out of memory errors on ESP8266 (#7835)

This commit is contained in:
Oleg Tarasov 2024-11-26 00:47:01 +03:00 committed by GitHub
parent cf835d1580
commit 89ecfc2004
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 39 additions and 37 deletions

View file

@ -138,7 +138,7 @@ OpenthermHub::OpenthermHub() : Component(), in_pin_{}, out_pin_{} {}
void OpenthermHub::process_response(OpenthermData &data) {
ESP_LOGD(TAG, "Received OpenTherm response with id %d (%s)", data.id,
this->opentherm_->message_id_to_str((MessageId) data.id));
ESP_LOGD(TAG, "%s", this->opentherm_->debug_data(data).c_str());
this->opentherm_->debug_data(data);
switch (data.id) {
OPENTHERM_SENSOR_MESSAGE_HANDLERS(OPENTHERM_MESSAGE_RESPONSE_MESSAGE, OPENTHERM_MESSAGE_RESPONSE_ENTITY, ,
@ -315,7 +315,7 @@ void OpenthermHub::start_conversation_() {
ESP_LOGD(TAG, "Sending request with id %d (%s)", request.id,
this->opentherm_->message_id_to_str((MessageId) request.id));
ESP_LOGD(TAG, "%s", this->opentherm_->debug_data(request).c_str());
this->opentherm_->debug_data(request);
// Send the request
this->last_conversation_start_ = millis();
this->opentherm_->send(request);
@ -340,19 +340,18 @@ void OpenthermHub::stop_opentherm_() {
this->opentherm_->stop();
this->last_conversation_end_ = millis();
}
void OpenthermHub::handle_protocol_write_error_() {
ESP_LOGW(TAG, "Error while sending request: %s",
this->opentherm_->operation_mode_to_str(this->opentherm_->get_mode()));
ESP_LOGW(TAG, "%s", this->opentherm_->debug_data(this->last_request_).c_str());
this->opentherm_->debug_data(this->last_request_);
}
void OpenthermHub::handle_protocol_read_error_() {
OpenThermError error;
this->opentherm_->get_protocol_error(error);
ESP_LOGW(TAG, "Protocol error occured while receiving response: %s", this->opentherm_->debug_error(error).c_str());
ESP_LOGW(TAG, "Protocol error occured while receiving response: %s",
this->opentherm_->protocol_error_to_to_str(error.error_type));
this->opentherm_->debug_error(error);
}
void OpenthermHub::handle_timeout_error_() {
ESP_LOGW(TAG, "Receive response timed out at a protocol level");
this->stop_opentherm_();

View file

@ -15,15 +15,11 @@
#include "Arduino.h"
#endif
#include <string>
#include <sstream>
#include <bitset>
namespace esphome {
namespace opentherm {
using std::string;
using std::bitset;
using std::stringstream;
using std::to_string;
static const char *const TAG = "opentherm";
@ -545,29 +541,17 @@ const char *OpenTherm::message_id_to_str(MessageId id) {
}
}
string OpenTherm::debug_data(OpenthermData &data) {
stringstream result;
result << bitset<8>(data.type) << " " << bitset<8>(data.id) << " " << bitset<8>(data.valueHB) << " "
<< bitset<8>(data.valueLB) << "\n";
result << "type: " << this->message_type_to_str((MessageType) data.type) << "; ";
result << "id: " << to_string(data.id) << "; ";
result << "HB: " << to_string(data.valueHB) << "; ";
result << "LB: " << to_string(data.valueLB) << "; ";
result << "uint_16: " << to_string(data.u16()) << "; ";
result << "float: " << to_string(data.f88());
return result.str();
void OpenTherm::debug_data(OpenthermData &data) {
ESP_LOGD(TAG, "%s %s %s %s", format_bin(data.type).c_str(), format_bin(data.id).c_str(),
format_bin(data.valueHB).c_str(), format_bin(data.valueLB).c_str());
ESP_LOGD(TAG, "type: %s; id: %s; HB: %s; LB: %s; uint_16: %s; float: %s",
this->message_type_to_str((MessageType) data.type), to_string(data.id).c_str(),
to_string(data.valueHB).c_str(), to_string(data.valueLB).c_str(), to_string(data.u16()).c_str(),
to_string(data.f88()).c_str());
}
std::string OpenTherm::debug_error(OpenThermError &error) {
stringstream result;
result << "type: " << this->protocol_error_to_to_str(error.error_type) << "; ";
result << "data: ";
result << format_hex(error.data);
result << "; clock: " << to_string(clock_);
result << "; capture: " << bitset<32>(error.capture);
result << "; bit_pos: " << to_string(error.bit_pos);
return result.str();
void OpenTherm::debug_error(OpenThermError &error) const {
ESP_LOGD(TAG, "data: %s; clock: %s; capture: %s; bit_pos: %s", format_hex(error.data).c_str(),
to_string(clock_).c_str(), format_bin(error.capture).c_str(), to_string(error.bit_pos).c_str());
}
float OpenthermData::f88() { return ((float) this->s16()) / 256.0; }

View file

@ -8,10 +8,9 @@
#pragma once
#include <string>
#include <sstream>
#include <iomanip>
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
#if defined(ESP32) || defined(USE_ESP_IDF)
#include "driver/timer.h"
@ -318,8 +317,8 @@ class OpenTherm {
OperationMode get_mode() { return mode_; }
std::string debug_data(OpenthermData &data);
std::string debug_error(OpenThermError &error);
void debug_data(OpenthermData &data);
void debug_error(OpenThermError &error) const;
const char *protocol_error_to_to_str(ProtocolErrorType error_type);
const char *message_type_to_str(MessageType message_type);

View file

@ -397,6 +397,18 @@ std::string format_hex_pretty(const uint16_t *data, size_t length) {
}
std::string format_hex_pretty(const std::vector<uint16_t> &data) { return format_hex_pretty(data.data(), data.size()); }
std::string format_bin(const uint8_t *data, size_t length) {
std::string result;
result.resize(length * 8);
for (size_t byte_idx = 0; byte_idx < length; byte_idx++) {
for (size_t bit_idx = 0; bit_idx < 8; bit_idx++) {
result[byte_idx * 8 + bit_idx] = ((data[byte_idx] >> (7 - bit_idx)) & 1) + '0';
}
}
return result;
}
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off) {
if (on == nullptr && strcasecmp(str, "on") == 0)
return PARSE_ON;

View file

@ -420,6 +420,14 @@ template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> std::stri
return format_hex_pretty(reinterpret_cast<uint8_t *>(&val), sizeof(T));
}
/// Format the byte array \p data of length \p len in binary.
std::string format_bin(const uint8_t *data, size_t length);
/// Format an unsigned integer in binary, starting with the most significant byte.
template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> std::string format_bin(T val) {
val = convert_big_endian(val);
return format_bin(reinterpret_cast<uint8_t *>(&val), sizeof(T));
}
/// Return values for parse_on_off().
enum ParseOnOffState {
PARSE_NONE = 0,