mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 05:24:53 +01:00
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
This commit is contained in:
parent
f4f1164b94
commit
4d31ad3bdc
3 changed files with 42 additions and 41 deletions
|
@ -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")
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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<typename... Ts> class RCSwitchRawAction : public RemoteTransmitterActionBase<Ts...> {
|
||||
public:
|
||||
|
@ -64,7 +64,7 @@ template<typename... Ts> 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<typename... Ts> 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<typename... Ts> 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<typename... Ts> class RCSwitchTypeCAction : public RemoteTransmitterAct
|
|||
|
||||
auto u_family = static_cast<uint8_t>(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<typename... Ts> class RCSwitchTypeDAction : public RemoteTransmitterAct
|
|||
|
||||
auto u_group = static_cast<uint8_t>(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<typename... Ts> 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_;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue