ESPHome 2026.3.0
Loading...
Searching...
No Matches
rf_bridge.cpp
Go to the documentation of this file.
1#include "rf_bridge.h"
4#include "esphome/core/log.h"
5#include <cinttypes>
6#include <cstring>
7
8namespace esphome {
9namespace rf_bridge {
10
11static const char *const TAG = "rf_bridge";
12
14 ESP_LOGV(TAG, "Sending ACK");
15 this->write(RF_CODE_START);
16 this->write(RF_CODE_ACK);
17 this->write(RF_CODE_STOP);
18 this->flush();
19}
20
22 size_t at = this->rx_buffer_.size();
23 this->rx_buffer_.push_back(byte);
24 const uint8_t *raw = &this->rx_buffer_[0];
25
26 ESP_LOGVV(TAG, "Processing byte: 0x%02X", byte);
27
28 // Byte 0: Start
29 if (at == 0)
30 return byte == RF_CODE_START;
31
32 // Byte 1: Action
33 if (at == 1)
34 return byte >= RF_CODE_ACK && byte <= RF_CODE_RFIN_BUCKET;
35 uint8_t action = raw[1];
36
37 switch (action) {
38 case RF_CODE_ACK:
39 ESP_LOGD(TAG, "Action OK");
40 break;
41 case RF_CODE_LEARN_KO:
42 ESP_LOGD(TAG, "Learning timeout");
43 break;
44 case RF_CODE_LEARN_OK:
45 case RF_CODE_RFIN: {
46 if (byte != RF_CODE_STOP || at < RF_MESSAGE_SIZE + 2)
47 return true;
48
49 RFBridgeData data;
50 data.sync = (raw[2] << 8) | raw[3];
51 data.low = (raw[4] << 8) | raw[5];
52 data.high = (raw[6] << 8) | raw[7];
53 data.code = (raw[8] << 16) | (raw[9] << 8) | raw[10];
54
55 if (action == RF_CODE_LEARN_OK) {
56 ESP_LOGD(TAG, "Learning success");
57 }
58
59 ESP_LOGI(TAG,
60 "Received RFBridge Code: sync=0x%04" PRIX16 " low=0x%04" PRIX16 " high=0x%04" PRIX16
61 " code=0x%06" PRIX32,
62 data.sync, data.low, data.high, data.code);
63 this->data_callback_.call(data);
64 break;
65 }
66 case RF_CODE_LEARN_OK_NEW:
67 case RF_CODE_ADVANCED_RFIN: {
68 if (byte != RF_CODE_STOP) {
69 return at < (raw[2] + 3);
70 }
71
73
74 data.length = raw[2];
75 data.protocol = raw[3];
76 char next_byte[3]; // 2 hex chars + null
77 for (uint8_t i = 0; i + 1 < data.length; i++) {
78 buf_append_printf(next_byte, sizeof(next_byte), 0, "%02X", raw[4 + i]);
79 data.code += next_byte;
80 }
81
82 ESP_LOGI(TAG, "Received RFBridge Advanced Code: length=0x%02X protocol=0x%02X code=0x%s", data.length,
83 data.protocol, data.code.c_str());
84 this->advanced_data_callback_.call(data);
85 break;
86 }
87 case RF_CODE_RFIN_BUCKET: {
88 if (byte != RF_CODE_STOP) {
89 return true;
90 }
91
92 uint8_t buckets = raw[2] << 1;
93 std::string str;
94 char next_byte[3]; // 2 hex chars + null
95
96 for (uint32_t i = 0; i <= at; i++) {
97 buf_append_printf(next_byte, sizeof(next_byte), 0, "%02X", raw[i]);
98 str += next_byte;
99 if ((i > 3) && buckets) {
100 buckets--;
101 }
102 if ((i < 3) || (buckets % 2) || (i == at - 1)) {
103 str += " ";
104 }
105 }
106 ESP_LOGI(TAG, "Received RFBridge Bucket: %s", str.c_str());
107 break;
108 }
109 default:
110 ESP_LOGW(TAG, "Unknown action: 0x%02X", action);
111 break;
112 }
113
114 ESP_LOGVV(TAG, "Parsed: 0x%02X", byte);
115
116 if (byte == RF_CODE_STOP && action != RF_CODE_ACK)
117 this->ack_();
118
119 // return false to reset buffer
120 return false;
121}
122
123void RFBridgeComponent::write_byte_str_(const std::string &codes) {
124 uint8_t code;
125 int size = codes.length();
126 for (int i = 0; i < size; i += 2) {
127 code = strtol(codes.substr(i, 2).c_str(), nullptr, 16);
128 this->write(code);
129 }
130}
131
134 if (now - this->last_bridge_byte_ > 50) {
135 this->rx_buffer_.clear();
136 this->last_bridge_byte_ = now;
137 }
138
139 size_t avail = this->available();
140 while (avail > 0) {
141 uint8_t buf[64];
142 size_t to_read = std::min(avail, sizeof(buf));
143 if (!this->read_array(buf, to_read)) {
144 break;
145 }
146 avail -= to_read;
147 for (size_t i = 0; i < to_read; i++) {
148 if (this->rx_buffer_.size() > MAX_RX_BUFFER_SIZE) {
149 this->rx_buffer_.clear();
150 }
151 if (this->parse_bridge_byte_(buf[i])) {
152 ESP_LOGVV(TAG, "Parsed: 0x%02X", buf[i]);
153 this->last_bridge_byte_ = now;
154 } else {
155 this->rx_buffer_.clear();
156 }
157 }
158 }
159}
160
162 ESP_LOGD(TAG, "Sending code: sync=0x%04" PRIX16 " low=0x%04" PRIX16 " high=0x%04" PRIX16 " code=0x%06" PRIX32,
163 data.sync, data.low, data.high, data.code);
164 this->write(RF_CODE_START);
165 this->write(RF_CODE_RFOUT);
166 this->write((data.sync >> 8) & 0xFF);
167 this->write(data.sync & 0xFF);
168 this->write((data.low >> 8) & 0xFF);
169 this->write(data.low & 0xFF);
170 this->write((data.high >> 8) & 0xFF);
171 this->write(data.high & 0xFF);
172 this->write((data.code >> 16) & 0xFF);
173 this->write((data.code >> 8) & 0xFF);
174 this->write(data.code & 0xFF);
175 this->write(RF_CODE_STOP);
176 this->flush();
177}
178
180 ESP_LOGD(TAG, "Sending advanced code: length=0x%02X protocol=0x%02X code=0x%s", data.length, data.protocol,
181 data.code.c_str());
182 this->write(RF_CODE_START);
183 this->write(RF_CODE_RFOUT_NEW);
184 this->write(data.length & 0xFF);
185 this->write(data.protocol & 0xFF);
186 this->write_byte_str_(data.code);
187 this->write(RF_CODE_STOP);
188 this->flush();
189}
190
192 ESP_LOGD(TAG, "Learning mode");
193 this->write(RF_CODE_START);
194 this->write(RF_CODE_LEARN);
195 this->write(RF_CODE_STOP);
196 this->flush();
197}
198
200 ESP_LOGCONFIG(TAG, "RF_Bridge:");
201 this->check_uart_settings(19200);
202}
203
205 ESP_LOGI(TAG, "Advanced Sniffing on");
206 this->write(RF_CODE_START);
207 this->write(RF_CODE_SNIFFING_ON);
208 this->write(RF_CODE_STOP);
209 this->flush();
210}
211
213 ESP_LOGI(TAG, "Advanced Sniffing off");
214 this->write(RF_CODE_START);
215 this->write(RF_CODE_SNIFFING_OFF);
216 this->write(RF_CODE_STOP);
217 this->flush();
218}
219
221 ESP_LOGI(TAG, "Raw Bucket Sniffing on");
222 this->write(RF_CODE_START);
223 this->write(RF_CODE_RFIN_BUCKET);
224 this->write(RF_CODE_STOP);
225 this->flush();
226}
227
228void RFBridgeComponent::send_raw(const std::string &raw_code) {
229 ESP_LOGD(TAG, "Sending Raw Code: %s", raw_code.c_str());
230
231 this->write_byte_str_(raw_code);
232 this->flush();
233}
234
235void RFBridgeComponent::beep(uint16_t ms) {
236 ESP_LOGD(TAG, "Beeping for %hu ms", ms);
237
238 this->write(RF_CODE_START);
239 this->write(RF_CODE_BEEP);
240 this->write((ms >> 8) & 0xFF);
241 this->write(ms & 0xFF);
242 this->write(RF_CODE_STOP);
243 this->flush();
244}
245
246} // namespace rf_bridge
247} // namespace esphome
uint8_t raw[35]
Definition bl0939.h:0
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
void send_raw(const std::string &code)
CallbackManager< void(RFBridgeAdvancedData)> advanced_data_callback_
Definition rf_bridge.h:77
void send_advanced_code(const RFBridgeAdvancedData &data)
CallbackManager< void(RFBridgeData)> data_callback_
Definition rf_bridge.h:76
void write_byte_str_(const std::string &codes)
void send_code(RFBridgeData data)
std::vector< uint8_t > rx_buffer_
Definition rf_bridge.h:73
optional< std::array< uint8_t, N > > read_array()
Definition uart.h:38
void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits=1, UARTParityOptions parity=UART_CONFIG_PARITY_NONE, uint8_t data_bits=8)
Check that the configuration of the UART bus matches the provided values and otherwise print a warnin...
Definition uart.cpp:16
FlushResult flush()
Definition uart.h:48
size_t write(uint8_t data)
Definition uart.h:57
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
size_t size
Definition helpers.h:929
Application App
Global storage of Application pointer - only one Application can exist.
static void uint32_t