remote_base changes (#5124)

This commit is contained in:
Sergey Dudanov 2023-07-31 00:07:33 +04:00 committed by GitHub
parent a120a455bf
commit 794a4bd9a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 147 additions and 164 deletions

View file

@ -187,11 +187,10 @@ std::string ProntoProtocol::dump_duration_(uint32_t duration, uint16_t timebase,
return dump_number_((duration + timebase / 2) / timebase, end); return dump_number_((duration + timebase / 2) / timebase, end);
} }
std::string ProntoProtocol::compensate_and_dump_sequence_(std::vector<int32_t> *data, uint16_t timebase) { std::string ProntoProtocol::compensate_and_dump_sequence_(const RawTimings &data, uint16_t timebase) {
std::string out; std::string out;
for (std::vector<int32_t>::size_type i = 0; i < data->size() - 1; i++) { for (int32_t t_length : data) {
int32_t t_length = data->at(i);
uint32_t t_duration; uint32_t t_duration;
if (t_length > 0) { if (t_length > 0) {
// Mark // Mark
@ -212,12 +211,12 @@ optional<ProntoData> ProntoProtocol::decode(RemoteReceiveData src) {
ProntoData out; ProntoData out;
uint16_t frequency = 38000U; uint16_t frequency = 38000U;
std::vector<int32_t> *data = src.get_raw_data(); auto &data = src.get_raw_data();
std::string prontodata; std::string prontodata;
prontodata += dump_number_(frequency > 0 ? LEARNED_TOKEN : LEARNED_NON_MODULATED_TOKEN); prontodata += dump_number_(frequency > 0 ? LEARNED_TOKEN : LEARNED_NON_MODULATED_TOKEN);
prontodata += dump_number_(to_frequency_code_(frequency)); prontodata += dump_number_(to_frequency_code_(frequency));
prontodata += dump_number_((data->size() + 1) / 2); prontodata += dump_number_((data.size() + 1) / 2);
prontodata += dump_number_(0); prontodata += dump_number_(0);
uint16_t timebase = to_timebase_(frequency); uint16_t timebase = to_timebase_(frequency);
prontodata += compensate_and_dump_sequence_(data, timebase); prontodata += compensate_and_dump_sequence_(data, timebase);

View file

@ -27,7 +27,7 @@ class ProntoProtocol : public RemoteProtocol<ProntoData> {
std::string dump_digit_(uint8_t x); std::string dump_digit_(uint8_t x);
std::string dump_number_(uint16_t number, bool end = false); std::string dump_number_(uint16_t number, bool end = false);
std::string dump_duration_(uint32_t duration, uint16_t timebase, bool end = false); std::string dump_duration_(uint32_t duration, uint16_t timebase, bool end = false);
std::string compensate_and_dump_sequence_(std::vector<int32_t> *data, uint16_t timebase); std::string compensate_and_dump_sequence_(const RawTimings &data, uint16_t timebase);
public: public:
void encode(RemoteTransmitData *dst, const ProntoData &data) override; void encode(RemoteTransmitData *dst, const ProntoData &data) override;

View file

@ -31,17 +31,17 @@ class RawBinarySensor : public RemoteReceiverBinarySensorBase {
size_t len_; size_t len_;
}; };
class RawTrigger : public Trigger<std::vector<int32_t>>, public Component, public RemoteReceiverListener { class RawTrigger : public Trigger<RawTimings>, public Component, public RemoteReceiverListener {
protected: protected:
bool on_receive(RemoteReceiveData src) override { bool on_receive(RemoteReceiveData src) override {
this->trigger(*src.get_raw_data()); this->trigger(src.get_raw_data());
return false; return false;
} }
}; };
template<typename... Ts> class RawAction : public RemoteTransmitterActionBase<Ts...> { template<typename... Ts> class RawAction : public RemoteTransmitterActionBase<Ts...> {
public: public:
void set_code_template(std::function<std::vector<int32_t>(Ts...)> func) { this->code_func_ = func; } void set_code_template(std::function<RawTimings(Ts...)> func) { this->code_func_ = func; }
void set_code_static(const int32_t *code, size_t len) { void set_code_static(const int32_t *code, size_t len) {
this->code_static_ = code; this->code_static_ = code;
this->code_static_len_ = len; this->code_static_len_ = len;
@ -65,7 +65,7 @@ template<typename... Ts> class RawAction : public RemoteTransmitterActionBase<Ts
} }
protected: protected:
std::function<std::vector<int32_t>(Ts...)> code_func_{}; std::function<RawTimings(Ts...)> code_func_{nullptr};
const int32_t *code_static_{nullptr}; const int32_t *code_static_{nullptr};
int32_t code_static_len_{0}; int32_t code_static_len_{0};
}; };

View file

@ -24,11 +24,105 @@ void RemoteRMTChannel::config_rmt(rmt_config_t &rmt) {
} }
#endif #endif
/* RemoteReceiveData */
bool RemoteReceiveData::peek_mark(uint32_t length, uint32_t offset) const {
if (!this->is_valid(offset))
return false;
const int32_t value = this->peek(offset);
const int32_t lo = this->lower_bound_(length);
const int32_t hi = this->upper_bound_(length);
return value >= 0 && lo <= value && value <= hi;
}
bool RemoteReceiveData::peek_space(uint32_t length, uint32_t offset) const {
if (!this->is_valid(offset))
return false;
const int32_t value = this->peek(offset);
const int32_t lo = this->lower_bound_(length);
const int32_t hi = this->upper_bound_(length);
return value <= 0 && lo <= -value && -value <= hi;
}
bool RemoteReceiveData::peek_space_at_least(uint32_t length, uint32_t offset) const {
if (!this->is_valid(offset))
return false;
const int32_t value = this->peek(offset);
const int32_t lo = this->lower_bound_(length);
return value <= 0 && lo <= -value;
}
bool RemoteReceiveData::expect_mark(uint32_t length) {
if (!this->peek_mark(length))
return false;
this->advance();
return true;
}
bool RemoteReceiveData::expect_space(uint32_t length) {
if (!this->peek_space(length))
return false;
this->advance();
return true;
}
bool RemoteReceiveData::expect_item(uint32_t mark, uint32_t space) {
if (!this->peek_item(mark, space))
return false;
this->advance(2);
return true;
}
bool RemoteReceiveData::expect_pulse_with_gap(uint32_t mark, uint32_t space) {
if (!this->peek_space_at_least(space, 1) || !this->peek_mark(mark))
return false;
this->advance(2);
return true;
}
/* RemoteReceiverBinarySensorBase */
bool RemoteReceiverBinarySensorBase::on_receive(RemoteReceiveData src) {
if (!this->matches(src))
return false;
this->publish_state(true);
yield();
this->publish_state(false);
return true;
}
/* RemoteReceiverBase */
void RemoteReceiverBase::register_dumper(RemoteReceiverDumperBase *dumper) {
if (dumper->is_secondary()) {
this->secondary_dumpers_.push_back(dumper);
} else {
this->dumpers_.push_back(dumper);
}
}
void RemoteReceiverBase::call_listeners_() {
for (auto *listener : this->listeners_)
listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_));
}
void RemoteReceiverBase::call_dumpers_() {
bool success = false;
for (auto *dumper : this->dumpers_) {
if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_)))
success = true;
}
if (!success) {
for (auto *dumper : this->secondary_dumpers_)
dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_));
}
}
void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); } void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); }
void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) { void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) {
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
const std::vector<int32_t> &vec = this->temp_.get_data(); const auto &vec = this->temp_.get_data();
char buffer[256]; char buffer[256];
uint32_t buffer_offset = 0; uint32_t buffer_offset = 0;
buffer_offset += sprintf(buffer, "Sending times=%u wait=%ums: ", send_times, send_wait); buffer_offset += sprintf(buffer, "Sending times=%u wait=%ums: ", send_times, send_wait);

View file

@ -15,146 +15,65 @@
namespace esphome { namespace esphome {
namespace remote_base { namespace remote_base {
using RawTimings = std::vector<int32_t>;
class RemoteTransmitData { class RemoteTransmitData {
public: public:
void mark(uint32_t length) { this->data_.push_back(length); } void mark(uint32_t length) { this->data_.push_back(length); }
void space(uint32_t length) { this->data_.push_back(-length); } void space(uint32_t length) { this->data_.push_back(-length); }
void item(uint32_t mark, uint32_t space) { void item(uint32_t mark, uint32_t space) {
this->mark(mark); this->mark(mark);
this->space(space); this->space(space);
} }
void reserve(uint32_t len) { this->data_.reserve(len); } void reserve(uint32_t len) { this->data_.reserve(len); }
void set_carrier_frequency(uint32_t carrier_frequency) { this->carrier_frequency_ = carrier_frequency; } void set_carrier_frequency(uint32_t carrier_frequency) { this->carrier_frequency_ = carrier_frequency; }
uint32_t get_carrier_frequency() const { return this->carrier_frequency_; } uint32_t get_carrier_frequency() const { return this->carrier_frequency_; }
const RawTimings &get_data() const { return this->data_; }
const std::vector<int32_t> &get_data() const { return this->data_; } void set_data(const RawTimings &data) { this->data_ = data; }
void set_data(const std::vector<int32_t> &data) {
this->data_.clear();
this->data_.reserve(data.size());
for (auto dat : data)
this->data_.push_back(dat);
}
void reset() { void reset() {
this->data_.clear(); this->data_.clear();
this->carrier_frequency_ = 0; this->carrier_frequency_ = 0;
} }
std::vector<int32_t>::iterator begin() { return this->data_.begin(); }
std::vector<int32_t>::iterator end() { return this->data_.end(); }
protected: protected:
std::vector<int32_t> data_{}; RawTimings data_{};
uint32_t carrier_frequency_{0}; uint32_t carrier_frequency_{0};
}; };
class RemoteReceiveData { class RemoteReceiveData {
public: public:
RemoteReceiveData(std::vector<int32_t> *data, uint8_t tolerance) : data_(data), tolerance_(tolerance) {} explicit RemoteReceiveData(const RawTimings &data, uint8_t tolerance)
: data_(data), index_(0), tolerance_(tolerance) {}
bool peek_mark(uint32_t length, uint32_t offset = 0) { const RawTimings &get_raw_data() const { return this->data_; }
if (int32_t(this->index_ + offset) >= this->size()) uint32_t get_index() const { return index_; }
return false; int32_t operator[](uint32_t index) const { return this->data_[index]; }
int32_t value = this->peek(offset); int32_t size() const { return this->data_.size(); }
const int32_t lo = this->lower_bound_(length); bool is_valid(uint32_t offset) const { return this->index_ + offset < this->data_.size(); }
const int32_t hi = this->upper_bound_(length); int32_t peek(uint32_t offset = 0) const { return this->data_[this->index_ + offset]; }
return value >= 0 && lo <= value && value <= hi; bool peek_mark(uint32_t length, uint32_t offset = 0) const;
bool peek_space(uint32_t length, uint32_t offset = 0) const;
bool peek_space_at_least(uint32_t length, uint32_t offset = 0) const;
bool peek_item(uint32_t mark, uint32_t space, uint32_t offset = 0) const {
return this->peek_space(space, offset + 1) && this->peek_mark(mark, offset);
} }
bool peek_space(uint32_t length, uint32_t offset = 0) { bool expect_mark(uint32_t length);
if (int32_t(this->index_ + offset) >= this->size()) bool expect_space(uint32_t length);
return false; bool expect_item(uint32_t mark, uint32_t space);
int32_t value = this->peek(offset); bool expect_pulse_with_gap(uint32_t mark, uint32_t space);
const int32_t lo = this->lower_bound_(length);
const int32_t hi = this->upper_bound_(length);
return value <= 0 && lo <= -value && -value <= hi;
}
bool peek_space_at_least(uint32_t length, uint32_t offset = 0) {
if (int32_t(this->index_ + offset) >= this->size())
return false;
int32_t value = this->pos(this->index_ + offset);
const int32_t lo = this->lower_bound_(length);
return value <= 0 && lo <= -value;
}
bool peek_item(uint32_t mark, uint32_t space, uint32_t offset = 0) {
return this->peek_mark(mark, offset) && this->peek_space(space, offset + 1);
}
int32_t peek(uint32_t offset = 0) { return (*this)[this->index_ + offset]; }
void advance(uint32_t amount = 1) { this->index_ += amount; } void advance(uint32_t amount = 1) { this->index_ += amount; }
bool expect_mark(uint32_t length) {
if (this->peek_mark(length)) {
this->advance();
return true;
}
return false;
}
bool expect_space(uint32_t length) {
if (this->peek_space(length)) {
this->advance();
return true;
}
return false;
}
bool expect_item(uint32_t mark, uint32_t space) {
if (this->peek_item(mark, space)) {
this->advance(2);
return true;
}
return false;
}
bool expect_pulse_with_gap(uint32_t mark, uint32_t space) {
if (this->peek_mark(mark, 0) && this->peek_space_at_least(space, 1)) {
this->advance(2);
return true;
}
return false;
}
uint32_t get_index() { return index_; }
void reset() { this->index_ = 0; } void reset() { this->index_ = 0; }
int32_t pos(uint32_t index) const { return (*this->data_)[index]; }
int32_t operator[](uint32_t index) const { return this->pos(index); }
int32_t size() const { return this->data_->size(); }
std::vector<int32_t> *get_raw_data() { return this->data_; }
protected: protected:
int32_t lower_bound_(uint32_t length) { return int32_t(100 - this->tolerance_) * length / 100U; } int32_t lower_bound_(uint32_t length) const { return int32_t(100 - this->tolerance_) * length / 100U; }
int32_t upper_bound_(uint32_t length) { return int32_t(100 + this->tolerance_) * length / 100U; } int32_t upper_bound_(uint32_t length) const { return int32_t(100 + this->tolerance_) * length / 100U; }
uint32_t index_{0}; const RawTimings &data_;
std::vector<int32_t> *data_; uint32_t index_;
uint8_t tolerance_; uint8_t tolerance_;
}; };
template<typename T> class RemoteProtocol {
public:
virtual void encode(RemoteTransmitData *dst, const T &data) = 0;
virtual optional<T> decode(RemoteReceiveData src) = 0;
virtual void dump(const T &data) = 0;
};
class RemoteComponentBase { class RemoteComponentBase {
public: public:
explicit RemoteComponentBase(InternalGPIOPin *pin) : pin_(pin){}; explicit RemoteComponentBase(InternalGPIOPin *pin) : pin_(pin){};
@ -196,7 +115,6 @@ class RemoteTransmitterBase : public RemoteComponentBase {
RemoteTransmitData *get_data() { return &this->parent_->temp_; } RemoteTransmitData *get_data() { return &this->parent_->temp_; }
void set_send_times(uint32_t send_times) { send_times_ = send_times; } void set_send_times(uint32_t send_times) { send_times_ = send_times; }
void set_send_wait(uint32_t send_wait) { send_wait_ = send_wait; } void set_send_wait(uint32_t send_wait) { send_wait_ = send_wait; }
void perform() { this->parent_->send_(this->send_times_, this->send_wait_); } void perform() { this->parent_->send_(this->send_times_, this->send_wait_); }
protected: protected:
@ -234,51 +152,22 @@ class RemoteReceiverBase : public RemoteComponentBase {
public: public:
RemoteReceiverBase(InternalGPIOPin *pin) : RemoteComponentBase(pin) {} RemoteReceiverBase(InternalGPIOPin *pin) : RemoteComponentBase(pin) {}
void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); } void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); }
void register_dumper(RemoteReceiverDumperBase *dumper) { void register_dumper(RemoteReceiverDumperBase *dumper);
if (dumper->is_secondary()) {
this->secondary_dumpers_.push_back(dumper);
} else {
this->dumpers_.push_back(dumper);
}
}
void set_tolerance(uint8_t tolerance) { tolerance_ = tolerance; } void set_tolerance(uint8_t tolerance) { tolerance_ = tolerance; }
protected: protected:
bool call_listeners_() { void call_listeners_();
bool success = false; void call_dumpers_();
for (auto *listener : this->listeners_) {
auto data = RemoteReceiveData(&this->temp_, this->tolerance_);
if (listener->on_receive(data))
success = true;
}
return success;
}
void call_dumpers_() {
bool success = false;
for (auto *dumper : this->dumpers_) {
auto data = RemoteReceiveData(&this->temp_, this->tolerance_);
if (dumper->dump(data))
success = true;
}
if (!success) {
for (auto *dumper : this->secondary_dumpers_) {
auto data = RemoteReceiveData(&this->temp_, this->tolerance_);
dumper->dump(data);
}
}
}
void call_listeners_dumpers_() { void call_listeners_dumpers_() {
if (this->call_listeners_()) this->call_listeners_();
return;
// If a listener handled, then do not dump
this->call_dumpers_(); this->call_dumpers_();
} }
std::vector<RemoteReceiverListener *> listeners_; std::vector<RemoteReceiverListener *> listeners_;
std::vector<RemoteReceiverDumperBase *> dumpers_; std::vector<RemoteReceiverDumperBase *> dumpers_;
std::vector<RemoteReceiverDumperBase *> secondary_dumpers_; std::vector<RemoteReceiverDumperBase *> secondary_dumpers_;
std::vector<int32_t> temp_; RawTimings temp_;
uint8_t tolerance_{25}; uint8_t tolerance_;
}; };
class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitiallyOff, class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitiallyOff,
@ -288,15 +177,16 @@ class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitial
explicit RemoteReceiverBinarySensorBase() {} explicit RemoteReceiverBinarySensorBase() {}
void dump_config() override; void dump_config() override;
virtual bool matches(RemoteReceiveData src) = 0; virtual bool matches(RemoteReceiveData src) = 0;
bool on_receive(RemoteReceiveData src) override { bool on_receive(RemoteReceiveData src) override;
if (this->matches(src)) { };
this->publish_state(true);
yield(); /* TEMPLATES */
this->publish_state(false);
return true; template<typename T> class RemoteProtocol {
} public:
return false; virtual void encode(RemoteTransmitData *dst, const T &data) = 0;
} virtual optional<T> decode(RemoteReceiveData src) = 0;
virtual void dump(const T &data) = 0;
}; };
template<typename T, typename D> class RemoteReceiverBinarySensor : public RemoteReceiverBinarySensorBase { template<typename T, typename D> class RemoteReceiverBinarySensor : public RemoteReceiverBinarySensorBase {

View file

@ -48,7 +48,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
esp_err_t error_code_{ESP_OK}; esp_err_t error_code_{ESP_OK};
bool inverted_{false}; bool inverted_{false};
#endif #endif
uint8_t carrier_duty_percent_{50}; uint8_t carrier_duty_percent_;
}; };
} // namespace remote_transmitter } // namespace remote_transmitter