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,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