ESPHome 2026.6.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
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
103 if (dumper->is_secondary()) {
104 this->secondary_dumpers_.push_back(dumper);
105 } else {
106 this->dumpers_.push_back(dumper);
107 }
108}
109
111 for (auto *listener : this->listeners_)
112 listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
113}
114
116 bool success = false;
117 for (auto *dumper : this->dumpers_) {
118 if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)))
119 success = true;
120 }
121 if (!success) {
122 for (auto *dumper : this->secondary_dumpers_)
123 dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
124 }
125}
126
127void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); }
128
129/* RemoteTransmitData */
130
131void RemoteTransmitData::set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count) {
132 this->data_.clear();
133 this->data_.reserve(count);
134
135 while (len > 0) {
136 // Parse varint (inline, no dependency on api component)
137 uint32_t raw = 0;
138 uint32_t shift = 0;
139 uint32_t consumed = 0;
140 for (; consumed < len && consumed < 5; consumed++) {
141 uint8_t byte = data[consumed];
142 raw |= (byte & 0x7F) << shift;
143 if ((byte & 0x80) == 0) {
144 consumed++;
145 break;
146 }
147 shift += 7;
148 }
149 if (consumed == 0)
150 break; // Parse error
151
152 // Zigzag decode: (n >> 1) ^ -(n & 1)
153 int32_t decoded = static_cast<int32_t>((raw >> 1) ^ (~(raw & 1) + 1));
154 this->data_.push_back(decoded);
155 data += consumed;
156 len -= consumed;
157 }
158}
159
160bool RemoteTransmitData::set_data_from_base64url(const std::string &base64url) {
161 return base64_decode_int32_vector(base64url, this->data_);
162}
163
164/* RemoteTransmitterBase */
165
166void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) {
167#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
168 const auto &vec = this->temp_.get_data();
169 char buffer[256];
170 size_t pos = buf_append_printf(buffer, sizeof(buffer), 0,
171 "Sending times=%" PRIu32 " wait=%" PRIu32 "ms: ", send_times, send_wait);
172
173 for (size_t i = 0; i < vec.size(); i++) {
174 const int32_t value = vec[i];
175 size_t prev_pos = pos;
176
177 if (i + 1 < vec.size()) {
178 pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32 ", ", value);
179 } else {
180 pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32, value);
181 }
182
183 if (pos >= sizeof(buffer) - 1) {
184 // buffer full, flush and continue
185 buffer[prev_pos] = '\0';
186 ESP_LOGVV(TAG, "%s", buffer);
187 if (i + 1 < vec.size()) {
188 pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32 ", ", value);
189 } else {
190 pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32, value);
191 }
192 }
193 }
194 if (pos != 0) {
195 ESP_LOGVV(TAG, "%s", buffer);
196 }
197#endif
198 this->send_internal(send_times, send_wait);
199}
200} // 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:63
bool peek_item(uint32_t mark, uint32_t space, uint32_t offset=0) const
Definition remote_base.h:70
int32_t upper_bound_(uint32_t length) const
Definition remote_base.h:97
bool is_valid(uint32_t offset=0) const
Definition remote_base.h:62
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:89
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:31
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.
void yield(void)
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:609
const void size_t len
Definition hal.h:64
size_t size_t pos
Definition helpers.h:1038
const void * src
Definition hal.h:64
static void uint32_t
uint16_t length
Definition tt21100.cpp:0