fix(gateway): update DALI configuration parameters for improved performance and reliability
This commit add comat parameter for some old DALI-1 control gear. Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -2781,10 +2781,10 @@ CONFIG_DALI_TIMER_RESOLUTION_HZ=3636363
|
|||||||
CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US=0
|
CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US=0
|
||||||
CONFIG_DALI_TX_STOP_CONDITION_US=0
|
CONFIG_DALI_TX_STOP_CONDITION_US=0
|
||||||
CONFIG_DALI_RX_STOP_CONDITION_US=0
|
CONFIG_DALI_RX_STOP_CONDITION_US=0
|
||||||
CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS=25
|
CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS=30
|
||||||
CONFIG_DALI_DOUBLE_SEND_DELAY_MS=15
|
CONFIG_DALI_DOUBLE_SEND_DELAY_MS=20
|
||||||
CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS=15
|
CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS=20
|
||||||
CONFIG_DALI_FORWARD_AFTER_BACKWARD_WAIT_MS=5
|
CONFIG_DALI_FORWARD_AFTER_BACKWARD_WAIT_MS=10
|
||||||
CONFIG_DALI_FORWARD_MAX_WAIT_MS=50
|
CONFIG_DALI_FORWARD_MAX_WAIT_MS=50
|
||||||
CONFIG_DALI_BACKWARD_IDLE_TIMEOUT_MS=10
|
CONFIG_DALI_BACKWARD_IDLE_TIMEOUT_MS=10
|
||||||
CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS=500
|
CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS=500
|
||||||
|
|||||||
@@ -623,7 +623,8 @@ CONFIG_GATEWAY_CHANNEL1_NATIVE_BAUDRATE=1200
|
|||||||
CONFIG_GATEWAY_CACHE_SUPPORTED=y
|
CONFIG_GATEWAY_CACHE_SUPPORTED=y
|
||||||
CONFIG_GATEWAY_CACHE_START_ENABLED=y
|
CONFIG_GATEWAY_CACHE_START_ENABLED=y
|
||||||
# CONFIG_GATEWAY_CACHE_RECONCILIATION_ENABLED is not set
|
# CONFIG_GATEWAY_CACHE_RECONCILIATION_ENABLED is not set
|
||||||
CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS=60000
|
CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS=10000
|
||||||
|
CONFIG_GATEWAY_CACHE_REFRESH_INTERVAL_MS=120000
|
||||||
# end of Gateway Cache
|
# end of Gateway Cache
|
||||||
|
|
||||||
# CONFIG_GATEWAY_ENABLE_DALI_BUS is not set
|
# CONFIG_GATEWAY_ENABLE_DALI_BUS is not set
|
||||||
@@ -674,7 +675,7 @@ CONFIG_GATEWAY_KNX_BRIDGE_SUPPORTED=y
|
|||||||
CONFIG_GATEWAY_START_KNX_BRIDGE_ENABLED=y
|
CONFIG_GATEWAY_START_KNX_BRIDGE_ENABLED=y
|
||||||
CONFIG_GATEWAY_KNX_DATA_SECURE_SUPPORTED=y
|
CONFIG_GATEWAY_KNX_DATA_SECURE_SUPPORTED=y
|
||||||
# CONFIG_GATEWAY_KNX_IP_SECURE_SUPPORTED is not set
|
# CONFIG_GATEWAY_KNX_IP_SECURE_SUPPORTED is not set
|
||||||
# CONFIG_GATEWAY_KNX_SECURITY_DEV_ENDPOINTS is not set
|
CONFIG_GATEWAY_KNX_SECURITY_DEV_ENDPOINTS=y
|
||||||
CONFIG_GATEWAY_KNX_SECURITY_PLAIN_NVS=y
|
CONFIG_GATEWAY_KNX_SECURITY_PLAIN_NVS=y
|
||||||
CONFIG_GATEWAY_KNX_OEM_MANUFACTURER_ID=0x01e5
|
CONFIG_GATEWAY_KNX_OEM_MANUFACTURER_ID=0x01e5
|
||||||
CONFIG_GATEWAY_KNX_OEM_HARDWARE_ID=0xa401
|
CONFIG_GATEWAY_KNX_OEM_HARDWARE_ID=0xa401
|
||||||
|
|||||||
+11
-11
@@ -17,11 +17,11 @@ config DALI_DEFAULT_BAUDRATE
|
|||||||
config DALI_TIMER_RESOLUTION_HZ
|
config DALI_TIMER_RESOLUTION_HZ
|
||||||
int "Native DALI timer resolution Hz"
|
int "Native DALI timer resolution Hz"
|
||||||
range 1000000 8000000
|
range 1000000 8000000
|
||||||
default 3000000
|
default 3636363
|
||||||
help
|
help
|
||||||
GPTimer resolution for native DALI Manchester timing. The default 3 MHz
|
GPTimer resolution for native DALI Manchester timing. The default
|
||||||
allows a 1200 bps half-bit period of 416.67 us to be represented as
|
3.636363 MHz timing matches the gateway's tuned 1200 bps behavior for
|
||||||
1250 timer ticks.
|
older control gear that needs more recovery margin between commands.
|
||||||
|
|
||||||
config DALI_CUSTOM_HALF_BIT_TIME_X100_US
|
config DALI_CUSTOM_HALF_BIT_TIME_X100_US
|
||||||
int "Custom native DALI half-bit time x100 us"
|
int "Custom native DALI half-bit time x100 us"
|
||||||
@@ -51,7 +51,7 @@ config DALI_RX_STOP_CONDITION_US
|
|||||||
config DALI_QUERY_RESPONSE_TIMEOUT_MS
|
config DALI_QUERY_RESPONSE_TIMEOUT_MS
|
||||||
int "DALI query response timeout ms"
|
int "DALI query response timeout ms"
|
||||||
range 10 100
|
range 10 100
|
||||||
default 25
|
default 30
|
||||||
help
|
help
|
||||||
Time to wait for a complete backward frame after a forward query has
|
Time to wait for a complete backward frame after a forward query has
|
||||||
finished transmitting. DALI backward frames start 5.5-10.5 ms after the
|
finished transmitting. DALI backward frames start 5.5-10.5 ms after the
|
||||||
@@ -61,7 +61,7 @@ config DALI_QUERY_RESPONSE_TIMEOUT_MS
|
|||||||
config DALI_DOUBLE_SEND_DELAY_MS
|
config DALI_DOUBLE_SEND_DELAY_MS
|
||||||
int "Double-send delay ms"
|
int "Double-send delay ms"
|
||||||
range 0 100
|
range 0 100
|
||||||
default 10
|
default 20
|
||||||
help
|
help
|
||||||
Delay between the two frames sent by dali_send_double(), measured after
|
Delay between the two frames sent by dali_send_double(), measured after
|
||||||
the first frame has completed. Exposed for development tuning.
|
the first frame has completed. Exposed for development tuning.
|
||||||
@@ -69,7 +69,7 @@ config DALI_DOUBLE_SEND_DELAY_MS
|
|||||||
config DALI_FORWARD_ACTIVITY_WAIT_MS
|
config DALI_FORWARD_ACTIVITY_WAIT_MS
|
||||||
int "Forward-frame wait after bus activity ms"
|
int "Forward-frame wait after bus activity ms"
|
||||||
range 0 1000
|
range 0 1000
|
||||||
default 25
|
default 20
|
||||||
help
|
help
|
||||||
Minimum delay before sending a 2- to 4-byte forward frame after normal
|
Minimum delay before sending a 2- to 4-byte forward frame after normal
|
||||||
bus activity. This is the native queue anti-collision wait.
|
bus activity. This is the native queue anti-collision wait.
|
||||||
@@ -77,7 +77,7 @@ config DALI_FORWARD_ACTIVITY_WAIT_MS
|
|||||||
config DALI_FORWARD_AFTER_BACKWARD_WAIT_MS
|
config DALI_FORWARD_AFTER_BACKWARD_WAIT_MS
|
||||||
int "Forward-frame wait after backward frame ms"
|
int "Forward-frame wait after backward frame ms"
|
||||||
range 0 1000
|
range 0 1000
|
||||||
default 5
|
default 10
|
||||||
help
|
help
|
||||||
Minimum delay before sending a 2- to 4-byte forward frame after the last
|
Minimum delay before sending a 2- to 4-byte forward frame after the last
|
||||||
valid 1-byte backward frame received by the native bus.
|
valid 1-byte backward frame received by the native bus.
|
||||||
@@ -94,7 +94,7 @@ config DALI_FORWARD_MAX_WAIT_MS
|
|||||||
config DALI_BACKWARD_IDLE_TIMEOUT_MS
|
config DALI_BACKWARD_IDLE_TIMEOUT_MS
|
||||||
int "Backward-frame idle wait timeout ms"
|
int "Backward-frame idle wait timeout ms"
|
||||||
range 0 1000
|
range 0 1000
|
||||||
default 9
|
default 10
|
||||||
help
|
help
|
||||||
Time a 1-byte backward frame waits for an idle bus before being sent
|
Time a 1-byte backward frame waits for an idle bus before being sent
|
||||||
anyway. Backward frame sends are not echo-verified because collisions
|
anyway. Backward frame sends are not echo-verified because collisions
|
||||||
@@ -103,7 +103,7 @@ config DALI_BACKWARD_IDLE_TIMEOUT_MS
|
|||||||
config DALI_BUS_POWER_CHECK_INTERVAL_MS
|
config DALI_BUS_POWER_CHECK_INTERVAL_MS
|
||||||
int "Bus power-down check interval ms"
|
int "Bus power-down check interval ms"
|
||||||
range 10 5000
|
range 10 5000
|
||||||
default 100
|
default 500
|
||||||
help
|
help
|
||||||
Interval used to resample the RX pin while the native DALI bus is marked
|
Interval used to resample the RX pin while the native DALI bus is marked
|
||||||
power-down. This lets the HAL recover when the bus was already powered
|
power-down. This lets the HAL recover when the bus was already powered
|
||||||
@@ -112,7 +112,7 @@ config DALI_BUS_POWER_CHECK_INTERVAL_MS
|
|||||||
config DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
|
config DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
|
||||||
int "Legacy bus abnormal report interval ms"
|
int "Legacy bus abnormal report interval ms"
|
||||||
range 0 60000
|
range 0 60000
|
||||||
default 1000
|
default 3000
|
||||||
help
|
help
|
||||||
Interval for publishing the legacy two-byte FF FD bus-abnormal raw frame
|
Interval for publishing the legacy two-byte FF FD bus-abnormal raw frame
|
||||||
while the native DALI bus is power-down. Set to 0 to disable the report.
|
while the native DALI bus is power-down. Set to 0 to disable the report.
|
||||||
|
|||||||
@@ -53,13 +53,13 @@ Use `menuconfig` under `DALI Component` to configure:
|
|||||||
|
|
||||||
The native bus monitor uses `CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS` to resample RX while
|
The native bus monitor uses `CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS` to resample RX while
|
||||||
power-down and `CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS` to publish legacy `FF FD`
|
power-down and `CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS` to publish legacy `FF FD`
|
||||||
raw frames while down. The report interval defaults to 1000 ms; set it to 0 to disable the
|
raw frames while down. The report interval defaults to 3000 ms; set it to 0 to disable the
|
||||||
compatibility report.
|
compatibility report.
|
||||||
|
|
||||||
Native timing defaults target standard 1200 bps DALI: a 416.67 us half-bit period is
|
Native timing defaults target standard 1200 bps DALI: a 416.67 us half-bit period is
|
||||||
generated by the default 3 MHz timer as 1250 ticks. `CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US`
|
generated by the default 3.636363 MHz timer. `CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US`
|
||||||
can override the half-bit period for development; keep it at 0 for baudrate-derived timing.
|
can override the half-bit period for development; keep it at 0 for baudrate-derived timing.
|
||||||
Query no-response timeout defaults to 25 ms, which covers the 5.5-10.5 ms backward-frame
|
Query no-response timeout defaults to 30 ms, which covers the 5.5-10.5 ms backward-frame
|
||||||
start window plus the approximately 9.95 ms backward frame duration.
|
start window plus the approximately 9.95 ms backward frame duration.
|
||||||
|
|
||||||
Native TX queue arbitration uses frame length as the frame type signal. Two- to four-byte
|
Native TX queue arbitration uses frame length as the frame type signal. Two- to four-byte
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS
|
#ifndef CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS
|
||||||
#define CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS 25
|
#define CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS 30
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_DOUBLE_SEND_DELAY_MS
|
#ifndef CONFIG_DALI_DOUBLE_SEND_DELAY_MS
|
||||||
#define CONFIG_DALI_DOUBLE_SEND_DELAY_MS 10
|
#define CONFIG_DALI_DOUBLE_SEND_DELAY_MS 20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static SemaphoreHandle_t s_dali_core_lock;
|
static SemaphoreHandle_t s_dali_core_lock;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_TIMER_RESOLUTION_HZ
|
#ifndef CONFIG_DALI_TIMER_RESOLUTION_HZ
|
||||||
#define CONFIG_DALI_TIMER_RESOLUTION_HZ 3000000
|
#define CONFIG_DALI_TIMER_RESOLUTION_HZ 3636363
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US
|
#ifndef CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US
|
||||||
@@ -80,19 +80,19 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS
|
#ifndef CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS
|
||||||
#define CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS 100
|
#define CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS 500
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
|
#ifndef CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
|
||||||
#define CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS 1000
|
#define CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS 3000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS
|
#ifndef CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS
|
||||||
#define CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS 25
|
#define CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS 20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_FORWARD_AFTER_BACKWARD_WAIT_MS
|
#ifndef CONFIG_DALI_FORWARD_AFTER_BACKWARD_WAIT_MS
|
||||||
#define CONFIG_DALI_FORWARD_AFTER_BACKWARD_WAIT_MS 5
|
#define CONFIG_DALI_FORWARD_AFTER_BACKWARD_WAIT_MS 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_FORWARD_MAX_WAIT_MS
|
#ifndef CONFIG_DALI_FORWARD_MAX_WAIT_MS
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_BACKWARD_IDLE_TIMEOUT_MS
|
#ifndef CONFIG_DALI_BACKWARD_IDLE_TIMEOUT_MS
|
||||||
#define CONFIG_DALI_BACKWARD_IDLE_TIMEOUT_MS 9
|
#define CONFIG_DALI_BACKWARD_IDLE_TIMEOUT_MS 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WITHIN_RANGE(x, min, max) ((x) > (min) && (x) < (max))
|
#define WITHIN_RANGE(x, min, max) ((x) > (min) && (x) < (max))
|
||||||
|
|||||||
@@ -247,6 +247,121 @@ void GatewayKnxBridge::runCommissioningScanTask() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!is_cancelled()) {
|
while (!is_cancelled()) {
|
||||||
|
auto log_and_record_ballast = [&](const GatewayKnxCommissioningBallast& ballast) {
|
||||||
|
record_ballast(ballast);
|
||||||
|
ESP_LOGI(kTag, "REG1-Dali scan found random=0x%02X%02X%02X short=%u",
|
||||||
|
ballast.high, ballast.middle, ballast.low,
|
||||||
|
static_cast<unsigned>(ballast.short_address));
|
||||||
|
};
|
||||||
|
auto withdraw_selected = [&]() {
|
||||||
|
return SendRaw(engine_, DALI_CMD_SPECIAL_WITHDRAW, DALI_CMD_OFF,
|
||||||
|
"knx-function-scan-withdraw");
|
||||||
|
};
|
||||||
|
auto program_selected_ballast =
|
||||||
|
[&](uint8_t short_address,
|
||||||
|
uint32_t fallback_random_address) -> std::optional<GatewayKnxCommissioningBallast> {
|
||||||
|
if (!ProgramShortAddressAndConfirm(engine_, short_address)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto random_address =
|
||||||
|
QueryRandomAddressForShortAddress(engine_, short_address).value_or(fallback_random_address);
|
||||||
|
GatewayKnxCommissioningBallast ballast;
|
||||||
|
ballast.high = static_cast<uint8_t>((random_address >> 16) & 0xff);
|
||||||
|
ballast.middle = static_cast<uint8_t>((random_address >> 8) & 0xff);
|
||||||
|
ballast.low = static_cast<uint8_t>(random_address & 0xff);
|
||||||
|
ballast.short_address = short_address;
|
||||||
|
return ballast;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.assign) {
|
||||||
|
const auto next_address = NextFreeShortAddress(used_addresses);
|
||||||
|
if (!next_address.has_value()) {
|
||||||
|
ESP_LOGW(kTag, "REG1-Dali scan has no free short address left");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto compare_base = FindSelectedCommissioningCompareBase(engine_);
|
||||||
|
if (!compare_base.has_value()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto first_ballast =
|
||||||
|
program_selected_ballast(next_address.value(), compare_base.value());
|
||||||
|
if (!first_ballast.has_value()) {
|
||||||
|
ESP_LOGW(kTag, "REG1-Dali scan failed to program short address %u",
|
||||||
|
static_cast<unsigned>(next_address.value()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
used_addresses[next_address.value()] = true;
|
||||||
|
log_and_record_ballast(first_ballast.value());
|
||||||
|
|
||||||
|
if (is_cancelled()) {
|
||||||
|
clear_results = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!withdraw_selected()) {
|
||||||
|
ESP_LOGW(kTag, "REG1-Dali scan failed while withdrawing matched device");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto compare_cursor = IncrementRandomAddress(compare_base.value());
|
||||||
|
bool compare_multi_failed = false;
|
||||||
|
while (!is_cancelled() && compare_cursor.has_value()) {
|
||||||
|
const auto contiguous_short = NextFreeShortAddress(used_addresses);
|
||||||
|
if (!contiguous_short.has_value()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto next_search = IncrementRandomAddress(compare_cursor.value());
|
||||||
|
if (!next_search.has_value()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto matched = CompareSelectedSearchAddress(
|
||||||
|
engine_, next_search.value(), "knx-function-scan-compare-multi");
|
||||||
|
if (!matched.has_value()) {
|
||||||
|
compare_multi_failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!matched.value()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
compare_cursor = next_search.value();
|
||||||
|
const auto ballast =
|
||||||
|
program_selected_ballast(contiguous_short.value(), compare_cursor.value());
|
||||||
|
if (!ballast.has_value()) {
|
||||||
|
ESP_LOGW(kTag, "REG1-Dali scan failed to program short address %u",
|
||||||
|
static_cast<unsigned>(contiguous_short.value()));
|
||||||
|
compare_multi_failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
used_addresses[contiguous_short.value()] = true;
|
||||||
|
log_and_record_ballast(ballast.value());
|
||||||
|
|
||||||
|
if (is_cancelled()) {
|
||||||
|
clear_results = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!withdraw_selected()) {
|
||||||
|
ESP_LOGW(kTag, "REG1-Dali scan failed while withdrawing matched device");
|
||||||
|
compare_multi_failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compare_multi_failed) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (is_cancelled()) {
|
||||||
|
clear_results = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto random_address = FindLowestSelectedRandomAddress(engine_);
|
const auto random_address = FindLowestSelectedRandomAddress(engine_);
|
||||||
if (!random_address.has_value()) {
|
if (!random_address.has_value()) {
|
||||||
break;
|
break;
|
||||||
@@ -258,38 +373,15 @@ void GatewayKnxBridge::runCommissioningScanTask() {
|
|||||||
ballast.low = static_cast<uint8_t>(random_address.value() & 0xff);
|
ballast.low = static_cast<uint8_t>(random_address.value() & 0xff);
|
||||||
ballast.short_address = 0xff;
|
ballast.short_address = 0xff;
|
||||||
|
|
||||||
if (options.assign) {
|
ballast.short_address = QuerySelectedShortAddress(engine_).value_or(0xff);
|
||||||
const auto next_address = NextFreeShortAddress(used_addresses);
|
|
||||||
if (!next_address.has_value()) {
|
|
||||||
ESP_LOGW(kTag, "REG1-Dali scan has no free short address left for 0x%06x",
|
|
||||||
static_cast<unsigned>(random_address.value()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!SendRaw(engine_, DALI_CMD_SPECIAL_PROGRAM_SHORT_ADDRESS,
|
|
||||||
DaliComm::toCmdAddr(next_address.value()),
|
|
||||||
"knx-function-scan-program-short") ||
|
|
||||||
!VerifyShortAddress(engine_, next_address.value())) {
|
|
||||||
ESP_LOGW(kTag, "REG1-Dali scan failed to program short address %u",
|
|
||||||
static_cast<unsigned>(next_address.value()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
used_addresses[next_address.value()] = true;
|
|
||||||
ballast.short_address = next_address.value();
|
|
||||||
} else {
|
|
||||||
ballast.short_address = QuerySelectedShortAddress(engine_).value_or(0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
record_ballast(ballast);
|
log_and_record_ballast(ballast);
|
||||||
ESP_LOGI(kTag, "REG1-Dali scan found random=0x%02X%02X%02X short=%u",
|
|
||||||
ballast.high, ballast.middle, ballast.low,
|
|
||||||
static_cast<unsigned>(ballast.short_address));
|
|
||||||
|
|
||||||
if (is_cancelled()) {
|
if (is_cancelled()) {
|
||||||
clear_results = true;
|
clear_results = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!SendRaw(engine_, DALI_CMD_SPECIAL_WITHDRAW, DALI_CMD_OFF,
|
if (!withdraw_selected()) {
|
||||||
"knx-function-scan-withdraw")) {
|
|
||||||
ESP_LOGW(kTag, "REG1-Dali scan failed while withdrawing matched device");
|
ESP_LOGW(kTag, "REG1-Dali scan failed while withdrawing matched device");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -662,12 +754,12 @@ bool GatewayKnxBridge::handleReg1AssignCommand(const uint8_t* data, size_t len,
|
|||||||
const uint8_t short_address = data[1] == 99 ? 0xff : data[1];
|
const uint8_t short_address = data[1] == 99 ? 0xff : data[1];
|
||||||
const bool ok = SendRawExt(engine_, DALI_CMD_SPECIAL_INITIALIZE, 0x00,
|
const bool ok = SendRawExt(engine_, DALI_CMD_SPECIAL_INITIALIZE, 0x00,
|
||||||
"knx-function-assign-init") &&
|
"knx-function-assign-init") &&
|
||||||
SendRaw(engine_, DALI_CMD_SPECIAL_SEARCHADDRH, data[2],
|
|
||||||
"knx-function-assign-search-h") &&
|
|
||||||
SendRaw(engine_, DALI_CMD_SPECIAL_SEARCHADDRM, data[3],
|
|
||||||
"knx-function-assign-search-m") &&
|
|
||||||
SendRaw(engine_, DALI_CMD_SPECIAL_SEARCHADDRL, data[4],
|
SendRaw(engine_, DALI_CMD_SPECIAL_SEARCHADDRL, data[4],
|
||||||
"knx-function-assign-search-l") &&
|
"knx-function-assign-search-l") &&
|
||||||
|
SendRaw(engine_, DALI_CMD_SPECIAL_SEARCHADDRM, data[3],
|
||||||
|
"knx-function-assign-search-m") &&
|
||||||
|
SendRaw(engine_, DALI_CMD_SPECIAL_SEARCHADDRH, data[2],
|
||||||
|
"knx-function-assign-search-h") &&
|
||||||
SendRaw(engine_, DALI_CMD_SPECIAL_PROGRAM_SHORT_ADDRESS,
|
SendRaw(engine_, DALI_CMD_SPECIAL_PROGRAM_SHORT_ADDRESS,
|
||||||
short_address == 0xff ? 0xff : DaliComm::toCmdAddr(short_address),
|
short_address == 0xff ? 0xff : DaliComm::toCmdAddr(short_address),
|
||||||
"knx-function-assign-program") &&
|
"knx-function-assign-program") &&
|
||||||
|
|||||||
@@ -969,19 +969,16 @@ DaliBridgeResult IgnoredResult(uint16_t group_address, uint16_t group_object_num
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SetSearchAddress(DaliBridgeEngine& engine, uint32_t search_address, const char* sequence) {
|
bool SetSearchAddress(DaliBridgeEngine& engine, uint32_t search_address, const char* sequence) {
|
||||||
return SendRaw(engine, DALI_CMD_SPECIAL_SEARCHADDRH,
|
return SendRaw(engine, DALI_CMD_SPECIAL_SEARCHADDRL,
|
||||||
static_cast<uint8_t>((search_address >> 16) & 0xff), sequence) &&
|
static_cast<uint8_t>(search_address & 0xff), sequence) &&
|
||||||
SendRaw(engine, DALI_CMD_SPECIAL_SEARCHADDRM,
|
SendRaw(engine, DALI_CMD_SPECIAL_SEARCHADDRM,
|
||||||
static_cast<uint8_t>((search_address >> 8) & 0xff), sequence) &&
|
static_cast<uint8_t>((search_address >> 8) & 0xff), sequence) &&
|
||||||
SendRaw(engine, DALI_CMD_SPECIAL_SEARCHADDRL,
|
SendRaw(engine, DALI_CMD_SPECIAL_SEARCHADDRH,
|
||||||
static_cast<uint8_t>(search_address & 0xff), sequence);
|
static_cast<uint8_t>((search_address >> 16) & 0xff), sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<bool> CompareSelectedSearchAddress(DaliBridgeEngine& engine, uint32_t search_address,
|
std::optional<bool> CompareCurrentSearchAddress(DaliBridgeEngine& engine,
|
||||||
const char* sequence) {
|
const char* sequence) {
|
||||||
if (!SetSearchAddress(engine, search_address, sequence)) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
const auto result = ExecuteRaw(engine, BridgeOperation::query, DALI_CMD_SPECIAL_COMPARE,
|
const auto result = ExecuteRaw(engine, BridgeOperation::query, DALI_CMD_SPECIAL_COMPARE,
|
||||||
DALI_CMD_OFF, sequence);
|
DALI_CMD_OFF, sequence);
|
||||||
if (result.ok && result.data.has_value()) {
|
if (result.ok && result.data.has_value()) {
|
||||||
@@ -989,14 +986,14 @@ std::optional<bool> CompareSelectedSearchAddress(DaliBridgeEngine& engine, uint3
|
|||||||
}
|
}
|
||||||
if (DaliQueryResultHasStatus(result, "noResponse") ||
|
if (DaliQueryResultHasStatus(result, "noResponse") ||
|
||||||
DaliQueryResultHasStatus(result, "timeout")) {
|
DaliQueryResultHasStatus(result, "timeout")) {
|
||||||
ESP_LOGD(kTag, "DALI compare no match seq=%s search=0x%06x status=%s",
|
ESP_LOGD(kTag, "DALI compare no match seq=%s status=%s",
|
||||||
sequence == nullptr ? "" : sequence, static_cast<unsigned>(search_address),
|
sequence == nullptr ? "" : sequence,
|
||||||
DaliQueryResultHasStatus(result, "timeout") ? "timeout" : "noResponse");
|
DaliQueryResultHasStatus(result, "timeout") ? "timeout" : "noResponse");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!result.error.empty()) {
|
if (!result.error.empty()) {
|
||||||
ESP_LOGW(kTag, "DALI compare failed seq=%s search=0x%06x error=%s",
|
ESP_LOGW(kTag, "DALI compare failed seq=%s error=%s",
|
||||||
sequence == nullptr ? "" : sequence, static_cast<unsigned>(search_address),
|
sequence == nullptr ? "" : sequence,
|
||||||
result.error.c_str());
|
result.error.c_str());
|
||||||
}
|
}
|
||||||
if (!result.ok || !result.data.has_value()) {
|
if (!result.ok || !result.data.has_value()) {
|
||||||
@@ -1005,6 +1002,53 @@ std::optional<bool> CompareSelectedSearchAddress(DaliBridgeEngine& engine, uint3
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<bool> CompareSelectedSearchAddress(DaliBridgeEngine& engine, uint32_t search_address,
|
||||||
|
const char* sequence) {
|
||||||
|
if (!SetSearchAddress(engine, search_address, sequence)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return CompareCurrentSearchAddress(engine, sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetSearchAddressComponent(DaliBridgeEngine& engine, int typ, uint8_t value,
|
||||||
|
const char* sequence) {
|
||||||
|
switch (typ) {
|
||||||
|
case 1:
|
||||||
|
return SendRaw(engine, DALI_CMD_SPECIAL_SEARCHADDRH, value, sequence);
|
||||||
|
case 2:
|
||||||
|
return SendRaw(engine, DALI_CMD_SPECIAL_SEARCHADDRM, value, sequence);
|
||||||
|
case 3:
|
||||||
|
return SendRaw(engine, DALI_CMD_SPECIAL_SEARCHADDRL, value, sequence);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<bool> CompareSelectedSearchComponent(DaliBridgeEngine& engine, int typ, int value,
|
||||||
|
const char* sequence) {
|
||||||
|
if (!SetSearchAddressComponent(engine, typ, static_cast<uint8_t>(value & 0xff), sequence)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return CompareCurrentSearchAddress(engine, sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint32_t> IncrementRandomAddress(uint32_t random_address) {
|
||||||
|
if (random_address >= 0x00ffffffu) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return random_address + 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint32_t> FindLowestSelectedRandomAddress(DaliBridgeEngine& engine);
|
||||||
|
|
||||||
|
std::optional<uint32_t> FindSelectedCommissioningCompareBase(DaliBridgeEngine& engine) {
|
||||||
|
const auto lowest = FindLowestSelectedRandomAddress(engine);
|
||||||
|
if (!lowest.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return lowest.value() == 0 ? 0u : lowest.value() - 1u;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<uint32_t> FindLowestSelectedRandomAddress(DaliBridgeEngine& engine) {
|
std::optional<uint32_t> FindLowestSelectedRandomAddress(DaliBridgeEngine& engine) {
|
||||||
const auto any = CompareSelectedSearchAddress(engine, 0x00ffffffu,
|
const auto any = CompareSelectedSearchAddress(engine, 0x00ffffffu,
|
||||||
"knx-function-scan-compare-any");
|
"knx-function-scan-compare-any");
|
||||||
@@ -1042,13 +1086,42 @@ std::optional<uint8_t> QuerySelectedShortAddress(DaliBridgeEngine& engine) {
|
|||||||
return static_cast<uint8_t>((raw.value() >> 1) & 0x3f);
|
return static_cast<uint8_t>((raw.value() >> 1) & 0x3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VerifyShortAddress(DaliBridgeEngine& engine, uint8_t short_address) {
|
bool VerifySelectedShortAddress(DaliBridgeEngine& engine, uint8_t short_address) {
|
||||||
const auto raw = ExecuteRawQuery(engine, DALI_CMD_SPECIAL_VERIFY_SHORT_ADDRESS,
|
const auto raw = ExecuteRawQuery(engine, DALI_CMD_SPECIAL_VERIFY_SHORT_ADDRESS,
|
||||||
DaliComm::toCmdAddr(short_address),
|
DaliComm::toCmdAddr(short_address),
|
||||||
"knx-function-scan-verify-short");
|
"knx-function-scan-verify-short");
|
||||||
return raw.has_value() && raw.value() == 0xff;
|
return raw.has_value() && raw.value() == 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProgramShortAddressAndConfirm(DaliBridgeEngine& engine, uint8_t short_address) {
|
||||||
|
if (!SendRaw(engine, DALI_CMD_SPECIAL_PROGRAM_SHORT_ADDRESS,
|
||||||
|
DaliComm::toCmdAddr(short_address),
|
||||||
|
"knx-function-scan-program-short")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (VerifySelectedShortAddress(engine, short_address)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto confirmed = QuerySelectedShortAddress(engine);
|
||||||
|
return confirmed.has_value() && confirmed.value() == short_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint32_t> QueryRandomAddressForShortAddress(DaliBridgeEngine& engine,
|
||||||
|
uint8_t short_address) {
|
||||||
|
const auto high = QueryShort(engine, short_address, DALI_CMD_QUERY_RANDOM_ADDRESS_H,
|
||||||
|
"knx-function-scan-query-random-h");
|
||||||
|
const auto middle = QueryShort(engine, short_address, DALI_CMD_QUERY_RANDOM_ADDRESS_M,
|
||||||
|
"knx-function-scan-query-random-m");
|
||||||
|
const auto low = QueryShort(engine, short_address, DALI_CMD_QUERY_RANDOM_ADDRESS_L,
|
||||||
|
"knx-function-scan-query-random-l");
|
||||||
|
if (!high.has_value() || !middle.has_value() || !low.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return (static_cast<uint32_t>(high.value() & 0xff) << 16) |
|
||||||
|
(static_cast<uint32_t>(middle.value() & 0xff) << 8) |
|
||||||
|
static_cast<uint32_t>(low.value() & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
std::array<bool, 64> QueryUsedShortAddresses(DaliBridgeEngine& engine) {
|
std::array<bool, 64> QueryUsedShortAddresses(DaliBridgeEngine& engine) {
|
||||||
std::array<bool, 64> used{};
|
std::array<bool, 64> used{};
|
||||||
for (int short_address = 0; short_address < static_cast<int>(used.size()); ++short_address) {
|
for (int short_address = 0; short_address < static_cast<int>(used.size()); ++short_address) {
|
||||||
|
|||||||
Reference in New Issue
Block a user