mirror of
https://github.com/esphome/esphome.git
synced 2025-09-26 23:22:21 +01:00
Implement zero-copy API for zwave_proxy (#10836)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
@@ -2292,7 +2292,7 @@ message ZWaveProxyFrame {
|
|||||||
option (ifdef) = "USE_ZWAVE_PROXY";
|
option (ifdef) = "USE_ZWAVE_PROXY";
|
||||||
option (no_delay) = true;
|
option (no_delay) = true;
|
||||||
|
|
||||||
bytes data = 1 [(fixed_array_size) = 257];
|
bytes data = 1 [(pointer_to_buffer) = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ZWaveProxyRequestType {
|
enum ZWaveProxyRequestType {
|
||||||
|
@@ -3035,12 +3035,9 @@ bool UpdateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
|||||||
bool ZWaveProxyFrame::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
bool ZWaveProxyFrame::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
||||||
switch (field_id) {
|
switch (field_id) {
|
||||||
case 1: {
|
case 1: {
|
||||||
const std::string &data_str = value.as_string();
|
// Use raw data directly to avoid allocation
|
||||||
this->data_len = data_str.size();
|
this->data = value.data();
|
||||||
if (this->data_len > 257) {
|
this->data_len = value.size();
|
||||||
this->data_len = 257;
|
|
||||||
}
|
|
||||||
memcpy(this->data, data_str.data(), this->data_len);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@@ -2931,11 +2931,11 @@ class UpdateCommandRequest final : public CommandProtoMessage {
|
|||||||
class ZWaveProxyFrame final : public ProtoDecodableMessage {
|
class ZWaveProxyFrame final : public ProtoDecodableMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t MESSAGE_TYPE = 128;
|
static constexpr uint8_t MESSAGE_TYPE = 128;
|
||||||
static constexpr uint8_t ESTIMATED_SIZE = 33;
|
static constexpr uint8_t ESTIMATED_SIZE = 19;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
const char *message_name() const override { return "z_wave_proxy_frame"; }
|
const char *message_name() const override { return "z_wave_proxy_frame"; }
|
||||||
#endif
|
#endif
|
||||||
uint8_t data[257]{};
|
const uint8_t *data{nullptr};
|
||||||
uint16_t data_len{0};
|
uint16_t data_len{0};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
void calculate_size(ProtoSize &size) const override;
|
void calculate_size(ProtoSize &size) const override;
|
||||||
|
@@ -106,14 +106,14 @@ void ZWaveProxy::process_uart_() {
|
|||||||
}
|
}
|
||||||
ESP_LOGV(TAG, "Sending to client: %s", YESNO(this->api_connection_ != nullptr));
|
ESP_LOGV(TAG, "Sending to client: %s", YESNO(this->api_connection_ != nullptr));
|
||||||
if (this->api_connection_ != nullptr) {
|
if (this->api_connection_ != nullptr) {
|
||||||
// minimize copying to reduce CPU overhead
|
// Zero-copy: point directly to our buffer
|
||||||
|
this->outgoing_proto_msg_.data = this->buffer_.data();
|
||||||
if (this->in_bootloader_) {
|
if (this->in_bootloader_) {
|
||||||
this->outgoing_proto_msg_.data_len = this->buffer_index_;
|
this->outgoing_proto_msg_.data_len = this->buffer_index_;
|
||||||
} else {
|
} else {
|
||||||
// If this is a data frame, use frame length indicator + 2 (for SoF + checksum), else assume 1 for ACK/NAK/CAN
|
// If this is a data frame, use frame length indicator + 2 (for SoF + checksum), else assume 1 for ACK/NAK/CAN
|
||||||
this->outgoing_proto_msg_.data_len = this->buffer_[0] == ZWAVE_FRAME_TYPE_START ? this->buffer_[1] + 2 : 1;
|
this->outgoing_proto_msg_.data_len = this->buffer_[0] == ZWAVE_FRAME_TYPE_START ? this->buffer_[1] + 2 : 1;
|
||||||
}
|
}
|
||||||
std::memcpy(this->outgoing_proto_msg_.data, this->buffer_.data(), this->outgoing_proto_msg_.data_len);
|
|
||||||
this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE);
|
this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,7 +272,9 @@ void ZWaveProxy::parse_start_(uint8_t byte) {
|
|||||||
}
|
}
|
||||||
// Forward response (ACK/NAK/CAN) back to client for processing
|
// Forward response (ACK/NAK/CAN) back to client for processing
|
||||||
if (this->api_connection_ != nullptr) {
|
if (this->api_connection_ != nullptr) {
|
||||||
this->outgoing_proto_msg_.data[0] = byte;
|
// Store single byte in buffer and point to it
|
||||||
|
this->buffer_[0] = byte;
|
||||||
|
this->outgoing_proto_msg_.data = this->buffer_.data();
|
||||||
this->outgoing_proto_msg_.data_len = 1;
|
this->outgoing_proto_msg_.data_len = 1;
|
||||||
this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE);
|
this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE);
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,8 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace zwave_proxy {
|
namespace zwave_proxy {
|
||||||
|
|
||||||
|
static constexpr size_t MAX_ZWAVE_FRAME_SIZE = 257; // Maximum Z-Wave frame size
|
||||||
|
|
||||||
enum ZWaveResponseTypes : uint8_t {
|
enum ZWaveResponseTypes : uint8_t {
|
||||||
ZWAVE_FRAME_TYPE_ACK = 0x06,
|
ZWAVE_FRAME_TYPE_ACK = 0x06,
|
||||||
ZWAVE_FRAME_TYPE_CAN = 0x18,
|
ZWAVE_FRAME_TYPE_CAN = 0x18,
|
||||||
@@ -66,7 +68,7 @@ class ZWaveProxy : public uart::UARTDevice, public Component {
|
|||||||
|
|
||||||
// Pre-allocated message - always ready to send
|
// Pre-allocated message - always ready to send
|
||||||
api::ZWaveProxyFrame outgoing_proto_msg_;
|
api::ZWaveProxyFrame outgoing_proto_msg_;
|
||||||
std::array<uint8_t, sizeof(api::ZWaveProxyFrame::data)> buffer_; // Fixed buffer for incoming data
|
std::array<uint8_t, MAX_ZWAVE_FRAME_SIZE> buffer_; // Fixed buffer for incoming data
|
||||||
std::array<uint8_t, 4> home_id_{0, 0, 0, 0}; // Fixed buffer for home ID
|
std::array<uint8_t, 4> home_id_{0, 0, 0, 0}; // Fixed buffer for home ID
|
||||||
|
|
||||||
// Pointers and 32-bit values (aligned together)
|
// Pointers and 32-bit values (aligned together)
|
||||||
|
Reference in New Issue
Block a user