10#include "esphome/core/log.h"
23inline void bytes_to_hex(
const uint8_t *data, uint8_t len,
char *out,
size_t out_size) {
28 for (uint8_t i = 0; i < len && pos + 4 < out_size; i++)
29 pos += snprintf(out + pos, out_size - pos,
"%02X ", data[i]);
41 if ((ctrl1 & CTRL1_ACK) != 0)
42 pos += snprintf(out + pos, out_size - pos,
"[ACK]");
43 if ((ctrl1 & CTRL1_LOW_POWER) != 0)
44 pos += snprintf(out + pos, out_size - pos,
"[LPM]");
45 if ((ctrl1 & CTRL1_PRIORITY) != 0)
46 pos += snprintf(out + pos, out_size - pos,
"[PRIO]");
47 if ((ctrl1 & CTRL1_ROUTED) != 0)
48 pos += snprintf(out + pos, out_size - pos,
"[R]");
49 if ((ctrl1 & CTRL1_BEACON) != 0)
50 snprintf(out + pos, out_size - pos,
"[B]");
75#ifndef IOHOME_UNSAFE_LOG_KEY_MATERIAL
81 char header_hex[(FRAME_MIN_SIZE * 3) + 4];
82 bytes_to_hex(data, FRAME_MIN_SIZE, header_hex,
sizeof(header_hex));
83 snprintf(out, out_size,
"%s[%u bytes masked]", header_hex,
static_cast<unsigned>(len - FRAME_MIN_SIZE));
122 void hold() { this->holding_ =
true; }
124 [[nodiscard]]
bool holding()
const {
return this->holding_; }
126 [[nodiscard]] uint8_t
held()
const {
return this->count_; }
133 if (!this->holding_) {
134 this->sink_(level, tag, text);
138 if (this->dropped_ < UINT8_MAX)
142 Line &line = this->lines_[this->count_++];
145 snprintf(line.text,
sizeof(line.text),
"%s", text);
151 for (uint8_t i = 0; i < this->count_; i++)
152 this->sink_(this->lines_[i].level, this->lines_[i].tag, this->lines_[i].text);
154 if (this->dropped_ > 0) {
156 snprintf(note,
sizeof(note),
"%u frame-log lines not printed (hold buffer full)", this->dropped_);
165 this->holding_ =
false;
177 bool holding_{
false};
183#ifdef IOHOME_FRAME_LOG
185inline void frame_log_print(
FrameLogLevel level,
const char *tag,
const char *text) {
188 ESP_LOGW(tag,
"%s", text);
191 ESP_LOGI(tag,
"%s", text);
194 ESP_LOGD(tag,
"%s", text);
208inline void frame_log_line(
FrameLogLevel level,
const char *tag,
const char *format, ...)
209 __attribute__((format(printf, 3, 4)));
210inline
void frame_log_line(
FrameLogLevel level, const
char *tag, const
char *format, ...) {
213 va_start(args, format);
214 vsnprintf(text,
sizeof(text), format, args);
216 frame_log_buffer().write(level, tag, text);
226inline void log_frame(
const char *prefix,
const uint8_t *data, uint8_t len, uint32_t freq, uint16_t preamble = 0) {
232 const char *cmd_str =
"";
233 if (len >= FRAME_MIN_SIZE) {
239 frame_log_line(
FrameLogLevel::INFO,
"io_frame",
"%s [%u bytes] freq=%" PRIu32
" preamble=%u cmd=%s %s: %s", prefix,
240 len, freq, preamble, cmd_str, flags, hex);
242 frame_log_line(
FrameLogLevel::INFO,
"io_frame",
"%s [%u bytes] freq=%" PRIu32
" cmd=%s %s: %s", prefix, len, freq,
243 cmd_str, flags, hex);
Keeps frame-log lines back while the hub answers a device, and prints them afterwards.
void(*)(FrameLogLevel level, const char *tag, const char *text) Sink
Prints one line. tag is the logging tag the line was written with.
void write(FrameLogLevel level, const char *tag, const char *text)
Print text now, or keep it until the next flush() while holding.
void flush()
Print the kept lines in the order they were written, then a note if any did not fit.
void release()
Print the kept lines and stop holding.
FrameLogBuffer(Sink sink)
void hold()
Start keeping lines back. Holding again while held changes nothing.
void bytes_to_hex(const uint8_t *data, uint8_t len, char *out, size_t out_size)
constexpr size_t FRAME_LOG_LINE_SIZE
One rendered frame-log line: the hex dump plus its prefix, frequency, command and flags.
void decode_ctrl1_flags(uint8_t ctrl1, char *out, size_t out_size)
Render decoded CTRL1 flags into a short annotation string.
const char * command_name(uint8_t cmd)
Get a human-readable name for any IO-Homecontrol command ID.
constexpr size_t FRAME_LOG_NOTE_SIZE
The overflow note flush() prints when lines did not fit.
void render_frame_hex_redacted(const uint8_t *data, uint8_t len, char *out, size_t out_size)
Render a frame's bytes as spaced hex text, masking the payload when the command carries key material ...
constexpr size_t FRAME_LOG_HEX_BUFFER_SIZE
Fits a full 32-byte frame rendered as spaced hex text.
constexpr size_t FRAME_LOG_FLAGS_BUFFER_SIZE
Buffer for decoded CTRL1 flag annotations.
constexpr size_t FRAME_LOG_HELD_LINES
Lines one hold can keep.
bool command_carries_key_material(uint8_t cmd)
Whether a frame command's payload carries key material that must never be logged or reported verbatim...
FrameLogLevel
Log level of one frame-log line, kept with the line while it is held.
IO-Homecontrol 2W frame container: control bytes, IoFrame and (de)serialization.
Key-material redaction helpers shared by every surface that can emit frame bytes or debug text (frame...