From bdf004867da39a1cc2d39041a09b7db1baa5b488 Mon Sep 17 00:00:00 2001 From: Seppel Hardt Date: Sun, 28 Feb 2021 00:16:27 +0100 Subject: [PATCH] Added samsung36 ir protocol (#1438) * Added samsung36 ir protocol * Make linter happy * Added test and fixed python failure * Sorry for the commits but linter was still not happy :) * Okay have to run script/clang-format -i Co-authored-by: tuxBurner --- esphome/components/remote_base/__init__.py | 36 ++++++ .../remote_base/samsung36_protocol.cpp | 103 ++++++++++++++++++ .../remote_base/samsung36_protocol.h | 39 +++++++ tests/test1.yaml | 6 + 4 files changed, 184 insertions(+) create mode 100644 esphome/components/remote_base/samsung36_protocol.cpp create mode 100644 esphome/components/remote_base/samsung36_protocol.h diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 770394faec..cc48ffc5b2 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -686,6 +686,42 @@ def samsung_action(var, config, args): cg.add(var.set_data(template_)) +# Samsung36 +(Samsung36Data, Samsung36BinarySensor, Samsung36Trigger, Samsung36Action, + Samsung36Dumper) = declare_protocol('Samsung36') +SAMSUNG36_SCHEMA = cv.Schema({ + cv.Required(CONF_ADDRESS): cv.hex_uint16_t, + cv.Required(CONF_COMMAND): cv.hex_uint32_t, +}) + + +@register_binary_sensor('samsung36', Samsung36BinarySensor, SAMSUNG36_SCHEMA) +def samsung36_binary_sensor(var, config): + cg.add(var.set_data(cg.StructInitializer( + Samsung36Data, + ('address', config[CONF_ADDRESS]), + ('command', config[CONF_COMMAND]), + ))) + + +@register_trigger('samsung36', Samsung36Trigger, Samsung36Data) +def samsung36_trigger(var, config): + pass + + +@register_dumper('samsung36', Samsung36Dumper) +def samsung36_dumper(var, config): + pass + + +@register_action('samsung36', Samsung36Action, SAMSUNG36_SCHEMA) +def samsung36_action(var, config, args): + template_ = yield cg.templatable(config[CONF_ADDRESS], args, cg.uint16) + cg.add(var.set_address(template_)) + template_ = yield cg.templatable(config[CONF_COMMAND], args, cg.uint32) + cg.add(var.set_command(template_)) + + # Panasonic (PanasonicData, PanasonicBinarySensor, PanasonicTrigger, PanasonicAction, PanasonicDumper) = declare_protocol('Panasonic') diff --git a/esphome/components/remote_base/samsung36_protocol.cpp b/esphome/components/remote_base/samsung36_protocol.cpp new file mode 100644 index 0000000000..22b158fd8a --- /dev/null +++ b/esphome/components/remote_base/samsung36_protocol.cpp @@ -0,0 +1,103 @@ +#include "samsung36_protocol.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace remote_base { + +static const char *TAG = "remote.samsung36"; + +static const uint8_t NBITS = 78; + +static const uint32_t HEADER_HIGH_US = 4500; +static const uint32_t HEADER_LOW_US = 4500; +static const uint32_t BIT_HIGH_US = 500; +static const uint32_t BIT_ONE_LOW_US = 1500; +static const uint32_t BIT_ZERO_LOW_US = 500; +static const uint32_t MIDDLE_HIGH_US = 500; +static const uint32_t MIDDLE_LOW_US = 4500; +static const uint32_t FOOTER_HIGH_US = 500; +static const uint32_t FOOTER_LOW_US = 59000; + +void Samsung36Protocol::encode(RemoteTransmitData *dst, const Samsung36Data &data) { + dst->set_carrier_frequency(38000); + dst->reserve(NBITS); + + // send header + dst->item(HEADER_HIGH_US, HEADER_LOW_US); + + // send first 16 bits + for (uint32_t mask = 1UL << 15; mask != 0; mask >>= 1) { + if (data.address & mask) { + dst->item(BIT_HIGH_US, BIT_ONE_LOW_US); + } else { + dst->item(BIT_HIGH_US, BIT_ZERO_LOW_US); + } + } + + // send middle header + dst->item(MIDDLE_HIGH_US, MIDDLE_LOW_US); + + // send last 20 bits + for (uint32_t mask = 1UL << 19; mask != 0; mask >>= 1) { + if (data.command & mask) { + dst->item(BIT_HIGH_US, BIT_ONE_LOW_US); + } else { + dst->item(BIT_HIGH_US, BIT_ZERO_LOW_US); + } + } + + // footer + dst->item(FOOTER_HIGH_US, FOOTER_LOW_US); +} + +optional Samsung36Protocol::decode(RemoteReceiveData src) { + Samsung36Data out{ + .address = 0, + .command = 0, + }; + + // check if header matches + if (!src.expect_item(HEADER_HIGH_US, HEADER_LOW_US)) + return {}; + + // check if we have enough bits + if (src.size() != NBITS) + return {}; + + // get the first 16 bits + for (uint8_t i = 0; i < 16; i++) { + out.address <<= 1UL; + if (src.expect_item(BIT_HIGH_US, BIT_ONE_LOW_US)) { + out.address |= 1UL; + } else if (src.expect_item(BIT_HIGH_US, BIT_ZERO_LOW_US)) { + out.address |= 0UL; + } else { + return {}; + } + } + + // check if the middle mark matches + if (!src.expect_item(MIDDLE_HIGH_US, MIDDLE_LOW_US)) { + return {}; + } + + // get the last 20 bits + for (uint8_t i = 0; i < 20; i++) { + out.command <<= 1UL; + if (src.expect_item(BIT_HIGH_US, BIT_ONE_LOW_US)) { + out.command |= 1UL; + } else if (src.expect_item(BIT_HIGH_US, BIT_ZERO_LOW_US)) { + out.command |= 0UL; + } else { + return {}; + } + } + + return out; +} +void Samsung36Protocol::dump(const Samsung36Data &data) { + ESP_LOGD(TAG, "Received Samsung36: address=0x%04X, command=0x%08X", data.address, data.command); +} + +} // namespace remote_base +} // namespace esphome diff --git a/esphome/components/remote_base/samsung36_protocol.h b/esphome/components/remote_base/samsung36_protocol.h new file mode 100644 index 0000000000..4ba6226edd --- /dev/null +++ b/esphome/components/remote_base/samsung36_protocol.h @@ -0,0 +1,39 @@ +#pragma once + +#include "esphome/core/component.h" +#include "remote_base.h" + +namespace esphome { +namespace remote_base { + +struct Samsung36Data { + uint16_t address; + uint32_t command; + + bool operator==(const Samsung36Data &rhs) const { return address == rhs.address && command == rhs.command; } +}; + +class Samsung36Protocol : public RemoteProtocol { + public: + void encode(RemoteTransmitData *dst, const Samsung36Data &data) override; + optional decode(RemoteReceiveData src) override; + void dump(const Samsung36Data &data) override; +}; + +DECLARE_REMOTE_PROTOCOL(Samsung36) + +template class Samsung36Action : public RemoteTransmitterActionBase { + public: + TEMPLATABLE_VALUE(uint16_t, address) + TEMPLATABLE_VALUE(uint32_t, command) + + void encode(RemoteTransmitData *dst, Ts... x) override { + Samsung36Data data{}; + data.address = this->address_.value(x...); + data.command = this->command_.value(x...); + Samsung36Protocol().encode(dst, data); + } +}; + +} // namespace remote_base +} // namespace esphome diff --git a/tests/test1.yaml b/tests/test1.yaml index e76d1d24c0..59c2bf96c4 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1478,6 +1478,12 @@ switch: turn_on_action: remote_transmitter.transmit_samsung: data: 0xABCDEF + - platform: template + name: Samsung36 + turn_on_action: + remote_transmitter.transmit_samsung36: + address: 0x0400 + command: 0x000E00FF - platform: template name: Sony turn_on_action: