mirror of
https://github.com/esphome/esphome.git
synced 2026-10-04 18:11:29 +00:00
[zigbee_proxy] Auto-detect USB UART channel from uart_id, drop usb_uart_id
The usb_uart_id key was redundant: uart_id already points at the channel. A new usb_uart.is_usb_uart_channel() helper checks the config tree (use_id resolution does not narrow the ID type), and zigbee_proxy uses it to enable the RX callback fast path and USB timeout defaults automatically.
This commit is contained in:
@@ -16,7 +16,7 @@ from esphome.const import (
|
||||
CONF_DUMMY_RECEIVER,
|
||||
CONF_ID,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.core import CORE, ID
|
||||
from esphome.cpp_types import Component
|
||||
|
||||
AUTO_LOAD = ["uart", "usb_host", "bytebuffer"]
|
||||
@@ -26,6 +26,21 @@ usb_uart_ns = cg.esphome_ns.namespace("usb_uart")
|
||||
USBUartComponent = usb_uart_ns.class_("USBUartComponent", Component)
|
||||
USBUartChannel = usb_uart_ns.class_("USBUartChannel", UARTComponent)
|
||||
|
||||
|
||||
def is_usb_uart_channel(uart_id: ID) -> bool:
|
||||
"""Return True if the given ID refers to a channel of a configured usb_uart device.
|
||||
|
||||
Lets UART device components detect that their uart_id points at a USB UART
|
||||
channel (use_id resolution does not narrow the ID's type) so they can enable
|
||||
USB-specific features such as the RX callback.
|
||||
"""
|
||||
return any(
|
||||
channel[CONF_ID] == uart_id
|
||||
for device in CORE.config.get("usb_uart") or []
|
||||
for channel in device[CONF_CHANNELS]
|
||||
)
|
||||
|
||||
|
||||
UARTParityOptions = usb_uart_ns.enum("UARTParityOptions")
|
||||
UART_PARITY_OPTIONS = {
|
||||
"NONE": UARTParityOptions.UART_CONFIG_PARITY_NONE,
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import uart, usb_uart
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_POWER_SAVE_MODE, CONF_WIFI
|
||||
from esphome.const import (
|
||||
CONF_BUFFER_SIZE,
|
||||
CONF_ID,
|
||||
CONF_POWER_SAVE_MODE,
|
||||
CONF_UART_ID,
|
||||
CONF_WIFI,
|
||||
)
|
||||
import esphome.final_validate as fv
|
||||
|
||||
CODEOWNERS = ["@kbx81"]
|
||||
DEPENDENCIES = ["api", "uart"]
|
||||
|
||||
CONF_BUFFER_SIZE = "buffer_size"
|
||||
CONF_INITIAL_TIMEOUT = "initial_timeout"
|
||||
CONF_MIN_TIMEOUT = "min_timeout"
|
||||
CONF_MAX_TIMEOUT = "max_timeout"
|
||||
@@ -47,10 +52,10 @@ CONFIG_SCHEMA = cv.All(
|
||||
esp8266=512,
|
||||
default=1024,
|
||||
),
|
||||
# When usb_uart_id is present the component registers an RX callback
|
||||
# for zero-wakeup-cycle data delivery and selects USB-optimized ACK
|
||||
# timeout defaults. Explicit timeout keys always win.
|
||||
cv.Optional(CONF_USB_UART_ID): cv.use_id(usb_uart.USBUartChannel),
|
||||
cv.Optional(CONF_USB_UART_ID): cv.invalid(
|
||||
"'usb_uart_id' has been removed; a USB UART channel is now "
|
||||
"detected automatically from 'uart_id'"
|
||||
),
|
||||
cv.Optional(CONF_INITIAL_TIMEOUT): cv.int_range(min=10, max=10000),
|
||||
cv.Optional(CONF_MIN_TIMEOUT): cv.int_range(min=10, max=5000),
|
||||
cv.Optional(CONF_MAX_TIMEOUT): cv.int_range(min=50, max=10000),
|
||||
@@ -74,14 +79,16 @@ async def to_code(config):
|
||||
if CONF_BUFFER_SIZE in config:
|
||||
cg.add_define("ZIGBEE_PROXY_BUFFER_SIZE", config[CONF_BUFFER_SIZE])
|
||||
|
||||
# Select timeout defaults based on UART transport type.
|
||||
# USB CDC ACM with the RX callback has ~3-5 ms round-trip latency; hardware
|
||||
# UART is similar (~2-5 ms). Different defaults are kept so that future
|
||||
# non-callback USB paths still get conservative starting values.
|
||||
is_usb = CONF_USB_UART_ID in config
|
||||
# A uart_id pointing at a USB UART channel is detected automatically: the
|
||||
# component then registers an RX callback for zero-wakeup-cycle data delivery
|
||||
# and selects USB-optimized ACK timeout defaults. Explicit timeout keys always
|
||||
# win. USB CDC ACM with the RX callback has ~3-5 ms round-trip latency;
|
||||
# hardware UART is similar (~2-5 ms). Different defaults are kept so that
|
||||
# future non-callback USB paths still get conservative starting values.
|
||||
is_usb = usb_uart.is_usb_uart_channel(config[CONF_UART_ID])
|
||||
if is_usb:
|
||||
cg.add_define("USE_ZIGBEE_PROXY_USB_UART")
|
||||
usb_ch = await cg.get_variable(config[CONF_USB_UART_ID])
|
||||
usb_ch = await cg.get_variable(config[CONF_UART_ID])
|
||||
cg.add(var.set_usb_uart_channel(usb_ch))
|
||||
|
||||
initial_timeout = config.get(
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
// Forward-declare USBUartChannel so the set_usb_uart_channel() setter can be declared
|
||||
// without pulling usb_uart.h into every translation unit that includes this header.
|
||||
// USE_ZIGBEE_PROXY_USB_UART is defined by the Python to_code() only when usb_uart_id
|
||||
// is present in the YAML, ensuring the header is actually in the build path.
|
||||
// USE_ZIGBEE_PROXY_USB_UART is defined by the Python to_code() only when uart_id
|
||||
// resolves to a USB UART channel, ensuring the header is actually in the build path.
|
||||
#ifdef USE_ZIGBEE_PROXY_USB_UART
|
||||
namespace esphome::usb_uart {
|
||||
class USBUartChannel;
|
||||
@@ -100,7 +100,7 @@ class ZigbeeProxy : public uart::UARTDevice, public Component {
|
||||
void set_max_timeout(uint32_t timeout_ms) { this->timeout_config_.max_timeout_ms = timeout_ms; }
|
||||
|
||||
#ifdef USE_ZIGBEE_PROXY_USB_UART
|
||||
/// Called from generated code when usb_uart_id is configured.
|
||||
/// Called from generated code when uart_id resolves to a USB UART channel.
|
||||
/// Registers an RX callback on the channel so incoming bytes are processed
|
||||
/// immediately in the same USBUartComponent::loop() iteration they arrive,
|
||||
/// without waiting for the next ZigbeeProxy::loop() call.
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
wifi:
|
||||
ssid: test
|
||||
password: password
|
||||
power_save_mode: none
|
||||
|
||||
api:
|
||||
|
||||
usb_host:
|
||||
|
||||
usb_uart:
|
||||
- type: CDC_ACM
|
||||
vid: 0x303A
|
||||
pid: 0x831A
|
||||
channels:
|
||||
- id: zigbee_usb_channel
|
||||
baud_rate: 460800
|
||||
|
||||
# uart_id points at a USB UART channel; the component must detect this
|
||||
# automatically and enable the RX callback fast path (USE_ZIGBEE_PROXY_USB_UART)
|
||||
zigbee_proxy:
|
||||
uart_id: zigbee_usb_channel
|
||||
Reference in New Issue
Block a user