ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
rc_switch_protocol.h
Go to the documentation of this file.
1#pragma once
2
3#include <type_traits>
4
6#include "remote_base.h"
7
8namespace esphome::remote_base {
9
11 uint64_t code;
12 uint8_t protocol;
13
14 bool operator==(const RCSwitchData &rhs) const { return code == rhs.code && protocol == rhs.protocol; }
15};
16
18 public:
20
21 constexpr RCSwitchBase() = default;
22 constexpr RCSwitchBase(uint32_t sync_high, uint32_t sync_low, uint32_t zero_high, uint32_t zero_low,
23 uint32_t one_high, uint32_t one_low, bool inverted)
24 : sync_high_(sync_high),
25 sync_low_(sync_low),
26 zero_high_(zero_high),
27 zero_low_(zero_low),
28 one_high_(one_high),
29 one_low_(one_low),
30 inverted_(inverted) {}
31
32 void one(RemoteTransmitData *dst) const;
33
34 void zero(RemoteTransmitData *dst) const;
35
36 void sync(RemoteTransmitData *dst) const;
37
38 void transmit(RemoteTransmitData *dst, uint64_t code, uint8_t len) const;
39
40 bool expect_one(RemoteReceiveData &src) const;
41
43
45
46 bool decode(RemoteReceiveData &src, uint64_t *out_data, uint8_t *out_nbits) const;
47
48 optional<RCSwitchData> decode(RemoteReceiveData &src) const;
49
50 static void simple_code_to_tristate(uint16_t code, uint8_t nbits, uint64_t *out_code);
51
52 static void type_a_code(uint8_t switch_group, uint8_t switch_device, bool state, uint64_t *out_code,
53 uint8_t *out_nbits);
54
55 static void type_b_code(uint8_t address_code, uint8_t channel_code, bool state, uint64_t *out_code,
56 uint8_t *out_nbits);
57
58 static void type_c_code(uint8_t family, uint8_t group, uint8_t device, bool state, uint64_t *out_code,
59 uint8_t *out_nbits);
60
61 static void type_d_code(uint8_t group, uint8_t device, bool state, uint64_t *out_code, uint8_t *out_nbits);
62
63 protected:
70 uint32_t inverted_{}; // bool widened so every field is a word: the table is read from flash
71
72 // A bool here would still pad to 28 bytes, so the size check below alone would not catch it.
73 static_assert(std::is_same_v<decltype(inverted_), uint32_t>, "inverted_ must stay a word for flash reads");
74};
75
76// Constant-initialized and kept in flash on every platform. The decoder reads entries in place
77// through a pointer, which ESP8266 only allows while every field is a whole word; copies out of
78// the table go through rc_switch_protocol()
79static_assert(sizeof(RCSwitchBase) == 7 * sizeof(uint32_t), "RCSwitchBase must stay word-only for flash reads");
80inline constexpr RCSwitchBase RC_SWITCH_PROTOCOLS[] PROGMEM = {
81 {0, 0, 0, 0, 0, 0, false},
82 {350, 10850, 350, 1050, 1050, 350, false},
83 {650, 6500, 650, 1300, 1300, 650, false},
84 {3000, 7100, 400, 1100, 900, 600, false},
85 {380, 2280, 380, 1140, 1140, 380, false},
86 {3000, 7000, 500, 1000, 1000, 500, false},
87 {10350, 450, 450, 900, 900, 450, true},
88 {300, 9300, 150, 900, 900, 150, false},
89 {250, 2500, 250, 1250, 250, 250, false},
90};
91
94RCSwitchBase rc_switch_protocol(uint8_t index);
97RCSwitchBase rc_switch_protocol_copy(const RCSwitchBase *protocol);
98
99uint64_t decode_binary_string(const std::string &data);
100
101uint64_t decode_binary_string_mask(const std::string &data);
102
103template<typename... Ts> class RCSwitchRawAction : public RemoteTransmitterActionBase<Ts...> {
104 public:
106 TEMPLATABLE_VALUE(std::string, code);
107
108 void encode(RemoteTransmitData *dst, Ts... x) override {
109 auto code = this->code_.value(x...);
110 uint64_t the_code = decode_binary_string(code);
111 uint8_t nbits = code.size();
112
113 auto proto = this->protocol_.value(x...);
114 proto.transmit(dst, the_code, nbits);
115 }
116};
117
118template<typename... Ts> class RCSwitchTypeAAction : public RemoteTransmitterActionBase<Ts...> {
119 public:
121 TEMPLATABLE_VALUE(std::string, group);
122 TEMPLATABLE_VALUE(std::string, device);
124
125 void encode(RemoteTransmitData *dst, Ts... x) override {
126 auto group = this->group_.value(x...);
127 auto device = this->device_.value(x...);
128 auto state = this->state_.value(x...);
129 uint8_t u_group = decode_binary_string(group);
130 uint8_t u_device = decode_binary_string(device);
131
132 uint64_t code;
133 uint8_t nbits;
134 RCSwitchBase::type_a_code(u_group, u_device, state, &code, &nbits);
135
136 auto proto = this->protocol_.value(x...);
137 proto.transmit(dst, code, nbits);
138 }
139};
140
141template<typename... Ts> class RCSwitchTypeBAction : public RemoteTransmitterActionBase<Ts...> {
142 public:
145 TEMPLATABLE_VALUE(uint8_t, channel);
147
148 void encode(RemoteTransmitData *dst, Ts... x) override {
149 auto address = this->address_.value(x...);
150 auto channel = this->channel_.value(x...);
151 auto state = this->state_.value(x...);
152
153 uint64_t code;
154 uint8_t nbits;
155 RCSwitchBase::type_b_code(address, channel, state, &code, &nbits);
156
157 auto proto = this->protocol_.value(x...);
158 proto.transmit(dst, code, nbits);
159 }
160};
161
162template<typename... Ts> class RCSwitchTypeCAction : public RemoteTransmitterActionBase<Ts...> {
163 public:
165 TEMPLATABLE_VALUE(std::string, family);
166 TEMPLATABLE_VALUE(uint8_t, group);
167 TEMPLATABLE_VALUE(uint8_t, device);
169
170 void encode(RemoteTransmitData *dst, Ts... x) override {
171 auto family = this->family_.value(x...);
172 auto group = this->group_.value(x...);
173 auto device = this->device_.value(x...);
174 auto state = this->state_.value(x...);
175
176 auto u_family = static_cast<uint8_t>(tolower(family[0]) - 'a');
177
178 uint64_t code;
179 uint8_t nbits;
180 RCSwitchBase::type_c_code(u_family, group, device, state, &code, &nbits);
181
182 auto proto = this->protocol_.value(x...);
183 proto.transmit(dst, code, nbits);
184 }
185};
186template<typename... Ts> class RCSwitchTypeDAction : public RemoteTransmitterActionBase<Ts...> {
187 public:
189 TEMPLATABLE_VALUE(std::string, group);
190 TEMPLATABLE_VALUE(uint8_t, device);
192
193 void encode(RemoteTransmitData *dst, Ts... x) override {
194 auto group = this->group_.value(x...);
195 auto device = this->device_.value(x...);
196 auto state = this->state_.value(x...);
197
198 auto u_group = static_cast<uint8_t>(tolower(group[0]) - 'a');
199
200 uint64_t code;
201 uint8_t nbits;
202 RCSwitchBase::type_d_code(u_group, device, state, &code, &nbits);
203
204 auto proto = this->protocol_.value(x...);
205 proto.transmit(dst, code, nbits);
206 }
207};
208
210 public:
212 void set_protocol(const RCSwitchBase *protocol) { this->protocol_ = protocol; }
213 void set_code(uint64_t code) { this->code_ = code; }
214 void set_code(const std::string &code) {
215 this->code_ = decode_binary_string(code);
216 this->mask_ = decode_binary_string_mask(code);
217 this->nbits_ = code.size();
218 }
219 void set_nbits(uint8_t nbits) { this->nbits_ = nbits; }
220 void set_type_a(const std::string &group, const std::string &device, bool state) {
221 uint8_t u_group = decode_binary_string(group);
222 uint8_t u_device = decode_binary_string(device);
223 RCSwitchBase::type_a_code(u_group, u_device, state, &this->code_, &this->nbits_);
224 }
225 void set_type_b(uint8_t address_code, uint8_t channel_code, bool state) {
226 RCSwitchBase::type_b_code(address_code, channel_code, state, &this->code_, &this->nbits_);
227 }
228 void set_type_c(std::string family, uint8_t group, uint8_t device, bool state) {
229 auto u_family = static_cast<uint8_t>(tolower(family[0]) - 'a');
230 RCSwitchBase::type_c_code(u_family, group, device, state, &this->code_, &this->nbits_);
231 }
232 void set_type_d(std::string group, uint8_t device, bool state) {
233 auto u_group = static_cast<uint8_t>(tolower(group[0]) - 'a');
234 RCSwitchBase::type_d_code(u_group, device, state, &this->code_, &this->nbits_);
235 }
236
237 protected:
238 bool matches(RemoteReceiveData src) override;
239
240 const RCSwitchBase *protocol_{nullptr}; // in flash; decoded in place (word-only fields)
241 uint64_t code_;
242 uint64_t mask_{0xFFFFFFFFFFFFFFFF};
243 uint8_t nbits_;
244};
245
247 public:
248 bool dump(RemoteReceiveData src) override;
249};
250
252
253} // namespace esphome::remote_base
uint8_t address
Definition bl0906.h:4
bool state
The current state of this binary sensor. Also used as the backing storage for StatefulEntityBase.
constexpr RCSwitchBase()=default
void zero(RemoteTransmitData *dst) const
static void type_b_code(uint8_t address_code, uint8_t channel_code, bool state, uint64_t *out_code, uint8_t *out_nbits)
bool expect_one(RemoteReceiveData &src) const
bool expect_zero(RemoteReceiveData &src) const
bool decode(RemoteReceiveData &src, uint64_t *out_data, uint8_t *out_nbits) const
static void type_c_code(uint8_t family, uint8_t group, uint8_t device, bool state, uint64_t *out_code, uint8_t *out_nbits)
void transmit(RemoteTransmitData *dst, uint64_t code, uint8_t len) const
static void type_a_code(uint8_t switch_group, uint8_t switch_device, bool state, uint64_t *out_code, uint8_t *out_nbits)
void one(RemoteTransmitData *dst) const
constexpr 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)
bool expect_sync(RemoteReceiveData &src) const
static void type_d_code(uint8_t group, uint8_t device, bool state, uint64_t *out_code, uint8_t *out_nbits)
static void simple_code_to_tristate(uint16_t code, uint8_t nbits, uint64_t *out_code)
bool dump(RemoteReceiveData src) override
TEMPLATABLE_VALUE(RCSwitchBase, protocol)
void encode(RemoteTransmitData *dst, Ts... x) override
void set_type_d(std::string group, uint8_t device, bool state)
void set_protocol(const RCSwitchBase *protocol)
protocol must outlive the receiver: a RC_SWITCH_PROTOCOLS entry or a codegen flash table.
void set_type_b(uint8_t address_code, uint8_t channel_code, bool state)
void set_type_a(const std::string &group, const std::string &device, bool state)
bool matches(RemoteReceiveData src) override
void set_type_c(std::string family, uint8_t group, uint8_t device, bool state)
void encode(RemoteTransmitData *dst, Ts... x) override
TEMPLATABLE_VALUE(RCSwitchBase, protocol)
TEMPLATABLE_VALUE(RCSwitchBase, protocol)
void encode(RemoteTransmitData *dst, Ts... x) override
void encode(RemoteTransmitData *dst, Ts... x) override
TEMPLATABLE_VALUE(RCSwitchBase, protocol)
void encode(RemoteTransmitData *dst, Ts... x) override
TEMPLATABLE_VALUE(RCSwitchBase, protocol)
bool state
Definition fan.h:2
uint64_t decode_binary_string_mask(const std::string &data)
RCSwitchBase rc_switch_protocol_copy(const RCSwitchBase *protocol)
RAM copy of a protocol stored in flash, made with progmem_memcpy (own name: rc_switch_protocol(0) sta...
uint64_t decode_binary_string(const std::string &data)
RCSwitchBase rc_switch_protocol(uint8_t index)
RAM copy of RC_SWITCH_PROTOCOLS[index] (0 when out of range) for the transmit actions and the dumper,...
const void size_t len
Definition hal.h:68
const void * src
Definition hal.h:68
static void uint32_t
bool operator==(const RCSwitchData &rhs) const
uint16_t sync
Definition sun_gtil2.cpp:0
uint16_t x
Definition tt21100.cpp:5