ESPHome 2026.2.3
Loading...
Searching...
No Matches
remote_base.cpp
Go to the documentation of this file.
1#include "remote_base.h"
3#include "esphome/core/log.h"
4
5namespace esphome {
6namespace remote_base {
7
8static const char *const TAG = "remote_base";
9
10/* RemoteReceiveData */
11
12bool RemoteReceiveData::peek_mark(uint32_t length, uint32_t offset) const {
13 if (!this->is_valid(offset))
14 return false;
15 const int32_t value = this->peek(offset);
16 const int32_t lo = this->lower_bound_(length);
17 const int32_t hi = this->upper_bound_(length);
18 return value >= 0 && lo <= value && value <= hi;
19}
20
21bool RemoteReceiveData::peek_mark_at_least(uint32_t length, uint32_t offset) const {
22 if (!this->is_valid(offset))
23 return false;
24 const int32_t value = this->peek(offset);
25 const int32_t lo = this->lower_bound_(length);
26 return value >= 0 && lo <= value;
27}
28
29bool RemoteReceiveData::peek_mark_at_most(uint32_t length, uint32_t offset) const {
30 if (!this->is_valid(offset))
31 return false;
32 const int32_t value = this->peek(offset);
33 const int32_t hi = this->upper_bound_(length);
34 return value >= 0 && value <= hi;
35}
36
37bool RemoteReceiveData::peek_space(uint32_t length, uint32_t offset) const {
38 if (!this->is_valid(offset))
39 return false;
40 const int32_t value = this->peek(offset);
41 const int32_t lo = this->lower_bound_(length);
42 const int32_t hi = this->upper_bound_(length);
43 return value <= 0 && lo <= -value && -value <= hi;
44}
45
46bool RemoteReceiveData::peek_space_at_least(uint32_t length, uint32_t offset) const {
47 if (!this->is_valid(offset))
48 return false;
49 const int32_t value = this->peek(offset);
50 const int32_t lo = this->lower_bound_(length);
51 return value <= 0 && lo <= -value;
52}
53
54bool RemoteReceiveData::peek_space_at_most(uint32_t length, uint32_t offset) const {
55 if (!this->is_valid(offset))
56 return false;
57 const int32_t value = this->peek(offset);
58 const int32_t hi = this->upper_bound_(length);
59 return value <= 0 && -value <= hi;
60}
61
63 if (!this->peek_mark(length))
64 return false;
65 this->advance();
66 return true;
67}
68
70 if (!this->peek_space(length))
71 return false;
72 this->advance();
73 return true;
74}
75
76bool RemoteReceiveData::expect_item(uint32_t mark, uint32_t space) {
77 if (!this->peek_item(mark, space))
78 return false;
79 this->advance(2);
80 return true;
81}
82
83bool RemoteReceiveData::expect_pulse_with_gap(uint32_t mark, uint32_t space) {
84 if (!this->peek_space_at_least(space, 1) || !this->peek_mark(mark))
85 return false;
86 this->advance(2);
87 return true;
88}
89
90/* RemoteReceiverBinarySensorBase */
91
93 if (!this->matches(src))
94 return false;
95 this->publish_state(true);
96 yield();
97 this->publish_state(false);
98 return true;
99}
100
101/* RemoteReceiverBase */
102
104 if (dumper->is_secondary()) {
105 this->secondary_dumpers_.push_back(dumper);
106 } else {
107 this->dumpers_.push_back(dumper);
108 }
109}
110
112 for (auto *listener : this->listeners_)
113 listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
114}
115
117 bool success = false;
118 for (auto *dumper : this->dumpers_) {
119 if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)))
120 success = true;
121 }
122 if (!success) {
123 for (auto *dumper : this->secondary_dumpers_)
124 dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
125 }
126}
127
128void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); }
129
130/* RemoteTransmitData */
131
132void RemoteTransmitData::set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count) {
133 this->data_.clear();
134 this->data_.reserve(count);
135
136 while (len > 0) {
137 // Parse varint (inline, no dependency on api component)
138 uint32_t raw = 0;
139 uint32_t shift = 0;
140 uint32_t consumed = 0;
141 for (; consumed < len && consumed < 5; consumed++) {
142 uint8_t byte = data[consumed];
143 raw |= (byte & 0x7F) << shift;
144 if ((byte & 0x80) == 0) {
145 consumed++;
146 break;
147 }
148 shift += 7;
149 }
150 if (consumed == 0)
151 break; // Parse error
152
153 // Zigzag decode: (n >> 1) ^ -(n & 1)
154 int32_t decoded = static_cast<int32_t>((raw >> 1) ^ (~(raw & 1) + 1));
155 this->data_.push_back(decoded);
156 data += consumed;
157 len -= consumed;
158 }
159}
160
161bool RemoteTransmitData::set_data_from_base64url(const std::string &base64url) {
162 return base64_decode_int32_vector(base64url, this->data_);
163}
164
165/* RemoteTransmitterBase */
166
167void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) {
168#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
169 const auto &vec = this->temp_.get_data();
170 char buffer[256];
171 size_t pos = buf_append_printf(buffer, sizeof(buffer), 0,
172 "Sending times=%" PRIu32 " wait=%" PRIu32 "ms: ", send_times, send_wait);
173
174 for (size_t i = 0; i < vec.size(); i++) {
175 const int32_t value = vec[i];
176 size_t prev_pos = pos;
177
178 if (i + 1 < vec.size()) {
179 pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32 ", ", value);
180 } else {
181 pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32, value);
182 }
183
184 if (pos >= sizeof(buffer) - 1) {
185 // buffer full, flush and continue
186 buffer[prev_pos] = '\0';
187 ESP_LOGVV(TAG, "%s", buffer);
188 if (i + 1 < vec.size()) {
189 pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32 ", ", value);
190 } else {
191 pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32, value);
192 }
193 }
194 }
195 if (pos != 0) {
196 ESP_LOGVV(TAG, "%s", buffer);
197 }
198#endif
199 this->send_internal(send_times, send_wait);
200}
201} // namespace remote_base
202} // namespace esphome
uint8_t raw[35]
Definition bl0939.h:0
void publish_state(bool new_state)
Publish a new state to the front-end.
bool peek_mark_at_most(uint32_t length, uint32_t offset=0) const
bool expect_item(uint32_t mark, uint32_t space)
bool peek_space(uint32_t length, uint32_t offset=0) const
bool peek_space_at_most(uint32_t length, uint32_t offset=0) const
int32_t peek(uint32_t offset=0) const
Definition remote_base.h:64
bool peek_item(uint32_t mark, uint32_t space, uint32_t offset=0) const
Definition remote_base.h:71
int32_t upper_bound_(uint32_t length) const
Definition remote_base.h:98
bool is_valid(uint32_t offset=0) const
Definition remote_base.h:63
bool peek_space_at_least(uint32_t length, uint32_t offset=0) const
int32_t lower_bound_(uint32_t length) const
Definition remote_base.h:90
bool peek_mark(uint32_t length, uint32_t offset=0) const
bool expect_pulse_with_gap(uint32_t mark, uint32_t space)
bool peek_mark_at_least(uint32_t length, uint32_t offset=0) const
std::vector< RemoteReceiverDumperBase * > dumpers_
std::vector< RemoteReceiverListener * > listeners_
void register_dumper(RemoteReceiverDumperBase *dumper)
std::vector< RemoteReceiverDumperBase * > secondary_dumpers_
virtual bool matches(RemoteReceiveData src)=0
bool on_receive(RemoteReceiveData src) override
bool set_data_from_base64url(const std::string &base64url)
Set data from base64url-encoded little-endian int32 values Base64url is URL-safe: uses '-' instead of...
const RawTimings & get_data() const
Definition remote_base.h:32
void set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count)
Set data from packed protobuf sint32 buffer (zigzag + varint encoded)
void send_(uint32_t send_times, uint32_t send_wait)
virtual void send_internal(uint32_t send_times, uint32_t send_wait)=0
RemoteTransmitData temp_
Use same vector for all transmits, avoids many allocations.
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
bool base64_decode_int32_vector(const std::string &base64, std::vector< int32_t > &out)
Decode base64/base64url string directly into vector of little-endian int32 values.
Definition helpers.cpp:666
std::string size_t len
Definition helpers.h:692
void IRAM_ATTR HOT yield()
Definition core.cpp:24
size_t size_t pos
Definition helpers.h:729
uint16_t length
Definition tt21100.cpp:0