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 "esp_err.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
|
||||||
@@ -220,9 +221,13 @@ class DaliDomainService {
|
|||||||
esp_err_t startSerialRxTask(DaliChannel& channel);
|
esp_err_t startSerialRxTask(DaliChannel& channel);
|
||||||
static void SerialRxTaskEntry(void* arg);
|
static void SerialRxTaskEntry(void* arg);
|
||||||
void serialRxTaskLoop(DaliChannel* channel);
|
void serialRxTaskLoop(DaliChannel* channel);
|
||||||
|
esp_err_t startRawFrameDispatchTask();
|
||||||
|
static void RawFrameDispatchTaskEntry(void* arg);
|
||||||
|
void rawFrameDispatchTaskLoop();
|
||||||
esp_err_t startRawFrameTask();
|
esp_err_t startRawFrameTask();
|
||||||
static void RawFrameTaskEntry(void* arg);
|
static void RawFrameTaskEntry(void* arg);
|
||||||
void rawFrameTaskLoop();
|
void rawFrameTaskLoop();
|
||||||
|
void queueRawFrame(const DaliChannel& channel, const uint8_t* data, size_t len);
|
||||||
void notifyRawFrameSinks(const DaliRawFrame& frame);
|
void notifyRawFrameSinks(const DaliRawFrame& frame);
|
||||||
void markBusActivity(uint8_t gateway_id) const;
|
void markBusActivity(uint8_t gateway_id) const;
|
||||||
|
|
||||||
@@ -234,6 +239,8 @@ class DaliDomainService {
|
|||||||
mutable SemaphoreHandle_t host_activity_lock_{nullptr};
|
mutable SemaphoreHandle_t host_activity_lock_{nullptr};
|
||||||
mutable std::map<uint8_t, TickType_t> last_host_activity_ticks_;
|
mutable std::map<uint8_t, TickType_t> last_host_activity_ticks_;
|
||||||
mutable std::map<uint8_t, RecentHostCommandFrame> recent_host_command_frames_;
|
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};
|
TaskHandle_t raw_frame_task_handle_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
#define CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS 25
|
#define CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS 25
|
||||||
#endif
|
#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";
|
static const char *TAG = "dali_domain";
|
||||||
|
|
||||||
namespace gateway {
|
namespace gateway {
|
||||||
@@ -24,6 +36,11 @@ namespace {
|
|||||||
|
|
||||||
constexpr size_t kSerialRxPacketMaxBytes = 8;
|
constexpr size_t kSerialRxPacketMaxBytes = 8;
|
||||||
constexpr UBaseType_t kSerialRxQueueDepth = 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 uint32_t kHardwareQueryRawPostSuppressMs = 10;
|
||||||
constexpr uint8_t kControlDeviceSendOpcode = 0x60;
|
constexpr uint8_t kControlDeviceSendOpcode = 0x60;
|
||||||
constexpr uint8_t kControlDeviceSendTwiceOpcode = 0x61;
|
constexpr uint8_t kControlDeviceSendTwiceOpcode = 0x61;
|
||||||
@@ -145,6 +162,14 @@ struct SerialRxPacket {
|
|||||||
uint8_t data[kSerialRxPacketMaxBytes]{};
|
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) {
|
std::vector<uint8_t> LegacyQueryResponse(uint8_t status, uint8_t value = 0x00) {
|
||||||
return {status, value};
|
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) {
|
if (!channel.serial_bus.has_value() || channel.serial_rx_queue == nullptr) {
|
||||||
return ESP_ERR_INVALID_STATE;
|
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,
|
const BaseType_t created = xTaskCreate(&DaliDomainService::SerialRxTaskEntry,
|
||||||
"dali_uart_rx", 4096, &channel, 4,
|
"dali_uart_rx", 4096, &channel, 4,
|
||||||
&channel.serial_rx_task_handle);
|
&channel.serial_rx_task_handle);
|
||||||
@@ -1765,11 +1794,52 @@ void DaliDomainService::serialRxTaskLoop(DaliChannel* channel) {
|
|||||||
if (packet.len != 2 && packet.len != 3) {
|
if (packet.len != 2 && packet.len != 3) {
|
||||||
continue;
|
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;
|
DaliRawFrame frame;
|
||||||
frame.channel_index = channel->config.channel_index;
|
frame.channel_index = event.channel_index;
|
||||||
frame.gateway_id = channel->config.gateway_id;
|
frame.gateway_id = event.gateway_id;
|
||||||
frame.phy_kind = channel->phy_kind;
|
frame.phy_kind = event.phy_kind;
|
||||||
frame.data.assign(packet.data, packet.data + packet.len);
|
frame.data.assign(event.data, event.data + event.len);
|
||||||
notifyRawFrameSinks(frame);
|
notifyRawFrameSinks(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1778,12 +1848,16 @@ esp_err_t DaliDomainService::startRawFrameTask() {
|
|||||||
if (raw_frame_task_handle_ != nullptr) {
|
if (raw_frame_task_handle_ != nullptr) {
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
esp_err_t err = startRawFrameDispatchTask();
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
QueueHandle_t queue = dali_hal_raw_receive_queue();
|
QueueHandle_t queue = dali_hal_raw_receive_queue();
|
||||||
if (queue == nullptr) {
|
if (queue == nullptr) {
|
||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
const BaseType_t created = xTaskCreate(&DaliDomainService::RawFrameTaskEntry,
|
const BaseType_t created = xTaskCreate(&DaliDomainService::RawFrameTaskEntry,
|
||||||
"dali_raw_rx", 4096, this, 4,
|
"dali_raw_rx", kRawFrameRxTaskStackSize, this, 4,
|
||||||
&raw_frame_task_handle_);
|
&raw_frame_task_handle_);
|
||||||
if (created != pdPASS) {
|
if (created != pdPASS) {
|
||||||
raw_frame_task_handle_ = nullptr;
|
raw_frame_task_handle_ = nullptr;
|
||||||
@@ -1825,15 +1899,41 @@ void DaliDomainService::rawFrameTaskLoop() {
|
|||||||
if (byte_count != 1 && byte_count != 2 && byte_count != 3) {
|
if (byte_count != 1 && byte_count != 2 && byte_count != 3) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
DaliRawFrame frame;
|
queueRawFrame(*channel, message.data, byte_count);
|
||||||
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::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) {
|
void DaliDomainService::notifyRawFrameSinks(const DaliRawFrame& frame) {
|
||||||
markBusActivity(frame.gateway_id);
|
markBusActivity(frame.gateway_id);
|
||||||
if (raw_frame_sink_lock_ != nullptr) {
|
if (raw_frame_sink_lock_ != nullptr) {
|
||||||
|
|||||||
@@ -408,6 +408,10 @@ void GatewayBleBridge::handleDaliRawFrame(const DaliRawFrame& frame) {
|
|||||||
if (!controller_.rawReportingEnabled(frame.gateway_id)) {
|
if (!controller_.rawReportingEnabled(frame.gateway_id)) {
|
||||||
return;
|
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));
|
notifyCharacteristic(frame.channel_index, LegacyRawPayload(frame.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user