mirror of
https://github.com/esphome/esphome.git
synced 2024-12-12 00:14:53 +01:00
231 lines
6 KiB
C++
231 lines
6 KiB
C++
#include "rf_bridge.h"
|
|
#include "esphome/core/log.h"
|
|
#include <cstring>
|
|
|
|
namespace esphome {
|
|
namespace rf_bridge {
|
|
|
|
static const char *const TAG = "rf_bridge";
|
|
|
|
void RFBridgeComponent::ack_() {
|
|
ESP_LOGV(TAG, "Sending ACK");
|
|
this->write(RF_CODE_START);
|
|
this->write(RF_CODE_ACK);
|
|
this->write(RF_CODE_STOP);
|
|
this->flush();
|
|
}
|
|
|
|
bool RFBridgeComponent::parse_bridge_byte_(uint8_t byte) {
|
|
size_t at = this->rx_buffer_.size();
|
|
this->rx_buffer_.push_back(byte);
|
|
const uint8_t *raw = &this->rx_buffer_[0];
|
|
|
|
ESP_LOGVV(TAG, "Processing byte: 0x%02X", byte);
|
|
|
|
// Byte 0: Start
|
|
if (at == 0)
|
|
return byte == RF_CODE_START;
|
|
|
|
// Byte 1: Action
|
|
if (at == 1)
|
|
return byte >= RF_CODE_ACK && byte <= RF_CODE_RFIN_BUCKET;
|
|
uint8_t action = raw[1];
|
|
|
|
switch (action) {
|
|
case RF_CODE_ACK:
|
|
ESP_LOGD(TAG, "Action OK");
|
|
break;
|
|
case RF_CODE_LEARN_KO:
|
|
ESP_LOGD(TAG, "Learning timeout");
|
|
break;
|
|
case RF_CODE_LEARN_OK:
|
|
case RF_CODE_RFIN: {
|
|
if (byte != RF_CODE_STOP || at < RF_MESSAGE_SIZE + 2)
|
|
return true;
|
|
|
|
RFBridgeData data;
|
|
data.sync = (raw[2] << 8) | raw[3];
|
|
data.low = (raw[4] << 8) | raw[5];
|
|
data.high = (raw[6] << 8) | raw[7];
|
|
data.code = (raw[8] << 16) | (raw[9] << 8) | raw[10];
|
|
|
|
if (action == RF_CODE_LEARN_OK)
|
|
ESP_LOGD(TAG, "Learning success");
|
|
|
|
ESP_LOGD(TAG, "Received RFBridge Code: sync=0x%04X low=0x%04X high=0x%04X code=0x%06X", data.sync, data.low,
|
|
data.high, data.code);
|
|
this->data_callback_.call(data);
|
|
break;
|
|
}
|
|
case RF_CODE_LEARN_OK_NEW:
|
|
case RF_CODE_ADVANCED_RFIN: {
|
|
if (byte != RF_CODE_STOP) {
|
|
return at < (raw[2] + 3);
|
|
}
|
|
|
|
RFBridgeAdvancedData data{};
|
|
|
|
data.length = raw[2];
|
|
data.protocol = raw[3];
|
|
char next_byte[3];
|
|
for (uint8_t i = 0; i < data.length - 1; i++) {
|
|
sprintf(next_byte, "%02X", raw[4 + i]);
|
|
data.code += next_byte;
|
|
}
|
|
|
|
ESP_LOGD(TAG, "Received RFBridge Advanced Code: length=0x%02X protocol=0x%02X code=0x%s", data.length,
|
|
data.protocol, data.code.c_str());
|
|
this->advanced_data_callback_.call(data);
|
|
break;
|
|
}
|
|
case RF_CODE_RFIN_BUCKET: {
|
|
if (byte != RF_CODE_STOP) {
|
|
return true;
|
|
}
|
|
|
|
uint8_t buckets = raw[2] << 1;
|
|
std::string str;
|
|
char next_byte[3];
|
|
|
|
for (uint32_t i = 0; i <= at; i++) {
|
|
sprintf(next_byte, "%02X", raw[i]);
|
|
str += next_byte;
|
|
if ((i > 3) && buckets) {
|
|
buckets--;
|
|
}
|
|
if ((i < 3) || (buckets % 2) || (i == at - 1)) {
|
|
str += " ";
|
|
}
|
|
}
|
|
ESP_LOGD(TAG, "Received RFBridge Bucket: %s", str.c_str());
|
|
break;
|
|
}
|
|
default:
|
|
ESP_LOGW(TAG, "Unknown action: 0x%02X", action);
|
|
break;
|
|
}
|
|
|
|
ESP_LOGVV(TAG, "Parsed: 0x%02X", byte);
|
|
|
|
if (byte == RF_CODE_STOP && action != RF_CODE_ACK)
|
|
this->ack_();
|
|
|
|
// return false to reset buffer
|
|
return false;
|
|
}
|
|
|
|
void RFBridgeComponent::write_byte_str_(const std::string &codes) {
|
|
uint8_t code;
|
|
int size = codes.length();
|
|
for (int i = 0; i < size; i += 2) {
|
|
code = strtol(codes.substr(i, 2).c_str(), nullptr, 16);
|
|
this->write(code);
|
|
}
|
|
}
|
|
|
|
void RFBridgeComponent::loop() {
|
|
const uint32_t now = millis();
|
|
if (now - this->last_bridge_byte_ > 50) {
|
|
this->rx_buffer_.clear();
|
|
this->last_bridge_byte_ = now;
|
|
}
|
|
|
|
while (this->available()) {
|
|
uint8_t byte;
|
|
this->read_byte(&byte);
|
|
if (this->parse_bridge_byte_(byte)) {
|
|
ESP_LOGVV(TAG, "Parsed: 0x%02X", byte);
|
|
this->last_bridge_byte_ = now;
|
|
} else {
|
|
this->rx_buffer_.clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
void RFBridgeComponent::send_code(RFBridgeData data) {
|
|
ESP_LOGD(TAG, "Sending code: sync=0x%04X low=0x%04X high=0x%04X code=0x%06X", data.sync, data.low, data.high,
|
|
data.code);
|
|
this->write(RF_CODE_START);
|
|
this->write(RF_CODE_RFOUT);
|
|
this->write((data.sync >> 8) & 0xFF);
|
|
this->write(data.sync & 0xFF);
|
|
this->write((data.low >> 8) & 0xFF);
|
|
this->write(data.low & 0xFF);
|
|
this->write((data.high >> 8) & 0xFF);
|
|
this->write(data.high & 0xFF);
|
|
this->write((data.code >> 16) & 0xFF);
|
|
this->write((data.code >> 8) & 0xFF);
|
|
this->write(data.code & 0xFF);
|
|
this->write(RF_CODE_STOP);
|
|
this->flush();
|
|
}
|
|
|
|
void RFBridgeComponent::send_advanced_code(const RFBridgeAdvancedData &data) {
|
|
ESP_LOGD(TAG, "Sending advanced code: length=0x%02X protocol=0x%02X code=0x%s", data.length, data.protocol,
|
|
data.code.c_str());
|
|
this->write(RF_CODE_START);
|
|
this->write(RF_CODE_RFOUT_NEW);
|
|
this->write(data.length & 0xFF);
|
|
this->write(data.protocol & 0xFF);
|
|
this->write_byte_str_(data.code);
|
|
this->write(RF_CODE_STOP);
|
|
this->flush();
|
|
}
|
|
|
|
void RFBridgeComponent::learn() {
|
|
ESP_LOGD(TAG, "Learning mode");
|
|
this->write(RF_CODE_START);
|
|
this->write(RF_CODE_LEARN);
|
|
this->write(RF_CODE_STOP);
|
|
this->flush();
|
|
}
|
|
|
|
void RFBridgeComponent::dump_config() {
|
|
ESP_LOGCONFIG(TAG, "RF_Bridge:");
|
|
this->check_uart_settings(19200);
|
|
}
|
|
|
|
void RFBridgeComponent::start_advanced_sniffing() {
|
|
ESP_LOGD(TAG, "Advanced Sniffing on");
|
|
this->write(RF_CODE_START);
|
|
this->write(RF_CODE_SNIFFING_ON);
|
|
this->write(RF_CODE_STOP);
|
|
this->flush();
|
|
}
|
|
|
|
void RFBridgeComponent::stop_advanced_sniffing() {
|
|
ESP_LOGD(TAG, "Advanced Sniffing off");
|
|
this->write(RF_CODE_START);
|
|
this->write(RF_CODE_SNIFFING_OFF);
|
|
this->write(RF_CODE_STOP);
|
|
this->flush();
|
|
}
|
|
|
|
void RFBridgeComponent::start_bucket_sniffing() {
|
|
ESP_LOGD(TAG, "Raw Bucket Sniffing on");
|
|
this->write(RF_CODE_START);
|
|
this->write(RF_CODE_RFIN_BUCKET);
|
|
this->write(RF_CODE_STOP);
|
|
this->flush();
|
|
}
|
|
|
|
void RFBridgeComponent::send_raw(const std::string &raw_code) {
|
|
ESP_LOGD(TAG, "Sending Raw Code: %s", raw_code.c_str());
|
|
|
|
this->write_byte_str_(raw_code);
|
|
this->flush();
|
|
}
|
|
|
|
void RFBridgeComponent::beep(uint16_t ms) {
|
|
ESP_LOGD(TAG, "Beeping for %hu ms", ms);
|
|
|
|
this->write(RF_CODE_START);
|
|
this->write(RF_CODE_BEEP);
|
|
this->write((ms >> 8) & 0xFF);
|
|
this->write(ms & 0xFF);
|
|
this->write(RF_CODE_STOP);
|
|
this->flush();
|
|
}
|
|
|
|
} // namespace rf_bridge
|
|
} // namespace esphome
|