feat(gateway): enhance DALI host activity tracking and presence management
Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user