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:
@@ -112,7 +112,8 @@ struct DaliDomainService::DaliChannel {
|
||||
std::optional<DaliSerialBusConfig> serial_bus;
|
||||
};
|
||||
|
||||
DaliDomainService::DaliDomainService() = default;
|
||||
DaliDomainService::DaliDomainService()
|
||||
: raw_frame_sink_lock_(xSemaphoreCreateMutex()) {}
|
||||
|
||||
DaliDomainService::~DaliDomainService() = default;
|
||||
|
||||
@@ -172,6 +173,10 @@ esp_err_t DaliDomainService::bindHardwareBus(const DaliHardwareBusConfig& config
|
||||
channel->phy_kind = DaliPhyKind::kNativeHardware;
|
||||
channel->hardware_bus = config;
|
||||
}
|
||||
err = startRawFrameTask();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(kTag, "failed to start raw frame task: %s", esp_err_to_name(err));
|
||||
}
|
||||
ESP_LOGI(kTag, "bound channel=%u gateway=%u hardware bus=%u tx=%u rx=%u baudrate=%lu",
|
||||
config.channel_index, config.gateway_id, config.bus_id, config.tx_pin, config.rx_pin,
|
||||
static_cast<unsigned long>(config.baudrate));
|
||||
@@ -290,6 +295,19 @@ std::vector<DaliChannelInfo> DaliDomainService::channelInfo() const {
|
||||
return info;
|
||||
}
|
||||
|
||||
void DaliDomainService::addRawFrameSink(std::function<void(const DaliRawFrame& frame)> sink) {
|
||||
if (!sink) {
|
||||
return;
|
||||
}
|
||||
if (raw_frame_sink_lock_ != nullptr) {
|
||||
xSemaphoreTake(raw_frame_sink_lock_, portMAX_DELAY);
|
||||
}
|
||||
raw_frame_sinks_.push_back(std::move(sink));
|
||||
if (raw_frame_sink_lock_ != nullptr) {
|
||||
xSemaphoreGive(raw_frame_sink_lock_);
|
||||
}
|
||||
}
|
||||
|
||||
bool DaliDomainService::resetBus(uint8_t gateway_id) const {
|
||||
const auto* channel = findChannelByGateway(gateway_id);
|
||||
return channel != nullptr && channel->comm != nullptr && channel->comm->resetBus();
|
||||
@@ -446,6 +464,81 @@ DaliDomainService::DaliChannel* DaliDomainService::findChannelByIndex(uint8_t ch
|
||||
return it == channels_.end() ? nullptr : it->get();
|
||||
}
|
||||
|
||||
const DaliDomainService::DaliChannel* DaliDomainService::findChannelByHardwareBus(
|
||||
uint8_t bus_id) const {
|
||||
const auto it = std::find_if(channels_.begin(), channels_.end(), [bus_id](const auto& channel) {
|
||||
return channel->hardware_bus.has_value() && channel->hardware_bus->bus_id == bus_id;
|
||||
});
|
||||
return it == channels_.end() ? nullptr : it->get();
|
||||
}
|
||||
|
||||
esp_err_t DaliDomainService::startRawFrameTask() {
|
||||
if (raw_frame_task_handle_ != nullptr) {
|
||||
return ESP_OK;
|
||||
}
|
||||
QueueHandle_t queue = dali_hal_raw_receive_queue();
|
||||
if (queue == nullptr) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
const BaseType_t created = xTaskCreate(&DaliDomainService::RawFrameTaskEntry,
|
||||
"dali_raw_rx", 4096, this, 4,
|
||||
&raw_frame_task_handle_);
|
||||
if (created != pdPASS) {
|
||||
raw_frame_task_handle_ = nullptr;
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void DaliDomainService::RawFrameTaskEntry(void* arg) {
|
||||
static_cast<DaliDomainService*>(arg)->rawFrameTaskLoop();
|
||||
}
|
||||
|
||||
void DaliDomainService::rawFrameTaskLoop() {
|
||||
QueueHandle_t queue = dali_hal_raw_receive_queue();
|
||||
Dali_msg_t message = {};
|
||||
while (true) {
|
||||
if (queue == nullptr) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
queue = dali_hal_raw_receive_queue();
|
||||
continue;
|
||||
}
|
||||
if (xQueueReceive(queue, &message, portMAX_DELAY) != pdTRUE) {
|
||||
continue;
|
||||
}
|
||||
if (message.status != DALI_FRAME_OK) {
|
||||
continue;
|
||||
}
|
||||
const auto* channel = findChannelByHardwareBus(message.id);
|
||||
if (channel == nullptr) {
|
||||
continue;
|
||||
}
|
||||
size_t byte_count = (static_cast<size_t>(message.length) + 7U) / 8U;
|
||||
if (byte_count > DALI_MAX_BYTES) {
|
||||
byte_count = DALI_MAX_BYTES;
|
||||
}
|
||||
DaliRawFrame frame;
|
||||
frame.channel_index = channel->config.channel_index;
|
||||
frame.gateway_id = channel->config.gateway_id;
|
||||
frame.phy_kind = channel->phy_kind;
|
||||
frame.data.assign(message.data, message.data + byte_count);
|
||||
notifyRawFrameSinks(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void DaliDomainService::notifyRawFrameSinks(const DaliRawFrame& frame) {
|
||||
if (raw_frame_sink_lock_ != nullptr) {
|
||||
xSemaphoreTake(raw_frame_sink_lock_, portMAX_DELAY);
|
||||
}
|
||||
auto sinks = raw_frame_sinks_;
|
||||
if (raw_frame_sink_lock_ != nullptr) {
|
||||
xSemaphoreGive(raw_frame_sink_lock_);
|
||||
}
|
||||
for (const auto& sink : sinks) {
|
||||
sink(frame);
|
||||
}
|
||||
}
|
||||
|
||||
bool DaliDomainService::hasSerialPort(int uart_port) const {
|
||||
return std::any_of(channels_.begin(), channels_.end(), [uart_port](const auto& channel) {
|
||||
return channel->serial_bus.has_value() && channel->serial_bus->uart_port == uart_port;
|
||||
|
||||
Reference in New Issue
Block a user