From d10ec6546d81206df7880bd3115c29654122bba5 Mon Sep 17 00:00:00 2001 From: Jonas Rabenstein Date: Tue, 23 Dec 2025 10:10:00 +0100 Subject: [PATCH] cleanup --- components/brmesh/controller.cpp | 275 ------------------------------- components/brmesh/controller.h | 78 --------- components/brmesh/debug.h | 43 ----- components/brmesh/light.cpp | 1 - components/brmesh/network.cpp | 1 - components/brmesh/protocol.cpp | 64 ------- components/brmesh/protocol.h | 18 -- components/brmesh/q.h | 72 -------- components/brmesh/utils.cpp | 126 -------------- components/brmesh/utils.h | 36 ---- components/brmesh/whitening.cpp | 1 - 11 files changed, 715 deletions(-) delete mode 100644 components/brmesh/controller.cpp delete mode 100644 components/brmesh/controller.h delete mode 100644 components/brmesh/debug.h delete mode 100644 components/brmesh/protocol.cpp delete mode 100644 components/brmesh/protocol.h delete mode 100644 components/brmesh/q.h delete mode 100644 components/brmesh/utils.cpp delete mode 100644 components/brmesh/utils.h diff --git a/components/brmesh/controller.cpp b/components/brmesh/controller.cpp deleted file mode 100644 index e62fe98..0000000 --- a/components/brmesh/controller.cpp +++ /dev/null @@ -1,275 +0,0 @@ -#if 0 -#include "esphome/core/component_iterator.h" -#include "esphome/core/log.h" -#include "esphome/components/esp32_ble/ble.h" -#include "controller.h" -#include "protocol.h" - -namespace { -const char *const TAG = "brmesh.controller"; - -template -std::enable_if_t<(addr_size == 3 || addr_size == std::dynamic_extent), uint16_t> -crc16(const std::span &addr, const std::span &data, const uint16_t init = 0xFFFF) -{ - constexpr auto step = [](uint16_t result, uint8_t byte)->uint16_t{ - result ^= static_cast(byte) << 8; - for (int j = 0; j < 4; j++) { - uint16_t tmp = result << 1; - if (result & 0x8000) - tmp ^= 0x1021; - result = tmp << 1; - if (tmp & 0x8000) - result ^= 0x1021; - } - return result; - }; - - auto result = init; - - for (const auto &c:addr) - result = step(result, c); - - for (const uint8_t &c:data) - result = step(result, esphome::reverse_bits(c)); - - return ~esphome::reverse_bits(result); -} - -} - - -namespace esphome { -namespace brmesh { -Controller::Controller(esp32_ble::ESP32BLE &ble, - const Key &key, - const uint16_t adv_interval_min, - const uint16_t adv_interval_max, - const uint16_t adv_duration, - const uint16_t adv_gap) - : ble_(ble), key_(key), - adv_interval_min_(adv_interval_min), - adv_interval_max_(adv_interval_max), - adv_duration_(adv_duration), - adv_gap_(adv_duration) -{ -} - -void Controller::setup() -{ - ESP_LOGCONFIG(TAG, "BRmesh Controller:\n" - " key: %02hx:%02hx:%02hx:%02hx\n" - " adv interval: %hd-%hd\n" - " adv duration: %hdms\n" - " adv gap: %hdms", - key_[0], key_[1], key_[2], key_[3], - adv_interval_min_, adv_interval_max_, - adv_duration_, - adv_gap_); - ble_.register_gap_event_handler(this); -} - -void Controller::loop() -{ - auto *light = q_.peek(); - disable_loop(); - if (light == nullptr) - light = q_.peek(); - if (light == nullptr) - return; -} - -void Controller::advertise(Light &light) -{ - esp_ble_adv_params_t adv_params = { - .adv_int_min = adv_interval_min_, - .adv_int_max = adv_interval_max_, - .adv_type = ADV_TYPE_NONCONN_IND, - .own_addr_type = BLE_ADDR_TYPE_PUBLIC, - .peer_addr = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - .peer_addr_type = BLE_ADDR_TYPE_PUBLIC, - .channel_map = ADV_CHNL_ALL, - .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, - }; - - std::array adv_data_raw[31]; - uint8_t adv_data_len = 0; - - // Add flags - adv_data_raw[adv_data_len++] = 2; - adv_data_raw[adv_data_len++] = ESP_BLE_AD_TYPE_FLAG; - adv_data_raw[adv_data_len++] = ESP_BLE_ADV_FLAG_BREDR_NOT_SPT | ESP_BLE_ADV_FLAG_GEN_DISC; - - // Add manufacturer data - const auto cmd_data_len = adv_data_len++; - adv_data_raw[adv_data_len++] = ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE; - adv_data_raw[adv_data_len++] = MANUFACTURER_DATA_ID & 0xFF; - adv_data_raw[adv_data_len++] = (MANUFACTURER_DATA_ID >> 8) & 0xFF; - - const auto cmd = command(std::span(adv_data_raw).subspan(adv_data_len), light); - adv_data_raw[cmd_data_len] = cmd.size_bytes(); - adv_data_len += cmd.size_bytes(); - - esp_err_t err = esp_ble_gap_config_adv_data_raw(adv_data_raw, adv_data_len); - if (err != ESP_OK) - { - ESP_LOGW(TAG, "Error setting raw advertisement data (err=%d): %s", err, esp_err_to_name(err)); - return; - } - - err = esp_ble_gap_start_advertising(&adv_params); - if (err != ESP_OK) - { - ESP_LOGW(TAG, "Error starting advertisement (err=%d): %s", err, esp_err_to_name(err)); - return; - } - - ESP_LOGD(TAG, "advertise id=%hd", light.id()); -} - -void -Controller::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) -{ - switch (event) { - case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: - ESP_LOD(TAG, "advertise: %hdms\n", adv_duration_); - set_timeout(adv_duration_, esp_ble_gap_stop_advertising); - return; - - case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: - ESP_LOGD(TAG, "advertise gap: %hdms\n", adv_gap_); - set_timeout(adv_gap_, [this](){ - q_.dequeue(); - auto *light = q_.peek(); - if (light == nullptr) - advertise(*light); - }); - return; - - default: - return; - } -} - -void -Controller::enqueue(Light &light) -{ - if (!q_.enqueue(light)) - return; - defer([this](){ advertise(*q_.peek()); }); -} - -std::vector Controller::single_control(uint32_t light_id_, const std::vector &light_data) -{ - std::vector result_data(12); - - result_data[0] = 2 | (((0xfffffff & (light_data.size() + 1)) << 4)); - result_data[1] = light_id_; - std::copy(light_data.begin(), light_data.end(), result_data.begin() + 2); - - // Debug output - print payload as hex - auto hex_str = vector_to_hex_string(result_data).data(); - ESP_LOGD(TAG, "Inner Payload (%d bytes): %s", result_data.size(), hex_str); - - return this->generate_command(5, light_id_, result_data, true); -} - -std::vector Controller::generate_command(uint8_t n, uint32_t light_id_, const std::vector &data, bool forward) -{ - uint8_t& sequence = seq_; - - // Create command body with header - std::vector body(data.size() + 4); - uint8_t i2 = (light_id_ / 256); - - // Construct header - body[0] = (i2 & 0b1111) | ((n & 0b111) << 4) | (forward ? 0x80 : 0); - body[1] = sequence++; // Use and increment sequence number - if (sequence >= 255) - sequence = 1; - - body[2] = this->key_[3]; // Safe key - - // Copy data - std::copy(data.begin(), data.end(), body.begin() + 4); - - // Calculate checksum - uint8_t checksum = 0; - for (size_t i = 0; i < body.size(); i++) - { - if (i != 3) - { - checksum = checksum + body[i]; - } - } - body[3] = checksum; - - // Encrypt header and data - for (size_t i = 0; i < 4; i++) - { - body[i] = DEFAULT_ENCRYPT_KEY[i & 3] ^ body[i]; - } - - for (size_t i = 0; i < data.size(); i++) - { - body[4 + i] = this->key_[i & 3] ^ body[4 + i]; - } - - // Prepare the final payload with RF protocol formatting - std::vector addr = {DEFAULT_BLE_ADDRESS.begin(), DEFAULT_BLE_ADDRESS.end()}; - return prepare_payload(addr, body); -} - -std::span Controller::payload(std::span &&span, const Light &light) -{ - const auto header = span.subspan(0, 3); - header[0] = 0x71; - header[1] = 0x0f; - header[2] = 0x55; - - const auto address = span.subspan(3, 3); - std::reverse_copy(address.begin(), address.end(), - DEFAULT_BLE_ADDRESS.cbegin(), - DEFAULT_BLE_ADDRESS.cend()); - - const auto data = command(span.subspan(6, 10), light); - const auto crc = span.subspan(6 + data.size(), 2); - const auto crc16 = ::crc16(address, data); - crc[0] = static_cast(crc16); - crc[1] = static_cast(crc16 >> 8); - - auto result = span.subspan(0, header.size() + address.size() + data.size() + crc.size()); - - // TODO: adjust seed to skip zero byte warmup - Whitening whitening(0x25); - for (size_t i = 0; i< 16; ++i) - (void) whitening.encode(0x00); - - whitening.encode(result); - - return result; -} - -std::span command(std::span &&span, const Light &light) -{ - static constexpr uint8_t n = 5; // TODO - static constexpr bool forward = true; // TODO - - const auto inner = span.subpsna(4, light.command(span.subspan(4, 6))); - - auto header = span.subspan(0, 4); - header[0] = (i2 & 0b1111) | ((n & 0b111) << 4) | (forward ? 0x80 : 0); - header[1] = seq_++; - header[2] = key_[3]; // safe key - header[3] = crc(inner); - - DEFAULT_ENCRYPT_KEY(header); - key_(inner); - - //prepare(DEFAULT_BLE_ADDRESS, span.subspan(4 + inner.size())); - return span.subspan(0, 4 + inner.size()); -} - -} // namespace brmesh -} // namespace esphome -#endif diff --git a/components/brmesh/controller.h b/components/brmesh/controller.h deleted file mode 100644 index 159e7b3..0000000 --- a/components/brmesh/controller.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include -#include -#include -#include "esphome/core/component.h" -#include "esphome/components/esp32_ble/ble.h" - -#include "q.h" -#include "key.h" - -namespace esphome { -namespace brmesh { - -class Light; - -class Controller : public Component, public esp32_ble::GAPEventHandler -{ -public: - Controller(esp32_ble::ESP32BLE *ble, const Key &key, uint16_t adv_interval_min, uint16_t adv_interval_max, uint16_t adv_duration, uint16_t adv_gap) - : Controller(*ble, key, adv_interval_min, adv_interval_max, adv_duration, adv_gap) {} - - Controller(esp32_ble::ESP32BLE &ble, const Key &key, uint16_t adv_interval_min, uint16_t adv_interval_max, uint16_t adv_duration, uint16_t adv_gap); - - std::vector single_control(uint32_t addr, const std::vector &light_data); - void enqueue(Light &); - - // interface: Component - void setup() override; - void loop() override; - - // interface: GAPEventHandler - void gap_event_handler(esp_gap_ble_cb_event_t, esp_ble_gap_cb_param_t *); - -protected: - struct Command - { - std::vector data; - uint32_t timestamp; - uint8_t retries{0}; - static constexpr uint8_t MAX_RETRIES = 3; - }; - - enum class AdvertiseState - { - IDLE, - ADVERTISING, - GAP - }; - - AdvertiseState adv_state_{AdvertiseState::IDLE}; - uint32_t state_start_time_{0}; - - // Protocol implementation - std::vector generate_command(uint8_t n, uint32_t light_id_, const std::vector &data, bool forward = true); - - static const uint16_t MANUFACTURER_DATA_ID = 0xfff0; -private: - esp32_ble::ESP32BLE &ble_; - Key key_; - - uint16_t adv_interval_min_; - uint16_t adv_interval_max_; - uint16_t adv_duration_; - uint16_t adv_gap_; - - Q q_ = {}; - uint8_t seq_ = 0; - - void advertise(Light &); - - std::span payload(std::span &span, const Light &light); - - std::span command(std::span &&span, const Light &light); -}; - -} // namespace brmesh -} // namespace esphome diff --git a/components/brmesh/debug.h b/components/brmesh/debug.h deleted file mode 100644 index 6b7ab59..0000000 --- a/components/brmesh/debug.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#if 0 -#include "esphome/core/log.h" -#include "esphome/core/defines.h" -#include "esphome/core/helpers.h" - -#ifdef USE_LOGGER -#include "esphome/components/logger/logger.h" -#endif - -#include - -namespace esphome { -namespace brmesh { - -namespace { -template -void hexdump(const unsigned level, const char *tag, unsigned line, const uint8_t *data, size_t size, const char *fmt, types&&...args) { - // TODO: conditional format_hex_pretty - const auto hex = format_hex_pretty(data, size); - ESP_LOGD(tag, fmt, std::forward(args)..., hex.c_str()); -} - -template -void hexdump(const unsigned level, const char *tag, const void *data, size_t size, const char *fmt, types&&...args) { - hexdump(level, tag, static_cast(data), size, fmt, std::forward(args)...); -} - -template -void hexdump(const unsigned level, const char *tag, const std::span &span, const char *fmt, types&&...args) { - hexdump(level, tag, static_cast(&span.front()), span.size_bytes(), fmt, std::forward(args)...); -} - -template -void hexdump(const char *tag, types&&...args) -{ - return hexdump(ESPHOME_LOG_LEVEL_DEBUG, tag, std::forward(args)...); -} - -} // namespace -} // namespace brmesh -} // namespace esphome -#endif diff --git a/components/brmesh/light.cpp b/components/brmesh/light.cpp index 23eb261..1dbf674 100644 --- a/components/brmesh/light.cpp +++ b/components/brmesh/light.cpp @@ -1,6 +1,5 @@ #include "light.h" -#include "debug.h" #include "network.h" #include "whitening.h" diff --git a/components/brmesh/network.cpp b/components/brmesh/network.cpp index d915023..68f7c26 100644 --- a/components/brmesh/network.cpp +++ b/components/brmesh/network.cpp @@ -1,6 +1,5 @@ #include "network.h" -#include "debug.h" #include "light.h" #include "whitening.h" diff --git a/components/brmesh/protocol.cpp b/components/brmesh/protocol.cpp deleted file mode 100644 index 2b8aba4..0000000 --- a/components/brmesh/protocol.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include "protocol.h" -#include "debug.h" - -namespace { -const char *TAG = "fastcon.protocol"; -} -namespace esphome -{ - namespace brmesh - { - std::vector get_rf_payload(const std::vector &addr, const std::vector &data) - { - const size_t data_offset = 0x12; - const size_t inverse_offset = 0x0f; - const size_t result_data_size = data_offset + addr.size() + data.size(); - - // Create result buffer including space for checksum - std::vector resultbuf(result_data_size + 2, 0); - - // Set hardcoded values - resultbuf[0x0f] = 0x71; - resultbuf[0x10] = 0x0f; - resultbuf[0x11] = 0x55; - - // Copy address in reverse - for (size_t i = 0; i < addr.size(); i++) - { - resultbuf[data_offset + addr.size() - i - 1] = addr[i]; - } - - // Copy data - std::copy(data.begin(), data.end(), resultbuf.begin() + data_offset + addr.size()); - - // Reverse bytes in specified range - for (size_t i = inverse_offset; i < inverse_offset + addr.size() + 3; i++) - { - resultbuf[i] = reverse_8(resultbuf[i]); - } - - // Add CRC - uint16_t crc = crc16(addr, data); - resultbuf[result_data_size] = crc & 0xFF; - resultbuf[result_data_size + 1] = (crc >> 8) & 0xFF; - - return resultbuf; - } - - std::vector prepare_payload(const std::vector &addr, const std::vector &data) - { - auto payload = get_rf_payload(addr, data); - - // Initialize whitening - WhiteningContext context; - whitening_init(0x25, context); - - // Apply whitening to the payload - whitening_encode(payload, context); - - // Return only the portion after 0xf bytes - return std::vector(payload.begin() + 0xf, payload.end()); - } - } // namespace brmesh -} // namespace esphome diff --git a/components/brmesh/protocol.h b/components/brmesh/protocol.h deleted file mode 100644 index ee25c20..0000000 --- a/components/brmesh/protocol.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include -#include -#include "utils.h" - -namespace esphome -{ - namespace brmesh - { - static const std::array DEFAULT_ENCRYPT_KEY = {0x5e, 0x36, 0x7b, 0xc4}; - static const std::array DEFAULT_BLE_FASTCON_ADDRESS = {0xC1, 0xC2, 0xC3}; - - std::vector get_rf_payload(const std::vector &addr, const std::vector &data); - std::vector prepare_payload(const std::vector &addr, const std::vector &data); - } // namespace brmesh -} // namespace esphome \ No newline at end of file diff --git a/components/brmesh/q.h b/components/brmesh/q.h deleted file mode 100644 index aedc24f..0000000 --- a/components/brmesh/q.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -namespace esphome { -namespace brmesh { - -template -class Q { -public: - class Node; - - constexpr Q() = default; - - bool enqueue(T &); - T *dequeue(); - T *peek(); -private: - Node *head_ = nullptr; - Node **tail_ = &head_; -}; - -template -class Q::Node { -public: - constexpr Node() = default; - - bool enqueue(Node *&head, Node **&tail); - static Node *dequeue(Node *&head, Node **&tail); -private: - Node *next_ = nullptr; -}; - -template -bool Q::enqueue(T &node) { - return static_cast(node).enqueue(head_, tail_); -} - -template -T *Q::dequeue() { - auto *node = Node::dequeue(head_, tail_); - return dynamic_cast(node); -} - -template -T *Q::peek() { - auto *node = head_; - return dynamic_cast(node); -} - - -template -bool Q::Node::enqueue(Node *&head, Node **&tail) { - const bool first = tail == &head; - *tail = this; - tail = &next_; - return first; -} - -template -Q::Node *Q::Node::dequeue(Node *&head, Node **&tail) { - auto *node = head; - if (node == nullptr) - return nullptr; - - head = node->next_; - if (head == nullptr) - tail = &head; - - return node; -} - -} // namespace brmesh -} // namespace esphome diff --git a/components/brmesh/utils.cpp b/components/brmesh/utils.cpp deleted file mode 100644 index f3a8eb3..0000000 --- a/components/brmesh/utils.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include -#include "esphome/core/log.h" -#include "utils.h" - -namespace esphome -{ - namespace brmesh - { - uint8_t reverse_8(uint8_t d) - { - uint8_t result = 0; - for (int i = 0; i < 8; i++) - { - result |= ((d >> i) & 1) << (7 - i); - } - return result; - } - - uint16_t reverse_16(uint16_t d) - { - uint16_t result = 0; - for (int i = 0; i < 16; i++) - { - result |= ((d >> i) & 1) << (15 - i); - } - return result; - } - - uint16_t crc16(const std::vector &addr, const std::vector &data) - { - uint16_t crc = 0xffff; - - // Process address in reverse - for (auto it = addr.rbegin(); it != addr.rend(); ++it) - { - crc ^= (static_cast(*it) << 8); - for (int j = 0; j < 4; j++) - { - uint16_t tmp = crc << 1; - if (crc & 0x8000) - { - tmp ^= 0x1021; - } - crc = tmp << 1; - if (tmp & 0x8000) - { - crc ^= 0x1021; - } - } - } - - // Process data - for (size_t i = 0; i < data.size(); i++) - { - crc ^= (static_cast(reverse_8(data[i])) << 8); - for (int j = 0; j < 4; j++) - { - uint16_t tmp = crc << 1; - if (crc & 0x8000) - { - tmp ^= 0x1021; - } - crc = tmp << 1; - if (tmp & 0x8000) - { - crc ^= 0x1021; - } - } - } - - crc = ~reverse_16(crc); - return crc; - } - - void whitening_init(uint32_t val, WhiteningContext &ctx) - { - uint32_t v0[] = {(val >> 5), (val >> 4), (val >> 3), (val >> 2)}; - - ctx.f_0x0 = 1; - ctx.f_0x4 = v0[0] & 1; - ctx.f_0x8 = v0[1] & 1; - ctx.f_0xc = v0[2] & 1; - ctx.f_0x10 = v0[3] & 1; - ctx.f_0x14 = (val >> 1) & 1; - ctx.f_0x18 = val & 1; - } - - void whitening_encode(std::vector &data, WhiteningContext &ctx) - { - for (size_t i = 0; i < data.size(); i++) - { - uint32_t varC = ctx.f_0xc; - uint32_t var14 = ctx.f_0x14; - uint32_t var18 = ctx.f_0x18; - uint32_t var10 = ctx.f_0x10; - uint32_t var8 = var14 ^ ctx.f_0x8; - uint32_t var4 = var10 ^ ctx.f_0x4; - uint32_t _var = var18 ^ varC; - uint32_t var0 = _var ^ ctx.f_0x0; - - uint8_t c = data[i]; - data[i] = ((c & 0x80) ^ ((var8 ^ var18) << 7)) + ((c & 0x40) ^ (var0 << 6)) + ((c & 0x20) ^ (var4 << 5)) + ((c & 0x10) ^ (var8 << 4)) + ((c & 0x08) ^ (_var << 3)) + ((c & 0x04) ^ (var10 << 2)) + ((c & 0x02) ^ (var14 << 1)) + ((c & 0x01) ^ (var18 << 0)); - - ctx.f_0x8 = var4; - ctx.f_0xc = var8; - ctx.f_0x10 = var8 ^ varC; - ctx.f_0x14 = var0 ^ var10; - ctx.f_0x18 = var4 ^ var14; - ctx.f_0x0 = var8 ^ var18; - ctx.f_0x4 = var0; - } - } - - std::vector vector_to_hex_string(std::vector &data) - { - std::vector hex_str(data.size() * 2 + 1); // Allocate the vector with the required size - for (size_t i = 0; i < data.size(); i++) - { - sprintf(hex_str.data() + (i * 2), "%02X", data[i]); - } - hex_str[data.size() * 2] = '\0'; // Ensure null termination - return hex_str; - } - } // namespace brmesh -} // namespace esphome \ No newline at end of file diff --git a/components/brmesh/utils.h b/components/brmesh/utils.h deleted file mode 100644 index 9783096..0000000 --- a/components/brmesh/utils.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include - -namespace esphome -{ - namespace brmesh - { - // Bit manipulation utilities - uint8_t reverse_8(uint8_t d); - uint16_t reverse_16(uint16_t d); - - // CRC calculation - uint16_t crc16(const std::vector &addr, const std::vector &data); - - // Whitening context and functions - struct WhiteningContext - { - uint32_t f_0x0; - uint32_t f_0x4; - uint32_t f_0x8; - uint32_t f_0xc; - uint32_t f_0x10; - uint32_t f_0x14; - uint32_t f_0x18; - - WhiteningContext() : f_0x0(0), f_0x4(0), f_0x8(0), f_0xc(0), f_0x10(0), f_0x14(0), f_0x18(0) {} - }; - - void whitening_init(uint32_t val, WhiteningContext &ctx); - void whitening_encode(std::vector &data, WhiteningContext &ctx); - - std::vector vector_to_hex_string(std::vector &data); - } // namespace brmesh -} // namespace esphome \ No newline at end of file diff --git a/components/brmesh/whitening.cpp b/components/brmesh/whitening.cpp index eee79ae..6a44c7a 100644 --- a/components/brmesh/whitening.cpp +++ b/components/brmesh/whitening.cpp @@ -1,5 +1,4 @@ #include "whitening.h" -#include "debug.h" #include "esphome/core/log.h" #include "esphome/core/helpers.h"