ESPHome 2026.1.1
Loading...
Searching...
No Matches
remote_base.cpp
Go to the documentation of this file.
1#include "remote_base.h"
2#include "esphome/core/log.h"
3
4#include <cinttypes>
5
6namespace esphome {
7namespace remote_base {
8
9static const char *const TAG = "remote_base";
10
11/* RemoteReceiveData */
12
13bool RemoteReceiveData::peek_mark(uint32_t length, uint32_t offset) const {
14 if (!this->is_valid(offset))
15 return false;
16 const int32_t value = this->peek(offset);
17 const int32_t lo = this->lower_bound_(length);
18 const int32_t hi = this->upper_bound_(length);
19 return value >= 0 && lo <= value && value <= hi;
20}
21
22bool RemoteReceiveData::peek_mark_at_least(uint32_t length, uint32_t offset) const {
23 if (!this->is_valid(offset))
24 return false;
25 const int32_t value = this->peek(offset);
26 const int32_t lo = this->lower_bound_(length);
27 return value >= 0 && lo <= value;
28}
29
30bool RemoteReceiveData::peek_mark_at_most(uint32_t length, uint32_t offset) const {
31 if (!this->is_valid(offset))
32 return false;
33 const int32_t value = this->peek(offset);
34 const int32_t hi = this->upper_bound_(length);
35 return value >= 0 && value <= hi;
36}
37
38bool RemoteReceiveData::peek_space(uint32_t length, uint32_t offset) const {
39 if (!this->is_valid(offset))
40 return false;
41 const int32_t value = this->peek(offset);
42 const int32_t lo = this->lower_bound_(length);
43 const int32_t hi = this->upper_bound_(length);
44 return value <= 0 && lo <= -value && -value <= hi;
45}
46
47bool RemoteReceiveData::peek_space_at_least(uint32_t length, uint32_t offset) const {
48 if (!this->is_valid(offset))
49 return false;
50 const int32_t value = this->peek(offset);
51 const int32_t lo = this->lower_bound_(length);
52 return value <= 0 && lo <= -value;
53}
54
55bool RemoteReceiveData::peek_space_at_most(uint32_t length, uint32_t offset) const {
56 if (!this->is_valid(offset))
57 return false;
58 const int32_t value = this->peek(offset);
59 const int32_t hi = this->upper_bound_(length);
60 return value <= 0 && -value <= hi;
61}
62
64 if (!this->peek_mark(length))
65 return false;
66 this->advance();
67 return true;
68}
69
71 if (!this->peek_space(length))
72 return false;
73 this->advance();
74 return true;
75}
76
77bool RemoteReceiveData::expect_item(uint32_t mark, uint32_t space) {
78 if (!this->peek_item(mark, space))
79 return false;
80 this->advance(2);
81 return true;
82}
83
84bool RemoteReceiveData::expect_pulse_with_gap(uint32_t mark, uint32_t space) {
85 if (!this->peek_space_at_least(space, 1) || !this->peek_mark(mark))
86 return false;
87 this->advance(2);
88 return true;
89}
90
91/* RemoteReceiverBinarySensorBase */
92
94 if (!this->matches(src))
95 return false;
96 this->publish_state(true);
97 yield();
98 this->publish_state(false);
99 return true;
100}
101
102/* RemoteReceiverBase */
103
105 if (dumper->is_secondary()) {
106 this->secondary_dumpers_.push_back(dumper);
107 } else {
108 this->dumpers_.push_back(dumper);
109 }
110}
111
113 for (auto *listener : this->listeners_)
114 listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
115}
116
118 bool success = false;
119 for (auto *dumper : this->dumpers_) {
120 if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)))
121 success = true;
122 }
123 if (!success) {
124 for (auto *dumper : this->secondary_dumpers_)
125 dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
126 }
127}
128
129void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); }
130
131/* RemoteTransmitData */
132
133void RemoteTransmitData::set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count) {
134 this->data_.clear();
135 this->data_.reserve(count);
136
137 while (len > 0) {
138 // Parse varint (inline, no dependency on api component)
139 uint32_t raw = 0;
140 uint32_t shift = 0;
141 uint32_t consumed = 0;
142 for (; consumed < len && consumed < 5; consumed++) {
143 uint8_t byte = data[consumed];
144 raw |= (byte & 0x7F) << shift;
145 if ((byte & 0x80) == 0) {
146 consumed++;
147 break;
148 }
149 shift += 7;
150 }
151 if (consumed == 0)
152 break; // Parse error
153
154 // Zigzag decode: (n >> 1) ^ -(n & 1)
155 int32_t decoded = static_cast<int32_t>((raw >> 1) ^ (~(raw & 1) + 1));
156 this->data_.push_back(decoded);
157 data += consumed;
158 len -= consumed;
159 }
160}
161
162/* RemoteTransmitterBase */
163
164void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) {
165#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
166 const auto &vec = this->temp_.get_data();
167 char buffer[256];
168 uint32_t buffer_offset = 0;
169 buffer_offset += sprintf(buffer, "Sending times=%" PRIu32 " wait=%" PRIu32 "ms: ", send_times, send_wait);
170
171 for (size_t i = 0; i < vec.size(); i++) {
172 const int32_t value = vec[i];
173 const uint32_t remaining_length = sizeof(buffer) - buffer_offset;
174 int written;
175
176 if (i + 1 < vec.size()) {
177 written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32 ", ", value);
178 } else {
179 written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32, value);
180 }
181
182 if (written < 0 || written >= int(remaining_length)) {
183 // write failed, flush...
184 buffer[buffer_offset] = '\0';
185 ESP_LOGVV(TAG, "%s", buffer);
186 buffer_offset = 0;
187 written = sprintf(buffer, " ");
188 if (i + 1 < vec.size()) {
189 written += sprintf(buffer + written, "%" PRId32 ", ", value);
190 } else {
191 written += sprintf(buffer + written, "%" PRId32, value);
192 }
193 }
194
195 buffer_offset += written;
196 }
197 if (buffer_offset != 0) {
198 ESP_LOGVV(TAG, "%s", buffer);
199 }
200#endif
201 this->send_internal(send_times, send_wait);
202}
203} // namespace remote_base
204} // 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:59
bool peek_item(uint32_t mark, uint32_t space, uint32_t offset=0) const
Definition remote_base.h:66
int32_t upper_bound_(uint32_t length) const
Definition remote_base.h:93
bool is_valid(uint32_t offset=0) const
Definition remote_base.h:58
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:85
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
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
std::string size_t len
Definition helpers.h:595
void IRAM_ATTR HOT yield()
Definition core.cpp:24
uint16_t length
Definition tt21100.cpp:0