ESPHome 2026.11.0-dev
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::remote_base {
6
7ESPHOME_LOG_TAG(TAG, "remote_base");
8
9/* RemoteReceiveData */
10
12 if (!this->is_valid(offset))
13 return false;
14 const int32_t value = this->peek(offset);
15 const int32_t lo = this->lower_bound_(length);
16 const int32_t hi = this->upper_bound_(length);
17 return value >= 0 && lo <= value && value <= hi;
18}
19
21 if (!this->is_valid(offset))
22 return false;
23 const int32_t value = this->peek(offset);
24 const int32_t lo = this->lower_bound_(length);
25 return value >= 0 && lo <= value;
26}
27
29 if (!this->is_valid(offset))
30 return false;
31 const int32_t value = this->peek(offset);
32 const int32_t hi = this->upper_bound_(length);
33 return value >= 0 && value <= hi;
34}
35
37 if (!this->is_valid(offset))
38 return false;
39 const int32_t value = this->peek(offset);
40 const int32_t lo = this->lower_bound_(length);
41 const int32_t hi = this->upper_bound_(length);
42 return value <= 0 && lo <= -value && -value <= hi;
43}
44
46 if (!this->is_valid(offset))
47 return false;
48 const int32_t value = this->peek(offset);
49 const int32_t lo = this->lower_bound_(length);
50 return value <= 0 && lo <= -value;
51}
52
54 if (!this->is_valid(offset))
55 return false;
56 const int32_t value = this->peek(offset);
57 const int32_t hi = this->upper_bound_(length);
58 return value <= 0 && -value <= hi;
59}
60
62 if (!this->peek_mark(length))
63 return false;
64 this->advance();
65 return true;
66}
67
69 if (!this->peek_space(length))
70 return false;
71 this->advance();
72 return true;
73}
74
76 if (!this->peek_item(mark, space))
77 return false;
78 this->advance(2);
79 return true;
80}
81
83 if (!this->peek_space_at_least(space, 1) || !this->peek_mark(mark))
84 return false;
85 this->advance(2);
86 return true;
87}
88
89/* RemoteReceiverBinarySensorBase */
90
92 if (!this->matches(src))
93 return false;
94 this->publish_state(true);
95 yield();
96 this->publish_state(false);
97 return true;
98}
99
100/* RemoteReceiverBase */
101
102// Slots are counted at code generation; a registration from C++ setup() has none
103#ifdef REMOTE_BASE_LISTENER_COUNT
105 if (this->listeners_.size() == REMOTE_BASE_LISTENER_COUNT) {
106 ESP_LOGE(TAG, "No %s slot: register it from to_code() with remote_base.add_%s", LOG_STR_LITERAL("listener"),
107 LOG_STR_LITERAL("listener"));
108 return;
109 }
110 this->listeners_.push_back(listener);
111}
112#endif
113
114#ifdef REMOTE_BASE_DUMPER_COUNT
116 if (dumper->is_secondary()) {
117 if (this->secondary_dumper_ == nullptr) {
118 this->secondary_dumper_ = dumper;
119 return;
120 }
121 } else if (this->dumpers_.size() != REMOTE_BASE_DUMPER_COUNT) {
122 this->dumpers_.push_back(dumper);
123 return;
124 }
125 ESP_LOGE(TAG, "No %s slot: register it from to_code() with remote_base.add_%s", LOG_STR_LITERAL("dumper"),
126 LOG_STR_LITERAL("dumper"));
127}
128#endif
129
131#ifdef REMOTE_BASE_LISTENER_COUNT
132 for (auto *listener : this->listeners_)
133 listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
134#endif
135#ifdef REMOTE_BASE_DUMPER_COUNT
136 bool success = false;
137 for (auto *dumper : this->dumpers_) {
138 if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)))
139 success = true;
140 }
141 if (!success && this->secondary_dumper_ != nullptr)
143#endif
144}
145
146void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); }
147
148/* RemoteTransmitData */
149
150void RemoteTransmitData::set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count) {
151 this->data_.clear();
152 this->data_.reserve(count);
153
154 while (len > 0) {
155 // Parse varint (inline, no dependency on api component)
156 uint32_t raw = 0;
157 uint32_t shift = 0;
158 uint32_t consumed = 0;
159 for (; consumed < len && consumed < 5; consumed++) {
160 uint8_t byte = data[consumed];
161 raw |= (byte & 0x7F) << shift;
162 if ((byte & 0x80) == 0) {
163 consumed++;
164 break;
165 }
166 shift += 7;
167 }
168 if (consumed == 0)
169 break; // Parse error
170
171 // Zigzag decode: (n >> 1) ^ -(n & 1)
172 int32_t decoded = static_cast<int32_t>((raw >> 1) ^ (~(raw & 1) + 1));
173 this->data_.push_back(decoded);
174 data += consumed;
175 len -= consumed;
176 }
177}
178
179bool RemoteTransmitData::set_data_from_base64url(const std::string &base64url) {
180 return base64_decode_int32_vector(base64url, this->data_);
181}
182
183/* RemoteTransmitterBase */
184
189
190void RemoteTransmitterBase::transmit_encoded_(EncodeFn encode, const void *data, uint32_t send_times,
191 uint32_t send_wait) {
192 auto call = this->transmit();
193 encode(call.get_data(), data);
194 call.set_send_times(send_times);
195 call.set_send_wait(send_wait);
196 call.perform();
197}
198
199void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait, [[maybe_unused]] uint16_t seq) {
200#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
201 const auto &vec = this->temp_.get_data();
202 char buffer[256];
203 size_t pos = buf_append_printf(buffer, sizeof(buffer), 0,
204 "Sending times=%" PRIu32 " wait=%" PRIu32 "ms: ", send_times, send_wait);
205
206 for (size_t i = 0; i < vec.size(); i++) {
207 const int32_t value = vec[i];
208 size_t prev_pos = pos;
209
210 if (i + 1 < vec.size()) {
211 pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32 ", ", value);
212 } else {
213 pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32, value);
214 }
215
216 if (pos >= sizeof(buffer) - 1) {
217 // buffer full, flush and continue
218 buffer[prev_pos] = '\0';
219 ESP_LOGVV(TAG, "%s", buffer);
220 if (i + 1 < vec.size()) {
221 pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32 ", ", value);
222 } else {
223 pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32, value);
224 }
225 }
226 }
227 if (pos != 0) {
228 ESP_LOGVV(TAG, "%s", buffer);
229 }
230#endif
232#ifdef USE_IR_RF_TRANSMIT_COMPLETE
233 this->current_seq_ = seq;
234#endif
235 this->send_internal(send_times, send_wait);
236}
237} // namespace esphome::remote_base
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:98
bool peek_item(uint32_t mark, uint32_t space, uint32_t offset=0) const
int32_t upper_bound_(uint32_t length) const
bool is_valid(uint32_t offset=0) const
Definition remote_base.h:97
bool peek_space_at_least(uint32_t length, uint32_t offset=0) const
int32_t lower_bound_(uint32_t length) const
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
void register_dumper(RemoteReceiverDumperBase *dumper)
StaticVector< RemoteReceiverDumperBase *, REMOTE_BASE_DUMPER_COUNT > dumpers_
void register_listener(RemoteReceiverListener *listener)
RemoteReceiverDumperBase * secondary_dumper_
StaticVector< RemoteReceiverListener *, REMOTE_BASE_LISTENER_COUNT > listeners_
virtual bool matches(RemoteReceiveData src)=0
bool on_receive(RemoteReceiveData src) override
virtual bool dump(RemoteReceiveData src)=0
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:66
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, uint16_t seq)
void(*)(RemoteTransmitData *dst, const void *data) EncodeFn
virtual void send_internal(uint32_t send_times, uint32_t send_wait)=0
void transmit_encoded_(EncodeFn encode, const void *data, uint32_t send_times, uint32_t send_wait)
RemoteTransmitData temp_
Use same vector for all transmits, avoids many allocations.
virtual void flush_pending_completion()
Platforms that report completion later wait out the previous frame here, before send_() assigns the n...
void yield(void)
unsigned count
Definition gif.cpp:51
uint32_t buffer
Definition gif.cpp:50
ESPHOME_LOG_TAG(TAG, "remote.abbwelcome")
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:732
const void size_t len
Definition hal.h:68
size_t size_t pos
Definition helpers.h:1255
const void * src
Definition hal.h:68
static void uint32_t
uint16_t seq
uint16_t length
Definition tt21100.cpp:0