feat: Add DALI raw frame handling and USB setup bridge
- Introduced DaliRawFrame structure to encapsulate raw frame data. - Enhanced DaliDomainService to manage raw frame sinks and processing. - Implemented raw frame task for asynchronous handling of incoming DALI frames. - Integrated raw frame handling in GatewayBleBridge and GatewayNetworkService. - Added GatewayUsbSetupBridge to facilitate USB Serial/JTAG communication with DALI. - Configured ESP-NOW for wireless communication and setup management. - Updated GatewayRuntime to support clearing wireless credentials on boot button long press. - Enhanced CMakeLists to include new components and dependencies. Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
idf_component_register(
|
||||
SRCS "src/gateway_usb_setup.cpp"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES dali_domain esp_driver_usb_serial_jtag freertos gateway_controller log
|
||||
)
|
||||
|
||||
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17)
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "dali_domain.hpp"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
namespace gateway {
|
||||
|
||||
class GatewayController;
|
||||
|
||||
struct GatewayUsbSetupBridgeConfig {
|
||||
bool enabled{false};
|
||||
uint8_t channel_index{0};
|
||||
size_t rx_buffer_size{256};
|
||||
size_t tx_buffer_size{256};
|
||||
uint32_t read_timeout_ms{20};
|
||||
uint32_t write_timeout_ms{20};
|
||||
uint32_t task_stack_size{4096};
|
||||
UBaseType_t task_priority{4};
|
||||
};
|
||||
|
||||
class GatewayUsbSetupBridge {
|
||||
public:
|
||||
GatewayUsbSetupBridge(GatewayController& controller, DaliDomainService& dali_domain,
|
||||
GatewayUsbSetupBridgeConfig config = {});
|
||||
|
||||
esp_err_t start();
|
||||
|
||||
private:
|
||||
static void TaskEntry(void* arg);
|
||||
void taskLoop();
|
||||
void handleBytes(const uint8_t* data, size_t len);
|
||||
void handleRawFrame(const DaliRawFrame& frame);
|
||||
uint8_t setupGatewayId() const;
|
||||
|
||||
GatewayController& controller_;
|
||||
DaliDomainService& dali_domain_;
|
||||
GatewayUsbSetupBridgeConfig config_;
|
||||
TaskHandle_t task_handle_{nullptr};
|
||||
bool started_{false};
|
||||
};
|
||||
|
||||
} // namespace gateway
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "gateway_usb_setup.hpp"
|
||||
|
||||
#include "gateway_controller.hpp"
|
||||
|
||||
#include "driver/usb_serial_jtag.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace gateway {
|
||||
|
||||
namespace {
|
||||
constexpr const char* kTag = "gateway_usb";
|
||||
constexpr size_t kCommandFrameMinLen = 7;
|
||||
}
|
||||
|
||||
GatewayUsbSetupBridge::GatewayUsbSetupBridge(GatewayController& controller,
|
||||
DaliDomainService& dali_domain,
|
||||
GatewayUsbSetupBridgeConfig config)
|
||||
: controller_(controller), dali_domain_(dali_domain), config_(config) {}
|
||||
|
||||
esp_err_t GatewayUsbSetupBridge::start() {
|
||||
if (started_) {
|
||||
return ESP_OK;
|
||||
}
|
||||
if (!config_.enabled) {
|
||||
ESP_LOGI(kTag, "USB Serial/JTAG setup bridge disabled; USB remains available for debug");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (!usb_serial_jtag_is_driver_installed()) {
|
||||
usb_serial_jtag_driver_config_t driver_config = {};
|
||||
driver_config.rx_buffer_size = static_cast<int>(config_.rx_buffer_size);
|
||||
driver_config.tx_buffer_size = static_cast<int>(config_.tx_buffer_size);
|
||||
esp_err_t err = usb_serial_jtag_driver_install(&driver_config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(kTag, "failed to install USB Serial/JTAG driver: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
dali_domain_.addRawFrameSink([this](const DaliRawFrame& frame) { handleRawFrame(frame); });
|
||||
|
||||
const BaseType_t ok = xTaskCreate(&GatewayUsbSetupBridge::TaskEntry, "gateway_usb_setup",
|
||||
static_cast<uint32_t>(config_.task_stack_size), this,
|
||||
config_.task_priority, &task_handle_);
|
||||
if (ok != pdPASS) {
|
||||
ESP_LOGE(kTag, "failed to create USB setup task");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
started_ = true;
|
||||
ESP_LOGI(kTag, "USB Serial/JTAG setup bridge started channel=%u", config_.channel_index);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void GatewayUsbSetupBridge::TaskEntry(void* arg) {
|
||||
auto* self = static_cast<GatewayUsbSetupBridge*>(arg);
|
||||
self->taskLoop();
|
||||
}
|
||||
|
||||
void GatewayUsbSetupBridge::taskLoop() {
|
||||
std::vector<uint8_t> buffer(std::max<size_t>(config_.rx_buffer_size, 64));
|
||||
const TickType_t timeout = pdMS_TO_TICKS(config_.read_timeout_ms);
|
||||
|
||||
while (true) {
|
||||
const int read_len = usb_serial_jtag_read_bytes(buffer.data(), buffer.size(), timeout);
|
||||
if (read_len > 0) {
|
||||
handleBytes(buffer.data(), static_cast<size_t>(read_len));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GatewayUsbSetupBridge::handleBytes(const uint8_t* data, size_t len) {
|
||||
if (data == nullptr || len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= kCommandFrameMinLen) {
|
||||
controller_.enqueueCommandFrame(std::vector<uint8_t>(data, data + len));
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t gateway_id = setupGatewayId();
|
||||
if (!dali_domain_.writeBridgeFrame(gateway_id, data, len)) {
|
||||
ESP_LOGW(kTag, "failed to write USB raw setup frame channel=%u len=%u", config_.channel_index,
|
||||
static_cast<unsigned>(len));
|
||||
}
|
||||
}
|
||||
|
||||
void GatewayUsbSetupBridge::handleRawFrame(const DaliRawFrame& frame) {
|
||||
if (!config_.enabled || frame.channel_index != config_.channel_index || frame.data.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int written = usb_serial_jtag_write_bytes(frame.data.data(), frame.data.size(),
|
||||
pdMS_TO_TICKS(config_.write_timeout_ms));
|
||||
if (written < 0 || static_cast<size_t>(written) != frame.data.size()) {
|
||||
ESP_LOGW(kTag, "failed to forward USB raw setup frame channel=%u len=%u", frame.channel_index,
|
||||
static_cast<unsigned>(frame.data.size()));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GatewayUsbSetupBridge::setupGatewayId() const {
|
||||
for (const auto& channel : dali_domain_.channelInfo()) {
|
||||
if (channel.channel_index == config_.channel_index) {
|
||||
return channel.gateway_id;
|
||||
}
|
||||
}
|
||||
return config_.channel_index;
|
||||
}
|
||||
|
||||
} // namespace gateway
|
||||
Reference in New Issue
Block a user