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