ESPHome 2026.1.3
Loading...
Searching...
No Matches
remote_base.h
Go to the documentation of this file.
1#include <utility>
2#include <vector>
3
4#pragma once
5
9#include "esphome/core/hal.h"
10
11namespace esphome {
12namespace remote_base {
13
18
19using RawTimings = std::vector<int32_t>;
20
22 public:
23 void mark(uint32_t length) { this->data_.push_back(length); }
24 void space(uint32_t length) { this->data_.push_back(-length); }
25 void item(uint32_t mark, uint32_t space) {
26 this->mark(mark);
27 this->space(space);
28 }
29 void reserve(uint32_t len) { this->data_.reserve(len); }
30 void set_carrier_frequency(uint32_t carrier_frequency) { this->carrier_frequency_ = carrier_frequency; }
31 uint32_t get_carrier_frequency() const { return this->carrier_frequency_; }
32 const RawTimings &get_data() const { return this->data_; }
33 void set_data(const RawTimings &data) { this->data_ = data; }
38 void set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count);
39 void reset() {
40 this->data_.clear();
41 this->carrier_frequency_ = 0;
42 }
43
44 protected:
46 uint32_t carrier_frequency_{0};
47};
48
50 public:
51 explicit RemoteReceiveData(const RawTimings &data, uint32_t tolerance, ToleranceMode tolerance_mode)
52 : data_(data), index_(0), tolerance_(tolerance), tolerance_mode_(tolerance_mode) {}
53
54 const RawTimings &get_raw_data() const { return this->data_; }
55 uint32_t get_index() const { return index_; }
56 int32_t operator[](uint32_t index) const { return this->data_[index]; }
57 int32_t size() const { return this->data_.size(); }
58 bool is_valid(uint32_t offset = 0) const { return this->index_ + offset < this->data_.size(); }
59 int32_t peek(uint32_t offset = 0) const { return this->data_[this->index_ + offset]; }
60 bool peek_mark(uint32_t length, uint32_t offset = 0) const;
61 bool peek_mark_at_least(uint32_t length, uint32_t offset = 0) const;
62 bool peek_mark_at_most(uint32_t length, uint32_t offset = 0) const;
63 bool peek_space(uint32_t length, uint32_t offset = 0) const;
64 bool peek_space_at_least(uint32_t length, uint32_t offset = 0) const;
65 bool peek_space_at_most(uint32_t length, uint32_t offset = 0) const;
66 bool peek_item(uint32_t mark, uint32_t space, uint32_t offset = 0) const {
67 return this->peek_space(space, offset + 1) && this->peek_mark(mark, offset);
68 }
69
70 bool expect_mark(uint32_t length);
71 bool expect_space(uint32_t length);
72 bool expect_item(uint32_t mark, uint32_t space);
73 bool expect_pulse_with_gap(uint32_t mark, uint32_t space);
74 void advance(uint32_t amount = 1) { this->index_ += amount; }
75 void reset() { this->index_ = 0; }
76
77 void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode) {
78 this->tolerance_ = tolerance;
79 this->tolerance_mode_ = tolerance_mode;
80 }
81 uint32_t get_tolerance() { return tolerance_; }
83
84 protected:
85 int32_t lower_bound_(uint32_t length) const {
87 return int32_t(length - this->tolerance_);
88 } else if (this->tolerance_mode_ == TOLERANCE_MODE_PERCENTAGE) {
89 return int32_t(100 - this->tolerance_) * length / 100U;
90 }
91 return 0;
92 }
93 int32_t upper_bound_(uint32_t length) const {
95 return int32_t(length + this->tolerance_);
96 } else if (this->tolerance_mode_ == TOLERANCE_MODE_PERCENTAGE) {
97 return int32_t(100 + this->tolerance_) * length / 100U;
98 }
99 return 0;
100 }
101
103 uint32_t index_;
104 uint32_t tolerance_;
106};
107
109 public:
110 explicit RemoteComponentBase(InternalGPIOPin *pin) : pin_(pin){};
111
112 protected:
114};
115
116#ifdef USE_ESP32
118 public:
119 void set_clock_resolution(uint32_t clock_resolution) { this->clock_resolution_ = clock_resolution; }
120 void set_rmt_symbols(uint32_t rmt_symbols) { this->rmt_symbols_ = rmt_symbols; }
121
122 protected:
123 uint32_t from_microseconds_(uint32_t us) {
124 const uint32_t ticks_per_ten_us = this->clock_resolution_ / 100000u;
125 return us * ticks_per_ten_us / 10;
126 }
127 uint32_t to_microseconds_(uint32_t ticks) {
128 const uint32_t ticks_per_ten_us = this->clock_resolution_ / 100000u;
129 return (ticks * 10) / ticks_per_ten_us;
130 }
132 uint32_t clock_resolution_{1000000};
133 uint32_t rmt_symbols_;
134};
135#endif
136
138 public:
141 public:
142 explicit TransmitCall(RemoteTransmitterBase *parent) : parent_(parent) {}
144 void set_send_times(uint32_t send_times) { send_times_ = send_times; }
145 void set_send_wait(uint32_t send_wait) { send_wait_ = send_wait; }
146 void perform() { this->parent_->send_(this->send_times_, this->send_wait_); }
147
148 protected:
150 uint32_t send_times_{1};
151 uint32_t send_wait_{0};
152 };
153
155 this->temp_.reset();
156 return TransmitCall(this);
157 }
158 template<typename Protocol>
159 void transmit(const typename Protocol::ProtocolData &data, uint32_t send_times = 1, uint32_t send_wait = 0) {
160 auto call = this->transmit();
161 Protocol().encode(call.get_data(), data);
162 call.set_send_times(send_times);
163 call.set_send_wait(send_wait);
164 call.perform();
165 }
166
167 protected:
168 void send_(uint32_t send_times, uint32_t send_wait);
169 virtual void send_internal(uint32_t send_times, uint32_t send_wait) = 0;
170 void send_single_() { this->send_(1, 0); }
171
174};
175
177 public:
178 virtual bool on_receive(RemoteReceiveData data) = 0;
179};
180
182 public:
183 virtual bool dump(RemoteReceiveData src) = 0;
184 virtual bool is_secondary() { return false; }
185};
186
188 public:
190 void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); }
192 void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode) {
193 this->tolerance_ = tolerance;
194 this->tolerance_mode_ = tolerance_mode;
195 }
196
197 protected:
198 void call_listeners_();
199 void call_dumpers_();
201 this->call_listeners_();
202 this->call_dumpers_();
203 }
204
205 std::vector<RemoteReceiverListener *> listeners_;
206 std::vector<RemoteReceiverDumperBase *> dumpers_;
207 std::vector<RemoteReceiverDumperBase *> secondary_dumpers_;
209 uint32_t tolerance_{25};
211};
212
214 public Component,
216 public:
218 void dump_config() override;
219 virtual bool matches(RemoteReceiveData src) = 0;
220 bool on_receive(RemoteReceiveData src) override;
221};
222
223/* TEMPLATES */
224
225template<typename T> class RemoteProtocol {
226 public:
227 using ProtocolData = T;
228 virtual void encode(RemoteTransmitData *dst, const ProtocolData &data) = 0;
230 virtual void dump(const ProtocolData &data) = 0;
231};
232
234 public:
236
237 protected:
238 bool matches(RemoteReceiveData src) override {
239 auto proto = T();
240 auto res = proto.decode(src);
241 return res.has_value() && *res == this->data_;
242 }
243
244 public:
245 void set_data(typename T::ProtocolData data) { data_ = data; }
246
247 protected:
248 typename T::ProtocolData data_;
249};
250
251template<typename T>
252class RemoteReceiverTrigger : public Trigger<typename T::ProtocolData>, public RemoteReceiverListener {
253 protected:
254 bool on_receive(RemoteReceiveData src) override {
255 auto proto = T();
256 auto res = proto.decode(src);
257 if (res.has_value()) {
258 this->trigger(*res);
259 return true;
260 }
261 return false;
262 }
263};
264
266 public:
269 void set_transmitter(RemoteTransmitterBase *transmitter) { this->transmitter_ = transmitter; }
270
271 protected:
272 template<typename Protocol>
273 void transmit_(const typename Protocol::ProtocolData &data, uint32_t send_times = 1, uint32_t send_wait = 0) {
274 this->transmitter_->transmit<Protocol>(data, send_times, send_wait);
275 }
277};
278
279template<typename... Ts> class RemoteTransmitterActionBase : public RemoteTransmittable, public Action<Ts...> {
280 TEMPLATABLE_VALUE(uint32_t, send_times)
281 TEMPLATABLE_VALUE(uint32_t, send_wait)
282
283 protected:
284 void play(const Ts &...x) override {
285 auto call = this->transmitter_->transmit();
286 this->encode(call.get_data(), x...);
287 call.set_send_times(this->send_times_.value_or(x..., 1));
288 call.set_send_wait(this->send_wait_.value_or(x..., 0));
289 call.perform();
290 }
291 virtual void encode(RemoteTransmitData *dst, Ts... x) = 0;
292};
293
294template<typename T> class RemoteReceiverDumper : public RemoteReceiverDumperBase {
295 public:
296 bool dump(RemoteReceiveData src) override {
297 auto proto = T();
298 auto decoded = proto.decode(src);
299 if (!decoded.has_value())
300 return false;
301 proto.dump(*decoded);
302 return true;
303 }
304};
305
306#define DECLARE_REMOTE_PROTOCOL_(prefix) \
307 using prefix##BinarySensor = RemoteReceiverBinarySensor<prefix##Protocol>; \
308 using prefix##Trigger = RemoteReceiverTrigger<prefix##Protocol>; \
309 using prefix##Dumper = RemoteReceiverDumper<prefix##Protocol>;
310#define DECLARE_REMOTE_PROTOCOL(prefix) DECLARE_REMOTE_PROTOCOL_(prefix)
311
312} // namespace remote_base
313} // namespace esphome
virtual void dump(const ProtocolData &data)=0
virtual optional< ProtocolData > decode(RemoteReceiveData src)=0
virtual void encode(RemoteTransmitData *dst, const ProtocolData &data)=0
void set_rmt_symbols(uint32_t rmt_symbols)
uint32_t to_microseconds_(uint32_t ticks)
uint32_t from_microseconds_(uint32_t us)
void set_clock_resolution(uint32_t clock_resolution)
int32_t operator[](uint32_t index) const
Definition remote_base.h:56
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
const RawTimings & get_raw_data() const
Definition remote_base.h:54
RemoteReceiveData(const RawTimings &data, uint32_t tolerance, ToleranceMode tolerance_mode)
Definition remote_base.h:51
void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode)
Definition remote_base.h:77
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_
void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode)
void register_listener(RemoteReceiverListener *listener)
virtual bool matches(RemoteReceiveData src)=0
bool on_receive(RemoteReceiveData src) override
void set_data(typename T::ProtocolData data)
bool matches(RemoteReceiveData src) override
virtual bool dump(RemoteReceiveData src)=0
bool dump(RemoteReceiveData src) override
virtual bool on_receive(RemoteReceiveData data)=0
bool on_receive(RemoteReceiveData src) override
void set_carrier_frequency(uint32_t carrier_frequency)
Definition remote_base.h:30
void item(uint32_t mark, uint32_t space)
Definition remote_base.h:25
const RawTimings & get_data() const
Definition remote_base.h:32
void set_data(const RawTimings &data)
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 set_transmitter(RemoteTransmitterBase *transmitter)
void transmit_(const typename Protocol::ProtocolData &data, uint32_t send_times=1, uint32_t send_wait=0)
RemoteTransmittable(RemoteTransmitterBase *transmitter)
virtual void encode(RemoteTransmitData *dst, Ts... x)=0
void send_(uint32_t send_times, uint32_t send_wait)
void transmit(const typename Protocol::ProtocolData &data, uint32_t send_times=1, uint32_t send_wait=0)
virtual void send_internal(uint32_t send_times, uint32_t send_wait)=0
RemoteTransmitData temp_
Use same vector for all transmits, avoids many allocations.
std::vector< int32_t > RawTimings
Definition remote_base.h:19
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:595
uint16_t length
Definition tt21100.cpp:0
uint16_t x
Definition tt21100.cpp:5