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:
@@ -3,6 +3,7 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "esp_err.h"
|
||||
@@ -20,18 +21,48 @@ enum class GatewayCachePriorityMode : uint8_t {
|
||||
|
||||
struct GatewayCacheConfig {
|
||||
std::string storage_namespace{"gateway_rt"};
|
||||
bool cache_enabled{true};
|
||||
bool reconciliation_enabled{true};
|
||||
bool full_state_mirror_enabled{false};
|
||||
uint32_t flush_interval_ms{5000};
|
||||
uint32_t task_stack_size{4096};
|
||||
UBaseType_t task_priority{3};
|
||||
GatewayCachePriorityMode default_priority_mode{GatewayCachePriorityMode::kOutsideBusFirst};
|
||||
};
|
||||
|
||||
enum class GatewayCacheRawFrameOrigin : uint8_t {
|
||||
kLocalGateway = 0,
|
||||
kOutsideBus = 1,
|
||||
};
|
||||
|
||||
struct GatewayCacheChannelFlags {
|
||||
bool need_update_group{false};
|
||||
bool need_update_scene{false};
|
||||
bool need_update_settings{false};
|
||||
};
|
||||
|
||||
struct GatewayCacheDaliSettingsSnapshot {
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
struct GatewayCacheDaliAddressState {
|
||||
bool group_mask_known{false};
|
||||
uint16_t group_mask{0};
|
||||
std::array<std::optional<uint8_t>, 16> scene_levels{};
|
||||
GatewayCacheDaliSettingsSnapshot settings;
|
||||
};
|
||||
|
||||
class GatewayCache {
|
||||
public:
|
||||
struct SceneEntry {
|
||||
@@ -80,20 +111,47 @@ class GatewayCache {
|
||||
std::pair<uint8_t, uint8_t> groupMask(uint8_t gateway_id);
|
||||
|
||||
GatewayCacheChannelFlags channelFlags(uint8_t gateway_id);
|
||||
GatewayCacheChannelFlags pendingChannelFlags(uint8_t gateway_id);
|
||||
GatewayCacheDaliAddressState daliAddressState(uint8_t gateway_id, uint8_t short_address);
|
||||
bool setDaliGroupMask(uint8_t gateway_id, uint8_t short_address,
|
||||
std::optional<uint16_t> group_mask);
|
||||
bool setDaliSceneLevel(uint8_t gateway_id, uint8_t short_address, uint8_t scene_id,
|
||||
std::optional<uint8_t> level);
|
||||
bool setDaliSettings(uint8_t gateway_id, uint8_t short_address,
|
||||
std::optional<GatewayCacheDaliSettingsSnapshot> settings);
|
||||
bool clearChannelFlagsIfMatched(uint8_t gateway_id, const GatewayCacheChannelFlags& flags);
|
||||
void markGroupUpdateNeeded(uint8_t gateway_id, bool needed = true);
|
||||
void markSceneUpdateNeeded(uint8_t gateway_id, bool needed = true);
|
||||
void markSettingsUpdateNeeded(uint8_t gateway_id, bool needed = true);
|
||||
|
||||
bool cacheEnabled() const;
|
||||
bool reconciliationEnabled() const;
|
||||
bool fullStateMirrorEnabled() const;
|
||||
bool observeDaliCommand(uint8_t gateway_id, uint8_t raw_addr, uint8_t command,
|
||||
GatewayCacheRawFrameOrigin origin);
|
||||
|
||||
GatewayCachePriorityMode priorityMode();
|
||||
void setPriorityMode(GatewayCachePriorityMode mode);
|
||||
|
||||
private:
|
||||
struct DtrState {
|
||||
std::optional<uint8_t> dtr0;
|
||||
std::optional<uint8_t> dtr1;
|
||||
std::optional<uint8_t> dtr2;
|
||||
};
|
||||
|
||||
static void TaskEntry(void* arg);
|
||||
void taskLoop();
|
||||
bool flushDirty();
|
||||
|
||||
bool openStorageLocked();
|
||||
void closeStorageLocked();
|
||||
bool persistSceneLocked(uint8_t gateway_id, uint8_t scene_id, const SceneEntry& scene);
|
||||
bool persistGroupLocked(uint8_t gateway_id, uint8_t group_id, const GroupEntry& group);
|
||||
bool commitStorageLocked();
|
||||
bool shouldTrackUpdateFlagsLocked() const;
|
||||
GatewayCacheDaliAddressState& ensureDaliAddressStateLocked(uint8_t gateway_id,
|
||||
uint8_t short_address);
|
||||
SceneStore& ensureSceneStoreLocked(uint8_t gateway_id);
|
||||
GroupStore& ensureGroupStoreLocked(uint8_t gateway_id);
|
||||
void loadSceneStoreLocked(uint8_t gateway_id, SceneStore& scenes);
|
||||
@@ -109,6 +167,8 @@ class GatewayCache {
|
||||
nvs_handle_t storage_{0};
|
||||
std::map<uint8_t, SceneStore> scenes_;
|
||||
std::map<uint8_t, GroupStore> groups_;
|
||||
std::map<uint8_t, std::array<GatewayCacheDaliAddressState, 64>> dali_states_;
|
||||
std::map<uint8_t, DtrState> dtr_states_;
|
||||
std::map<uint8_t, GatewayCacheChannelFlags> channel_flags_;
|
||||
bool dirty_{false};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user