From c40f44f4bdd4fe559925407d22712b93636dc4b8 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 9 Jan 2026 04:06:03 -0600 Subject: [PATCH] [remote_base] Add zero-copy packed sint32 decoder for #12985 (#13093) --- .../components/remote_base/remote_base.cpp | 33 +++++++++++++++++++ esphome/components/remote_base/remote_base.h | 5 +++ 2 files changed, 38 insertions(+) diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 34aba236b3..2f1c107bf4 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -128,6 +128,39 @@ void RemoteReceiverBase::call_dumpers_() { void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); } +/* RemoteTransmitData */ + +void RemoteTransmitData::set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count) { + this->data_.clear(); + this->data_.reserve(count); + + while (len > 0) { + // Parse varint (inline, no dependency on api component) + uint32_t raw = 0; + uint32_t shift = 0; + uint32_t consumed = 0; + for (; consumed < len && consumed < 5; consumed++) { + uint8_t byte = data[consumed]; + raw |= (byte & 0x7F) << shift; + if ((byte & 0x80) == 0) { + consumed++; + break; + } + shift += 7; + } + if (consumed == 0) + break; // Parse error + + // Zigzag decode: (n >> 1) ^ -(n & 1) + int32_t decoded = static_cast((raw >> 1) ^ (~(raw & 1) + 1)); + this->data_.push_back(decoded); + data += consumed; + len -= consumed; + } +} + +/* RemoteTransmitterBase */ + void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) { #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE const auto &vec = this->temp_.get_data(); diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index 2cb79bf571..a11e0271af 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -31,6 +31,11 @@ class RemoteTransmitData { uint32_t get_carrier_frequency() const { return this->carrier_frequency_; } const RawTimings &get_data() const { return this->data_; } void set_data(const RawTimings &data) { this->data_ = data; } + /// Set data from packed protobuf sint32 buffer (zigzag + varint encoded) + /// @param data Pointer to packed zigzag-varint-encoded sint32 values + /// @param len Length of the buffer in bytes + /// @param count Number of values (for reserve optimization) + void set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count); void reset() { this->data_.clear(); this->carrier_frequency_ = 0;