ESPHome 2025.5.0
Loading...
Searching...
No Matches
uart_debugger.cpp
Go to the documentation of this file.
2#ifdef USE_UART_DEBUGGER
3
4#include <vector>
5#include "uart_debugger.h"
7#include "esphome/core/log.h"
8
9namespace esphome {
10namespace uart {
11
12static const char *const TAG = "uart_debug";
13
15 parent->add_debug_callback([this](UARTDirection direction, uint8_t byte) {
16 if (!this->is_my_direction_(direction) || this->is_recursive_()) {
17 return;
18 }
19 this->trigger_after_direction_change_(direction);
20 this->store_byte_(direction, byte);
21 this->trigger_after_delimiter_(byte);
23 });
24}
25
27
31
33
40
42 this->bytes_.push_back(byte);
44 this->last_time_ = millis();
45}
46
48 if (this->after_delimiter_.empty() || !this->has_buffered_bytes_()) {
49 return;
50 }
51 if (this->after_delimiter_[this->after_delimiter_pos_] != byte) {
52 this->after_delimiter_pos_ = 0;
53 return;
54 }
56 if (this->after_delimiter_pos_ == this->after_delimiter_.size()) {
57 this->fire_trigger_();
58 this->after_delimiter_pos_ = 0;
59 }
60}
61
63 if (this->has_buffered_bytes_() && this->after_bytes_ > 0 && this->bytes_.size() >= this->after_bytes_) {
64 this->fire_trigger_();
65 }
66}
67
69 if (this->has_buffered_bytes_() && this->after_timeout_ > 0 && millis() - this->last_time_ >= this->after_timeout_) {
70 this->fire_trigger_();
71 }
72}
73
74bool UARTDebugger::has_buffered_bytes_() { return !this->bytes_.empty(); }
75
77 this->is_triggering_ = true;
78 trigger(this->last_direction_, this->bytes_);
79 this->bytes_.clear();
80 this->is_triggering_ = false;
81}
82
84 // Reading up to a limited number of bytes, to make sure that this loop()
85 // won't lock up the system on a continuous incoming stream of bytes.
86 uint8_t data;
87 int count = 50;
88 while (this->available() && count--) {
89 this->read_byte(&data);
90 }
91}
92
93// In the upcoming log functions, a delay was added after all log calls.
94// This is done to allow the system to ship the log lines via the API
95// TCP connection(s). Without these delays, debug log lines could go
96// missing when UART devices block the main loop for too long.
97
98void UARTDebug::log_hex(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator) {
99 std::string res;
101 res += "<<< ";
102 } else {
103 res += ">>> ";
104 }
105 size_t len = bytes.size();
106 char buf[5];
107 for (size_t i = 0; i < len; i++) {
108 if (i > 0) {
109 res += separator;
110 }
111 sprintf(buf, "%02X", bytes[i]);
112 res += buf;
113 }
114 ESP_LOGD(TAG, "%s", res.c_str());
115 delay(10);
116}
117
118void UARTDebug::log_string(UARTDirection direction, std::vector<uint8_t> bytes) {
119 std::string res;
121 res += "<<< \"";
122 } else {
123 res += ">>> \"";
124 }
125 size_t len = bytes.size();
126 char buf[5];
127 for (size_t i = 0; i < len; i++) {
128 if (bytes[i] == 7) {
129 res += "\\a";
130 } else if (bytes[i] == 8) {
131 res += "\\b";
132 } else if (bytes[i] == 9) {
133 res += "\\t";
134 } else if (bytes[i] == 10) {
135 res += "\\n";
136 } else if (bytes[i] == 11) {
137 res += "\\v";
138 } else if (bytes[i] == 12) {
139 res += "\\f";
140 } else if (bytes[i] == 13) {
141 res += "\\r";
142 } else if (bytes[i] == 27) {
143 res += "\\e";
144 } else if (bytes[i] == 34) {
145 res += "\\\"";
146 } else if (bytes[i] == 39) {
147 res += "\\'";
148 } else if (bytes[i] == 92) {
149 res += "\\\\";
150 } else if (bytes[i] < 32 || bytes[i] > 127) {
151 sprintf(buf, "\\x%02X", bytes[i]);
152 res += buf;
153 } else {
154 res += bytes[i];
155 }
156 }
157 res += '"';
158 ESP_LOGD(TAG, "%s", res.c_str());
159 delay(10);
160}
161
162void UARTDebug::log_int(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator) {
163 std::string res;
164 size_t len = bytes.size();
166 res += "<<< ";
167 } else {
168 res += ">>> ";
169 }
170 for (size_t i = 0; i < len; i++) {
171 if (i > 0) {
172 res += separator;
173 }
174 res += to_string(bytes[i]);
175 }
176 ESP_LOGD(TAG, "%s", res.c_str());
177 delay(10);
178}
179
180void UARTDebug::log_binary(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator) {
181 std::string res;
182 size_t len = bytes.size();
184 res += "<<< ";
185 } else {
186 res += ">>> ";
187 }
188 char buf[20];
189 for (size_t i = 0; i < len; i++) {
190 if (i > 0) {
191 res += separator;
192 }
193 sprintf(buf, "0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(bytes[i]), bytes[i]);
194 res += buf;
195 }
196 ESP_LOGD(TAG, "%s", res.c_str());
197 delay(10);
198}
199
200} // namespace uart
201} // namespace esphome
202#endif
void add_debug_callback(std::function< void(UARTDirection, uint8_t)> &&callback)
static void log_hex(UARTDirection direction, std::vector< uint8_t > bytes, uint8_t separator)
Log the bytes as hex values, separated by the provided separator character.
static void log_binary(UARTDirection direction, std::vector< uint8_t > bytes, uint8_t separator)
Log the bytes as '<binary> (<hex>)' values, separated by the provided separator.
static void log_string(UARTDirection direction, std::vector< uint8_t > bytes)
Log the bytes as string values, escaping unprintable characters.
static void log_int(UARTDirection direction, std::vector< uint8_t > bytes, uint8_t separator)
Log the bytes as integer values, separated by the provided separator character.
void store_byte_(UARTDirection direction, uint8_t byte)
bool is_my_direction_(UARTDirection direction)
void trigger_after_direction_change_(UARTDirection direction)
std::vector< uint8_t > bytes_
std::vector< uint8_t > after_delimiter_
void trigger_after_delimiter_(uint8_t byte)
UARTDebugger(UARTComponent *parent)
bool read_byte(uint8_t *data)
Definition uart.h:29
FanDirection direction
Definition fan.h:3
const char *const TAG
Definition spi.cpp:8
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:301
std::string to_string(int value)
Definition helpers.cpp:82
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:28
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27