ESPHome  2024.3.1
rf_bridge.cpp
Go to the documentation of this file.
1 #include "rf_bridge.h"
2 #include "esphome/core/log.h"
3 #include <cinttypes>
4 #include <cstring>
5 
6 namespace esphome {
7 namespace rf_bridge {
8 
9 static const char *const TAG = "rf_bridge";
10 
12  ESP_LOGV(TAG, "Sending ACK");
13  this->write(RF_CODE_START);
14  this->write(RF_CODE_ACK);
15  this->write(RF_CODE_STOP);
16  this->flush();
17 }
18 
20  size_t at = this->rx_buffer_.size();
21  this->rx_buffer_.push_back(byte);
22  const uint8_t *raw = &this->rx_buffer_[0];
23 
24  ESP_LOGVV(TAG, "Processing byte: 0x%02X", byte);
25 
26  // Byte 0: Start
27  if (at == 0)
28  return byte == RF_CODE_START;
29 
30  // Byte 1: Action
31  if (at == 1)
32  return byte >= RF_CODE_ACK && byte <= RF_CODE_RFIN_BUCKET;
33  uint8_t action = raw[1];
34 
35  switch (action) {
36  case RF_CODE_ACK:
37  ESP_LOGD(TAG, "Action OK");
38  break;
39  case RF_CODE_LEARN_KO:
40  ESP_LOGD(TAG, "Learning timeout");
41  break;
42  case RF_CODE_LEARN_OK:
43  case RF_CODE_RFIN: {
44  if (byte != RF_CODE_STOP || at < RF_MESSAGE_SIZE + 2)
45  return true;
46 
47  RFBridgeData data;
48  data.sync = (raw[2] << 8) | raw[3];
49  data.low = (raw[4] << 8) | raw[5];
50  data.high = (raw[6] << 8) | raw[7];
51  data.code = (raw[8] << 16) | (raw[9] << 8) | raw[10];
52 
53  if (action == RF_CODE_LEARN_OK) {
54  ESP_LOGD(TAG, "Learning success");
55  }
56 
57  ESP_LOGI(TAG,
58  "Received RFBridge Code: sync=0x%04" PRIX16 " low=0x%04" PRIX16 " high=0x%04" PRIX16
59  " code=0x%06" PRIX32,
60  data.sync, data.low, data.high, data.code);
61  this->data_callback_.call(data);
62  break;
63  }
64  case RF_CODE_LEARN_OK_NEW:
65  case RF_CODE_ADVANCED_RFIN: {
66  if (byte != RF_CODE_STOP) {
67  return at < (raw[2] + 3);
68  }
69 
70  RFBridgeAdvancedData data{};
71 
72  data.length = raw[2];
73  data.protocol = raw[3];
74  char next_byte[3];
75  for (uint8_t i = 0; i < data.length - 1; i++) {
76  sprintf(next_byte, "%02X", raw[4 + i]);
77  data.code += next_byte;
78  }
79 
80  ESP_LOGI(TAG, "Received RFBridge Advanced Code: length=0x%02X protocol=0x%02X code=0x%s", data.length,
81  data.protocol, data.code.c_str());
82  this->advanced_data_callback_.call(data);
83  break;
84  }
85  case RF_CODE_RFIN_BUCKET: {
86  if (byte != RF_CODE_STOP) {
87  return true;
88  }
89 
90  uint8_t buckets = raw[2] << 1;
91  std::string str;
92  char next_byte[3];
93 
94  for (uint32_t i = 0; i <= at; i++) {
95  sprintf(next_byte, "%02X", raw[i]);
96  str += next_byte;
97  if ((i > 3) && buckets) {
98  buckets--;
99  }
100  if ((i < 3) || (buckets % 2) || (i == at - 1)) {
101  str += " ";
102  }
103  }
104  ESP_LOGI(TAG, "Received RFBridge Bucket: %s", str.c_str());
105  break;
106  }
107  default:
108  ESP_LOGW(TAG, "Unknown action: 0x%02X", action);
109  break;
110  }
111 
112  ESP_LOGVV(TAG, "Parsed: 0x%02X", byte);
113 
114  if (byte == RF_CODE_STOP && action != RF_CODE_ACK)
115  this->ack_();
116 
117  // return false to reset buffer
118  return false;
119 }
120 
121 void RFBridgeComponent::write_byte_str_(const std::string &codes) {
122  uint8_t code;
123  int size = codes.length();
124  for (int i = 0; i < size; i += 2) {
125  code = strtol(codes.substr(i, 2).c_str(), nullptr, 16);
126  this->write(code);
127  }
128 }
129 
131  const uint32_t now = millis();
132  if (now - this->last_bridge_byte_ > 50) {
133  this->rx_buffer_.clear();
134  this->last_bridge_byte_ = now;
135  }
136 
137  while (this->available()) {
138  uint8_t byte;
139  this->read_byte(&byte);
140  if (this->parse_bridge_byte_(byte)) {
141  ESP_LOGVV(TAG, "Parsed: 0x%02X", byte);
142  this->last_bridge_byte_ = now;
143  } else {
144  this->rx_buffer_.clear();
145  }
146  }
147 }
148 
150  ESP_LOGD(TAG, "Sending code: sync=0x%04" PRIX16 " low=0x%04" PRIX16 " high=0x%04" PRIX16 " code=0x%06" PRIX32,
151  data.sync, data.low, data.high, data.code);
152  this->write(RF_CODE_START);
153  this->write(RF_CODE_RFOUT);
154  this->write((data.sync >> 8) & 0xFF);
155  this->write(data.sync & 0xFF);
156  this->write((data.low >> 8) & 0xFF);
157  this->write(data.low & 0xFF);
158  this->write((data.high >> 8) & 0xFF);
159  this->write(data.high & 0xFF);
160  this->write((data.code >> 16) & 0xFF);
161  this->write((data.code >> 8) & 0xFF);
162  this->write(data.code & 0xFF);
163  this->write(RF_CODE_STOP);
164  this->flush();
165 }
166 
168  ESP_LOGD(TAG, "Sending advanced code: length=0x%02X protocol=0x%02X code=0x%s", data.length, data.protocol,
169  data.code.c_str());
170  this->write(RF_CODE_START);
171  this->write(RF_CODE_RFOUT_NEW);
172  this->write(data.length & 0xFF);
173  this->write(data.protocol & 0xFF);
174  this->write_byte_str_(data.code);
175  this->write(RF_CODE_STOP);
176  this->flush();
177 }
178 
180  ESP_LOGD(TAG, "Learning mode");
181  this->write(RF_CODE_START);
182  this->write(RF_CODE_LEARN);
183  this->write(RF_CODE_STOP);
184  this->flush();
185 }
186 
188  ESP_LOGCONFIG(TAG, "RF_Bridge:");
189  this->check_uart_settings(19200);
190 }
191 
193  ESP_LOGI(TAG, "Advanced Sniffing on");
194  this->write(RF_CODE_START);
195  this->write(RF_CODE_SNIFFING_ON);
196  this->write(RF_CODE_STOP);
197  this->flush();
198 }
199 
201  ESP_LOGI(TAG, "Advanced Sniffing off");
202  this->write(RF_CODE_START);
203  this->write(RF_CODE_SNIFFING_OFF);
204  this->write(RF_CODE_STOP);
205  this->flush();
206 }
207 
209  ESP_LOGI(TAG, "Raw Bucket Sniffing on");
210  this->write(RF_CODE_START);
211  this->write(RF_CODE_RFIN_BUCKET);
212  this->write(RF_CODE_STOP);
213  this->flush();
214 }
215 
216 void RFBridgeComponent::send_raw(const std::string &raw_code) {
217  ESP_LOGD(TAG, "Sending Raw Code: %s", raw_code.c_str());
218 
219  this->write_byte_str_(raw_code);
220  this->flush();
221 }
222 
223 void RFBridgeComponent::beep(uint16_t ms) {
224  ESP_LOGD(TAG, "Beeping for %hu ms", ms);
225 
226  this->write(RF_CODE_START);
227  this->write(RF_CODE_BEEP);
228  this->write((ms >> 8) & 0xFF);
229  this->write(ms & 0xFF);
230  this->write(RF_CODE_STOP);
231  this->flush();
232 }
233 
234 } // namespace rf_bridge
235 } // namespace esphome
void send_raw(const std::string &code)
Definition: rf_bridge.cpp:216
CallbackManager< void(RFBridgeData)> data_callback_
Definition: rf_bridge.h:75
uint8_t raw[35]
Definition: bl0939.h:19
CallbackManager< void(RFBridgeAdvancedData)> advanced_data_callback_
Definition: rf_bridge.h:76
void send_code(RFBridgeData data)
Definition: rf_bridge.cpp:149
bool parse_bridge_byte_(uint8_t byte)
Definition: rf_bridge.cpp:19
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
std::vector< uint8_t > rx_buffer_
Definition: rf_bridge.h:72
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:13
bool read_byte(uint8_t *data)
Definition: uart.h:29
void send_advanced_code(const RFBridgeAdvancedData &data)
Definition: rf_bridge.cpp:167
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void write_byte_str_(const std::string &codes)
Definition: rf_bridge.cpp:121
size_t write(uint8_t data)
Definition: uart.h:52