ESPHome 2026.10.0
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
7static const char *const 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
185void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait, [[maybe_unused]] uint16_t seq) {
186#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
187 const auto &vec = this->temp_.get_data();
188 char buffer[256];
189 size_t pos = buf_append_printf(buffer, sizeof(buffer), 0,
190 "Sending times=%" PRIu32 " wait=%" PRIu32 "ms: ", send_times, send_wait);
191
192 for (size_t i = 0; i < vec.size(); i++) {
193 const int32_t value = vec[i];
194 size_t prev_pos = pos;
195
196 if (i + 1 < vec.size()) {
197 pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32 ", ", value);
198 } else {
199 pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32, value);
200 }
201
202 if (pos >= sizeof(buffer) - 1) {
203 // buffer full, flush and continue
204 buffer[prev_pos] = '\0';
205 ESP_LOGVV(TAG, "%s", buffer);
206 if (i + 1 < vec.size()) {
207 pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32 ", ", value);
208 } else {
209 pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32, value);
210 }
211 }
212 }
213 if (pos != 0) {
214 ESP_LOGVV(TAG, "%s", buffer);
215 }
216#endif
218#ifdef USE_IR_RF_TRANSMIT_COMPLETE
219 this->current_seq_ = seq;
220#endif
221 this->send_internal(send_times, send_wait);
222}
223} // 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:65
bool peek_item(uint32_t mark, uint32_t space, uint32_t offset=0) const
Definition remote_base.h:72
int32_t upper_bound_(uint32_t length) const
Definition remote_base.h:99
bool is_valid(uint32_t offset=0) const
Definition remote_base.h:64
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:91
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:33
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)
virtual void send_internal(uint32_t send_times, uint32_t send_wait)=0
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
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:677
const void size_t len
Definition hal.h:64
size_t size_t pos
Definition helpers.h:1186
const void * src
Definition hal.h:64
static void uint32_t
uint16_t seq
uint16_t length
Definition tt21100.cpp:0