ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
uart_tcp.cpp
Go to the documentation of this file.
1#include "uart_tcp.h"
2
4#include "esphome/core/log.h"
5
6#include <algorithm>
7#include <cerrno>
8#include <cinttypes>
9
11
12ESPHOME_LOG_TAG(TAG, "uart_tcp");
13
15 this->link_.begin(TAG);
16#ifdef USE_SOCKET_TCP_LISTENER
17 this->listener_.begin(TAG);
18#endif
19 if (this->connected_sensor_ != nullptr) {
20 this->connected_sensor_->publish_state(false);
21 }
22#ifdef USE_SENSOR
23 if (this->disconnects_sensor_ != nullptr) {
25 }
26#endif
27}
28
30 ESP_LOGCONFIG(TAG,
31 "UART TCP:\n"
32 " %s: %s:%u\n"
33 " Reconnect Interval: %" PRIu32 "ms",
34 this->server_ ? LOG_STR_LITERAL("Listen") : LOG_STR_LITERAL("Host"),
35 this->server_ ? LOG_STR_LITERAL("*") : this->link_.host(), this->link_.port(),
36 this->link_.reconnect_interval());
37#ifdef USE_SOCKET_TCP_LISTENER
38 this->listener_.dump_config();
39#endif
40 LOG_BINARY_SENSOR(" ", "Connected", this->connected_sensor_);
41#ifdef USE_SENSOR
42 LOG_SENSOR(" ", "Disconnects", this->disconnects_sensor_);
43#endif
44}
45
47 this->link_.close();
48#ifdef USE_SOCKET_TCP_LISTENER
49 this->listener_.close();
50#endif
51}
52
54 bool up = this->link_.connected();
55 this->link_was_up_ = up;
56 if (up) {
57 // The driver kept whatever arrived while the link was down.
58 this->discard_uart_();
59 }
60 if (this->connected_sensor_ != nullptr) {
62 }
63#ifdef USE_SENSOR
64 // Only edges get here, so down is the falling edge.
65 if (!up && this->disconnects_sensor_ != nullptr) {
66 this->disconnects_++;
68 }
69#endif
70}
71
73 // A hardware write blocks until the driver takes every byte. Leave what does
74 // not fit in the socket, so TCP flow control throttles the peer.
75 size_t room = this->parent_->paced_write_room(this->last_write_ms_);
76 if (room == 0) {
77 this->rx_pending_ = true;
78 return;
79 }
80 uint8_t tmp[READ_CHUNK];
81 size_t want = std::min(room, sizeof(tmp));
82 ssize_t count = this->link_.read(tmp, want);
83 if (count <= 0) {
84 // A dropped link (-1) is cleaned up by sync_link_() on the next loop.
85 if (count == 0) {
86 this->rx_pending_ = false;
87 }
88 return;
89 }
90 this->rx_pending_ = static_cast<size_t>(count) == want;
91 this->write_array(tmp, static_cast<size_t>(count));
93}
94
96 // Drain exactly what was buffered while the link was down; later bytes are live.
97 uint8_t dump[DISCARD_CHUNK];
98 size_t left = this->available();
99 while (left != 0) {
100 size_t n = std::min(left, sizeof(dump));
101 if (!this->read_array(dump, n)) {
102 return;
103 }
104 left -= n;
105 }
106}
107
109 size_t want = std::min<size_t>(this->available(), this->link_.tx_free());
110 if (want != 0 && this->read_array(this->link_.tx_tail(), want)) {
111 this->link_.tx_commit(want);
112 }
113}
114
116#ifdef USE_SOCKET_TCP_LISTENER
117 if (this->server_) {
118 // link_was_up_ holds the accept until the previous drop's edge has run,
119 // so the sensor and the stale UART discard always see the disconnect.
120 this->listener_.poll(this->link_, !this->link_was_up_);
121 } else {
122 this->link_.poll();
123 }
124#else
125 this->link_.poll();
126#endif
127 if (this->link_.connected() != this->link_was_up_) {
128 this->sync_link_();
129 }
130 if (!this->link_was_up_) {
131 return;
132 }
133 if (this->rx_pending_ || this->link_.ready()) {
134 this->read_socket_();
135 }
136 // UART bytes picked up here go out in the same pass.
137 this->read_uart_();
138 this->link_.flush_tx();
139}
140
141} // namespace esphome::uart_tcp
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
void publish_state(bool new_state)
Publish a new state to the front-end.
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:65
void poll(TcpClientLink &link, bool may_accept)
Server state machine; call every loop.
void begin(const char *tag)
Call from setup(); tag names the log lines.
void dump_config() const
One config line per allowed network.
size_t paced_write_room(uint32_t last_write_ms)
optional< std::array< uint8_t, N > > read_array()
Definition uart.h:40
UARTComponent * parent_
Definition uart.h:77
void write_array(const uint8_t *data, size_t len)
Definition uart.h:27
static constexpr size_t DISCARD_CHUNK
Definition uart_tcp.h:50
socket::TcpClientLink link_
Definition uart_tcp.h:52
sensor::Sensor * disconnects_sensor_
Definition uart_tcp.h:60
void on_shutdown() override
Definition uart_tcp.cpp:46
static constexpr size_t READ_CHUNK
Definition uart_tcp.h:48
socket::TcpListener listener_
Definition uart_tcp.h:54
binary_sensor::BinarySensor * connected_sensor_
Definition uart_tcp.h:56
void dump_config() override
Definition uart_tcp.cpp:29
void setup() override
Definition uart_tcp.cpp:14
unsigned count
Definition gif.cpp:51
__int64 ssize_t
Definition httplib.h:178
ESPHOME_LOG_TAG(TAG, "uart_tcp")
Application App
Global storage of Application pointer - only one Application can exist.