mirror of
https://github.com/esphome/esphome.git
synced 2026-02-13 03:02:02 +00:00
Compare commits
14 Commits
20260210-s
...
usb-host-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1688f9af0f | ||
|
|
8dd3021030 | ||
|
|
cacd2b5fa3 | ||
|
|
60fef5e656 | ||
|
|
725e774fe7 | ||
|
|
9aa98ed6c6 | ||
|
|
9c72c022b2 | ||
|
|
7b251dcc31 | ||
|
|
8a08c688f6 | ||
|
|
d6461251f9 | ||
|
|
da1ea2cfa3 | ||
|
|
c9d2adb717 | ||
|
|
db6aea8969 | ||
|
|
96eb129cf8 |
@@ -1 +1 @@
|
||||
74867fc82764102ce1275ea2bc43e3aeee7619679537c6db61114a33342bb4c7
|
||||
ce05c28e9dc0b12c4f6e7454986ffea5123ac974a949da841be698c535f2083e
|
||||
|
||||
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@@ -115,6 +115,7 @@ jobs:
|
||||
python-version:
|
||||
- "3.11"
|
||||
- "3.13"
|
||||
- "3.14"
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macOS-latest
|
||||
|
||||
@@ -429,7 +429,6 @@ esphome/components/sen21231/* @shreyaskarnik
|
||||
esphome/components/sen5x/* @martgras
|
||||
esphome/components/sensirion_common/* @martgras
|
||||
esphome/components/sensor/* @esphome/core
|
||||
esphome/components/serial_proxy/* @kbx81
|
||||
esphome/components/sfa30/* @ghsensdev
|
||||
esphome/components/sgp40/* @SenexCrenshaw
|
||||
esphome/components/sgp4x/* @martgras @SenexCrenshaw
|
||||
|
||||
2
Doxyfile
2
Doxyfile
@@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 2026.2.0-dev
|
||||
PROJECT_NUMBER = 2026.3.0-dev
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -256,7 +256,7 @@ SYMBOL_PATTERNS = {
|
||||
"ipv6_stack": ["nd6_", "ip6_", "mld6_", "icmp6_", "icmp6_input"],
|
||||
# Order matters! More specific categories must come before general ones.
|
||||
# mdns must come before bluetooth to avoid "_mdns_disable_pcb" matching "ble_" pattern
|
||||
"mdns_lib": ["mdns"],
|
||||
"mdns_lib": ["mdns", "packet$"],
|
||||
# memory_mgmt must come before wifi_stack to catch mmu_hal_* symbols
|
||||
"memory_mgmt": [
|
||||
"mem_",
|
||||
@@ -794,7 +794,6 @@ SYMBOL_PATTERNS = {
|
||||
"s_dp",
|
||||
"s_ni",
|
||||
"s_reg_dump",
|
||||
"packet$",
|
||||
"d_mult_table",
|
||||
"K",
|
||||
"fcstab",
|
||||
|
||||
@@ -69,12 +69,6 @@ service APIConnection {
|
||||
rpc zwave_proxy_request(ZWaveProxyRequest) returns (void) {}
|
||||
|
||||
rpc infrared_rf_transmit_raw_timings(InfraredRFTransmitRawTimingsRequest) returns (void) {}
|
||||
|
||||
rpc serial_proxy_configure(SerialProxyConfigureRequest) returns (void) {}
|
||||
rpc serial_proxy_write(SerialProxyWriteRequest) returns (void) {}
|
||||
rpc serial_proxy_set_modem_pins(SerialProxySetModemPinsRequest) returns (void) {}
|
||||
rpc serial_proxy_get_modem_pins(SerialProxyGetModemPinsRequest) returns (void) {}
|
||||
rpc serial_proxy_request(SerialProxyRequest) returns (void) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -204,17 +198,6 @@ message DeviceInfo {
|
||||
uint32 area_id = 3;
|
||||
}
|
||||
|
||||
enum SerialProxyPortType {
|
||||
SERIAL_PROXY_PORT_TYPE_TTL = 0;
|
||||
SERIAL_PROXY_PORT_TYPE_RS232 = 1;
|
||||
SERIAL_PROXY_PORT_TYPE_RS485 = 2;
|
||||
}
|
||||
|
||||
message SerialProxyInfo {
|
||||
string name = 1; // Human-readable port name
|
||||
SerialProxyPortType port_type = 2; // Port type (RS232, RS485)
|
||||
}
|
||||
|
||||
message DeviceInfoResponse {
|
||||
option (id) = 10;
|
||||
option (source) = SOURCE_SERVER;
|
||||
@@ -277,9 +260,6 @@ message DeviceInfoResponse {
|
||||
// Indicates if Z-Wave proxy support is available and features supported
|
||||
uint32 zwave_proxy_feature_flags = 23 [(field_ifdef) = "USE_ZWAVE_PROXY"];
|
||||
uint32 zwave_home_id = 24 [(field_ifdef) = "USE_ZWAVE_PROXY"];
|
||||
|
||||
// Serial proxy instance metadata
|
||||
repeated SerialProxyInfo serial_proxies = 25 [(field_ifdef) = "USE_SERIAL_PROXY", (fixed_array_size_define) = "SERIAL_PROXY_COUNT"];
|
||||
}
|
||||
|
||||
message ListEntitiesRequest {
|
||||
@@ -2508,92 +2488,3 @@ message InfraredRFReceiveEvent {
|
||||
fixed32 key = 2; // Key identifying the receiver instance
|
||||
repeated sint32 timings = 3 [packed = true, (container_pointer_no_template) = "std::vector<int32_t>"]; // Raw timings in microseconds (zigzag-encoded): alternating mark/space periods
|
||||
}
|
||||
|
||||
// ==================== SERIAL PROXY ====================
|
||||
|
||||
enum SerialProxyParity {
|
||||
SERIAL_PROXY_PARITY_NONE = 0;
|
||||
SERIAL_PROXY_PARITY_EVEN = 1;
|
||||
SERIAL_PROXY_PARITY_ODD = 2;
|
||||
}
|
||||
|
||||
// Configure UART parameters for a serial proxy instance
|
||||
message SerialProxyConfigureRequest {
|
||||
option (id) = 138;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
uint32 baudrate = 2; // Baud rate in bits per second
|
||||
bool flow_control = 3; // Enable hardware flow control
|
||||
SerialProxyParity parity = 4; // Parity setting
|
||||
uint32 stop_bits = 5; // Number of stop bits (1 or 2)
|
||||
uint32 data_size = 6; // Number of data bits (5-8)
|
||||
}
|
||||
|
||||
// Data received from a serial device, forwarded to clients
|
||||
message SerialProxyDataReceived {
|
||||
option (id) = 139;
|
||||
option (source) = SOURCE_SERVER;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
option (no_delay) = true;
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
bytes data = 2; // Raw data received from the serial device
|
||||
}
|
||||
|
||||
// Write data to a serial device
|
||||
message SerialProxyWriteRequest {
|
||||
option (id) = 140;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
option (no_delay) = true;
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
bytes data = 2; // Raw data to write to the serial device
|
||||
}
|
||||
|
||||
// Set modem control pin states (RTS and DTR)
|
||||
message SerialProxySetModemPinsRequest {
|
||||
option (id) = 141;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
bool rts = 2; // Desired RTS pin state
|
||||
bool dtr = 3; // Desired DTR pin state
|
||||
}
|
||||
|
||||
// Request current modem control pin states
|
||||
message SerialProxyGetModemPinsRequest {
|
||||
option (id) = 142;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
}
|
||||
|
||||
// Response with current modem control pin states
|
||||
message SerialProxyGetModemPinsResponse {
|
||||
option (id) = 143;
|
||||
option (source) = SOURCE_SERVER;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
bool rts = 2; // Current RTS pin state
|
||||
bool dtr = 3; // Current DTR pin state
|
||||
}
|
||||
|
||||
enum SerialProxyRequestType {
|
||||
SERIAL_PROXY_REQUEST_TYPE_FLUSH = 0; // Flush the serial port (block until all TX data is sent)
|
||||
}
|
||||
|
||||
// Generic request message for simple serial proxy operations
|
||||
message SerialProxyRequest {
|
||||
option (id) = 144;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
SerialProxyRequestType type = 2; // Request type
|
||||
}
|
||||
|
||||
@@ -1413,73 +1413,6 @@ void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
void APIConnection::on_serial_proxy_configure_request(const SerialProxyConfigureRequest &msg) {
|
||||
auto &proxies = App.get_serial_proxies();
|
||||
if (msg.instance >= proxies.size()) {
|
||||
ESP_LOGW(TAG, "Serial proxy instance %u out of range (max %u)", msg.instance,
|
||||
static_cast<uint32_t>(proxies.size()));
|
||||
return;
|
||||
}
|
||||
proxies[msg.instance]->configure(msg.baudrate, msg.flow_control, static_cast<uint8_t>(msg.parity), msg.stop_bits,
|
||||
msg.data_size);
|
||||
}
|
||||
|
||||
void APIConnection::on_serial_proxy_write_request(const SerialProxyWriteRequest &msg) {
|
||||
auto &proxies = App.get_serial_proxies();
|
||||
if (msg.instance >= proxies.size()) {
|
||||
ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance);
|
||||
return;
|
||||
}
|
||||
proxies[msg.instance]->write(msg.data, msg.data_len);
|
||||
}
|
||||
|
||||
void APIConnection::on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &msg) {
|
||||
auto &proxies = App.get_serial_proxies();
|
||||
if (msg.instance >= proxies.size()) {
|
||||
ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance);
|
||||
return;
|
||||
}
|
||||
proxies[msg.instance]->set_modem_pins(msg.rts, msg.dtr);
|
||||
}
|
||||
|
||||
void APIConnection::on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &msg) {
|
||||
auto &proxies = App.get_serial_proxies();
|
||||
if (msg.instance >= proxies.size()) {
|
||||
ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance);
|
||||
return;
|
||||
}
|
||||
bool rts, dtr;
|
||||
proxies[msg.instance]->get_modem_pins(rts, dtr);
|
||||
|
||||
SerialProxyGetModemPinsResponse resp{};
|
||||
resp.instance = msg.instance;
|
||||
resp.rts = rts;
|
||||
resp.dtr = dtr;
|
||||
this->send_message(resp, SerialProxyGetModemPinsResponse::MESSAGE_TYPE);
|
||||
}
|
||||
|
||||
void APIConnection::on_serial_proxy_request(const SerialProxyRequest &msg) {
|
||||
auto &proxies = App.get_serial_proxies();
|
||||
if (msg.instance >= proxies.size()) {
|
||||
ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance);
|
||||
return;
|
||||
}
|
||||
switch (msg.type) {
|
||||
case enums::SERIAL_PROXY_REQUEST_TYPE_FLUSH:
|
||||
proxies[msg.instance]->flush_port();
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "Unknown serial proxy request type: %u", static_cast<uint32_t>(msg.type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void APIConnection::send_serial_proxy_data(const SerialProxyDataReceived &msg) {
|
||||
this->send_message(msg, SerialProxyDataReceived::MESSAGE_TYPE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_INFRARED
|
||||
uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
|
||||
auto *infrared = static_cast<infrared::Infrared *>(entity);
|
||||
@@ -1694,16 +1627,6 @@ bool APIConnection::send_device_info_response_() {
|
||||
resp.zwave_proxy_feature_flags = zwave_proxy::global_zwave_proxy->get_feature_flags();
|
||||
resp.zwave_home_id = zwave_proxy::global_zwave_proxy->get_home_id();
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
size_t serial_proxy_index = 0;
|
||||
for (auto const &proxy : App.get_serial_proxies()) {
|
||||
if (serial_proxy_index >= SERIAL_PROXY_COUNT)
|
||||
break;
|
||||
auto &info = resp.serial_proxies[serial_proxy_index++];
|
||||
info.name = StringRef(proxy->get_name());
|
||||
info.port_type = proxy->get_port_type();
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_API_NOISE
|
||||
resp.api_encryption_supported = true;
|
||||
#endif
|
||||
|
||||
@@ -182,15 +182,6 @@ class APIConnection final : public APIServerConnectionBase {
|
||||
void send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &msg) override;
|
||||
void on_serial_proxy_write_request(const SerialProxyWriteRequest &msg) override;
|
||||
void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &msg) override;
|
||||
void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &msg) override;
|
||||
void on_serial_proxy_request(const SerialProxyRequest &msg) override;
|
||||
void send_serial_proxy_data(const SerialProxyDataReceived &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_EVENT
|
||||
void send_event(event::Event *event);
|
||||
#endif
|
||||
|
||||
@@ -65,16 +65,6 @@ void DeviceInfo::calculate_size(ProtoSize &size) const {
|
||||
size.add_uint32(1, this->area_id);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
void SerialProxyInfo::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(1, this->name);
|
||||
buffer.encode_uint32(2, static_cast<uint32_t>(this->port_type));
|
||||
}
|
||||
void SerialProxyInfo::calculate_size(ProtoSize &size) const {
|
||||
size.add_length(1, this->name.size());
|
||||
size.add_uint32(1, static_cast<uint32_t>(this->port_type));
|
||||
}
|
||||
#endif
|
||||
void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(2, this->name);
|
||||
buffer.encode_string(3, this->mac_address);
|
||||
@@ -129,11 +119,6 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
buffer.encode_uint32(24, this->zwave_home_id);
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
for (const auto &it : this->serial_proxies) {
|
||||
buffer.encode_message(25, it);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void DeviceInfoResponse::calculate_size(ProtoSize &size) const {
|
||||
size.add_length(1, this->name.size());
|
||||
@@ -189,11 +174,6 @@ void DeviceInfoResponse::calculate_size(ProtoSize &size) const {
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
size.add_uint32(2, this->zwave_home_id);
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
for (const auto &it : this->serial_proxies) {
|
||||
size.add_message_object_force(2, it);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
@@ -3460,111 +3440,5 @@ void InfraredRFReceiveEvent::calculate_size(ProtoSize &size) const {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
bool SerialProxyConfigureRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
case 2:
|
||||
this->baudrate = value.as_uint32();
|
||||
break;
|
||||
case 3:
|
||||
this->flow_control = value.as_bool();
|
||||
break;
|
||||
case 4:
|
||||
this->parity = static_cast<enums::SerialProxyParity>(value.as_uint32());
|
||||
break;
|
||||
case 5:
|
||||
this->stop_bits = value.as_uint32();
|
||||
break;
|
||||
case 6:
|
||||
this->data_size = value.as_uint32();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void SerialProxyDataReceived::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint32(1, this->instance);
|
||||
buffer.encode_bytes(2, this->data_ptr_, this->data_len_);
|
||||
}
|
||||
void SerialProxyDataReceived::calculate_size(ProtoSize &size) const {
|
||||
size.add_uint32(1, this->instance);
|
||||
size.add_length(1, this->data_len_);
|
||||
}
|
||||
bool SerialProxyWriteRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SerialProxyWriteRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
||||
switch (field_id) {
|
||||
case 2: {
|
||||
this->data = value.data();
|
||||
this->data_len = value.size();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SerialProxySetModemPinsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
case 2:
|
||||
this->rts = value.as_bool();
|
||||
break;
|
||||
case 3:
|
||||
this->dtr = value.as_bool();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SerialProxyGetModemPinsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void SerialProxyGetModemPinsResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint32(1, this->instance);
|
||||
buffer.encode_bool(2, this->rts);
|
||||
buffer.encode_bool(3, this->dtr);
|
||||
}
|
||||
void SerialProxyGetModemPinsResponse::calculate_size(ProtoSize &size) const {
|
||||
size.add_uint32(1, this->instance);
|
||||
size.add_bool(1, this->rts);
|
||||
size.add_bool(1, this->dtr);
|
||||
}
|
||||
bool SerialProxyRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
case 2:
|
||||
this->type = static_cast<enums::SerialProxyRequestType>(value.as_uint32());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace esphome::api
|
||||
|
||||
@@ -12,11 +12,6 @@ namespace esphome::api {
|
||||
|
||||
namespace enums {
|
||||
|
||||
enum SerialProxyPortType : uint32_t {
|
||||
SERIAL_PROXY_PORT_TYPE_TTL = 0,
|
||||
SERIAL_PROXY_PORT_TYPE_RS232 = 1,
|
||||
SERIAL_PROXY_PORT_TYPE_RS485 = 2,
|
||||
};
|
||||
enum EntityCategory : uint32_t {
|
||||
ENTITY_CATEGORY_NONE = 0,
|
||||
ENTITY_CATEGORY_CONFIG = 1,
|
||||
@@ -316,16 +311,6 @@ enum ZWaveProxyRequestType : uint32_t {
|
||||
ZWAVE_PROXY_REQUEST_TYPE_HOME_ID_CHANGE = 2,
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
enum SerialProxyParity : uint32_t {
|
||||
SERIAL_PROXY_PARITY_NONE = 0,
|
||||
SERIAL_PROXY_PARITY_EVEN = 1,
|
||||
SERIAL_PROXY_PARITY_ODD = 2,
|
||||
};
|
||||
enum SerialProxyRequestType : uint32_t {
|
||||
SERIAL_PROXY_REQUEST_TYPE_FLUSH = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace enums
|
||||
|
||||
@@ -486,24 +471,10 @@ class DeviceInfo final : public ProtoMessage {
|
||||
protected:
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
class SerialProxyInfo final : public ProtoMessage {
|
||||
public:
|
||||
StringRef name{};
|
||||
enums::SerialProxyPortType port_type{};
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void calculate_size(ProtoSize &size) const override;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
};
|
||||
#endif
|
||||
class DeviceInfoResponse final : public ProtoMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 10;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 309;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 255;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "device_info_response"; }
|
||||
#endif
|
||||
@@ -555,9 +526,6 @@ class DeviceInfoResponse final : public ProtoMessage {
|
||||
#endif
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
uint32_t zwave_home_id{0};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
std::array<SerialProxyInfo, SERIAL_PROXY_COUNT> serial_proxies{};
|
||||
#endif
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void calculate_size(ProtoSize &size) const override;
|
||||
@@ -3057,133 +3025,5 @@ class InfraredRFReceiveEvent final : public ProtoMessage {
|
||||
protected:
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
class SerialProxyConfigureRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 138;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 20;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_configure_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
uint32_t baudrate{0};
|
||||
bool flow_control{false};
|
||||
enums::SerialProxyParity parity{};
|
||||
uint32_t stop_bits{0};
|
||||
uint32_t data_size{0};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class SerialProxyDataReceived final : public ProtoMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 139;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 23;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_data_received"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
const uint8_t *data_ptr_{nullptr};
|
||||
size_t data_len_{0};
|
||||
void set_data(const uint8_t *data, size_t len) {
|
||||
this->data_ptr_ = data;
|
||||
this->data_len_ = len;
|
||||
}
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void calculate_size(ProtoSize &size) const override;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
};
|
||||
class SerialProxyWriteRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 140;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 23;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_write_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
const uint8_t *data{nullptr};
|
||||
uint16_t data_len{0};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 141;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 8;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_set_modem_pins_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
bool rts{false};
|
||||
bool dtr{false};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 142;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 4;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_get_modem_pins_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class SerialProxyGetModemPinsResponse final : public ProtoMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 143;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 8;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_get_modem_pins_response"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
bool rts{false};
|
||||
bool dtr{false};
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void calculate_size(ProtoSize &size) const override;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
};
|
||||
class SerialProxyRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 144;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 6;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
enums::SerialProxyRequestType type{};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace esphome::api
|
||||
|
||||
@@ -100,18 +100,6 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint
|
||||
out.append(hex_buf).append("\n");
|
||||
}
|
||||
|
||||
template<> const char *proto_enum_to_string<enums::SerialProxyPortType>(enums::SerialProxyPortType value) {
|
||||
switch (value) {
|
||||
case enums::SERIAL_PROXY_PORT_TYPE_TTL:
|
||||
return "SERIAL_PROXY_PORT_TYPE_TTL";
|
||||
case enums::SERIAL_PROXY_PORT_TYPE_RS232:
|
||||
return "SERIAL_PROXY_PORT_TYPE_RS232";
|
||||
case enums::SERIAL_PROXY_PORT_TYPE_RS485:
|
||||
return "SERIAL_PROXY_PORT_TYPE_RS485";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<enums::EntityCategory>(enums::EntityCategory value) {
|
||||
switch (value) {
|
||||
case enums::ENTITY_CATEGORY_NONE:
|
||||
@@ -748,28 +736,6 @@ template<> const char *proto_enum_to_string<enums::ZWaveProxyRequestType>(enums:
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
template<> const char *proto_enum_to_string<enums::SerialProxyParity>(enums::SerialProxyParity value) {
|
||||
switch (value) {
|
||||
case enums::SERIAL_PROXY_PARITY_NONE:
|
||||
return "SERIAL_PROXY_PARITY_NONE";
|
||||
case enums::SERIAL_PROXY_PARITY_EVEN:
|
||||
return "SERIAL_PROXY_PARITY_EVEN";
|
||||
case enums::SERIAL_PROXY_PARITY_ODD:
|
||||
return "SERIAL_PROXY_PARITY_ODD";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<enums::SerialProxyRequestType>(enums::SerialProxyRequestType value) {
|
||||
switch (value) {
|
||||
case enums::SERIAL_PROXY_REQUEST_TYPE_FLUSH:
|
||||
return "SERIAL_PROXY_REQUEST_TYPE_FLUSH";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *HelloRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "HelloRequest");
|
||||
@@ -819,14 +785,6 @@ const char *DeviceInfo::dump_to(DumpBuffer &out) const {
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
const char *SerialProxyInfo::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyInfo");
|
||||
dump_field(out, "name", this->name);
|
||||
dump_field(out, "port_type", static_cast<enums::SerialProxyPortType>(this->port_type));
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "DeviceInfoResponse");
|
||||
dump_field(out, "name", this->name);
|
||||
@@ -887,13 +845,6 @@ const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const {
|
||||
#endif
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
dump_field(out, "zwave_home_id", this->zwave_home_id);
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
for (const auto &it : this->serial_proxies) {
|
||||
out.append(" serial_proxies: ");
|
||||
it.dump_to(out);
|
||||
out.append("\n");
|
||||
}
|
||||
#endif
|
||||
return out.c_str();
|
||||
}
|
||||
@@ -2518,55 +2469,6 @@ const char *InfraredRFReceiveEvent::dump_to(DumpBuffer &out) const {
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
const char *SerialProxyConfigureRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyConfigureRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_field(out, "baudrate", this->baudrate);
|
||||
dump_field(out, "flow_control", this->flow_control);
|
||||
dump_field(out, "parity", static_cast<enums::SerialProxyParity>(this->parity));
|
||||
dump_field(out, "stop_bits", this->stop_bits);
|
||||
dump_field(out, "data_size", this->data_size);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyDataReceived::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyDataReceived");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_bytes_field(out, "data", this->data_ptr_, this->data_len_);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyWriteRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyWriteRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_bytes_field(out, "data", this->data, this->data_len);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxySetModemPinsRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxySetModemPinsRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_field(out, "rts", this->rts);
|
||||
dump_field(out, "dtr", this->dtr);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyGetModemPinsRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyGetModemPinsRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyGetModemPinsResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyGetModemPinsResponse");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_field(out, "rts", this->rts);
|
||||
dump_field(out, "dtr", this->dtr);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_field(out, "type", static_cast<enums::SerialProxyRequestType>(this->type));
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace esphome::api
|
||||
|
||||
|
||||
@@ -634,61 +634,6 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
|
||||
this->on_infrared_rf_transmit_raw_timings_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxyConfigureRequest::MESSAGE_TYPE: {
|
||||
SerialProxyConfigureRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_configure_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_configure_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxyWriteRequest::MESSAGE_TYPE: {
|
||||
SerialProxyWriteRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_write_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_write_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxySetModemPinsRequest::MESSAGE_TYPE: {
|
||||
SerialProxySetModemPinsRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_set_modem_pins_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_set_modem_pins_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxyGetModemPinsRequest::MESSAGE_TYPE: {
|
||||
SerialProxyGetModemPinsRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_get_modem_pins_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_get_modem_pins_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxyRequest::MESSAGE_TYPE: {
|
||||
SerialProxyRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -224,23 +224,6 @@ class APIServerConnectionBase : public ProtoService {
|
||||
virtual void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &value){};
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &value){};
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_write_request(const SerialProxyWriteRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &value){};
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_request(const SerialProxyRequest &value){};
|
||||
#endif
|
||||
protected:
|
||||
void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override;
|
||||
};
|
||||
|
||||
@@ -370,17 +370,6 @@ void APIServer::send_infrared_rf_receive_event([[maybe_unused]] uint32_t device_
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
void APIServer::send_serial_proxy_data(uint32_t instance, const uint8_t *data, size_t len) {
|
||||
SerialProxyDataReceived msg{};
|
||||
msg.instance = instance;
|
||||
msg.set_data(data, len);
|
||||
|
||||
for (auto &c : this->clients_)
|
||||
c->send_serial_proxy_data(msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_ALARM_CONTROL_PANEL
|
||||
API_DISPATCH_UPDATE(alarm_control_panel::AlarmControlPanel, alarm_control_panel)
|
||||
#endif
|
||||
|
||||
@@ -189,10 +189,6 @@ class APIServer : public Component,
|
||||
void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector<int32_t> *timings);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
void send_serial_proxy_data(uint32_t instance, const uint8_t *data, size_t len);
|
||||
#endif
|
||||
|
||||
bool is_connected(bool state_subscription_only = false) const;
|
||||
|
||||
#ifdef USE_API_HOMEASSISTANT_STATES
|
||||
|
||||
@@ -645,11 +645,12 @@ def _is_framework_url(source: str) -> bool:
|
||||
# The default/recommended arduino framework version
|
||||
# - https://github.com/espressif/arduino-esp32/releases
|
||||
ARDUINO_FRAMEWORK_VERSION_LOOKUP = {
|
||||
"recommended": cv.Version(3, 3, 6),
|
||||
"latest": cv.Version(3, 3, 6),
|
||||
"dev": cv.Version(3, 3, 6),
|
||||
"recommended": cv.Version(3, 3, 7),
|
||||
"latest": cv.Version(3, 3, 7),
|
||||
"dev": cv.Version(3, 3, 7),
|
||||
}
|
||||
ARDUINO_PLATFORM_VERSION_LOOKUP = {
|
||||
cv.Version(3, 3, 7): cv.Version(55, 3, 37),
|
||||
cv.Version(3, 3, 6): cv.Version(55, 3, 36),
|
||||
cv.Version(3, 3, 5): cv.Version(55, 3, 35),
|
||||
cv.Version(3, 3, 4): cv.Version(55, 3, 31, "2"),
|
||||
@@ -668,6 +669,7 @@ ARDUINO_PLATFORM_VERSION_LOOKUP = {
|
||||
# These versions correspond to pioarduino/esp-idf releases
|
||||
# See: https://github.com/pioarduino/esp-idf/releases
|
||||
ARDUINO_IDF_VERSION_LOOKUP = {
|
||||
cv.Version(3, 3, 7): cv.Version(5, 5, 2),
|
||||
cv.Version(3, 3, 6): cv.Version(5, 5, 2),
|
||||
cv.Version(3, 3, 5): cv.Version(5, 5, 2),
|
||||
cv.Version(3, 3, 4): cv.Version(5, 5, 1),
|
||||
@@ -691,7 +693,7 @@ ESP_IDF_FRAMEWORK_VERSION_LOOKUP = {
|
||||
"dev": cv.Version(5, 5, 2),
|
||||
}
|
||||
ESP_IDF_PLATFORM_VERSION_LOOKUP = {
|
||||
cv.Version(5, 5, 2): cv.Version(55, 3, 36),
|
||||
cv.Version(5, 5, 2): cv.Version(55, 3, 37),
|
||||
cv.Version(5, 5, 1): cv.Version(55, 3, 31, "2"),
|
||||
cv.Version(5, 5, 0): cv.Version(55, 3, 31, "2"),
|
||||
cv.Version(5, 4, 3): cv.Version(55, 3, 32),
|
||||
@@ -708,8 +710,8 @@ ESP_IDF_PLATFORM_VERSION_LOOKUP = {
|
||||
# The platform-espressif32 version
|
||||
# - https://github.com/pioarduino/platform-espressif32/releases
|
||||
PLATFORM_VERSION_LOOKUP = {
|
||||
"recommended": cv.Version(55, 3, 36),
|
||||
"latest": cv.Version(55, 3, 36),
|
||||
"recommended": cv.Version(55, 3, 37),
|
||||
"latest": cv.Version(55, 3, 37),
|
||||
"dev": "https://github.com/pioarduino/platform-espressif32.git#develop",
|
||||
}
|
||||
|
||||
|
||||
@@ -1686,6 +1686,10 @@ BOARDS = {
|
||||
"name": "Espressif ESP32-C6-DevKitM-1",
|
||||
"variant": VARIANT_ESP32C6,
|
||||
},
|
||||
"esp32-c61-devkitc1": {
|
||||
"name": "Espressif ESP32-C61-DevKitC-1 (4 MB Flash)",
|
||||
"variant": VARIANT_ESP32C61,
|
||||
},
|
||||
"esp32-c61-devkitc1-n8r2": {
|
||||
"name": "Espressif ESP32-C61-DevKitC-1 N8R2 (8 MB Flash Quad, 2 MB PSRAM Quad)",
|
||||
"variant": VARIANT_ESP32C61,
|
||||
@@ -1718,6 +1722,10 @@ BOARDS = {
|
||||
"name": "Espressif ESP32-P4 rev.300 generic",
|
||||
"variant": VARIANT_ESP32P4,
|
||||
},
|
||||
"esp32-p4_r3-evboard": {
|
||||
"name": "Espressif ESP32-P4 Function EV Board v1.6 (rev.301)",
|
||||
"variant": VARIANT_ESP32P4,
|
||||
},
|
||||
"esp32-pico-devkitm-2": {
|
||||
"name": "Espressif ESP32-PICO-DevKitM-2",
|
||||
"variant": VARIANT_ESP32,
|
||||
@@ -2554,6 +2562,10 @@ BOARDS = {
|
||||
"name": "XinaBox CW02",
|
||||
"variant": VARIANT_ESP32,
|
||||
},
|
||||
"yb_esp32s3_amp": {
|
||||
"name": "YelloByte YB-ESP32-S3-AMP",
|
||||
"variant": VARIANT_ESP32S3,
|
||||
},
|
||||
"yb_esp32s3_amp_v2": {
|
||||
"name": "YelloByte YB-ESP32-S3-AMP (Rev.2)",
|
||||
"variant": VARIANT_ESP32S3,
|
||||
@@ -2562,6 +2574,10 @@ BOARDS = {
|
||||
"name": "YelloByte YB-ESP32-S3-AMP (Rev.3)",
|
||||
"variant": VARIANT_ESP32S3,
|
||||
},
|
||||
"yb_esp32s3_dac": {
|
||||
"name": "YelloByte YB-ESP32-S3-DAC",
|
||||
"variant": VARIANT_ESP32S3,
|
||||
},
|
||||
"yb_esp32s3_drv": {
|
||||
"name": "YelloByte YB-ESP32-S3-DRV",
|
||||
"variant": VARIANT_ESP32S3,
|
||||
|
||||
@@ -130,11 +130,16 @@ ETHERNET_TYPES = {
|
||||
}
|
||||
|
||||
# PHY types that need compile-time defines for conditional compilation
|
||||
# Each RMII PHY type gets a define so unused PHY drivers are excluded by the linker
|
||||
_PHY_TYPE_TO_DEFINE = {
|
||||
"LAN8720": "USE_ETHERNET_LAN8720",
|
||||
"RTL8201": "USE_ETHERNET_RTL8201",
|
||||
"DP83848": "USE_ETHERNET_DP83848",
|
||||
"IP101": "USE_ETHERNET_IP101",
|
||||
"JL1101": "USE_ETHERNET_JL1101",
|
||||
"KSZ8081": "USE_ETHERNET_KSZ8081",
|
||||
"KSZ8081RNA": "USE_ETHERNET_KSZ8081",
|
||||
"LAN8670": "USE_ETHERNET_LAN8670",
|
||||
# Add other PHY types here only if they need conditional compilation
|
||||
}
|
||||
|
||||
SPI_ETHERNET_TYPES = ["W5500", "DM9051"]
|
||||
|
||||
@@ -186,31 +186,43 @@ void EthernetComponent::setup() {
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_ETH_USE_ESP32_EMAC
|
||||
#ifdef USE_ETHERNET_LAN8720
|
||||
case ETHERNET_TYPE_LAN8720: {
|
||||
this->phy_ = esp_eth_phy_new_lan87xx(&phy_config);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_RTL8201
|
||||
case ETHERNET_TYPE_RTL8201: {
|
||||
this->phy_ = esp_eth_phy_new_rtl8201(&phy_config);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_DP83848
|
||||
case ETHERNET_TYPE_DP83848: {
|
||||
this->phy_ = esp_eth_phy_new_dp83848(&phy_config);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_IP101
|
||||
case ETHERNET_TYPE_IP101: {
|
||||
this->phy_ = esp_eth_phy_new_ip101(&phy_config);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_JL1101
|
||||
case ETHERNET_TYPE_JL1101: {
|
||||
this->phy_ = esp_eth_phy_new_jl1101(&phy_config);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_KSZ8081
|
||||
case ETHERNET_TYPE_KSZ8081:
|
||||
case ETHERNET_TYPE_KSZ8081RNA: {
|
||||
this->phy_ = esp_eth_phy_new_ksz80xx(&phy_config);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_LAN8670
|
||||
case ETHERNET_TYPE_LAN8670: {
|
||||
this->phy_ = esp_eth_phy_new_lan867x(&phy_config);
|
||||
@@ -343,26 +355,32 @@ void EthernetComponent::loop() {
|
||||
void EthernetComponent::dump_config() {
|
||||
const char *eth_type;
|
||||
switch (this->type_) {
|
||||
#ifdef USE_ETHERNET_LAN8720
|
||||
case ETHERNET_TYPE_LAN8720:
|
||||
eth_type = "LAN8720";
|
||||
break;
|
||||
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_RTL8201
|
||||
case ETHERNET_TYPE_RTL8201:
|
||||
eth_type = "RTL8201";
|
||||
break;
|
||||
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_DP83848
|
||||
case ETHERNET_TYPE_DP83848:
|
||||
eth_type = "DP83848";
|
||||
break;
|
||||
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_IP101
|
||||
case ETHERNET_TYPE_IP101:
|
||||
eth_type = "IP101";
|
||||
break;
|
||||
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_JL1101
|
||||
case ETHERNET_TYPE_JL1101:
|
||||
eth_type = "JL1101";
|
||||
break;
|
||||
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_KSZ8081
|
||||
case ETHERNET_TYPE_KSZ8081:
|
||||
eth_type = "KSZ8081";
|
||||
break;
|
||||
@@ -370,19 +388,22 @@ void EthernetComponent::dump_config() {
|
||||
case ETHERNET_TYPE_KSZ8081RNA:
|
||||
eth_type = "KSZ8081RNA";
|
||||
break;
|
||||
|
||||
#endif
|
||||
#if CONFIG_ETH_SPI_ETHERNET_W5500
|
||||
case ETHERNET_TYPE_W5500:
|
||||
eth_type = "W5500";
|
||||
break;
|
||||
|
||||
case ETHERNET_TYPE_OPENETH:
|
||||
eth_type = "OPENETH";
|
||||
break;
|
||||
|
||||
#endif
|
||||
#if CONFIG_ETH_SPI_ETHERNET_DM9051
|
||||
case ETHERNET_TYPE_DM9051:
|
||||
eth_type = "DM9051";
|
||||
break;
|
||||
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_OPENETH
|
||||
case ETHERNET_TYPE_OPENETH:
|
||||
eth_type = "OPENETH";
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_LAN8670
|
||||
case ETHERNET_TYPE_LAN8670:
|
||||
eth_type = "LAN8670";
|
||||
@@ -686,16 +707,22 @@ void EthernetComponent::dump_connect_params_() {
|
||||
char gateway_buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||
char dns1_buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||
char dns2_buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||
char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
ESP_LOGCONFIG(TAG,
|
||||
" IP Address: %s\n"
|
||||
" Hostname: '%s'\n"
|
||||
" Subnet: %s\n"
|
||||
" Gateway: %s\n"
|
||||
" DNS1: %s\n"
|
||||
" DNS2: %s",
|
||||
" DNS2: %s\n"
|
||||
" MAC Address: %s\n"
|
||||
" Is Full Duplex: %s\n"
|
||||
" Link Speed: %u",
|
||||
network::IPAddress(&ip.ip).str_to(ip_buf), App.get_name().c_str(),
|
||||
network::IPAddress(&ip.netmask).str_to(subnet_buf), network::IPAddress(&ip.gw).str_to(gateway_buf),
|
||||
network::IPAddress(dns_ip1).str_to(dns1_buf), network::IPAddress(dns_ip2).str_to(dns2_buf));
|
||||
network::IPAddress(dns_ip1).str_to(dns1_buf), network::IPAddress(dns_ip2).str_to(dns2_buf),
|
||||
this->get_eth_mac_address_pretty_into_buffer(mac_buf),
|
||||
YESNO(this->get_duplex_mode() == ETH_DUPLEX_FULL), this->get_link_speed() == ETH_SPEED_100M ? 100 : 10);
|
||||
|
||||
#if USE_NETWORK_IPV6
|
||||
struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES];
|
||||
@@ -706,14 +733,6 @@ void EthernetComponent::dump_connect_params_() {
|
||||
ESP_LOGCONFIG(TAG, " IPv6: " IPV6STR, IPV62STR(if_ip6s[i]));
|
||||
}
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
|
||||
char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
ESP_LOGCONFIG(TAG,
|
||||
" MAC Address: %s\n"
|
||||
" Is Full Duplex: %s\n"
|
||||
" Link Speed: %u",
|
||||
this->get_eth_mac_address_pretty_into_buffer(mac_buf),
|
||||
YESNO(this->get_duplex_mode() == ETH_DUPLEX_FULL), this->get_link_speed() == ETH_SPEED_100M ? 100 : 10);
|
||||
}
|
||||
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
@@ -837,13 +856,15 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) {
|
||||
|
||||
void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister register_data) {
|
||||
esp_err_t err;
|
||||
constexpr uint8_t eth_phy_psr_reg_addr = 0x1F;
|
||||
|
||||
#ifdef USE_ETHERNET_RTL8201
|
||||
constexpr uint8_t eth_phy_psr_reg_addr = 0x1F;
|
||||
if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) {
|
||||
ESP_LOGD(TAG, "Select PHY Register Page: 0x%02" PRIX32, register_data.page);
|
||||
err = mac->write_phy_reg(mac, this->phy_addr_, eth_phy_psr_reg_addr, register_data.page);
|
||||
ESPHL_ERROR_CHECK(err, "Select PHY Register page failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Writing to PHY Register Address: 0x%02" PRIX32 "\n"
|
||||
@@ -852,11 +873,13 @@ void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister regi
|
||||
err = mac->write_phy_reg(mac, this->phy_addr_, register_data.address, register_data.value);
|
||||
ESPHL_ERROR_CHECK(err, "Writing PHY Register failed");
|
||||
|
||||
#ifdef USE_ETHERNET_RTL8201
|
||||
if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) {
|
||||
ESP_LOGD(TAG, "Select PHY Register Page 0x00");
|
||||
err = mac->write_phy_reg(mac, this->phy_addr_, eth_phy_psr_reg_addr, 0x0);
|
||||
ESPHL_ERROR_CHECK(err, "Select PHY Register Page 0 failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
from esphome.components.mipi import DriverChip
|
||||
from esphome.components.mipi import (
|
||||
ETMOD,
|
||||
FRMCTR2,
|
||||
GMCTRN1,
|
||||
GMCTRP1,
|
||||
IFCTR,
|
||||
MODE_RGB,
|
||||
PWCTR1,
|
||||
PWCTR3,
|
||||
PWCTR4,
|
||||
PWCTR5,
|
||||
PWSET,
|
||||
DriverChip,
|
||||
)
|
||||
import esphome.config_validation as cv
|
||||
|
||||
from .amoled import CO5300
|
||||
@@ -129,6 +142,16 @@ DriverChip(
|
||||
),
|
||||
),
|
||||
)
|
||||
ST7789P = DriverChip(
|
||||
"ST7789P",
|
||||
# Max supported dimensions
|
||||
width=240,
|
||||
height=320,
|
||||
# SPI: RGB layout
|
||||
color_order=MODE_RGB,
|
||||
invert_colors=True,
|
||||
draw_rounding=1,
|
||||
)
|
||||
|
||||
ILI9488_A.extend(
|
||||
"PICO-RESTOUCH-LCD-3.5",
|
||||
@@ -162,3 +185,61 @@ AXS15231.extend(
|
||||
cs_pin=9,
|
||||
reset_pin=21,
|
||||
)
|
||||
|
||||
# Waveshare 1.83-v2
|
||||
#
|
||||
# Do not use on 1.83-v1: Vendor warning on different chip!
|
||||
ST7789P.extend(
|
||||
"WAVESHARE-1.83-V2",
|
||||
# Panel size smaller than ST7789 max allowed
|
||||
width=240,
|
||||
height=284,
|
||||
# Vendor specific init derived from vendor sample code
|
||||
# "LCD_1.83_Code_Rev2/ESP32/LCD_1in83/LCD_Driver.cpp"
|
||||
# Compatible MIT license, see esphome/LICENSE file.
|
||||
initsequence=(
|
||||
(FRMCTR2, 0x0C, 0x0C, 0x00, 0x33, 0x33),
|
||||
(ETMOD, 0x35),
|
||||
(0xBB, 0x19),
|
||||
(PWCTR1, 0x2C),
|
||||
(PWCTR3, 0x01),
|
||||
(PWCTR4, 0x12),
|
||||
(PWCTR5, 0x20),
|
||||
(IFCTR, 0x0F),
|
||||
(PWSET, 0xA4, 0xA1),
|
||||
(
|
||||
GMCTRP1,
|
||||
0xD0,
|
||||
0x04,
|
||||
0x0D,
|
||||
0x11,
|
||||
0x13,
|
||||
0x2B,
|
||||
0x3F,
|
||||
0x54,
|
||||
0x4C,
|
||||
0x18,
|
||||
0x0D,
|
||||
0x0B,
|
||||
0x1F,
|
||||
0x23,
|
||||
),
|
||||
(
|
||||
GMCTRN1,
|
||||
0xD0,
|
||||
0x04,
|
||||
0x0C,
|
||||
0x11,
|
||||
0x13,
|
||||
0x2C,
|
||||
0x3F,
|
||||
0x44,
|
||||
0x51,
|
||||
0x2F,
|
||||
0x1F,
|
||||
0x1F,
|
||||
0x20,
|
||||
0x23,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
"""
|
||||
Serial Proxy component for ESPHome.
|
||||
|
||||
WARNING: 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.
|
||||
|
||||
Provides a proxy to/from a serial interface on the ESPHome device, allowing
|
||||
Home Assistant to connect to the serial port and send/receive data to/from
|
||||
an arbitrary serial device.
|
||||
"""
|
||||
|
||||
from esphome import pins
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import uart
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_NAME
|
||||
|
||||
CODEOWNERS = ["@kbx81"]
|
||||
DEPENDENCIES = ["api", "uart"]
|
||||
|
||||
MULTI_CONF = True
|
||||
|
||||
serial_proxy_ns = cg.esphome_ns.namespace("serial_proxy")
|
||||
SerialProxy = serial_proxy_ns.class_("SerialProxy", cg.Component, uart.UARTDevice)
|
||||
|
||||
api_enums_ns = cg.esphome_ns.namespace("api").namespace("enums")
|
||||
SerialProxyPortType = api_enums_ns.enum("SerialProxyPortType")
|
||||
SERIAL_PROXY_PORT_TYPES = {
|
||||
"TTL": SerialProxyPortType.SERIAL_PROXY_PORT_TYPE_TTL,
|
||||
"RS232": SerialProxyPortType.SERIAL_PROXY_PORT_TYPE_RS232,
|
||||
"RS485": SerialProxyPortType.SERIAL_PROXY_PORT_TYPE_RS485,
|
||||
}
|
||||
|
||||
CONF_DTR_PIN = "dtr_pin"
|
||||
CONF_PORT_TYPE = "port_type"
|
||||
CONF_RTS_PIN = "rts_pin"
|
||||
|
||||
_serial_proxy_count = []
|
||||
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(SerialProxy),
|
||||
cv.Required(CONF_NAME): cv.string_strict,
|
||||
cv.Required(CONF_PORT_TYPE): cv.enum(SERIAL_PROXY_PORT_TYPES, upper=True),
|
||||
cv.Optional(CONF_RTS_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Optional(CONF_DTR_PIN): pins.gpio_output_pin_schema,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
cg.add(cg.App.register_serial_proxy(var))
|
||||
cg.add(var.set_name(config[CONF_NAME]))
|
||||
cg.add(var.set_port_type(config[CONF_PORT_TYPE]))
|
||||
cg.add_define("USE_SERIAL_PROXY")
|
||||
# Track instance count — last define wins, so the final value is the total count
|
||||
_serial_proxy_count.append(var)
|
||||
cg.add_define("SERIAL_PROXY_COUNT", len(_serial_proxy_count))
|
||||
|
||||
if CONF_RTS_PIN in config:
|
||||
rts_pin = await cg.gpio_pin_expression(config[CONF_RTS_PIN])
|
||||
cg.add(var.set_rts_pin(rts_pin))
|
||||
|
||||
if CONF_DTR_PIN in config:
|
||||
dtr_pin = await cg.gpio_pin_expression(config[CONF_DTR_PIN])
|
||||
cg.add(var.set_dtr_pin(dtr_pin))
|
||||
|
||||
# Request UART to wake the main loop when data arrives for low-latency processing
|
||||
uart.request_wake_loop_on_rx()
|
||||
@@ -1,137 +0,0 @@
|
||||
#include "serial_proxy.h"
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#ifdef USE_API
|
||||
#include "esphome/components/api/api_server.h"
|
||||
#endif
|
||||
|
||||
namespace esphome::serial_proxy {
|
||||
|
||||
static const char *const TAG = "serial_proxy";
|
||||
|
||||
void SerialProxy::setup() {
|
||||
// Set up modem control pins if configured
|
||||
if (this->rts_pin_ != nullptr) {
|
||||
this->rts_pin_->setup();
|
||||
this->rts_pin_->digital_write(this->rts_state_);
|
||||
}
|
||||
if (this->dtr_pin_ != nullptr) {
|
||||
this->dtr_pin_->setup();
|
||||
this->dtr_pin_->digital_write(this->dtr_state_);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialProxy::loop() {
|
||||
// Read available data from UART and forward to API clients
|
||||
size_t available = this->available();
|
||||
if (available == 0)
|
||||
return;
|
||||
|
||||
// Read in chunks up to SERIAL_PROXY_MAX_READ_SIZE
|
||||
uint8_t buffer[SERIAL_PROXY_MAX_READ_SIZE];
|
||||
size_t to_read = std::min(available, sizeof(buffer));
|
||||
|
||||
if (!this->read_array(buffer, to_read))
|
||||
return;
|
||||
|
||||
#ifdef USE_API
|
||||
if (api::global_api_server != nullptr) {
|
||||
api::global_api_server->send_serial_proxy_data(this->instance_index_, buffer, to_read);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SerialProxy::dump_config() {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"Serial Proxy [%u]:\n"
|
||||
" Name: %s\n"
|
||||
" Port Type: %s\n"
|
||||
" RTS Pin: %s\n"
|
||||
" DTR Pin: %s",
|
||||
this->instance_index_, this->name_.c_str(),
|
||||
this->port_type_ == api::enums::SERIAL_PROXY_PORT_TYPE_RS485 ? "RS485"
|
||||
: this->port_type_ == api::enums::SERIAL_PROXY_PORT_TYPE_RS232 ? "RS232"
|
||||
: "TTL",
|
||||
this->rts_pin_ != nullptr ? "configured" : "not configured",
|
||||
this->dtr_pin_ != nullptr ? "configured" : "not configured");
|
||||
}
|
||||
|
||||
void SerialProxy::configure(uint32_t baudrate, bool flow_control, uint8_t parity, uint8_t stop_bits,
|
||||
uint8_t data_size) {
|
||||
ESP_LOGD(TAG, "Configuring serial proxy [%u]: baud=%u, flow_ctrl=%s, parity=%u, stop=%u, data=%u",
|
||||
this->instance_index_, baudrate, YESNO(flow_control), parity, stop_bits, data_size);
|
||||
|
||||
auto *uart_comp = this->parent_;
|
||||
if (uart_comp == nullptr) {
|
||||
ESP_LOGE(TAG, "UART component not available");
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply UART parameters
|
||||
uart_comp->set_baud_rate(baudrate);
|
||||
uart_comp->set_stop_bits(stop_bits);
|
||||
uart_comp->set_data_bits(data_size);
|
||||
|
||||
// Map parity enum to UARTParityOptions
|
||||
switch (parity) {
|
||||
case 0:
|
||||
uart_comp->set_parity(uart::UART_CONFIG_PARITY_NONE);
|
||||
break;
|
||||
case 1:
|
||||
uart_comp->set_parity(uart::UART_CONFIG_PARITY_EVEN);
|
||||
break;
|
||||
case 2:
|
||||
uart_comp->set_parity(uart::UART_CONFIG_PARITY_ODD);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "Unknown parity value: %u, using NONE", parity);
|
||||
uart_comp->set_parity(uart::UART_CONFIG_PARITY_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
// Apply the new settings
|
||||
// load_settings() is available on ESP8266 and ESP32 platforms
|
||||
#if defined(USE_ESP8266) || defined(USE_ESP32)
|
||||
uart_comp->load_settings(true);
|
||||
#endif
|
||||
|
||||
// Note: Hardware flow control configuration is stored but not yet applied
|
||||
// to the UART hardware - this requires additional platform support
|
||||
(void) flow_control;
|
||||
}
|
||||
|
||||
void SerialProxy::write(const uint8_t *data, size_t len) {
|
||||
if (data == nullptr || len == 0)
|
||||
return;
|
||||
this->write_array(data, len);
|
||||
}
|
||||
|
||||
void SerialProxy::set_modem_pins(bool rts, bool dtr) {
|
||||
ESP_LOGV(TAG, "Setting modem pins [%u]: RTS=%s, DTR=%s", this->instance_index_, ONOFF(rts), ONOFF(dtr));
|
||||
|
||||
if (this->rts_pin_ != nullptr) {
|
||||
this->rts_state_ = rts;
|
||||
this->rts_pin_->digital_write(rts);
|
||||
}
|
||||
if (this->dtr_pin_ != nullptr) {
|
||||
this->dtr_state_ = dtr;
|
||||
this->dtr_pin_->digital_write(dtr);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialProxy::get_modem_pins(bool &rts, bool &dtr) const {
|
||||
rts = this->rts_state_;
|
||||
dtr = this->dtr_state_;
|
||||
}
|
||||
|
||||
void SerialProxy::flush_port() {
|
||||
ESP_LOGV(TAG, "Flushing serial proxy [%u]", this->instance_index_);
|
||||
this->flush();
|
||||
}
|
||||
|
||||
} // namespace esphome::serial_proxy
|
||||
|
||||
#endif // USE_SERIAL_PROXY
|
||||
@@ -1,101 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// WARNING: This component is EXPERIMENTAL. The API 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.
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
|
||||
#include "esphome/components/api/api_pb2.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace esphome::serial_proxy {
|
||||
|
||||
/// Maximum bytes to read from UART in a single loop iteration
|
||||
static constexpr size_t SERIAL_PROXY_MAX_READ_SIZE = 256;
|
||||
|
||||
class SerialProxy : public uart::UARTDevice, public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_CONNECTION; }
|
||||
|
||||
/// Get the instance index (position in Application's serial_proxies_ vector)
|
||||
uint32_t get_instance_index() const { return this->instance_index_; }
|
||||
|
||||
/// Set the instance index (called by Application::register_serial_proxy)
|
||||
void set_instance_index(uint32_t index) { this->instance_index_ = index; }
|
||||
|
||||
/// Set the human-readable port name (from YAML configuration)
|
||||
void set_name(const std::string &name) { this->name_ = name; }
|
||||
|
||||
/// Get the human-readable port name
|
||||
const std::string &get_name() const { return this->name_; }
|
||||
|
||||
/// Set the port type (from YAML configuration)
|
||||
void set_port_type(api::enums::SerialProxyPortType port_type) { this->port_type_ = port_type; }
|
||||
|
||||
/// Get the port type
|
||||
api::enums::SerialProxyPortType get_port_type() const { return this->port_type_; }
|
||||
|
||||
/// Configure UART parameters and apply them
|
||||
/// @param baudrate Baud rate in bits per second
|
||||
/// @param flow_control True to enable hardware flow control
|
||||
/// @param parity Parity setting (0=none, 1=even, 2=odd)
|
||||
/// @param stop_bits Number of stop bits (1 or 2)
|
||||
/// @param data_size Number of data bits (5-8)
|
||||
void configure(uint32_t baudrate, bool flow_control, uint8_t parity, uint8_t stop_bits, uint8_t data_size);
|
||||
|
||||
/// Write data to the serial device
|
||||
/// @param data Pointer to data buffer
|
||||
/// @param len Number of bytes to write
|
||||
void write(const uint8_t *data, size_t len);
|
||||
|
||||
/// Set modem pin states (RTS and DTR)
|
||||
/// @param rts Desired RTS pin state
|
||||
/// @param dtr Desired DTR pin state
|
||||
void set_modem_pins(bool rts, bool dtr);
|
||||
|
||||
/// Get current modem pin states
|
||||
/// @param[out] rts Current RTS pin state
|
||||
/// @param[out] dtr Current DTR pin state
|
||||
void get_modem_pins(bool &rts, bool &dtr) const;
|
||||
|
||||
/// Flush the serial port (block until all TX data is sent)
|
||||
void flush_port();
|
||||
|
||||
/// Set the RTS GPIO pin (from YAML configuration)
|
||||
void set_rts_pin(GPIOPin *pin) { this->rts_pin_ = pin; }
|
||||
|
||||
/// Set the DTR GPIO pin (from YAML configuration)
|
||||
void set_dtr_pin(GPIOPin *pin) { this->dtr_pin_ = pin; }
|
||||
|
||||
protected:
|
||||
/// Instance index for identifying this proxy in API messages
|
||||
uint32_t instance_index_{0};
|
||||
|
||||
/// Human-readable port name
|
||||
std::string name_;
|
||||
|
||||
/// Port type
|
||||
api::enums::SerialProxyPortType port_type_{api::enums::SERIAL_PROXY_PORT_TYPE_TTL};
|
||||
|
||||
/// Optional GPIO pins for modem control
|
||||
GPIOPin *rts_pin_{nullptr};
|
||||
GPIOPin *dtr_pin_{nullptr};
|
||||
|
||||
/// Current modem pin states
|
||||
bool rts_state_{false};
|
||||
bool dtr_state_{false};
|
||||
};
|
||||
|
||||
} // namespace esphome::serial_proxy
|
||||
|
||||
#endif // USE_SERIAL_PROXY
|
||||
@@ -90,7 +90,6 @@ void IDFUARTComponent::setup() {
|
||||
return;
|
||||
}
|
||||
this->uart_num_ = static_cast<uart_port_t>(next_uart_num++);
|
||||
this->lock_ = xSemaphoreCreateMutex();
|
||||
|
||||
#if (SOC_UART_LP_NUM >= 1)
|
||||
size_t fifo_len = ((this->uart_num_ < SOC_UART_HP_NUM) ? SOC_UART_FIFO_LEN : SOC_LP_UART_FIFO_LEN);
|
||||
@@ -102,11 +101,7 @@ void IDFUARTComponent::setup() {
|
||||
this->rx_buffer_size_ = fifo_len * 2;
|
||||
}
|
||||
|
||||
xSemaphoreTake(this->lock_, portMAX_DELAY);
|
||||
|
||||
this->load_settings(false);
|
||||
|
||||
xSemaphoreGive(this->lock_);
|
||||
}
|
||||
|
||||
void IDFUARTComponent::load_settings(bool dump_config) {
|
||||
@@ -126,13 +121,20 @@ void IDFUARTComponent::load_settings(bool dump_config) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef USE_UART_WAKE_LOOP_ON_RX
|
||||
constexpr int event_queue_size = 20;
|
||||
QueueHandle_t *event_queue_ptr = &this->uart_event_queue_;
|
||||
#else
|
||||
constexpr int event_queue_size = 0;
|
||||
QueueHandle_t *event_queue_ptr = nullptr;
|
||||
#endif
|
||||
err = uart_driver_install(this->uart_num_, // UART number
|
||||
this->rx_buffer_size_, // RX ring buffer size
|
||||
0, // TX ring buffer size. If zero, driver will not use a TX buffer and TX function will
|
||||
// block task until all data has been sent out
|
||||
20, // event queue size/depth
|
||||
&this->uart_event_queue_, // event queue
|
||||
0 // Flags used to allocate the interrupt
|
||||
0, // TX ring buffer size. If zero, driver will not use a TX buffer and TX function will
|
||||
// block task until all data has been sent out
|
||||
event_queue_size, // event queue size/depth
|
||||
event_queue_ptr, // event queue
|
||||
0 // Flags used to allocate the interrupt
|
||||
);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "uart_driver_install failed: %s", esp_err_to_name(err));
|
||||
@@ -282,9 +284,7 @@ void IDFUARTComponent::set_rx_timeout(size_t rx_timeout) {
|
||||
}
|
||||
|
||||
void IDFUARTComponent::write_array(const uint8_t *data, size_t len) {
|
||||
xSemaphoreTake(this->lock_, portMAX_DELAY);
|
||||
int32_t write_len = uart_write_bytes(this->uart_num_, data, len);
|
||||
xSemaphoreGive(this->lock_);
|
||||
if (write_len != (int32_t) len) {
|
||||
ESP_LOGW(TAG, "uart_write_bytes failed: %d != %zu", write_len, len);
|
||||
this->mark_failed();
|
||||
@@ -299,7 +299,6 @@ void IDFUARTComponent::write_array(const uint8_t *data, size_t len) {
|
||||
bool IDFUARTComponent::peek_byte(uint8_t *data) {
|
||||
if (!this->check_read_timeout_())
|
||||
return false;
|
||||
xSemaphoreTake(this->lock_, portMAX_DELAY);
|
||||
if (this->has_peek_) {
|
||||
*data = this->peek_byte_;
|
||||
} else {
|
||||
@@ -311,7 +310,6 @@ bool IDFUARTComponent::peek_byte(uint8_t *data) {
|
||||
this->peek_byte_ = *data;
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(this->lock_);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -320,7 +318,6 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) {
|
||||
int32_t read_len = 0;
|
||||
if (!this->check_read_timeout_(len))
|
||||
return false;
|
||||
xSemaphoreTake(this->lock_, portMAX_DELAY);
|
||||
if (this->has_peek_) {
|
||||
length_to_read--;
|
||||
*data = this->peek_byte_;
|
||||
@@ -329,7 +326,6 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) {
|
||||
}
|
||||
if (length_to_read > 0)
|
||||
read_len = uart_read_bytes(this->uart_num_, data, length_to_read, 20 / portTICK_PERIOD_MS);
|
||||
xSemaphoreGive(this->lock_);
|
||||
#ifdef USE_UART_DEBUGGER
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
this->debug_callback_.call(UART_DIRECTION_RX, data[i]);
|
||||
@@ -342,9 +338,7 @@ size_t IDFUARTComponent::available() {
|
||||
size_t available = 0;
|
||||
esp_err_t err;
|
||||
|
||||
xSemaphoreTake(this->lock_, portMAX_DELAY);
|
||||
err = uart_get_buffered_data_len(this->uart_num_, &available);
|
||||
xSemaphoreGive(this->lock_);
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "uart_get_buffered_data_len failed: %s", esp_err_to_name(err));
|
||||
@@ -358,9 +352,7 @@ size_t IDFUARTComponent::available() {
|
||||
|
||||
void IDFUARTComponent::flush() {
|
||||
ESP_LOGVV(TAG, " Flushing");
|
||||
xSemaphoreTake(this->lock_, portMAX_DELAY);
|
||||
uart_wait_tx_done(this->uart_num_, portMAX_DELAY);
|
||||
xSemaphoreGive(this->lock_);
|
||||
}
|
||||
|
||||
void IDFUARTComponent::check_logger_conflict() {}
|
||||
@@ -384,6 +376,13 @@ void IDFUARTComponent::start_rx_event_task_() {
|
||||
ESP_LOGV(TAG, "RX event task started");
|
||||
}
|
||||
|
||||
// FreeRTOS task that relays UART ISR events to the main loop.
|
||||
// This task exists because wake_loop_threadsafe() is not ISR-safe (it uses a
|
||||
// UDP loopback socket), so we need a task as an ISR-to-main-loop trampoline.
|
||||
// IMPORTANT: This task must NOT call any UART wrapper methods (read_array,
|
||||
// write_array, peek_byte, etc.) or touch has_peek_/peek_byte_ — all reading
|
||||
// is done by the main loop. This task only reads from the event queue and
|
||||
// calls App.wake_loop_threadsafe().
|
||||
void IDFUARTComponent::rx_event_task_func(void *param) {
|
||||
auto *self = static_cast<IDFUARTComponent *>(param);
|
||||
uart_event_t event;
|
||||
@@ -405,8 +404,14 @@ void IDFUARTComponent::rx_event_task_func(void *param) {
|
||||
|
||||
case UART_FIFO_OVF:
|
||||
case UART_BUFFER_FULL:
|
||||
ESP_LOGW(TAG, "FIFO overflow or ring buffer full - clearing");
|
||||
uart_flush_input(self->uart_num_);
|
||||
// Don't call uart_flush_input() here — this task does not own the read side.
|
||||
// ESP-IDF examples flush on overflow because the same task handles both events
|
||||
// and reads, so flush and read are serialized. Here, reads happen on the main
|
||||
// loop, so flushing from this task races with read_array() and can destroy data
|
||||
// mid-read. The driver self-heals without an explicit flush: uart_read_bytes()
|
||||
// calls uart_check_buf_full() after each chunk, which moves stashed FIFO bytes
|
||||
// into the ring buffer and re-enables RX interrupts once space is freed.
|
||||
ESP_LOGW(TAG, "FIFO overflow or ring buffer full");
|
||||
#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE)
|
||||
App.wake_loop_threadsafe();
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,13 @@
|
||||
|
||||
namespace esphome::uart {
|
||||
|
||||
/// ESP-IDF UART driver wrapper.
|
||||
///
|
||||
/// Thread safety: All public methods must only be called from the main loop.
|
||||
/// The ESP-IDF UART driver API does not guarantee thread safety, and ESPHome's
|
||||
/// peek byte state (has_peek_/peek_byte_) is not synchronized. The rx_event_task
|
||||
/// (when enabled) must not call any of these methods — it communicates with the
|
||||
/// main loop exclusively via App.wake_loop_threadsafe().
|
||||
class IDFUARTComponent : public UARTComponent, public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
@@ -26,7 +33,9 @@ class IDFUARTComponent : public UARTComponent, public Component {
|
||||
void flush() override;
|
||||
|
||||
uint8_t get_hw_serial_number() { return this->uart_num_; }
|
||||
#ifdef USE_UART_WAKE_LOOP_ON_RX
|
||||
QueueHandle_t *get_uart_event_queue() { return &this->uart_event_queue_; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Load the UART with the current settings.
|
||||
@@ -46,18 +55,20 @@ class IDFUARTComponent : public UARTComponent, public Component {
|
||||
protected:
|
||||
void check_logger_conflict() override;
|
||||
uart_port_t uart_num_;
|
||||
QueueHandle_t uart_event_queue_;
|
||||
uart_config_t get_config_();
|
||||
SemaphoreHandle_t lock_;
|
||||
|
||||
bool has_peek_{false};
|
||||
uint8_t peek_byte_;
|
||||
|
||||
#ifdef USE_UART_WAKE_LOOP_ON_RX
|
||||
// RX notification support
|
||||
// RX notification support — runs on a separate FreeRTOS task.
|
||||
// IMPORTANT: rx_event_task_func must NOT call any UART wrapper methods (read_array,
|
||||
// write_array, etc.) or touch has_peek_/peek_byte_. It must only read from the
|
||||
// event queue and call App.wake_loop_threadsafe().
|
||||
void start_rx_event_task_();
|
||||
static void rx_event_task_func(void *param);
|
||||
|
||||
QueueHandle_t uart_event_queue_;
|
||||
TaskHandle_t rx_event_task_handle_{nullptr};
|
||||
#endif // USE_UART_WAKE_LOOP_ON_RX
|
||||
};
|
||||
|
||||
@@ -148,6 +148,7 @@ class USBClient : public Component {
|
||||
EventPool<UsbEvent, USB_EVENT_QUEUE_SIZE> event_pool;
|
||||
|
||||
protected:
|
||||
void handle_open_state_();
|
||||
TransferRequest *get_trq_(); // Lock-free allocation using atomic bitmask (multi-consumer safe)
|
||||
virtual void disconnect();
|
||||
virtual void on_connected() {}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <atomic>
|
||||
#include <span>
|
||||
namespace esphome {
|
||||
namespace usb_host {
|
||||
|
||||
@@ -142,18 +143,23 @@ static void usb_client_print_config_descriptor(const usb_config_desc_t *cfg_desc
|
||||
} while (next_desc != NULL);
|
||||
}
|
||||
#endif
|
||||
static std::string get_descriptor_string(const usb_str_desc_t *desc) {
|
||||
char buffer[256];
|
||||
if (desc == nullptr)
|
||||
// USB string descriptors: bLength (uint8_t, max 255) includes the 2-byte header (bLength and bDescriptorType).
|
||||
// Character count = (bLength - 2) / 2, max 126 chars + null terminator.
|
||||
static constexpr size_t DESC_STRING_BUF_SIZE = 128;
|
||||
|
||||
static const char *get_descriptor_string(const usb_str_desc_t *desc, std::span<char, DESC_STRING_BUF_SIZE> buffer) {
|
||||
if (desc == nullptr || desc->bLength < 2)
|
||||
return "(unspecified)";
|
||||
char *p = buffer;
|
||||
for (int i = 0; i != desc->bLength / 2; i++) {
|
||||
int char_count = (desc->bLength - 2) / 2;
|
||||
char *p = buffer.data();
|
||||
char *end = p + buffer.size() - 1;
|
||||
for (int i = 0; i != char_count && p < end; i++) {
|
||||
auto c = desc->wData[i];
|
||||
if (c < 0x100)
|
||||
*p++ = static_cast<char>(c);
|
||||
}
|
||||
*p = '\0';
|
||||
return {buffer};
|
||||
return buffer.data();
|
||||
}
|
||||
|
||||
// CALLBACK CONTEXT: USB task (called from usb_host_client_handle_events in USB task)
|
||||
@@ -259,60 +265,63 @@ void USBClient::loop() {
|
||||
ESP_LOGW(TAG, "Dropped %u USB events due to queue overflow", dropped);
|
||||
}
|
||||
|
||||
switch (this->state_) {
|
||||
case USB_CLIENT_OPEN: {
|
||||
int err;
|
||||
ESP_LOGD(TAG, "Open device %d", this->device_addr_);
|
||||
err = usb_host_device_open(this->handle_, this->device_addr_, &this->device_handle_);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Device open failed: %s", esp_err_to_name(err));
|
||||
this->state_ = USB_CLIENT_INIT;
|
||||
break;
|
||||
}
|
||||
ESP_LOGD(TAG, "Get descriptor device %d", this->device_addr_);
|
||||
const usb_device_desc_t *desc;
|
||||
err = usb_host_get_device_descriptor(this->device_handle_, &desc);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Device get_desc failed: %s", esp_err_to_name(err));
|
||||
this->disconnect();
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Device descriptor: vid %X pid %X", desc->idVendor, desc->idProduct);
|
||||
if (desc->idVendor == this->vid_ && desc->idProduct == this->pid_ || this->vid_ == 0 && this->pid_ == 0) {
|
||||
usb_device_info_t dev_info;
|
||||
err = usb_host_device_info(this->device_handle_, &dev_info);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Device info failed: %s", esp_err_to_name(err));
|
||||
this->disconnect();
|
||||
break;
|
||||
}
|
||||
this->state_ = USB_CLIENT_CONNECTED;
|
||||
ESP_LOGD(TAG, "Device connected: Manuf: %s; Prod: %s; Serial: %s",
|
||||
get_descriptor_string(dev_info.str_desc_manufacturer).c_str(),
|
||||
get_descriptor_string(dev_info.str_desc_product).c_str(),
|
||||
get_descriptor_string(dev_info.str_desc_serial_num).c_str());
|
||||
if (this->state_ == USB_CLIENT_OPEN) {
|
||||
this->handle_open_state_();
|
||||
}
|
||||
}
|
||||
|
||||
void USBClient::handle_open_state_() {
|
||||
int err;
|
||||
ESP_LOGD(TAG, "Open device %d", this->device_addr_);
|
||||
err = usb_host_device_open(this->handle_, this->device_addr_, &this->device_handle_);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Device open failed: %s", esp_err_to_name(err));
|
||||
this->state_ = USB_CLIENT_INIT;
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "Get descriptor device %d", this->device_addr_);
|
||||
const usb_device_desc_t *desc;
|
||||
err = usb_host_get_device_descriptor(this->device_handle_, &desc);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Device get_desc failed: %s", esp_err_to_name(err));
|
||||
this->disconnect();
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "Device descriptor: vid %X pid %X", desc->idVendor, desc->idProduct);
|
||||
if (desc->idVendor != this->vid_ || desc->idProduct != this->pid_) {
|
||||
if (this->vid_ != 0 || this->pid_ != 0) {
|
||||
ESP_LOGD(TAG, "Not our device, closing");
|
||||
this->disconnect();
|
||||
return;
|
||||
}
|
||||
}
|
||||
usb_device_info_t dev_info;
|
||||
err = usb_host_device_info(this->device_handle_, &dev_info);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Device info failed: %s", esp_err_to_name(err));
|
||||
this->disconnect();
|
||||
return;
|
||||
}
|
||||
this->state_ = USB_CLIENT_CONNECTED;
|
||||
char buf_manuf[DESC_STRING_BUF_SIZE];
|
||||
char buf_product[DESC_STRING_BUF_SIZE];
|
||||
char buf_serial[DESC_STRING_BUF_SIZE];
|
||||
ESP_LOGD(TAG, "Device connected: Manuf: %s; Prod: %s; Serial: %s",
|
||||
get_descriptor_string(dev_info.str_desc_manufacturer, buf_manuf),
|
||||
get_descriptor_string(dev_info.str_desc_product, buf_product),
|
||||
get_descriptor_string(dev_info.str_desc_serial_num, buf_serial));
|
||||
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
const usb_device_desc_t *device_desc;
|
||||
err = usb_host_get_device_descriptor(this->device_handle_, &device_desc);
|
||||
if (err == ESP_OK)
|
||||
usb_client_print_device_descriptor(device_desc);
|
||||
const usb_config_desc_t *config_desc;
|
||||
err = usb_host_get_active_config_descriptor(this->device_handle_, &config_desc);
|
||||
if (err == ESP_OK)
|
||||
usb_client_print_config_descriptor(config_desc, nullptr);
|
||||
const usb_device_desc_t *device_desc;
|
||||
err = usb_host_get_device_descriptor(this->device_handle_, &device_desc);
|
||||
if (err == ESP_OK)
|
||||
usb_client_print_device_descriptor(device_desc);
|
||||
const usb_config_desc_t *config_desc;
|
||||
err = usb_host_get_active_config_descriptor(this->device_handle_, &config_desc);
|
||||
if (err == ESP_OK)
|
||||
usb_client_print_config_descriptor(config_desc, nullptr);
|
||||
#endif
|
||||
this->on_connected();
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Not our device, closing");
|
||||
this->disconnect();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this->on_connected();
|
||||
}
|
||||
|
||||
void USBClient::on_opened(uint8_t addr) {
|
||||
|
||||
@@ -557,7 +557,9 @@ static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, J
|
||||
root[ESPHOME_F("device")] = device_name;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ENTITY_ICON
|
||||
root[ESPHOME_F("icon")] = obj->get_icon_ref();
|
||||
#endif
|
||||
root[ESPHOME_F("entity_category")] = obj->get_entity_category();
|
||||
bool is_disabled = obj->is_disabled_by_default();
|
||||
if (is_disabled)
|
||||
|
||||
@@ -288,11 +288,6 @@ def _validate(config):
|
||||
config = config.copy()
|
||||
config[CONF_NETWORKS] = []
|
||||
|
||||
if config.get(CONF_FAST_CONNECT, False):
|
||||
networks = config.get(CONF_NETWORKS, [])
|
||||
if not networks:
|
||||
raise cv.Invalid("At least one network required for fast_connect!")
|
||||
|
||||
if CONF_USE_ADDRESS not in config:
|
||||
use_address = CORE.name + config[CONF_DOMAIN]
|
||||
if CONF_MANUAL_IP in config:
|
||||
|
||||
@@ -4,7 +4,7 @@ from enum import Enum
|
||||
|
||||
from esphome.enum import StrEnum
|
||||
|
||||
__version__ = "2026.2.0-dev"
|
||||
__version__ = "2026.3.0-dev"
|
||||
|
||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||
|
||||
@@ -94,9 +94,6 @@
|
||||
#ifdef USE_INFRARED
|
||||
#include "esphome/components/infrared/infrared.h"
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
#include "esphome/components/serial_proxy/serial_proxy.h"
|
||||
#endif
|
||||
#ifdef USE_EVENT
|
||||
#include "esphome/components/event/event.h"
|
||||
#endif
|
||||
@@ -237,13 +234,6 @@ class Application {
|
||||
void register_infrared(infrared::Infrared *infrared) { this->infrareds_.push_back(infrared); }
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
void register_serial_proxy(serial_proxy::SerialProxy *proxy) {
|
||||
proxy->set_instance_index(this->serial_proxies_.size());
|
||||
this->serial_proxies_.push_back(proxy);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_EVENT
|
||||
void register_event(event::Event *event) { this->events_.push_back(event); }
|
||||
#endif
|
||||
@@ -483,10 +473,6 @@ class Application {
|
||||
GET_ENTITY_METHOD(infrared::Infrared, infrared, infrareds)
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
auto &get_serial_proxies() const { return this->serial_proxies_; }
|
||||
#endif
|
||||
|
||||
#ifdef USE_EVENT
|
||||
auto &get_events() const { return this->events_; }
|
||||
GET_ENTITY_METHOD(event::Event, event, events)
|
||||
@@ -704,9 +690,6 @@ class Application {
|
||||
#ifdef USE_INFRARED
|
||||
StaticVector<infrared::Infrared *, ESPHOME_ENTITY_INFRARED_COUNT> infrareds_{};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
std::vector<serial_proxy::SerialProxy *> serial_proxies_{};
|
||||
#endif
|
||||
#ifdef USE_UPDATE
|
||||
StaticVector<update::UpdateEntity *, ESPHOME_ENTITY_UPDATE_COUNT> updates_{};
|
||||
#endif
|
||||
|
||||
@@ -99,7 +99,6 @@
|
||||
#define MDNS_SERVICE_COUNT 3
|
||||
#define USE_MDNS_DYNAMIC_TXT
|
||||
#define MDNS_DYNAMIC_TXT_COUNT 2
|
||||
#define SERIAL_PROXY_COUNT 2
|
||||
#define SNTP_SERVER_COUNT 3
|
||||
#define USE_MEDIA_PLAYER
|
||||
#define USE_NEXTION_TFT_UPLOAD
|
||||
@@ -110,7 +109,6 @@
|
||||
#define USE_SAFE_MODE_CALLBACK
|
||||
#define USE_SELECT
|
||||
#define USE_SENSOR
|
||||
#define USE_SERIAL_PROXY
|
||||
#define USE_STATUS_LED
|
||||
#define USE_STATUS_SENSOR
|
||||
#define USE_SWITCH
|
||||
@@ -241,9 +239,15 @@
|
||||
#define USB_HOST_MAX_REQUESTS 16
|
||||
|
||||
#ifdef USE_ARDUINO
|
||||
#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 6)
|
||||
#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 7)
|
||||
#define USE_ETHERNET
|
||||
#define USE_ETHERNET_LAN8720
|
||||
#define USE_ETHERNET_RTL8201
|
||||
#define USE_ETHERNET_DP83848
|
||||
#define USE_ETHERNET_IP101
|
||||
#define USE_ETHERNET_JL1101
|
||||
#define USE_ETHERNET_KSZ8081
|
||||
#define USE_ETHERNET_LAN8670
|
||||
#define USE_ETHERNET_MANUAL_IP
|
||||
#define USE_ETHERNET_IP_STATE_LISTENERS
|
||||
#define USE_ETHERNET_CONNECT_TRIGGER
|
||||
|
||||
@@ -133,9 +133,9 @@ extra_scripts = post:esphome/components/esp8266/post_build.py.script
|
||||
; This are common settings for the ESP32 (all variants) using Arduino.
|
||||
[common:esp32-arduino]
|
||||
extends = common:arduino
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
|
||||
platform_packages =
|
||||
pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.3.6/esp32-core-3.3.6.tar.xz
|
||||
pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.3.7/esp32-core-3.3.7.tar.xz
|
||||
pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.2/esp-idf-v5.5.2.tar.xz
|
||||
|
||||
framework = arduino, espidf ; Arduino as an ESP-IDF component
|
||||
@@ -169,7 +169,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script
|
||||
; This are common settings for the ESP32 (all variants) using IDF.
|
||||
[common:esp32-idf]
|
||||
extends = common:idf
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
|
||||
platform_packages =
|
||||
pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.2/esp-idf-v5.5.2.tar.xz
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ classifiers = [
|
||||
"Topic :: Home Automation",
|
||||
]
|
||||
|
||||
# Python 3.14 is currently not supported by IDF <= 5.5.1, see https://github.com/esphome/esphome/issues/11502
|
||||
requires-python = ">=3.11.0,<3.14"
|
||||
# Python 3.14 is not supported on Windows, see https://github.com/zephyrproject-rtos/windows-curses/issues/76
|
||||
requires-python = ">=3.11.0,<3.15"
|
||||
|
||||
dynamic = ["dependencies", "optional-dependencies", "version"]
|
||||
|
||||
|
||||
@@ -369,7 +369,7 @@ def get_logger_tags():
|
||||
"api.service",
|
||||
]
|
||||
for file in CORE_COMPONENTS_PATH.rglob("*.cpp"):
|
||||
data = file.read_text()
|
||||
data = file.read_text(encoding="utf-8")
|
||||
match = pattern.search(data)
|
||||
if match:
|
||||
tags.append(match.group(1))
|
||||
|
||||
@@ -3,9 +3,15 @@ display:
|
||||
spi_16: true
|
||||
pixel_mode: 18bit
|
||||
model: ili9488
|
||||
dc_pin: ${dc_pin}
|
||||
cs_pin: ${cs_pin}
|
||||
reset_pin: ${reset_pin}
|
||||
dc_pin:
|
||||
allow_other_uses: true
|
||||
number: ${dc_pin}
|
||||
cs_pin:
|
||||
allow_other_uses: true
|
||||
number: ${cs_pin}
|
||||
reset_pin:
|
||||
allow_other_uses: true
|
||||
number: ${reset_pin}
|
||||
data_rate: 20MHz
|
||||
invert_colors: true
|
||||
show_test_card: true
|
||||
@@ -24,3 +30,15 @@ display:
|
||||
height: 200
|
||||
enable_pin: ${enable_pin}
|
||||
bus_mode: single
|
||||
|
||||
- platform: mipi_spi
|
||||
model: WAVESHARE-1.83-V2
|
||||
dc_pin:
|
||||
allow_other_uses: true
|
||||
number: ${dc_pin}
|
||||
cs_pin:
|
||||
allow_other_uses: true
|
||||
number: ${cs_pin}
|
||||
reset_pin:
|
||||
allow_other_uses: true
|
||||
number: ${reset_pin}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
api:
|
||||
|
||||
serial_proxy:
|
||||
- id: serial_proxy_1
|
||||
name: Test Serial Port
|
||||
port_type: RS232
|
||||
@@ -1,8 +0,0 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp32-idf.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -1,8 +0,0 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO0
|
||||
rx_pin: GPIO2
|
||||
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp8266-ard.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -1,8 +0,0 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/rp2040-ard.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
Reference in New Issue
Block a user