From 9598147dd5883f1a07fcdec3b34b08b2e1bd44da Mon Sep 17 00:00:00 2001 From: Tony Date: Sun, 14 Jun 2026 21:20:42 +0800 Subject: [PATCH] feat: implement raw frame dispatch and handling in DaliDomainService Signed-off-by: Tony --- .../dali_domain/include/dali_domain.hpp | 7 + components/dali_domain/src/dali_domain.cpp | 122 ++++++++++++++++-- components/gateway_ble/src/gateway_ble.cpp | 4 + 3 files changed, 122 insertions(+), 11 deletions(-) diff --git a/components/dali_domain/include/dali_domain.hpp b/components/dali_domain/include/dali_domain.hpp index 58cfc17..25c0d0d 100644 --- a/components/dali_domain/include/dali_domain.hpp +++ b/components/dali_domain/include/dali_domain.hpp @@ -13,6 +13,7 @@ #include "esp_err.h" #include "freertos/FreeRTOS.h" +#include "freertos/queue.h" #include "freertos/semphr.h" #include "freertos/task.h" @@ -220,9 +221,13 @@ class DaliDomainService { esp_err_t startSerialRxTask(DaliChannel& channel); static void SerialRxTaskEntry(void* arg); void serialRxTaskLoop(DaliChannel* channel); + esp_err_t startRawFrameDispatchTask(); + static void RawFrameDispatchTaskEntry(void* arg); + void rawFrameDispatchTaskLoop(); esp_err_t startRawFrameTask(); static void RawFrameTaskEntry(void* arg); void rawFrameTaskLoop(); + void queueRawFrame(const DaliChannel& channel, const uint8_t* data, size_t len); void notifyRawFrameSinks(const DaliRawFrame& frame); void markBusActivity(uint8_t gateway_id) const; @@ -234,6 +239,8 @@ class DaliDomainService { mutable SemaphoreHandle_t host_activity_lock_{nullptr}; mutable std::map last_host_activity_ticks_; mutable std::map recent_host_command_frames_; + QueueHandle_t raw_frame_dispatch_queue_{nullptr}; + TaskHandle_t raw_frame_dispatch_task_handle_{nullptr}; TaskHandle_t raw_frame_task_handle_{nullptr}; }; diff --git a/components/dali_domain/src/dali_domain.cpp b/components/dali_domain/src/dali_domain.cpp index d345d0f..5ea1db5 100644 --- a/components/dali_domain/src/dali_domain.cpp +++ b/components/dali_domain/src/dali_domain.cpp @@ -16,6 +16,18 @@ #define CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS 25 #endif +#ifndef CONFIG_DALI_DOMAIN_RAW_RX_TASK_STACK_SIZE +#define CONFIG_DALI_DOMAIN_RAW_RX_TASK_STACK_SIZE 4096 +#endif + +#ifndef CONFIG_DALI_DOMAIN_RAW_DISPATCH_TASK_STACK_SIZE +#define CONFIG_DALI_DOMAIN_RAW_DISPATCH_TASK_STACK_SIZE 12288 +#endif + +#ifndef CONFIG_DALI_DOMAIN_RAW_DISPATCH_QUEUE_LEN +#define CONFIG_DALI_DOMAIN_RAW_DISPATCH_QUEUE_LEN 16 +#endif + static const char *TAG = "dali_domain"; namespace gateway { @@ -24,6 +36,11 @@ namespace { constexpr size_t kSerialRxPacketMaxBytes = 8; constexpr UBaseType_t kSerialRxQueueDepth = 8; +constexpr size_t kRawFrameMaxBytes = DALI_MAX_BYTES; +constexpr UBaseType_t kRawFrameDispatchQueueDepth = CONFIG_DALI_DOMAIN_RAW_DISPATCH_QUEUE_LEN; +constexpr uint32_t kRawFrameRxTaskStackSize = CONFIG_DALI_DOMAIN_RAW_RX_TASK_STACK_SIZE; +constexpr uint32_t kRawFrameDispatchTaskStackSize = + CONFIG_DALI_DOMAIN_RAW_DISPATCH_TASK_STACK_SIZE; constexpr uint32_t kHardwareQueryRawPostSuppressMs = 10; constexpr uint8_t kControlDeviceSendOpcode = 0x60; constexpr uint8_t kControlDeviceSendTwiceOpcode = 0x61; @@ -145,6 +162,14 @@ struct SerialRxPacket { uint8_t data[kSerialRxPacketMaxBytes]{}; }; +struct RawFrameEvent { + uint8_t channel_index{0}; + uint8_t gateway_id{0}; + DaliPhyKind phy_kind{DaliPhyKind::kCustom}; + size_t len{0}; + uint8_t data[kRawFrameMaxBytes]{}; +}; + std::vector LegacyQueryResponse(uint8_t status, uint8_t value = 0x00) { return {status, value}; } @@ -1723,6 +1748,10 @@ esp_err_t DaliDomainService::startSerialRxTask(DaliChannel& channel) { if (!channel.serial_bus.has_value() || channel.serial_rx_queue == nullptr) { return ESP_ERR_INVALID_STATE; } + const esp_err_t dispatch_err = startRawFrameDispatchTask(); + if (dispatch_err != ESP_OK) { + ESP_LOGW(TAG, "serial raw frame dispatch disabled: %s", esp_err_to_name(dispatch_err)); + } const BaseType_t created = xTaskCreate(&DaliDomainService::SerialRxTaskEntry, "dali_uart_rx", 4096, &channel, 4, &channel.serial_rx_task_handle); @@ -1765,11 +1794,52 @@ void DaliDomainService::serialRxTaskLoop(DaliChannel* channel) { if (packet.len != 2 && packet.len != 3) { continue; } + queueRawFrame(*channel, packet.data, packet.len); + } +} + +esp_err_t DaliDomainService::startRawFrameDispatchTask() { + if (raw_frame_dispatch_task_handle_ != nullptr) { + return ESP_OK; + } + if (raw_frame_dispatch_queue_ == nullptr) { + raw_frame_dispatch_queue_ = + xQueueCreate(kRawFrameDispatchQueueDepth, sizeof(RawFrameEvent)); + if (raw_frame_dispatch_queue_ == nullptr) { + return ESP_ERR_NO_MEM; + } + } + + const BaseType_t created = + xTaskCreate(&DaliDomainService::RawFrameDispatchTaskEntry, "dali_raw_dispatch", + kRawFrameDispatchTaskStackSize, this, 4, + &raw_frame_dispatch_task_handle_); + if (created != pdPASS) { + raw_frame_dispatch_task_handle_ = nullptr; + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +void DaliDomainService::RawFrameDispatchTaskEntry(void* arg) { + static_cast(arg)->rawFrameDispatchTaskLoop(); +} + +void DaliDomainService::rawFrameDispatchTaskLoop() { + RawFrameEvent event; + while (true) { + if (raw_frame_dispatch_queue_ == nullptr) { + vTaskDelay(pdMS_TO_TICKS(10)); + continue; + } + if (xQueueReceive(raw_frame_dispatch_queue_, &event, portMAX_DELAY) != pdTRUE) { + continue; + } 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(packet.data, packet.data + packet.len); + frame.channel_index = event.channel_index; + frame.gateway_id = event.gateway_id; + frame.phy_kind = event.phy_kind; + frame.data.assign(event.data, event.data + event.len); notifyRawFrameSinks(frame); } } @@ -1778,12 +1848,16 @@ esp_err_t DaliDomainService::startRawFrameTask() { if (raw_frame_task_handle_ != nullptr) { return ESP_OK; } + esp_err_t err = startRawFrameDispatchTask(); + if (err != ESP_OK) { + return err; + } 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, + "dali_raw_rx", kRawFrameRxTaskStackSize, this, 4, &raw_frame_task_handle_); if (created != pdPASS) { raw_frame_task_handle_ = nullptr; @@ -1825,15 +1899,41 @@ void DaliDomainService::rawFrameTaskLoop() { if (byte_count != 1 && byte_count != 2 && byte_count != 3) { continue; } - 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); + queueRawFrame(*channel, message.data, byte_count); } } +void DaliDomainService::queueRawFrame(const DaliChannel& channel, const uint8_t* data, + size_t len) { + if (data == nullptr || len == 0) { + return; + } + if (len > kRawFrameMaxBytes) { + len = kRawFrameMaxBytes; + } + + markBusActivity(channel.config.gateway_id); + + if (raw_frame_dispatch_queue_ == nullptr) { + return; + } + + RawFrameEvent event; + event.channel_index = channel.config.channel_index; + event.gateway_id = channel.config.gateway_id; + event.phy_kind = channel.phy_kind; + event.len = len; + std::copy(data, data + len, event.data); + + if (xQueueSendToBack(raw_frame_dispatch_queue_, &event, 0) == pdTRUE) { + return; + } + + RawFrameEvent dropped; + xQueueReceive(raw_frame_dispatch_queue_, &dropped, 0); + xQueueSendToBack(raw_frame_dispatch_queue_, &event, 0); +} + void DaliDomainService::notifyRawFrameSinks(const DaliRawFrame& frame) { markBusActivity(frame.gateway_id); if (raw_frame_sink_lock_ != nullptr) { diff --git a/components/gateway_ble/src/gateway_ble.cpp b/components/gateway_ble/src/gateway_ble.cpp index e15d7a7..7117b6f 100644 --- a/components/gateway_ble/src/gateway_ble.cpp +++ b/components/gateway_ble/src/gateway_ble.cpp @@ -408,6 +408,10 @@ void GatewayBleBridge::handleDaliRawFrame(const DaliRawFrame& frame) { if (!controller_.rawReportingEnabled(frame.gateway_id)) { return; } + // Forward/control events are already published on FFF3 as structured 0x22 frames. + if (notify_enabled_[kGatewayCharacteristicIndex] && frame.data.size() != 1) { + return; + } notifyCharacteristic(frame.channel_index, LegacyRawPayload(frame.data)); }