feat: implement raw frame dispatch and handling in DaliDomainService
Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -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<uint8_t, TickType_t> last_host_activity_ticks_;
|
||||
mutable std::map<uint8_t, RecentHostCommandFrame> 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};
|
||||
};
|
||||
|
||||
|
||||
@@ -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<uint8_t> 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<DaliDomainService*>(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) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user