#include "esphome/core/log.h" #include "esphome/core/application.h" #include "uart_transport.h" namespace esphome::uart { static const char *const TAG = "uart_transport"; void UARTTransport::loop() { PacketTransport::loop(); while (this->parent_->available()) { uint8_t byte; if (!this->parent_->read_byte(&byte)) { ESP_LOGW(TAG, "Failed to read byte from UART"); return; } if (byte == FLAG_BYTE) { if (this->rx_started_ && this->receive_buffer_.size() > 6) { auto len = this->receive_buffer_.size(); auto crc = crc16(this->receive_buffer_.data(), len - 2); if (crc != (this->receive_buffer_[len - 2] | (this->receive_buffer_[len - 1] << 8))) { ESP_LOGD(TAG, "CRC mismatch, discarding packet"); this->rx_started_ = false; this->receive_buffer_.clear(); continue; } this->receive_buffer_.resize(len - 2); this->process_(this->receive_buffer_); this->rx_started_ = false; } else { this->rx_started_ = true; } this->receive_buffer_.clear(); this->rx_control_ = false; continue; } if (!this->rx_started_) continue; if (byte == CONTROL_BYTE) { this->rx_control_ = true; continue; } if (this->rx_control_) { byte ^= 0x20; this->rx_control_ = false; } if (this->receive_buffer_.size() == MAX_PACKET_SIZE) { ESP_LOGD(TAG, "Packet too large, discarding"); this->rx_started_ = false; this->receive_buffer_.clear(); continue; } this->receive_buffer_.push_back(byte); } } /** * Write a byte to the UART bus. If the byte is a flag or control byte, it will be escaped. * @param byte The byte to write. */ void UARTTransport::write_byte_(uint8_t byte) const { if (byte == FLAG_BYTE || byte == CONTROL_BYTE) { this->parent_->write_byte(CONTROL_BYTE); byte ^= 0x20; } this->parent_->write_byte(byte); } void UARTTransport::send_packet(const std::vector &buf) const { this->parent_->write_byte(FLAG_BYTE); for (uint8_t byte : buf) { this->write_byte_(byte); } auto crc = crc16(buf.data(), buf.size()); this->write_byte_(crc & 0xFF); this->write_byte_(crc >> 8); this->parent_->write_byte(FLAG_BYTE); } } // namespace esphome::uart