feat(gateway): implement reconciliation mechanism and command prioritization

- Introduced a reconciliation job structure to manage the reconciliation process for gateway channels.
- Added methods to schedule and run reconciliation steps, including group, scene, and settings reconciliation.
- Implemented a locking mechanism to ensure thread safety during reconciliation operations.
- Enhanced command handling in GatewayRuntime to classify commands by priority (control, normal, maintenance).
- Updated command enqueueing and processing to respect command priorities, ensuring maintenance commands are handled appropriately.
- Added configuration options for enabling/disabling cache functionality in GatewayRuntime.
- Improved logging to include cache status during runtime initialization.

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Tony
2026-05-02 03:04:06 +08:00
parent 70c39ea1e1
commit 639fdd860e
11 changed files with 1209 additions and 34 deletions
@@ -2,6 +2,7 @@
#include <cstddef>
#include <cstdint>
#include <array>
#include <functional>
#include <map>
#include <memory>
@@ -93,6 +94,21 @@ struct DaliDomainSnapshot {
std::map<std::string, std::vector<double>> number_arrays;
};
struct DaliAddressSettingsSnapshot {
std::optional<uint8_t> power_on_level;
std::optional<uint8_t> system_failure_level;
std::optional<uint8_t> min_level;
std::optional<uint8_t> max_level;
std::optional<uint8_t> fade_time;
std::optional<uint8_t> fade_rate;
bool anyKnown() const {
return power_on_level.has_value() || system_failure_level.has_value() ||
min_level.has_value() || max_level.has_value() || fade_time.has_value() ||
fade_rate.has_value();
}
};
class DaliDomainService {
public:
DaliDomainService();
@@ -141,6 +157,15 @@ class DaliDomainService {
bool on(uint8_t gateway_id, int short_address) const;
bool off(uint8_t gateway_id, int short_address) const;
bool off(int short_address) const;
std::optional<uint16_t> queryGroupMask(uint8_t gateway_id, int short_address) const;
std::optional<uint8_t> querySceneLevel(uint8_t gateway_id, int short_address, int scene) const;
std::optional<DaliAddressSettingsSnapshot> queryAddressSettings(uint8_t gateway_id,
int short_address) const;
bool applyGroupMask(uint8_t gateway_id, int short_address, uint16_t group_mask) const;
bool applySceneLevel(uint8_t gateway_id, int short_address, int scene,
std::optional<uint8_t> level) const;
bool applyAddressSettings(uint8_t gateway_id, int short_address,
const DaliAddressSettingsSnapshot& settings) const;
bool updateChannelName(uint8_t gateway_id, std::string_view name);
bool allocateAllAddr(uint8_t gateway_id, int start_address = 0) const;
void stopAllocAddr(uint8_t gateway_id) const;
+119
View File
@@ -779,6 +779,125 @@ bool DaliDomainService::off(int short_address) const {
return off(channels_.front()->config.gateway_id, short_address);
}
std::optional<uint16_t> DaliDomainService::queryGroupMask(uint8_t gateway_id,
int short_address) const {
const auto* channel = findChannelByGateway(gateway_id);
if (channel == nullptr || channel->dali == nullptr) {
return std::nullopt;
}
const auto group_mask = channel->dali->base.getGroup(short_address);
if (!group_mask.has_value()) {
return std::nullopt;
}
return static_cast<uint16_t>(*group_mask);
}
std::optional<uint8_t> DaliDomainService::querySceneLevel(uint8_t gateway_id, int short_address,
int scene) const {
const auto* channel = findChannelByGateway(gateway_id);
if (channel == nullptr || channel->dali == nullptr) {
return std::nullopt;
}
const auto level = channel->dali->base.getScene(short_address, scene);
if (!level.has_value()) {
return std::nullopt;
}
return static_cast<uint8_t>(*level);
}
std::optional<DaliAddressSettingsSnapshot> DaliDomainService::queryAddressSettings(
uint8_t gateway_id, int short_address) const {
const auto* channel = findChannelByGateway(gateway_id);
if (channel == nullptr || channel->dali == nullptr) {
return std::nullopt;
}
DaliAddressSettingsSnapshot settings{};
if (const auto value = channel->dali->base.getPowerOnLevel(short_address); value.has_value()) {
settings.power_on_level = static_cast<uint8_t>(*value);
}
if (const auto value = channel->dali->base.getSystemFailureLevel(short_address);
value.has_value()) {
settings.system_failure_level = static_cast<uint8_t>(*value);
}
if (const auto value = channel->dali->base.getMinLevel(short_address); value.has_value()) {
settings.min_level = static_cast<uint8_t>(*value);
}
if (const auto value = channel->dali->base.getMaxLevel(short_address); value.has_value()) {
settings.max_level = static_cast<uint8_t>(*value);
}
if (const auto value = channel->dali->base.getFadeTime(short_address); value.has_value()) {
settings.fade_time = static_cast<uint8_t>(*value);
}
if (const auto value = channel->dali->base.getFadeRate(short_address); value.has_value()) {
settings.fade_rate = static_cast<uint8_t>(*value);
}
if (!settings.anyKnown()) {
return std::nullopt;
}
return settings;
}
bool DaliDomainService::applyGroupMask(uint8_t gateway_id, int short_address,
uint16_t group_mask) const {
const auto* channel = findChannelByGateway(gateway_id);
return channel != nullptr && channel->dali != nullptr &&
channel->dali->base.setGroup(short_address, group_mask);
}
bool DaliDomainService::applySceneLevel(uint8_t gateway_id, int short_address, int scene,
std::optional<uint8_t> level) const {
const auto* channel = findChannelByGateway(gateway_id);
if (channel == nullptr || channel->dali == nullptr || !level.has_value()) {
return false;
}
if (*level == 255U) {
return channel->dali->base.removeScene(short_address, scene);
}
return channel->dali->base.setDTR(*level) &&
channel->dali->base.storeDTRAsSceneBright(short_address, scene);
}
bool DaliDomainService::applyAddressSettings(uint8_t gateway_id, int short_address,
const DaliAddressSettingsSnapshot& settings) const {
const auto* channel = findChannelByGateway(gateway_id);
if (channel == nullptr || channel->dali == nullptr) {
return false;
}
bool ok = true;
if (settings.power_on_level.has_value()) {
ok = ok && channel->dali->base.setPowerOnLevel(short_address, *settings.power_on_level);
}
if (settings.system_failure_level.has_value()) {
ok = ok &&
channel->dali->base.setSystemFailureLevel(short_address, *settings.system_failure_level);
}
if (settings.min_level.has_value()) {
ok = ok && channel->dali->base.setMinLevel(short_address, *settings.min_level);
}
if (settings.max_level.has_value()) {
ok = ok && channel->dali->base.setMaxLevel(short_address, *settings.max_level);
}
if (settings.fade_time.has_value()) {
ok = ok && channel->dali->base.setFadeTime(short_address, *settings.fade_time);
}
if (settings.fade_rate.has_value()) {
ok = ok && channel->dali->base.setFadeRate(short_address, *settings.fade_rate);
}
return ok;
}
bool DaliDomainService::updateChannelName(uint8_t gateway_id, std::string_view name) {
auto* channel = findChannelByGateway(gateway_id);
if (channel == nullptr) {