diff --git a/esphome/codegen.py b/esphome/codegen.py index 8361faeb81..c05cc5efca 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -60,6 +60,7 @@ from esphome.cpp_types import ( # noqa uint8, uint16, uint32, + uint64, int32, const_char_ptr, NAN, diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 76e4b51bde..9416c2220d 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -866,7 +866,8 @@ def rc_switch_dumper(var, config): ) = declare_protocol("Samsung") SAMSUNG_SCHEMA = cv.Schema( { - cv.Required(CONF_DATA): cv.hex_uint32_t, + cv.Required(CONF_DATA): cv.hex_uint64_t, + cv.Optional(CONF_NBITS, default=32): cv.int_range(32, 64), } ) @@ -878,6 +879,7 @@ def samsung_binary_sensor(var, config): cg.StructInitializer( SamsungData, ("data", config[CONF_DATA]), + ("nbits", config[CONF_NBITS]), ) ) ) @@ -895,8 +897,10 @@ def samsung_dumper(var, config): @register_action("samsung", SamsungAction, SAMSUNG_SCHEMA) async def samsung_action(var, config, args): - template_ = await cg.templatable(config[CONF_DATA], args, cg.uint32) + template_ = await cg.templatable(config[CONF_DATA], args, cg.uint64) cg.add(var.set_data(template_)) + template_ = await cg.templatable(config[CONF_NBITS], args, cg.uint8) + cg.add(var.set_nbits(template_)) # Samsung36 diff --git a/esphome/components/remote_base/samsung_protocol.cpp b/esphome/components/remote_base/samsung_protocol.cpp index 5062c46126..0f2605d865 100644 --- a/esphome/components/remote_base/samsung_protocol.cpp +++ b/esphome/components/remote_base/samsung_protocol.cpp @@ -6,7 +6,6 @@ namespace remote_base { static const char *const TAG = "remote.samsung"; -static const uint8_t NBITS = 32; static const uint32_t HEADER_HIGH_US = 4500; static const uint32_t HEADER_LOW_US = 4500; static const uint32_t BIT_HIGH_US = 560; @@ -17,12 +16,12 @@ static const uint32_t FOOTER_LOW_US = 560; void SamsungProtocol::encode(RemoteTransmitData *dst, const SamsungData &data) { dst->set_carrier_frequency(38000); - dst->reserve(4 + NBITS * 2u); + dst->reserve(4 + data.nbits * 2u); dst->item(HEADER_HIGH_US, HEADER_LOW_US); - for (uint32_t mask = 1UL << (NBITS - 1); mask != 0; mask >>= 1) { - if (data.data & mask) + for (uint8_t bit = data.nbits; bit > 0; bit--) { + if ((data.data >> (bit - 1)) & 1) dst->item(BIT_HIGH_US, BIT_ONE_LOW_US); else dst->item(BIT_HIGH_US, BIT_ZERO_LOW_US); @@ -33,16 +32,20 @@ void SamsungProtocol::encode(RemoteTransmitData *dst, const SamsungData &data) { optional SamsungProtocol::decode(RemoteReceiveData src) { SamsungData out{ .data = 0, + .nbits = 0, }; if (!src.expect_item(HEADER_HIGH_US, HEADER_LOW_US)) return {}; - for (uint8_t i = 0; i < NBITS; i++) { - out.data <<= 1UL; + for (out.nbits = 0; out.nbits < 64; out.nbits++) { if (src.expect_item(BIT_HIGH_US, BIT_ONE_LOW_US)) { - out.data |= 1UL; + out.data = (out.data << 1) | 1; } else if (src.expect_item(BIT_HIGH_US, BIT_ZERO_LOW_US)) { - out.data |= 0UL; + out.data = (out.data << 1) | 0; + } else if (out.nbits >= 31) { + if (!src.expect_mark(FOOTER_HIGH_US)) + return {}; + return out; } else { return {}; } @@ -52,7 +55,9 @@ optional SamsungProtocol::decode(RemoteReceiveData src) { return {}; return out; } -void SamsungProtocol::dump(const SamsungData &data) { ESP_LOGD(TAG, "Received Samsung: data=0x%08X", data.data); } +void SamsungProtocol::dump(const SamsungData &data) { + ESP_LOGD(TAG, "Received Samsung: data=0x%" PRIX64 ", nbits=%d", data.data, data.nbits); +} } // namespace remote_base } // namespace esphome diff --git a/esphome/components/remote_base/samsung_protocol.h b/esphome/components/remote_base/samsung_protocol.h index f7a54788e5..41434f2889 100644 --- a/esphome/components/remote_base/samsung_protocol.h +++ b/esphome/components/remote_base/samsung_protocol.h @@ -7,9 +7,10 @@ namespace esphome { namespace remote_base { struct SamsungData { - uint32_t data; + uint64_t data; + uint8_t nbits; - bool operator==(const SamsungData &rhs) const { return data == rhs.data; } + bool operator==(const SamsungData &rhs) const { return data == rhs.data && nbits == rhs.nbits; } }; class SamsungProtocol : public RemoteProtocol { @@ -23,11 +24,13 @@ DECLARE_REMOTE_PROTOCOL(Samsung) template class SamsungAction : public RemoteTransmitterActionBase { public: - TEMPLATABLE_VALUE(uint32_t, data) + TEMPLATABLE_VALUE(uint64_t, data) + TEMPLATABLE_VALUE(uint8_t, nbits) void encode(RemoteTransmitData *dst, Ts... x) override { SamsungData data{}; data.data = this->data_.value(x...); + data.nbits = this->nbits_.value(x...); SamsungProtocol().encode(dst, data); } }; diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 7292cc3af5..aad147dbc9 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1018,9 +1018,11 @@ def requires_component(comp): uint8_t = int_range(min=0, max=255) uint16_t = int_range(min=0, max=65535) uint32_t = int_range(min=0, max=4294967295) +uint64_t = int_range(min=0, max=18446744073709551615) hex_uint8_t = hex_int_range(min=0, max=255) hex_uint16_t = hex_int_range(min=0, max=65535) hex_uint32_t = hex_int_range(min=0, max=4294967295) +hex_uint64_t = hex_int_range(min=0, max=18446744073709551615) i2c_address = hex_uint8_t diff --git a/esphome/cpp_types.py b/esphome/cpp_types.py index 3036249a03..ee606ec7b3 100644 --- a/esphome/cpp_types.py +++ b/esphome/cpp_types.py @@ -13,6 +13,7 @@ std_vector = std_ns.class_("vector") uint8 = global_ns.namespace("uint8_t") uint16 = global_ns.namespace("uint16_t") uint32 = global_ns.namespace("uint32_t") +uint64 = global_ns.namespace("uint64_t") int32 = global_ns.namespace("int32_t") const_char_ptr = global_ns.namespace("const char *") NAN = global_ns.namespace("NAN")