ESPHome  2022.11.3
remote_base.h
Go to the documentation of this file.
1 #include <utility>
2 
3 #pragma once
4 
6 #include "esphome/core/hal.h"
9 
10 #ifdef USE_ESP32
11 #include <driver/rmt.h>
12 #endif
13 
14 namespace esphome {
15 namespace remote_base {
16 
18  public:
19  void mark(uint32_t length) { this->data_.push_back(length); }
20 
21  void space(uint32_t length) { this->data_.push_back(-length); }
22 
23  void item(uint32_t mark, uint32_t space) {
24  this->mark(mark);
25  this->space(space);
26  }
27 
28  void reserve(uint32_t len) { this->data_.reserve(len); }
29 
30  void set_carrier_frequency(uint32_t carrier_frequency) { this->carrier_frequency_ = carrier_frequency; }
31 
32  uint32_t get_carrier_frequency() const { return this->carrier_frequency_; }
33 
34  const std::vector<int32_t> &get_data() const { return this->data_; }
35 
36  void set_data(const std::vector<int32_t> &data) {
37  this->data_.clear();
38  this->data_.reserve(data.size());
39  for (auto dat : data)
40  this->data_.push_back(dat);
41  }
42 
43  void reset() {
44  this->data_.clear();
45  this->carrier_frequency_ = 0;
46  }
47 
48  std::vector<int32_t>::iterator begin() { return this->data_.begin(); }
49 
50  std::vector<int32_t>::iterator end() { return this->data_.end(); }
51 
52  protected:
53  std::vector<int32_t> data_{};
54  uint32_t carrier_frequency_{0};
55 };
56 
58  public:
59  RemoteReceiveData(std::vector<int32_t> *data, uint8_t tolerance) : data_(data), tolerance_(tolerance) {}
60 
61  bool peek_mark(uint32_t length, uint32_t offset = 0) {
62  if (int32_t(this->index_ + offset) >= this->size())
63  return false;
64  int32_t value = this->peek(offset);
65  const int32_t lo = this->lower_bound_(length);
66  const int32_t hi = this->upper_bound_(length);
67  return value >= 0 && lo <= value && value <= hi;
68  }
69 
70  bool peek_space(uint32_t length, uint32_t offset = 0) {
71  if (int32_t(this->index_ + offset) >= this->size())
72  return false;
73  int32_t value = this->peek(offset);
74  const int32_t lo = this->lower_bound_(length);
75  const int32_t hi = this->upper_bound_(length);
76  return value <= 0 && lo <= -value && -value <= hi;
77  }
78 
79  bool peek_space_at_least(uint32_t length, uint32_t offset = 0) {
80  if (int32_t(this->index_ + offset) >= this->size())
81  return false;
82  int32_t value = this->pos(this->index_ + offset);
83  const int32_t lo = this->lower_bound_(length);
84  return value <= 0 && lo <= -value;
85  }
86 
87  bool peek_item(uint32_t mark, uint32_t space, uint32_t offset = 0) {
88  return this->peek_mark(mark, offset) && this->peek_space(space, offset + 1);
89  }
90 
91  int32_t peek(uint32_t offset = 0) { return (*this)[this->index_ + offset]; }
92 
93  void advance(uint32_t amount = 1) { this->index_ += amount; }
94 
95  bool expect_mark(uint32_t length) {
96  if (this->peek_mark(length)) {
97  this->advance();
98  return true;
99  }
100  return false;
101  }
102 
103  bool expect_space(uint32_t length) {
104  if (this->peek_space(length)) {
105  this->advance();
106  return true;
107  }
108  return false;
109  }
110 
111  bool expect_item(uint32_t mark, uint32_t space) {
112  if (this->peek_item(mark, space)) {
113  this->advance(2);
114  return true;
115  }
116  return false;
117  }
118 
119  bool expect_pulse_with_gap(uint32_t mark, uint32_t space) {
120  if (this->peek_mark(mark, 0) && this->peek_space_at_least(space, 1)) {
121  this->advance(2);
122  return true;
123  }
124  return false;
125  }
126 
127  uint32_t get_index() { return index_; }
128 
129  void reset() { this->index_ = 0; }
130 
131  int32_t pos(uint32_t index) const { return (*this->data_)[index]; }
132 
133  int32_t operator[](uint32_t index) const { return this->pos(index); }
134 
135  int32_t size() const { return this->data_->size(); }
136 
137  std::vector<int32_t> *get_raw_data() { return this->data_; }
138 
139  protected:
140  int32_t lower_bound_(uint32_t length) { return int32_t(100 - this->tolerance_) * length / 100U; }
141  int32_t upper_bound_(uint32_t length) { return int32_t(100 + this->tolerance_) * length / 100U; }
142 
143  uint32_t index_{0};
144  std::vector<int32_t> *data_;
145  uint8_t tolerance_;
146 };
147 
148 template<typename T> class RemoteProtocol {
149  public:
150  virtual void encode(RemoteTransmitData *dst, const T &data) = 0;
151 
152  virtual optional<T> decode(RemoteReceiveData src) = 0;
153 
154  virtual void dump(const T &data) = 0;
155 };
156 
158  public:
159  explicit RemoteComponentBase(InternalGPIOPin *pin) : pin_(pin){};
160 
161  protected:
162  InternalGPIOPin *pin_;
163 };
164 
165 #ifdef USE_ESP32
167  public:
168  explicit RemoteRMTChannel(uint8_t mem_block_num = 1);
169 
170  void config_rmt(rmt_config_t &rmt);
171  void set_clock_divider(uint8_t clock_divider) { this->clock_divider_ = clock_divider; }
172 
173  protected:
174  uint32_t from_microseconds_(uint32_t us) {
175  const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u;
176  return us * ticks_per_ten_us / 10;
177  }
178  uint32_t to_microseconds_(uint32_t ticks) {
179  const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u;
180  return (ticks * 10) / ticks_per_ten_us;
181  }
183  rmt_channel_t channel_{RMT_CHANNEL_0};
184  uint8_t mem_block_num_;
185  uint8_t clock_divider_{80};
186 };
187 #endif
188 
190  public:
192  class TransmitCall {
193  public:
194  explicit TransmitCall(RemoteTransmitterBase *parent) : parent_(parent) {}
195  RemoteTransmitData *get_data() { return &this->parent_->temp_; }
196  void set_send_times(uint32_t send_times) { send_times_ = send_times; }
197  void set_send_wait(uint32_t send_wait) { send_wait_ = send_wait; }
198 
199  void perform() { this->parent_->send_(this->send_times_, this->send_wait_); }
200 
201  protected:
203  uint32_t send_times_{1};
204  uint32_t send_wait_{0};
205  };
206 
208  this->temp_.reset();
209  return TransmitCall(this);
210  }
211 
212  protected:
213  void send_(uint32_t send_times, uint32_t send_wait);
214  virtual void send_internal(uint32_t send_times, uint32_t send_wait) = 0;
215  void send_single_() { this->send_(1, 0); }
216 
219 };
220 
222  public:
223  virtual bool on_receive(RemoteReceiveData data) = 0;
224 };
225 
227  public:
228  virtual bool dump(RemoteReceiveData src) = 0;
229  virtual bool is_secondary() { return false; }
230 };
231 
233  public:
235  void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); }
237  if (dumper->is_secondary()) {
238  this->secondary_dumpers_.push_back(dumper);
239  } else {
240  this->dumpers_.push_back(dumper);
241  }
242  }
243  void set_tolerance(uint8_t tolerance) { tolerance_ = tolerance; }
244 
245  protected:
247  bool success = false;
248  for (auto *listener : this->listeners_) {
249  auto data = RemoteReceiveData(&this->temp_, this->tolerance_);
250  if (listener->on_receive(data))
251  success = true;
252  }
253  return success;
254  }
255  void call_dumpers_() {
256  bool success = false;
257  for (auto *dumper : this->dumpers_) {
258  auto data = RemoteReceiveData(&this->temp_, this->tolerance_);
259  if (dumper->dump(data))
260  success = true;
261  }
262  if (!success) {
263  for (auto *dumper : this->secondary_dumpers_) {
264  auto data = RemoteReceiveData(&this->temp_, this->tolerance_);
265  dumper->dump(data);
266  }
267  }
268  }
270  if (this->call_listeners_())
271  return;
272  // If a listener handled, then do not dump
273  this->call_dumpers_();
274  }
275 
276  std::vector<RemoteReceiverListener *> listeners_;
277  std::vector<RemoteReceiverDumperBase *> dumpers_;
278  std::vector<RemoteReceiverDumperBase *> secondary_dumpers_;
279  std::vector<int32_t> temp_;
280  uint8_t tolerance_{25};
281 };
282 
284  public Component,
285  public RemoteReceiverListener {
286  public:
288  void dump_config() override;
289  virtual bool matches(RemoteReceiveData src) = 0;
290  bool on_receive(RemoteReceiveData src) override {
291  if (this->matches(src)) {
292  this->publish_state(true);
293  yield();
294  this->publish_state(false);
295  return true;
296  }
297  return false;
298  }
299 };
300 
301 template<typename T, typename D> class RemoteReceiverBinarySensor : public RemoteReceiverBinarySensorBase {
302  public:
304 
305  protected:
306  bool matches(RemoteReceiveData src) override {
307  auto proto = T();
308  auto res = proto.decode(src);
309  return res.has_value() && *res == this->data_;
310  }
311 
312  public:
313  void set_data(D data) { data_ = data; }
314 
315  protected:
316  D data_;
317 };
318 
319 template<typename T, typename D> class RemoteReceiverTrigger : public Trigger<D>, public RemoteReceiverListener {
320  protected:
321  bool on_receive(RemoteReceiveData src) override {
322  auto proto = T();
323  auto res = proto.decode(src);
324  if (res.has_value()) {
325  this->trigger(*res);
326  return true;
327  }
328  return false;
329  }
330 };
331 
332 template<typename... Ts> class RemoteTransmitterActionBase : public Action<Ts...> {
333  public:
334  void set_parent(RemoteTransmitterBase *parent) { this->parent_ = parent; }
335 
336  TEMPLATABLE_VALUE(uint32_t, send_times);
337  TEMPLATABLE_VALUE(uint32_t, send_wait);
338 
339  void play(Ts... x) override {
340  auto call = this->parent_->transmit();
341  this->encode(call.get_data(), x...);
342  call.set_send_times(this->send_times_.value_or(x..., 1));
343  call.set_send_wait(this->send_wait_.value_or(x..., 0));
344  call.perform();
345  }
346 
347  protected:
348  virtual void encode(RemoteTransmitData *dst, Ts... x) = 0;
349 
351 };
352 
353 template<typename T, typename D> class RemoteReceiverDumper : public RemoteReceiverDumperBase {
354  public:
355  bool dump(RemoteReceiveData src) override {
356  auto proto = T();
357  auto decoded = proto.decode(src);
358  if (!decoded.has_value())
359  return false;
360  proto.dump(*decoded);
361  return true;
362  }
363 };
364 
365 #define DECLARE_REMOTE_PROTOCOL_(prefix) \
366  using prefix##BinarySensor = RemoteReceiverBinarySensor<prefix##Protocol, prefix##Data>; \
367  using prefix##Trigger = RemoteReceiverTrigger<prefix##Protocol, prefix##Data>; \
368  using prefix##Dumper = RemoteReceiverDumper<prefix##Protocol, prefix##Data>;
369 #define DECLARE_REMOTE_PROTOCOL(prefix) DECLARE_REMOTE_PROTOCOL_(prefix)
370 
371 } // namespace remote_base
372 } // namespace esphome
void register_listener(RemoteReceiverListener *listener)
Definition: remote_base.h:235
bool expect_pulse_with_gap(uint32_t mark, uint32_t space)
Definition: remote_base.h:119
RemoteTransmitData temp_
Use same vector for all transmits, avoids many allocations.
Definition: remote_base.h:218
int32_t operator[](uint32_t index) const
Definition: remote_base.h:133
RemoteReceiveData(std::vector< int32_t > *data, uint8_t tolerance)
Definition: remote_base.h:59
void set_carrier_frequency(uint32_t carrier_frequency)
Definition: remote_base.h:30
bool on_receive(RemoteReceiveData src) override
Definition: remote_base.h:321
void item(uint32_t mark, uint32_t space)
Definition: remote_base.h:23
int32_t peek(uint32_t offset=0)
Definition: remote_base.h:91
std::vector< int32_t > * get_raw_data()
Definition: remote_base.h:137
std::vector< int32_t > * data_
Definition: remote_base.h:144
std::vector< int32_t >::iterator begin()
Definition: remote_base.h:48
bool peek_space(uint32_t length, uint32_t offset=0)
Definition: remote_base.h:70
std::vector< RemoteReceiverDumperBase * > dumpers_
Definition: remote_base.h:277
std::vector< RemoteReceiverDumperBase * > secondary_dumpers_
Definition: remote_base.h:278
const std::vector< int32_t > & get_data() const
Definition: remote_base.h:34
RemoteComponentBase(InternalGPIOPin *pin)
Definition: remote_base.h:159
RemoteComponentBase * remote_base_
Definition: remote_base.h:182
int32_t upper_bound_(uint32_t length)
Definition: remote_base.h:141
bool dump(RemoteReceiveData src) override
Definition: remote_base.h:355
std::vector< int32_t >::iterator end()
Definition: remote_base.h:50
bool peek_mark(uint32_t length, uint32_t offset=0)
Definition: remote_base.h:61
int32_t lower_bound_(uint32_t length)
Definition: remote_base.h:140
std::vector< RemoteReceiverListener * > listeners_
Definition: remote_base.h:276
bool on_receive(RemoteReceiveData src) override
Definition: remote_base.h:290
int32_t pos(uint32_t index) const
Definition: remote_base.h:131
void set_data(const std::vector< int32_t > &data)
Definition: remote_base.h:36
RemoteReceiverBase(InternalGPIOPin *pin)
Definition: remote_base.h:234
void set_clock_divider(uint8_t clock_divider)
Definition: remote_base.h:171
void set_parent(RemoteTransmitterBase *parent)
Definition: remote_base.h:334
bool matches(RemoteReceiveData src) override
Definition: remote_base.h:306
std::string size_t len
Definition: helpers.h:281
void IRAM_ATTR HOT yield()
Definition: core.cpp:25
bool peek_item(uint32_t mark, uint32_t space, uint32_t offset=0)
Definition: remote_base.h:87
Definition: a4988.cpp:4
void register_dumper(RemoteReceiverDumperBase *dumper)
Definition: remote_base.h:236
bool expect_item(uint32_t mark, uint32_t space)
Definition: remote_base.h:111
void advance(uint32_t amount=1)
Definition: remote_base.h:93
void set_tolerance(uint8_t tolerance)
Definition: remote_base.h:243
uint32_t to_microseconds_(uint32_t ticks)
Definition: remote_base.h:178
bool peek_space_at_least(uint32_t length, uint32_t offset=0)
Definition: remote_base.h:79
uint32_t from_microseconds_(uint32_t us)
Definition: remote_base.h:174