feat(gateway): update BLE connection parameters and enhance DALI timeout configurations

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-05-15 08:42:20 +08:00
parent 70ae1ae6cf
commit f005d2bc09
5 changed files with 152 additions and 118 deletions
+3 -3
View File
@@ -402,9 +402,9 @@ static uint32_t tx_completion_timeout_ms(const Dali_msg_t *msg)
uint64_t frame_us = ((uint64_t)(2U + bits * 2U) * hb) + stop_us;
uint32_t frame_ms = (uint32_t)((frame_us + 999U) / 1000U);
uint32_t timeout_ms = frame_ms + 30U;
if (timeout_ms < 30U) {
timeout_ms = 30U;
uint32_t timeout_ms = frame_ms + 20U;
if (timeout_ms < 20U) {
timeout_ms = 20U;
}
if (timeout_ms > 500U) {
timeout_ms = 500U;
+48 -26
View File
@@ -1,10 +1,12 @@
#include "dali_domain.hpp"
#define LOG_LOCAL_LEVEL CONFIG_DALI_LOG_LEVEL
#include "esp_log.h"
#include "dali.h"
#include "dali_hal.h"
#include "dali.hpp"
#include "driver/uart.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include <algorithm>
@@ -14,25 +16,29 @@
#define CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS 25
#endif
static const char *TAG = "dali_domain";
namespace gateway {
namespace {
constexpr const char* kTag = "dali_domain";
constexpr size_t kSerialRxPacketMaxBytes = 8;
constexpr UBaseType_t kSerialRxQueueDepth = 8;
constexpr uint32_t kHardwareQueryRawSuppressMs = CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS + 10;
constexpr uint32_t kHardwareQueryRawPostSuppressMs = 10;
portMUX_TYPE s_query_raw_suppress_lock = portMUX_INITIALIZER_UNLOCKED;
TickType_t s_query_raw_suppress_until[DALI_PHY_COUNT] = {};
uint8_t s_query_raw_suppress_inflight[DALI_PHY_COUNT] = {};
TickType_t s_query_raw_suppress_post_until[DALI_PHY_COUNT] = {};
void BeginHardwareQueryRawSuppress(uint8_t bus_id) {
if (bus_id >= DALI_PHY_COUNT) {
return;
}
const TickType_t until = xTaskGetTickCount() + pdMS_TO_TICKS(kHardwareQueryRawSuppressMs);
portENTER_CRITICAL(&s_query_raw_suppress_lock);
s_query_raw_suppress_until[bus_id] = until;
if (s_query_raw_suppress_inflight[bus_id] < UINT8_MAX) {
++s_query_raw_suppress_inflight[bus_id];
}
s_query_raw_suppress_post_until[bus_id] = 0;
portEXIT_CRITICAL(&s_query_raw_suppress_lock);
}
@@ -44,12 +50,13 @@ bool TakeHardwareQueryRawSuppress(uint8_t bus_id) {
bool suppress = false;
const TickType_t now = xTaskGetTickCount();
portENTER_CRITICAL(&s_query_raw_suppress_lock);
const TickType_t until = s_query_raw_suppress_until[bus_id];
if (until != 0 && now <= until) {
const TickType_t post_until = s_query_raw_suppress_post_until[bus_id];
if (s_query_raw_suppress_inflight[bus_id] > 0) {
suppress = true;
s_query_raw_suppress_until[bus_id] = 0;
} else if (until != 0) {
s_query_raw_suppress_until[bus_id] = 0;
} else if (post_until != 0 && now <= post_until) {
suppress = true;
} else if (post_until != 0) {
s_query_raw_suppress_post_until[bus_id] = 0;
}
portEXIT_CRITICAL(&s_query_raw_suppress_lock);
return suppress;
@@ -59,8 +66,15 @@ void ClearHardwareQueryRawSuppress(uint8_t bus_id) {
if (bus_id >= DALI_PHY_COUNT) {
return;
}
const TickType_t post_until = xTaskGetTickCount() +
pdMS_TO_TICKS(kHardwareQueryRawPostSuppressMs);
portENTER_CRITICAL(&s_query_raw_suppress_lock);
s_query_raw_suppress_until[bus_id] = 0;
if (s_query_raw_suppress_inflight[bus_id] > 0) {
--s_query_raw_suppress_inflight[bus_id];
}
if (s_query_raw_suppress_inflight[bus_id] == 0) {
s_query_raw_suppress_post_until[bus_id] = post_until;
}
portEXIT_CRITICAL(&s_query_raw_suppress_lock);
}
@@ -128,9 +142,11 @@ bool SendHardwareFrame(uint8_t bus_id, const uint8_t* data, size_t len) {
switch (data[0]) {
case 0x10:
ESP_LOGD(TAG, "sending hardware frame for bus=%u data=%02x %02x", bus_id, data[1], data[2]);
dali_send(&tx);
return true;
case 0x11:
ESP_LOGD(TAG, "sending extended frame for bus=%u data=%02x %02x", bus_id, data[1], data[2]);
dali_send_double(&tx);
return true;
default:
@@ -148,7 +164,7 @@ std::vector<uint8_t> TransactHardwareFrame(uint8_t bus_id, const uint8_t* data,
switch (data[0]) {
case 0x00:
return {0xFF};
ESP_LOGD(TAG, "received reset for bus=%u", bus_id);
case 0x01:
return {1};
case 0x10:
@@ -156,15 +172,21 @@ std::vector<uint8_t> TransactHardwareFrame(uint8_t bus_id, const uint8_t* data,
return SendHardwareFrame(bus_id, data, len) ? std::vector<uint8_t>{0xFF}
: std::vector<uint8_t>{0xFD};
case 0x12: {
ESP_LOGD(TAG, "received hardware query frame for bus=%u data=%02x %02x", bus_id, data[1],
data[2]);
Dali_msg_t tx = dali_msg_new(data[1], data[2]);
tx.id = bus_id;
Dali_msg_t rx = {};
BeginHardwareQueryRawSuppress(bus_id);
if (dali_query(&tx, &rx) == pdTRUE) {
ClearHardwareQueryRawSuppress(bus_id);
if (rx.status != DALI_FRAME_OK || rx.length != 8) {
ClearHardwareQueryRawSuppress(bus_id);
ESP_LOGW(TAG, "hardware query response for bus=%u has invalid status or length", bus_id);
return LegacyQueryResponse(0xFD);
}
ESP_LOGD(TAG, "got hardware query response for bus=%u status=%u len=%u data=%02x %02x "
"%02x %02x",
bus_id, rx.status, rx.length, rx.data[0], rx.data[1], rx.data[2], rx.data[3]);
return {0xFF, rx.data[0]};
}
ClearHardwareQueryRawSuppress(bus_id);
@@ -290,14 +312,14 @@ bool DaliDomainService::bindTransport(const DaliChannelConfig& config, DaliTrans
esp_err_t DaliDomainService::bindHardwareBus(const DaliHardwareBusConfig& config) {
esp_err_t err = dali_hal_set_baudrate(config.baudrate);
if (err != ESP_OK) {
ESP_LOGE(kTag, "failed to set baudrate=%lu: %s", static_cast<unsigned long>(config.baudrate),
ESP_LOGE(TAG, "failed to set baudrate=%lu: %s", static_cast<unsigned long>(config.baudrate),
esp_err_to_name(err));
return err;
}
err = dali_hal_init(config.bus_id, config.tx_pin, config.rx_pin);
if (err != ESP_OK) {
ESP_LOGE(kTag, "failed to init bus=%u tx=%u rx=%u: %s", config.bus_id, config.tx_pin,
ESP_LOGE(TAG, "failed to init bus=%u tx=%u rx=%u: %s", config.bus_id, config.tx_pin,
config.rx_pin, esp_err_to_name(err));
return err;
}
@@ -323,9 +345,9 @@ esp_err_t DaliDomainService::bindHardwareBus(const DaliHardwareBusConfig& config
}
err = startRawFrameTask();
if (err != ESP_OK) {
ESP_LOGW(kTag, "failed to start raw frame task: %s", esp_err_to_name(err));
ESP_LOGW(TAG, "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",
ESP_LOGI(TAG, "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));
return ESP_OK;
@@ -336,7 +358,7 @@ esp_err_t DaliDomainService::bindSerialBus(const DaliSerialBusConfig& config) {
return ESP_ERR_INVALID_ARG;
}
if (hasSerialPort(config.uart_port)) {
ESP_LOGE(kTag, "uart%d is already assigned to another DALI channel", config.uart_port);
ESP_LOGE(TAG, "uart%d is already assigned to another DALI channel", config.uart_port);
return ESP_ERR_INVALID_STATE;
}
@@ -352,27 +374,27 @@ esp_err_t DaliDomainService::bindSerialBus(const DaliSerialBusConfig& config) {
auto uart = static_cast<uart_port_t>(config.uart_port);
esp_err_t err = uart_param_config(uart, &uart_config);
if (err != ESP_OK) {
ESP_LOGE(kTag, "failed to configure uart%d: %s", config.uart_port, esp_err_to_name(err));
ESP_LOGE(TAG, "failed to configure uart%d: %s", config.uart_port, esp_err_to_name(err));
return err;
}
err = uart_set_pin(uart, config.tx_pin < 0 ? UART_PIN_NO_CHANGE : config.tx_pin,
config.rx_pin < 0 ? UART_PIN_NO_CHANGE : config.rx_pin,
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
if (err != ESP_OK) {
ESP_LOGE(kTag, "failed to set uart%d pins tx=%d rx=%d: %s", config.uart_port,
ESP_LOGE(TAG, "failed to set uart%d pins tx=%d rx=%d: %s", config.uart_port,
config.tx_pin, config.rx_pin, esp_err_to_name(err));
return err;
}
err = uart_driver_install(uart, config.rx_buffer_size, config.tx_buffer_size, 0, nullptr, 0);
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
ESP_LOGE(kTag, "failed to install uart%d driver: %s", config.uart_port, esp_err_to_name(err));
ESP_LOGE(TAG, "failed to install uart%d driver: %s", config.uart_port, esp_err_to_name(err));
return err;
}
uart_flush_input(uart);
QueueHandle_t serial_rx_queue = xQueueCreate(kSerialRxQueueDepth, sizeof(SerialRxPacket));
if (serial_rx_queue == nullptr) {
ESP_LOGE(kTag, "failed to create uart%d RX queue", config.uart_port);
ESP_LOGE(TAG, "failed to create uart%d RX queue", config.uart_port);
return ESP_ERR_NO_MEM;
}
@@ -402,12 +424,12 @@ esp_err_t DaliDomainService::bindSerialBus(const DaliSerialBusConfig& config) {
channel->serial_rx_queue = serial_rx_queue;
err = startSerialRxTask(*channel);
if (err != ESP_OK) {
ESP_LOGE(kTag, "failed to start uart%d RX task: %s", config.uart_port,
ESP_LOGE(TAG, "failed to start uart%d RX task: %s", config.uart_port,
esp_err_to_name(err));
return err;
}
}
ESP_LOGI(kTag, "bound channel=%u gateway=%u serial uart%d tx=%d rx=%d baudrate=%lu",
ESP_LOGI(TAG, "bound channel=%u gateway=%u serial uart%d tx=%d rx=%d baudrate=%lu",
config.channel_index, config.gateway_id, config.uart_port, config.tx_pin, config.rx_pin,
static_cast<unsigned long>(config.baudrate));
return ESP_OK;
@@ -1281,7 +1303,7 @@ void DaliDomainService::rawFrameTaskLoop() {
Dali_msg_t message = {};
while (true) {
if (queue == nullptr) {
vTaskDelay(pdMS_TO_TICKS(100));
vTaskDelay(pdMS_TO_TICKS(10));
queue = dali_hal_raw_receive_queue();
continue;
}
@@ -455,6 +455,18 @@ int GatewayBleBridge::handleGapEvent(struct ble_gap_event* event) {
notify_enabled_.fill(false);
last_notify_payload_.clear();
last_notify_at_us_ = 0;
struct ble_gap_upd_params params = {
.itvl_min = 15,
.itvl_max = 15,
.latency = 3,
.supervision_timeout = 1000,
.min_ce_len = 0,
.max_ce_len = 0,
};
int rc = ble_gap_update_params(event->connect.conn_handle, &params);
if (rc != 0) {
ESP_LOGW(kTag, "ble_gap_update_params rc=%d", rc);
}
ESP_LOGI(kTag, "BLE client connected handle=%u", conn_handle_);
} else if (enabled_) {
startAdvertising();