mirror of
https://github.com/Threnklyn/esphome-dev.git
synced 2026-05-19 04:33:27 +02:00
6682c43dfa
## Description: Move esphome-core codebase into esphome (and a bunch of other refactors). See https://github.com/esphome/feature-requests/issues/97 Yes this is a shit ton of work and no there's no way to automate it :( But it will be worth it 👍 Progress: - Core support (file copy etc): 80% - Base Abstractions (light, switch): ~50% - Integrations: ~10% - Working? Yes, (but only with ported components). Other refactors: - Moves all codegen related stuff into a single class: `esphome.codegen` (imported as `cg`) - Rework coroutine syntax - Move from `component/platform.py` to `domain/component.py` structure as with HA - Move all defaults out of C++ and into config validation. - Remove `make_...` helpers from Application class. Reason: Merge conflicts with every single new integration. - Pointer Variables are stored globally instead of locally in setup(). Reason: stack size limit. Future work: - Rework const.py - Move all `CONF_...` into a conf class (usage `conf.UPDATE_INTERVAL` vs `CONF_UPDATE_INTERVAL`). Reason: Less convoluted import block - Enable loading from `custom_components` folder. **Related issue (if applicable):** https://github.com/esphome/feature-requests/issues/97 **Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here> ## Checklist: - [ ] The code change is tested and works locally. - [ ] Tests have been added to verify that the new code works (under `tests/` folder). If user exposed functionality or configuration variables are added/changed: - [ ] Documentation added/updated in [esphomedocs](https://github.com/OttoWinter/esphomedocs).
246 lines
7.7 KiB
C++
246 lines
7.7 KiB
C++
#include "rc_switch_protocol.h"
|
|
#include "esphome/core/log.h"
|
|
|
|
namespace esphome {
|
|
namespace remote_base {
|
|
|
|
static const char *TAG = "remote.rc_switch";
|
|
|
|
RCSwitchBase rc_switch_protocols[8] = {RCSwitchBase(0, 0, 0, 0, 0, 0, false),
|
|
RCSwitchBase(350, 10850, 350, 1050, 1050, 350, false),
|
|
RCSwitchBase(650, 6500, 650, 1300, 1300, 650, false),
|
|
RCSwitchBase(3000, 7100, 400, 1100, 900, 600, false),
|
|
RCSwitchBase(380, 2280, 380, 1140, 1140, 380, false),
|
|
RCSwitchBase(3000, 7000, 500, 1000, 1000, 500, false),
|
|
RCSwitchBase(10350, 450, 450, 900, 900, 450, true),
|
|
RCSwitchBase(300, 9300, 150, 900, 900, 150, false)};
|
|
|
|
RCSwitchBase::RCSwitchBase(uint32_t sync_high, uint32_t sync_low, uint32_t zero_high, uint32_t zero_low,
|
|
uint32_t one_high, uint32_t one_low, bool inverted)
|
|
: sync_high_(sync_high),
|
|
sync_low_(sync_low),
|
|
zero_high_(zero_high),
|
|
zero_low_(zero_low),
|
|
one_high_(one_high),
|
|
one_low_(one_low),
|
|
inverted_(inverted) {}
|
|
|
|
void RCSwitchBase::one(RemoteTransmitData *dst) const {
|
|
if (!this->inverted_) {
|
|
dst->mark(this->one_high_);
|
|
dst->space(this->one_low_);
|
|
} else {
|
|
dst->space(this->one_high_);
|
|
dst->mark(this->one_low_);
|
|
}
|
|
}
|
|
void RCSwitchBase::zero(RemoteTransmitData *dst) const {
|
|
if (!this->inverted_) {
|
|
dst->mark(this->zero_high_);
|
|
dst->space(this->zero_low_);
|
|
} else {
|
|
dst->space(this->zero_high_);
|
|
dst->mark(this->zero_low_);
|
|
}
|
|
}
|
|
void RCSwitchBase::sync(RemoteTransmitData *dst) const {
|
|
if (!this->inverted_) {
|
|
dst->mark(this->sync_high_);
|
|
dst->space(this->sync_low_);
|
|
} else {
|
|
dst->space(this->sync_high_);
|
|
dst->mark(this->sync_low_);
|
|
}
|
|
}
|
|
void RCSwitchBase::transmit(RemoteTransmitData *dst, uint32_t code, uint8_t len) const {
|
|
for (int16_t i = len - 1; i >= 0; i--) {
|
|
if (code & (1 << i))
|
|
this->one(dst);
|
|
else
|
|
this->zero(dst);
|
|
}
|
|
this->sync(dst);
|
|
}
|
|
|
|
bool RCSwitchBase::expect_one(RemoteReceiveData &src) const {
|
|
if (!this->inverted_) {
|
|
if (!src.peek_mark(this->one_high_))
|
|
return false;
|
|
if (!src.peek_space(this->one_low_, 1))
|
|
return false;
|
|
} else {
|
|
if (!src.peek_space(this->one_high_))
|
|
return false;
|
|
if (!src.peek_mark(this->one_low_, 1))
|
|
return false;
|
|
}
|
|
src.advance(2);
|
|
return true;
|
|
}
|
|
bool RCSwitchBase::expect_zero(RemoteReceiveData &src) const {
|
|
if (!this->inverted_) {
|
|
if (!src.peek_mark(this->zero_high_))
|
|
return false;
|
|
if (!src.peek_space(this->zero_low_, 1))
|
|
return false;
|
|
} else {
|
|
if (!src.peek_space(this->zero_high_))
|
|
return false;
|
|
if (!src.peek_mark(this->zero_low_, 1))
|
|
return false;
|
|
}
|
|
src.advance(2);
|
|
return true;
|
|
}
|
|
bool RCSwitchBase::expect_sync(RemoteReceiveData &src) const {
|
|
if (!this->inverted_) {
|
|
if (!src.peek_mark(this->sync_high_))
|
|
return false;
|
|
if (!src.peek_space(this->sync_low_, 1))
|
|
return false;
|
|
} else {
|
|
if (!src.peek_space(this->sync_high_))
|
|
return false;
|
|
if (!src.peek_mark(this->sync_low_, 1))
|
|
return false;
|
|
}
|
|
src.advance(2);
|
|
return true;
|
|
}
|
|
bool RCSwitchBase::decode(RemoteReceiveData &src, uint32_t *out_data, uint8_t *out_nbits) const {
|
|
// ignore if sync doesn't exist
|
|
this->expect_sync(src);
|
|
|
|
*out_data = 0;
|
|
for (*out_nbits = 1; *out_nbits < 32; *out_nbits += 1) {
|
|
if (this->expect_zero(src)) {
|
|
*out_data <<= 1;
|
|
*out_data |= 0;
|
|
} else if (this->expect_one(src)) {
|
|
*out_data <<= 1;
|
|
*out_data |= 1;
|
|
} else {
|
|
*out_nbits -= 1;
|
|
return *out_nbits >= 8;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void RCSwitchBase::simple_code_to_tristate(uint16_t code, uint8_t nbits, uint32_t *out_code) {
|
|
*out_code = 0;
|
|
for (int8_t i = nbits - 1; i >= 0; i--) {
|
|
*out_code <<= 2;
|
|
if (code & (1 << i))
|
|
*out_code |= 0b01;
|
|
else
|
|
*out_code |= 0b00;
|
|
}
|
|
}
|
|
void RCSwitchBase::type_a_code(uint8_t switch_group, uint8_t switch_device, bool state, uint32_t *out_code,
|
|
uint8_t *out_nbits) {
|
|
uint16_t code = 0;
|
|
code |= (switch_group & 0b0001) ? 0 : 0b1000;
|
|
code |= (switch_group & 0b0010) ? 0 : 0b0100;
|
|
code |= (switch_group & 0b0100) ? 0 : 0b0010;
|
|
code |= (switch_group & 0b1000) ? 0 : 0b0001;
|
|
code <<= 4;
|
|
code |= (switch_device & 0b0001) ? 0 : 0b1000;
|
|
code |= (switch_device & 0b0010) ? 0 : 0b0100;
|
|
code |= (switch_device & 0b0100) ? 0 : 0b0010;
|
|
code |= (switch_device & 0b1000) ? 0 : 0b0001;
|
|
code <<= 2;
|
|
code |= state ? 0b01 : 0b10;
|
|
simple_code_to_tristate(code, 10, out_code);
|
|
*out_nbits = 20;
|
|
}
|
|
void RCSwitchBase::type_b_code(uint8_t address_code, uint8_t channel_code, bool state, uint32_t *out_code,
|
|
uint8_t *out_nbits) {
|
|
uint16_t code = 0;
|
|
code |= (address_code == 1) ? 0 : 0b1000;
|
|
code |= (address_code == 2) ? 0 : 0b0100;
|
|
code |= (address_code == 3) ? 0 : 0b0010;
|
|
code |= (address_code == 4) ? 0 : 0b0001;
|
|
code <<= 4;
|
|
code |= (channel_code == 1) ? 0 : 0b1000;
|
|
code |= (channel_code == 2) ? 0 : 0b0100;
|
|
code |= (channel_code == 3) ? 0 : 0b0010;
|
|
code |= (channel_code == 4) ? 0 : 0b0001;
|
|
code <<= 4;
|
|
code |= 0b1110;
|
|
code |= state ? 0b1 : 0b0;
|
|
simple_code_to_tristate(code, 12, out_code);
|
|
*out_nbits = 24;
|
|
}
|
|
void RCSwitchBase::type_c_code(uint8_t family, uint8_t group, uint8_t device, bool state, uint32_t *out_code,
|
|
uint8_t *out_nbits) {
|
|
uint16_t code = 0;
|
|
code |= (family & 0b0001) ? 0b1000 : 0;
|
|
code |= (family & 0b0010) ? 0b0100 : 0;
|
|
code |= (family & 0b0100) ? 0b0010 : 0;
|
|
code |= (family & 0b1000) ? 0b0001 : 0;
|
|
code <<= 4;
|
|
code |= ((device - 1) & 0b01) ? 0b1000 : 0;
|
|
code |= ((device - 1) & 0b10) ? 0b0100 : 0;
|
|
code |= ((group - 1) & 0b01) ? 0b0010 : 0;
|
|
code |= ((group - 1) & 0b10) ? 0b0001 : 0;
|
|
code <<= 4;
|
|
code |= 0b0110;
|
|
code |= state ? 0b1 : 0b0;
|
|
simple_code_to_tristate(code, 12, out_code);
|
|
*out_nbits = 24;
|
|
}
|
|
void RCSwitchBase::type_d_code(uint8_t group, uint8_t device, bool state, uint32_t *out_code, uint8_t *out_nbits) {
|
|
*out_code = 0;
|
|
*out_code |= (group == 0) ? 0b11000000 : 0b01000000;
|
|
*out_code |= (group == 1) ? 0b00110000 : 0b00010000;
|
|
*out_code |= (group == 2) ? 0b00001100 : 0b00000100;
|
|
*out_code |= (group == 3) ? 0b00000011 : 0b00000001;
|
|
*out_code <<= 6;
|
|
*out_code |= (device == 1) ? 0b110000 : 0b010000;
|
|
*out_code |= (device == 2) ? 0b001100 : 0b000100;
|
|
*out_code |= (device == 3) ? 0b000011 : 0b000001;
|
|
*out_code <<= 6;
|
|
*out_code |= 0b000000;
|
|
*out_code <<= 4;
|
|
*out_code |= state ? 0b1100 : 0b0011;
|
|
*out_nbits = 24;
|
|
}
|
|
|
|
uint32_t decode_binary_string(const std::string &data) {
|
|
uint32_t ret = 0;
|
|
for (char c : data) {
|
|
ret <<= 1UL;
|
|
ret |= (c != '0');
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool RCSwitchRawReceiver::matches(RemoteReceiveData src) {
|
|
uint32_t decoded_code;
|
|
uint8_t decoded_nbits;
|
|
if (!this->protocol_.decode(src, &decoded_code, &decoded_nbits))
|
|
return false;
|
|
|
|
return decoded_nbits == this->nbits_ && decoded_code == this->code_;
|
|
}
|
|
void RCSwitchDumper::dump(RemoteReceiveData src) {
|
|
for (uint8_t i = 1; i <= 7; i++) {
|
|
src.reset();
|
|
uint32_t out_data;
|
|
uint8_t out_nbits;
|
|
RCSwitchBase *protocol = &rc_switch_protocols[i];
|
|
if (protocol->decode(src, &out_data, &out_nbits)) {
|
|
char buffer[32];
|
|
for (uint8_t j = 0; j < out_nbits; j++)
|
|
buffer[j] = (out_data & (1 << (out_nbits - j - 1))) ? '1' : '0';
|
|
|
|
buffer[out_nbits] = '\0';
|
|
ESP_LOGD(TAG, "Received RCSwitch Raw: protocol=%u data='%s'", i, buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace remote_base
|
|
} // namespace esphome
|