Serial Proxy
IMPORTANT
This component is EXPERIMENTAL. The API (both Python configuration and C++ interfaces) may change at any time without following the normal breaking changes policy. Use at your own risk. Once the API is considered stable, this warning will be removed.
The serial_proxy component exposes a physical UART serial port on your ESPHome device to API clients
(such as Home Assistant) via the Native API. This allows an API client to send and
receive data directly to and from a serial device connected to the ESP, effectively creating a
network-attached serial port.
The component requires the Native API and UART components.
Multiple serial_proxy instances may be configured on a single device, each attached to a different UART.
# Example configuration entryserial_proxy: - id: serial_proxy_1 uart_id: serial_1 name: My Serial Device port_type: TTLConfiguration variables
Section titled “Configuration variables”- id (Optional, ID): Manually specify the ID to use for code generation.
- name (Required, string): A human-readable name for this serial port, used to identify it to API clients.
- uart_id (Required, ID): The ID of the UART component this proxy is attached to.
- port_type (Required, string): The electrical type of the serial port. One of:
TTL: Standard TTL logic-level UART (3.3V or 5V). Typically used for direct connections to most microcontrollers.RS232: RS-232 standard serial port (typically ±12V levels via an appropriate line-driver IC). Typically used for PC-style serial connections, often with a DB9-type connector.RS485: RS-485 differential serial bus. Typically used for industrial/multi-drop serial networks.USB_SERIAL: A serial device attached through a USB bridge. Requiresuart_idto refer to a USB UART channel.
- rts_pin (Optional, Pin): GPIO pin to use as the RTS (Request to Send) modem control output. The state of this pin may be controlled by the API client at runtime.
- dtr_pin (Optional, Pin): GPIO pin to use as the DTR (Data Terminal Ready) modem control output. The state of this pin may be controlled by the API client at runtime.
How It Works
Section titled “How It Works”An API client uses a port by subscribing to it. A port has one subscriber at a time, and only the subscribed client can use it. Once subscribed, the client can:
-
Send data to the serial device by writing bytes through the API. Writes are not flow-controlled: bytes the UART cannot buffer stall the device until they have gone out on the wire. The proxy lets such stalls add up to one second per pass of the main loop. A write that would go past that is cut to what the UART can buffer right now; the rest is discarded without telling the client, and a warning is logged on the device. To avoid this, set the UART’s
tx_buffer_size(ESP32 only) to the largest block a client writes at once. This matters most at low baud rates, where even a few hundred bytes take seconds to send. -
Receive data from the serial device — data arriving on the UART is forwarded to the client automatically each loop iteration (up to 256 bytes at a time).
-
Reconfigure the UART at runtime — the API client may change the baud rate, data bits, stop bits, and parity without reflashing firmware.
-
Control modem pins — if
rts_pinordtr_pinare configured, the API client can set their states at runtime. -
Switch the port mode — every port starts in
RAWmode, a plain byte pipe that passes data through unchanged. The client can switch the port toPROTOCOLmode, letting a protocol-aware component on the device observe the traffic and send protocol messages such as acknowledgements on the client’s behalf. The port returns toRAWwhen the client unsubscribes or disconnects, so a client doing something sensitive with the attached device — uploading firmware to it, for example — can rely onRAWpassing bytes through untouched.No component that ships with ESPHome provides protocol handling yet;
PROTOCOLmode is an extension point for component authors (seeSerialProxyTapin API Reference: serial_proxy.h). On a port without such a component, a request to switch toPROTOCOLmode is refused and the port stays inRAWmode.
A client can also subscribe to the identity of every port, without subscribing to the ports themselves. For a port
whose uart_id refers to a USB UART channel, the identity holds the vendor and product
IDs, the manufacturer, product and serial number strings and the interface number of the attached USB device, much
like a /dev/serial/by-id name on Linux. The client gets the identity of every port when it subscribes, and an
update whenever a USB device is attached or removed, so it can find a device by identity rather than by port number.
Full Example
Section titled “Full Example”# Two serial proxies on separate UARTsuart: - id: device_uart tx_pin: GPIO4 rx_pin: GPIO5 baud_rate: 9600
- id: rs485_uart tx_pin: GPIO16 rx_pin: GPIO17 baud_rate: 19200
api:
serial_proxy: - id: device_serial uart_id: device_uart name: TTL Device port_type: TTL
- id: rs485_serial uart_id: rs485_uart name: RS-485 Bus port_type: RS485 rts_pin: GPIO18See Also
Section titled “See Also”- UART Bus
- USB UART
- Native API Component
- aioesphomeapi — Python library implementing the ESPHome native API
- API Reference: serial_proxy.h