mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00: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 (no_delay) = true; | ||||
|  | ||||
|   bytes data = 1 [(fixed_array_size) = 257]; | ||||
|   bytes data = 1 [(pointer_to_buffer) = true]; | ||||
| } | ||||
|  | ||||
| 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) { | ||||
|   switch (field_id) { | ||||
|     case 1: { | ||||
|       const std::string &data_str = value.as_string(); | ||||
|       this->data_len = data_str.size(); | ||||
|       if (this->data_len > 257) { | ||||
|         this->data_len = 257; | ||||
|       } | ||||
|       memcpy(this->data, data_str.data(), this->data_len); | ||||
|       // Use raw data directly to avoid allocation | ||||
|       this->data = value.data(); | ||||
|       this->data_len = value.size(); | ||||
|       break; | ||||
|     } | ||||
|     default: | ||||
|   | ||||
| @@ -2931,11 +2931,11 @@ class UpdateCommandRequest final : public CommandProtoMessage { | ||||
| class ZWaveProxyFrame final : public ProtoDecodableMessage { | ||||
|  public: | ||||
|   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 | ||||
|   const char *message_name() const override { return "z_wave_proxy_frame"; } | ||||
| #endif | ||||
|   uint8_t data[257]{}; | ||||
|   const uint8_t *data{nullptr}; | ||||
|   uint16_t data_len{0}; | ||||
|   void encode(ProtoWriteBuffer buffer) 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)); | ||||
|       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_) { | ||||
|           this->outgoing_proto_msg_.data_len = this->buffer_index_; | ||||
|         } else { | ||||
|           // 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; | ||||
|         } | ||||
|         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); | ||||
|       } | ||||
|     } | ||||
| @@ -272,7 +272,9 @@ void ZWaveProxy::parse_start_(uint8_t byte) { | ||||
|   } | ||||
|   // Forward response (ACK/NAK/CAN) back to client for processing | ||||
|   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->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE); | ||||
|   } | ||||
|   | ||||
| @@ -11,6 +11,8 @@ | ||||
| namespace esphome { | ||||
| namespace zwave_proxy { | ||||
|  | ||||
| static constexpr size_t MAX_ZWAVE_FRAME_SIZE = 257;  // Maximum Z-Wave frame size | ||||
|  | ||||
| enum ZWaveResponseTypes : uint8_t { | ||||
|   ZWAVE_FRAME_TYPE_ACK = 0x06, | ||||
|   ZWAVE_FRAME_TYPE_CAN = 0x18, | ||||
| @@ -66,8 +68,8 @@ class ZWaveProxy : public uart::UARTDevice, public Component { | ||||
|  | ||||
|   // Pre-allocated message - always ready to send | ||||
|   api::ZWaveProxyFrame outgoing_proto_msg_; | ||||
|   std::array<uint8_t, sizeof(api::ZWaveProxyFrame::data)> 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, 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 | ||||
|  | ||||
|   // Pointers and 32-bit values (aligned together) | ||||
|   api::APIConnection *api_connection_{nullptr};  // Current subscribed client | ||||
|   | ||||
		Reference in New Issue
	
	Block a user