feat(gateway): enhance DALI host activity tracking and presence management

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-05-26 22:21:36 +08:00
parent f922993d2f
commit 865bf8425a
9 changed files with 441 additions and 39 deletions
@@ -5,6 +5,7 @@
#include <map>
#include <optional>
#include <string>
#include <vector>
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
@@ -42,6 +43,12 @@ enum class GatewayCacheDaliTargetKind : uint8_t {
kBroadcast = 2,
};
enum class GatewayCacheDaliPresence : uint8_t {
kUnknown = 0,
kOnline = 1,
kOffline = 2,
};
struct GatewayCacheDaliTarget {
GatewayCacheDaliTargetKind kind{GatewayCacheDaliTargetKind::kShortAddress};
uint8_t value{0};
@@ -138,6 +145,12 @@ class GatewayCache {
GatewayCacheChannelFlags channelFlags(uint8_t gateway_id);
GatewayCacheChannelFlags pendingChannelFlags(uint8_t gateway_id);
GatewayCacheDaliAddressState daliAddressState(uint8_t gateway_id, uint8_t short_address);
GatewayCacheDaliPresence daliAddressPresence(uint8_t gateway_id, uint8_t short_address);
void markDaliAddressPresence(uint8_t gateway_id, uint8_t short_address,
GatewayCacheDaliPresence presence);
std::optional<GatewayCacheDaliTarget> decodeDaliTarget(uint8_t raw_addr);
std::vector<uint8_t> reconciliationAddresses(
uint8_t gateway_id, std::optional<GatewayCacheDaliTarget> target);
GatewayCacheDaliRuntimeStatus daliGroupStatus(uint8_t gateway_id, uint8_t group_id);
GatewayCacheDaliRuntimeStatus daliBroadcastStatus(uint8_t gateway_id);
bool setDaliGroupMask(uint8_t gateway_id, uint8_t short_address,
@@ -183,6 +196,8 @@ class GatewayCache {
bool commitStorageLocked();
bool shouldTrackUpdateFlagsLocked() const;
uint32_t nextDaliRuntimeRevisionLocked();
void markDaliAddressPresenceLocked(uint8_t gateway_id, uint8_t short_address,
GatewayCacheDaliPresence presence);
bool mirrorDaliCommandLocked(uint8_t gateway_id, uint8_t raw_addr, uint8_t command);
void clearDaliTargetStateLocked(uint8_t gateway_id, const GatewayCacheDaliTarget& target,
uint32_t revision);
@@ -225,6 +240,7 @@ class GatewayCache {
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, std::array<GatewayCacheDaliPresence, 64>> dali_presence_;
std::map<uint8_t, std::array<GatewayCacheDaliRuntimeStatus, 16>> dali_group_status_;
std::map<uint8_t, GatewayCacheDaliRuntimeStatus> dali_broadcast_status_;
std::map<uint8_t, DtrState> dtr_states_;
@@ -759,6 +759,86 @@ GatewayCacheDaliAddressState GatewayCache::daliAddressState(uint8_t gateway_id,
return ensureDaliAddressStateLocked(gateway_id, short_address);
}
GatewayCacheDaliPresence GatewayCache::daliAddressPresence(uint8_t gateway_id,
uint8_t short_address) {
LockGuard guard(lock_);
if (short_address >= 64) {
return GatewayCacheDaliPresence::kUnknown;
}
if (const auto it = dali_presence_.find(gateway_id); it != dali_presence_.end()) {
return it->second[short_address];
}
return GatewayCacheDaliPresence::kUnknown;
}
void GatewayCache::markDaliAddressPresence(uint8_t gateway_id, uint8_t short_address,
GatewayCacheDaliPresence presence) {
LockGuard guard(lock_);
markDaliAddressPresenceLocked(gateway_id, short_address, presence);
}
std::optional<GatewayCacheDaliTarget> GatewayCache::decodeDaliTarget(uint8_t raw_addr) {
return DecodeDaliTarget(raw_addr);
}
std::vector<uint8_t> GatewayCache::reconciliationAddresses(
uint8_t gateway_id, std::optional<GatewayCacheDaliTarget> target) {
LockGuard guard(lock_);
std::vector<uint8_t> addresses;
auto presence = [&](uint8_t short_address) {
if (const auto it = dali_presence_.find(gateway_id); it != dali_presence_.end()) {
return it->second[short_address];
}
return GatewayCacheDaliPresence::kUnknown;
};
auto add_if_known_online = [&](uint8_t short_address) {
if (short_address < 64 && presence(short_address) == GatewayCacheDaliPresence::kOnline) {
addresses.push_back(short_address);
}
};
if (!target.has_value()) {
for (uint8_t short_address = 0; short_address < 64; ++short_address) {
add_if_known_online(short_address);
}
return addresses;
}
switch (target->kind) {
case GatewayCacheDaliTargetKind::kShortAddress:
if (target->value < 64 && presence(target->value) != GatewayCacheDaliPresence::kOffline) {
addresses.push_back(target->value);
}
break;
case GatewayCacheDaliTargetKind::kGroup: {
if (target->value >= 16) {
break;
}
const uint16_t bit = static_cast<uint16_t>(1U << target->value);
auto [states_it, inserted] = dali_states_.try_emplace(gateway_id);
if (inserted) {
loadDaliStateStoreLocked(gateway_id, states_it->second);
}
for (uint8_t short_address = 0; short_address < states_it->second.size(); ++short_address) {
const auto& state = states_it->second[short_address];
if (state.group_mask_known && (state.group_mask & bit) != 0) {
add_if_known_online(short_address);
}
}
break;
}
case GatewayCacheDaliTargetKind::kBroadcast:
for (uint8_t short_address = 0; short_address < 64; ++short_address) {
add_if_known_online(short_address);
}
break;
default:
break;
}
return addresses;
}
GatewayCacheDaliRuntimeStatus GatewayCache::daliGroupStatus(uint8_t gateway_id,
uint8_t group_id) {
LockGuard guard(lock_);
@@ -1535,6 +1615,20 @@ bool GatewayCache::shouldTrackUpdateFlagsLocked() const {
return config_.cache_enabled && config_.reconciliation_enabled;
}
void GatewayCache::markDaliAddressPresenceLocked(uint8_t gateway_id, uint8_t short_address,
GatewayCacheDaliPresence presence) {
if (short_address >= 64) {
return;
}
auto& states = dali_presence_[gateway_id];
const auto previous = states[short_address];
states[short_address] = presence;
if (previous != presence) {
ESP_LOGD(kTag, "presence gateway=%u short=%u state=%u", gateway_id, short_address,
static_cast<unsigned>(presence));
}
}
GatewayCacheDaliAddressState& GatewayCache::ensureDaliAddressStateLocked(uint8_t gateway_id,
uint8_t short_address) {
auto [it, inserted] = dali_states_.try_emplace(gateway_id);