1
0
mirror of https://github.com/esphome/esphome.git synced 2024-10-06 10:50:58 +01:00

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);
}
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;
for (std::vector<int32_t>::size_type i = 0; i < data->size() - 1; i++) {
int32_t t_length = data->at(i);
for (int32_t t_length : data) {
uint32_t t_duration;
if (t_length > 0) {
// Mark
@ -212,12 +211,12 @@ optional<ProntoData> ProntoProtocol::decode(RemoteReceiveData src) {
ProntoData out;
uint16_t frequency = 38000U;
std::vector<int32_t> *data = src.get_raw_data();
auto &data = src.get_raw_data();
std::string prontodata;
prontodata += dump_number_(frequency > 0 ? LEARNED_TOKEN : LEARNED_NON_MODULATED_TOKEN);
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);
uint16_t timebase = to_timebase_(frequency);
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_number_(uint16_t number, 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:
void encode(RemoteTransmitData *dst, const ProntoData &data) override;

View File

@ -31,17 +31,17 @@ class RawBinarySensor : public RemoteReceiverBinarySensorBase {
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:
bool on_receive(RemoteReceiveData src) override {
this->trigger(*src.get_raw_data());
this->trigger(src.get_raw_data());
return false;
}
};
template<typename... Ts> class RawAction : public RemoteTransmitterActionBase<Ts...> {
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) {
this->code_static_ = code;
this->code_static_len_ = len;
@ -65,7 +65,7 @@ template<typename... Ts> class RawAction : public RemoteTransmitterActionBase<Ts
}
protected:
std::function<std::vector<int32_t>(Ts...)> code_func_{};
std::function<RawTimings(Ts...)> code_func_{nullptr};
const int32_t *code_static_{nullptr};
int32_t code_static_len_{0};
};

View File

@ -24,11 +24,105 @@ void RemoteRMTChannel::config_rmt(rmt_config_t &rmt) {
}
#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 RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) {
#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];
uint32_t buffer_offset = 0;
buffer_offset += sprintf(buffer, "Sending times=%u wait=%ums: ", send_times, send_wait);

View File

@ -15,146 +15,65 @@
namespace esphome {
namespace remote_base {
using RawTimings = std::vector<int32_t>;
class RemoteTransmitData {
public:
void mark(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) {
this->mark(mark);
this->space(space);
}
void reserve(uint32_t len) { this->data_.reserve(len); }
void set_carrier_frequency(uint32_t carrier_frequency) { this->carrier_frequency_ = carrier_frequency; }
uint32_t get_carrier_frequency() const { return this->carrier_frequency_; }
const std::vector<int32_t> &get_data() const { return this->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);
}
const RawTimings &get_data() const { return this->data_; }
void set_data(const RawTimings &data) { this->data_ = data; }
void reset() {
this->data_.clear();
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:
std::vector<int32_t> data_{};
RawTimings data_{};
uint32_t carrier_frequency_{0};
};
class RemoteReceiveData {
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) {
if (int32_t(this->index_ + offset) >= this->size())
return false;
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;
const RawTimings &get_raw_data() const { return this->data_; }
uint32_t get_index() const { return index_; }
int32_t operator[](uint32_t index) const { return this->data_[index]; }
int32_t size() const { return this->data_.size(); }
bool is_valid(uint32_t offset) const { return this->index_ + offset < this->data_.size(); }
int32_t peek(uint32_t offset = 0) const { return this->data_[this->index_ + offset]; }
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) {
if (int32_t(this->index_ + offset) >= this->size())
return false;
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 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]; }
bool expect_mark(uint32_t length);
bool expect_space(uint32_t length);
bool expect_item(uint32_t mark, uint32_t space);
bool expect_pulse_with_gap(uint32_t mark, uint32_t space);
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; }
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:
int32_t lower_bound_(uint32_t length) { 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 lower_bound_(uint32_t length) const { 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};
std::vector<int32_t> *data_;
const RawTimings &data_;
uint32_t index_;
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 {
public:
explicit RemoteComponentBase(InternalGPIOPin *pin) : pin_(pin){};
@ -196,7 +115,6 @@ class RemoteTransmitterBase : public RemoteComponentBase {
RemoteTransmitData *get_data() { return &this->parent_->temp_; }
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 perform() { this->parent_->send_(this->send_times_, this->send_wait_); }
protected:
@ -234,51 +152,22 @@ class RemoteReceiverBase : public RemoteComponentBase {
public:
RemoteReceiverBase(InternalGPIOPin *pin) : RemoteComponentBase(pin) {}
void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); }
void register_dumper(RemoteReceiverDumperBase *dumper) {
if (dumper->is_secondary()) {
this->secondary_dumpers_.push_back(dumper);
} else {
this->dumpers_.push_back(dumper);
}
}
void register_dumper(RemoteReceiverDumperBase *dumper);
void set_tolerance(uint8_t tolerance) { tolerance_ = tolerance; }
protected:
bool call_listeners_() {
bool success = false;
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_();
void call_dumpers_();
void call_listeners_dumpers_() {
if (this->call_listeners_())
return;
// If a listener handled, then do not dump
this->call_listeners_();
this->call_dumpers_();
}
std::vector<RemoteReceiverListener *> listeners_;
std::vector<RemoteReceiverDumperBase *> dumpers_;
std::vector<RemoteReceiverDumperBase *> secondary_dumpers_;
std::vector<int32_t> temp_;
uint8_t tolerance_{25};
RawTimings temp_;
uint8_t tolerance_;
};
class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitiallyOff,
@ -288,15 +177,16 @@ class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitial
explicit RemoteReceiverBinarySensorBase() {}
void dump_config() override;
virtual bool matches(RemoteReceiveData src) = 0;
bool on_receive(RemoteReceiveData src) override {
if (this->matches(src)) {
this->publish_state(true);
yield();
this->publish_state(false);
return true;
}
return false;
}
bool on_receive(RemoteReceiveData src) override;
};
/* TEMPLATES */
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;
};
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};
bool inverted_{false};
#endif
uint8_t carrier_duty_percent_{50};
uint8_t carrier_duty_percent_;
};
} // namespace remote_transmitter