ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
uart_packet_interface.cpp
Go to the documentation of this file.
1#include "esphome/core/log.h"
3
4namespace esphome::uart {
5
6using packet_interface::PacketBuffer;
7using packet_interface::PacketMetaData;
8
9ESPHOME_LOG_TAG(TAG, "uart.packet_interface");
10
11static constexpr uint8_t FLAG_BYTE = 0x7E;
12static constexpr uint8_t CONTROL_BYTE = 0x7D;
13static constexpr uint8_t ESCAPE_XOR = 0x20;
14// Raw bytes escaped and written per UART write
15static constexpr size_t TX_CHUNK_SIZE = 32;
16
18 this->read_available([this](uint8_t byte) { this->handle_rx_byte_(byte); });
19}
20
22 if (byte == FLAG_BYTE) {
23 // A flag that ends a frame also starts the next, so an unfinished frame cannot hide the one after it
24 if (this->rx_started_ && this->rx_length_ != 0)
25 this->on_receive_from_interface_(PacketBuffer(this->rx_buffer_.data(), this->rx_length_), {});
26 this->rx_started_ = true;
27 this->rx_length_ = 0;
28 this->rx_control_ = false;
29 return;
30 }
31 if (!this->rx_started_)
32 return;
33 if (byte == CONTROL_BYTE) {
34 this->rx_control_ = true;
35 return;
36 }
37 if (this->rx_control_) {
38 byte ^= ESCAPE_XOR;
39 this->rx_control_ = false;
40 }
41 if (this->rx_length_ >= this->rx_buffer_.size()) {
42 ESP_LOGD(TAG, "Packet too large, discarding");
43 this->rx_started_ = false;
44 this->rx_length_ = 0;
45 return;
46 }
47 this->rx_buffer_[this->rx_length_++] = byte;
48}
49
51 size_t size = data.size();
52 if (size == 0)
53 return true;
54 if (size > this->max_packet_size_) {
55 ESP_LOGW(TAG, "Packet of %zu bytes is larger than %zu", size, this->max_packet_size_);
56 return false;
57 }
58 uint8_t raw[TX_CHUNK_SIZE]{};
59 // Every byte may be escaped, plus a flag byte at each end
60 uint8_t out[TX_CHUNK_SIZE * 2 + 2];
61 size_t out_len = 0;
62 out[out_len++] = FLAG_BYTE;
63 for (size_t offset = 0; offset < size;) {
64 size_t count = data.copy_to(raw, TX_CHUNK_SIZE, offset);
65 offset += count;
66 for (size_t i = 0; i != count; i++) {
67 uint8_t byte = raw[i];
68 if (byte == FLAG_BYTE || byte == CONTROL_BYTE) {
69 out[out_len++] = CONTROL_BYTE;
70 byte ^= ESCAPE_XOR;
71 }
72 out[out_len++] = byte;
73 }
74 if (offset == size)
75 out[out_len++] = FLAG_BYTE;
76 this->write_array(out, out_len);
77 out_len = 0;
78 }
79 return true;
80}
81
82} // namespace esphome::uart
uint8_t raw[35]
Definition bl0939.h:0
A buffer class that efficiently represents a composite buffer with three sections:
void on_receive_from_interface_(const PacketBuffer &data, const PacketMetaData &meta_data)
This function should be called by implementing classes with received data to be passed to any listene...
A struct to hold metadata about a packet.
bool read_available(F &&on_byte)
Same as read_available_chunks(), calling on_byte(uint8_t) once per byte.
Definition uart.h:77
void write_array(const uint8_t *data, size_t len)
Definition uart.h:30
const std::span< uint8_t > rx_buffer_
bool send_to_interface(const packet_interface::PacketBuffer &data, const packet_interface::PacketMetaData &meta_data) override
std::vector< uint8_t > & out
Definition gif.cpp:49
unsigned count
Definition gif.cpp:51
ESPHOME_LOG_TAG(TAG, "uart.binary_sensor")
uint16_t size
Definition helpers.cpp:34