mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 13:34:54 +01:00
remote_base changes (#5124)
This commit is contained in:
parent
a120a455bf
commit
794a4bd9a1
6 changed files with 147 additions and 164 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue