Compare commits

..

1 Commits

Author SHA1 Message Date
J. Nick Koston
9cbee92589 [tormatic] Use stack buffers instead of str_sprintf in debug methods 2026-01-14 15:36:35 -10:00
2 changed files with 25 additions and 39 deletions

View File

@@ -2,7 +2,6 @@
#include "esphome/core/application.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include <cstdarg>
namespace esphome {
namespace cse7766 {
@@ -10,32 +9,6 @@ namespace cse7766 {
static const char *const TAG = "cse7766";
static constexpr size_t CSE7766_RAW_DATA_SIZE = 24;
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
/// @brief Safely append formatted string to buffer.
/// @param buf Destination buffer (must be non-null)
/// @param size Total buffer size in bytes
/// @param pos Current write position (0 to size-1 for valid positions, size means full)
/// @param fmt printf-style format string
/// @return New write position: pos + chars_written, capped at size when buffer is full.
/// Returns size (not size-1) when full because vsnprintf already wrote the null
/// terminator at buf[size-1]. Returning size signals "no room for more content".
/// On encoding error, returns pos unchanged (no write occurred).
__attribute__((format(printf, 4, 5))) static size_t buf_append(char *buf, size_t size, size_t pos, const char *fmt,
...) {
if (pos >= size) {
return size;
}
va_list args;
va_start(args, fmt);
int written = vsnprintf(buf + pos, size - pos, fmt, args);
va_end(args);
if (written < 0) {
return pos; // encoding error
}
return std::min(pos + static_cast<size_t>(written), size);
}
#endif
void CSE7766Component::loop() {
const uint32_t now = App.get_loop_component_start_time();
if (now - this->last_transmission_ >= 500) {
@@ -234,23 +207,20 @@ void CSE7766Component::parse_data_() {
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
{
// Buffer: 7 + 15 + 33 + 15 + 25 = 95 chars max + null, rounded to 128 for safety margin.
// Float sizes with %.4f can be up to 11 chars for large values (e.g., 999999.9999).
char buf[128];
size_t pos = buf_append(buf, sizeof(buf), 0, "Parsed:");
std::string buf = "Parsed:";
if (have_voltage) {
pos = buf_append(buf, sizeof(buf), pos, " V=%.4fV", voltage);
buf += str_sprintf(" V=%fV", voltage);
}
if (have_current) {
pos = buf_append(buf, sizeof(buf), pos, " I=%.4fmA (~%.4fmA)", current * 1000.0f, calculated_current * 1000.0f);
buf += str_sprintf(" I=%fmA (~%fmA)", current * 1000.0f, calculated_current * 1000.0f);
}
if (have_power) {
pos = buf_append(buf, sizeof(buf), pos, " P=%.4fW", power);
buf += str_sprintf(" P=%fW", power);
}
if (energy != 0.0f) {
buf_append(buf, sizeof(buf), pos, " E=%.4fkWh (%u)", energy, cf_pulses);
buf += str_sprintf(" E=%fkWh (%u)", energy, cf_pulses);
}
ESP_LOGVV(TAG, "%s", buf);
ESP_LOGVV(TAG, "%s", buf.c_str());
}
#endif
}

View File

@@ -55,6 +55,7 @@ enum MessageType : uint16_t {
COMMAND = 0x0106,
};
// Max string length: 7 ("Unknown"/"Command"). Update print() buffer sizes if adding longer strings.
inline const char *message_type_to_str(MessageType t) {
switch (t) {
case STATUS:
@@ -83,7 +84,11 @@ struct MessageHeader {
}
std::string print() {
return str_sprintf("MessageHeader: seq %d, len %d, type %s", this->seq, this->len, message_type_to_str(this->type));
// 64 bytes: "MessageHeader: seq " + uint16 + ", len " + uint32 + ", type " + type + safety margin
char buf[64];
snprintf(buf, sizeof(buf), "MessageHeader: seq %d, len %d, type %s", this->seq, this->len,
message_type_to_str(this->type));
return buf;
}
void byteswap() {
@@ -131,6 +136,7 @@ inline CoverOperation gate_status_to_cover_operation(GateStatus s) {
return COVER_OPERATION_IDLE;
}
// Max string length: 11 ("Ventilating"). Update print() buffer sizes if adding longer strings.
inline const char *gate_status_to_str(GateStatus s) {
switch (s) {
case PAUSED:
@@ -170,7 +176,12 @@ struct StatusReply {
GateStatus state;
uint8_t trailer = 0x0;
std::string print() { return str_sprintf("StatusReply: state %s", gate_status_to_str(this->state)); }
std::string print() {
// 48 bytes: "StatusReply: state " (19) + state (11) + safety margin
char buf[48];
snprintf(buf, sizeof(buf), "StatusReply: state %s", gate_status_to_str(this->state));
return buf;
}
void byteswap(){};
} __attribute__((packed));
@@ -202,7 +213,12 @@ struct CommandRequestReply {
CommandRequestReply() = default;
CommandRequestReply(GateStatus state) { this->state = state; }
std::string print() { return str_sprintf("CommandRequestReply: state %s", gate_status_to_str(this->state)); }
std::string print() {
// 56 bytes: "CommandRequestReply: state " (27) + state (11) + safety margin
char buf[56];
snprintf(buf, sizeof(buf), "CommandRequestReply: state %s", gate_status_to_str(this->state));
return buf;
}
void byteswap() { this->type = convert_big_endian(this->type); }
} __attribute__((packed));