From 4d31ad3bdc7d7182de4abb22079a9629eba50321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ab=C3=ADlio=20Costa?= Date: Sat, 12 Oct 2019 13:42:27 +0100 Subject: [PATCH] Allow 64 bit codes and add nexa remote support. (#662) * add nexa remote support. This is inspired by: https://github.com/sui77/rc-switch/pull/124 As described there: "The remotes sold in ClasOhlson in scandinavia have a slightly longer sync sequence(added a skip pulse field in the protocol) and a 64 bit code word. Part of the code gets lost but that seems to be OK until support for 64 bit codes is added." * add default value to ctor * allow 64bit codes * lint * make vars 64 bits --- esphome/components/remote_base/__init__.py | 10 ++--- .../remote_base/rc_switch_protocol.cpp | 37 ++++++++++--------- .../remote_base/rc_switch_protocol.h | 36 +++++++++--------- 3 files changed, 42 insertions(+), 41 deletions(-) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index f3042e5598..a62304c87d 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -420,7 +420,7 @@ def rc5_action(var, config, args): RC_SWITCH_TIMING_SCHEMA = cv.All([cv.uint8_t], cv.Length(min=2, max=2)) RC_SWITCH_PROTOCOL_SCHEMA = cv.Any( - cv.int_range(min=1, max=7), + cv.int_range(min=1, max=8), cv.Schema({ cv.Required(CONF_PULSE_LENGTH): cv.uint32_t, cv.Optional(CONF_SYNC, default=[1, 31]): RC_SWITCH_TIMING_SCHEMA, @@ -438,8 +438,8 @@ def validate_rc_switch_code(value): if c not in ('0', '1'): raise cv.Invalid(u"Invalid RCSwitch code character '{}'. Only '0' and '1' are allowed" u"".format(c)) - if len(value) > 32: - raise cv.Invalid("Maximum length for RCSwitch codes is 32, code '{}' has length {}" + if len(value) > 64: + raise cv.Invalid("Maximum length for RCSwitch codes is 64, code '{}' has length {}" "".format(value, len(value))) if not value: raise cv.Invalid("RCSwitch code must not be empty") @@ -454,8 +454,8 @@ def validate_rc_switch_raw_code(value): raise cv.Invalid( "Invalid RCSwitch raw code character '{}'.Only '0', '1' and 'x' are allowed" .format(c)) - if len(value) > 32: - raise cv.Invalid("Maximum length for RCSwitch raw codes is 32, code '{}' has length {}" + if len(value) > 64: + raise cv.Invalid("Maximum length for RCSwitch raw codes is 64, code '{}' has length {}" "".format(value, len(value))) if not value: raise cv.Invalid("RCSwitch raw code must not be empty") diff --git a/esphome/components/remote_base/rc_switch_protocol.cpp b/esphome/components/remote_base/rc_switch_protocol.cpp index a04b13ecfd..258e6352e2 100644 --- a/esphome/components/remote_base/rc_switch_protocol.cpp +++ b/esphome/components/remote_base/rc_switch_protocol.cpp @@ -6,14 +6,15 @@ namespace remote_base { static const char *TAG = "remote.rc_switch"; -RCSwitchBase rc_switch_protocols[8] = {RCSwitchBase(0, 0, 0, 0, 0, 0, false), +RCSwitchBase rc_switch_protocols[9] = {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(300, 9300, 150, 900, 900, 150, false), + RCSwitchBase(250, 2500, 250, 1250, 250, 250, 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) @@ -52,7 +53,7 @@ void RCSwitchBase::sync(RemoteTransmitData *dst) const { dst->mark(this->sync_low_); } } -void RCSwitchBase::transmit(RemoteTransmitData *dst, uint32_t code, uint8_t len) const { +void RCSwitchBase::transmit(RemoteTransmitData *dst, uint64_t code, uint8_t len) const { dst->set_carrier_frequency(0); for (int16_t i = len - 1; i >= 0; i--) { if (code & (1 << i)) @@ -108,12 +109,12 @@ bool RCSwitchBase::expect_sync(RemoteReceiveData &src) const { src.advance(2); return true; } -bool RCSwitchBase::decode(RemoteReceiveData &src, uint32_t *out_data, uint8_t *out_nbits) const { +bool RCSwitchBase::decode(RemoteReceiveData &src, uint64_t *out_data, uint8_t *out_nbits) const { // ignore if sync doesn't exist this->expect_sync(src); *out_data = 0; - for (*out_nbits = 0; *out_nbits < 32; *out_nbits += 1) { + for (*out_nbits = 0; *out_nbits < 64; *out_nbits += 1) { if (this->expect_zero(src)) { *out_data <<= 1; *out_data |= 0; @@ -127,7 +128,7 @@ bool RCSwitchBase::decode(RemoteReceiveData &src, uint32_t *out_data, uint8_t *o return true; } -void RCSwitchBase::simple_code_to_tristate(uint16_t code, uint8_t nbits, uint32_t *out_code) { +void RCSwitchBase::simple_code_to_tristate(uint16_t code, uint8_t nbits, uint64_t *out_code) { *out_code = 0; for (int8_t i = nbits - 1; i >= 0; i--) { *out_code <<= 2; @@ -137,7 +138,7 @@ void RCSwitchBase::simple_code_to_tristate(uint16_t code, uint8_t nbits, uint32_ *out_code |= 0b00; } } -void RCSwitchBase::type_a_code(uint8_t switch_group, uint8_t switch_device, bool state, uint32_t *out_code, +void RCSwitchBase::type_a_code(uint8_t switch_group, uint8_t switch_device, bool state, uint64_t *out_code, uint8_t *out_nbits) { uint16_t code = 0; code |= (switch_group & 0b0001) ? 0 : 0b1000; @@ -154,7 +155,7 @@ void RCSwitchBase::type_a_code(uint8_t switch_group, uint8_t switch_device, bool 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, +void RCSwitchBase::type_b_code(uint8_t address_code, uint8_t channel_code, bool state, uint64_t *out_code, uint8_t *out_nbits) { uint16_t code = 0; code |= (address_code == 1) ? 0 : 0b1000; @@ -172,7 +173,7 @@ void RCSwitchBase::type_b_code(uint8_t address_code, uint8_t channel_code, bool 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, +void RCSwitchBase::type_c_code(uint8_t family, uint8_t group, uint8_t device, bool state, uint64_t *out_code, uint8_t *out_nbits) { uint16_t code = 0; code |= (family & 0b0001) ? 0b1000 : 0; @@ -190,7 +191,7 @@ void RCSwitchBase::type_c_code(uint8_t family, uint8_t group, uint8_t device, bo 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) { +void RCSwitchBase::type_d_code(uint8_t group, uint8_t device, bool state, uint64_t *out_code, uint8_t *out_nbits) { *out_code = 0; *out_code |= (group == 0) ? 0b11000000 : 0b01000000; *out_code |= (group == 1) ? 0b00110000 : 0b00010000; @@ -207,8 +208,8 @@ void RCSwitchBase::type_d_code(uint8_t group, uint8_t device, bool state, uint32 *out_nbits = 24; } -uint32_t decode_binary_string(const std::string &data) { - uint32_t ret = 0; +uint64_t decode_binary_string(const std::string &data) { + uint64_t ret = 0; for (char c : data) { ret <<= 1UL; ret |= (c != '0'); @@ -216,8 +217,8 @@ uint32_t decode_binary_string(const std::string &data) { return ret; } -uint32_t decode_binary_string_mask(const std::string &data) { - uint32_t ret = 0; +uint64_t decode_binary_string_mask(const std::string &data) { + uint64_t ret = 0; for (char c : data) { ret <<= 1UL; ret |= (c != 'x'); @@ -226,7 +227,7 @@ uint32_t decode_binary_string_mask(const std::string &data) { } bool RCSwitchRawReceiver::matches(RemoteReceiveData src) { - uint32_t decoded_code; + uint64_t decoded_code; uint8_t decoded_nbits; if (!this->protocol_.decode(src, &decoded_code, &decoded_nbits)) return false; @@ -234,13 +235,13 @@ bool RCSwitchRawReceiver::matches(RemoteReceiveData src) { return decoded_nbits == this->nbits_ && (decoded_code & this->mask_) == (this->code_ & this->mask_); } bool RCSwitchDumper::dump(RemoteReceiveData src) { - for (uint8_t i = 1; i <= 7; i++) { + for (uint8_t i = 1; i <= 8; i++) { src.reset(); - uint32_t out_data; + uint64_t out_data; uint8_t out_nbits; RCSwitchBase *protocol = &rc_switch_protocols[i]; if (protocol->decode(src, &out_data, &out_nbits) && out_nbits >= 3) { - char buffer[33]; + char buffer[65]; for (uint8_t j = 0; j < out_nbits; j++) buffer[j] = (out_data & (1 << (out_nbits - j - 1))) ? '1' : '0'; diff --git a/esphome/components/remote_base/rc_switch_protocol.h b/esphome/components/remote_base/rc_switch_protocol.h index d937efbd25..0983da27ea 100644 --- a/esphome/components/remote_base/rc_switch_protocol.h +++ b/esphome/components/remote_base/rc_switch_protocol.h @@ -18,7 +18,7 @@ class RCSwitchBase { void sync(RemoteTransmitData *dst) const; - void transmit(RemoteTransmitData *dst, uint32_t code, uint8_t len) const; + void transmit(RemoteTransmitData *dst, uint64_t code, uint8_t len) const; bool expect_one(RemoteReceiveData &src) const; @@ -26,20 +26,20 @@ class RCSwitchBase { bool expect_sync(RemoteReceiveData &src) const; - bool decode(RemoteReceiveData &src, uint32_t *out_data, uint8_t *out_nbits) const; + bool decode(RemoteReceiveData &src, uint64_t *out_data, uint8_t *out_nbits) const; - static void simple_code_to_tristate(uint16_t code, uint8_t nbits, uint32_t *out_code); + static void simple_code_to_tristate(uint16_t code, uint8_t nbits, uint64_t *out_code); - static void type_a_code(uint8_t switch_group, uint8_t switch_device, bool state, uint32_t *out_code, + static void type_a_code(uint8_t switch_group, uint8_t switch_device, bool state, uint64_t *out_code, uint8_t *out_nbits); - static void type_b_code(uint8_t address_code, uint8_t channel_code, bool state, uint32_t *out_code, + static void type_b_code(uint8_t address_code, uint8_t channel_code, bool state, uint64_t *out_code, uint8_t *out_nbits); - static void type_c_code(uint8_t family, uint8_t group, uint8_t device, bool state, uint32_t *out_code, + static void type_c_code(uint8_t family, uint8_t group, uint8_t device, bool state, uint64_t *out_code, uint8_t *out_nbits); - static void type_d_code(uint8_t group, uint8_t device, bool state, uint32_t *out_code, uint8_t *out_nbits); + static void type_d_code(uint8_t group, uint8_t device, bool state, uint64_t *out_code, uint8_t *out_nbits); protected: uint32_t sync_high_{}; @@ -51,11 +51,11 @@ class RCSwitchBase { bool inverted_{}; }; -extern RCSwitchBase rc_switch_protocols[8]; +extern RCSwitchBase rc_switch_protocols[9]; -uint32_t decode_binary_string(const std::string &data); +uint64_t decode_binary_string(const std::string &data); -uint32_t decode_binary_string_mask(const std::string &data); +uint64_t decode_binary_string_mask(const std::string &data); template class RCSwitchRawAction : public RemoteTransmitterActionBase { public: @@ -64,7 +64,7 @@ template class RCSwitchRawAction : public RemoteTransmitterActio void encode(RemoteTransmitData *dst, Ts... x) override { auto code = this->code_.value(x...); - uint32_t the_code = decode_binary_string(code); + uint64_t the_code = decode_binary_string(code); uint8_t nbits = code.size(); auto proto = this->protocol_.value(x...); @@ -86,7 +86,7 @@ template class RCSwitchTypeAAction : public RemoteTransmitterAct uint8_t u_group = decode_binary_string(group); uint8_t u_device = decode_binary_string(device); - uint32_t code; + uint64_t code; uint8_t nbits; RCSwitchBase::type_a_code(u_group, u_device, state, &code, &nbits); @@ -107,7 +107,7 @@ template class RCSwitchTypeBAction : public RemoteTransmitterAct auto channel = this->channel_.value(x...); auto state = this->state_.value(x...); - uint32_t code; + uint64_t code; uint8_t nbits; RCSwitchBase::type_b_code(address, channel, state, &code, &nbits); @@ -132,7 +132,7 @@ template class RCSwitchTypeCAction : public RemoteTransmitterAct auto u_family = static_cast(tolower(family[0]) - 'a'); - uint32_t code; + uint64_t code; uint8_t nbits; RCSwitchBase::type_c_code(u_family, group, device, state, &code, &nbits); @@ -154,7 +154,7 @@ template class RCSwitchTypeDAction : public RemoteTransmitterAct auto u_group = static_cast(tolower(group[0]) - 'a'); - uint32_t code; + uint64_t code; uint8_t nbits; RCSwitchBase::type_d_code(u_group, device, state, &code, &nbits); @@ -166,7 +166,7 @@ template class RCSwitchTypeDAction : public RemoteTransmitterAct class RCSwitchRawReceiver : public RemoteReceiverBinarySensorBase { public: void set_protocol(const RCSwitchBase &a_protocol) { this->protocol_ = a_protocol; } - void set_code(uint32_t code) { this->code_ = code; } + void set_code(uint64_t code) { this->code_ = code; } void set_code(const std::string &code) { this->code_ = decode_binary_string(code); this->mask_ = decode_binary_string_mask(code); @@ -194,8 +194,8 @@ class RCSwitchRawReceiver : public RemoteReceiverBinarySensorBase { bool matches(RemoteReceiveData src) override; RCSwitchBase protocol_; - uint32_t code_; - uint32_t mask_{0xFFFFFFFF}; + uint64_t code_; + uint64_t mask_{0xFFFFFFFFFFFFFFFF}; uint8_t nbits_; };