Refactor GatewayController to integrate DaliGateway types
- Updated GatewayController to use DaliGateway types instead of GatewayCache types for channel flags, targets, and states. - Modified methods to reflect changes in data structures, including flag checks and state management. - Adjusted cache handling to utilize DaliGatewayCache for address and group management. - Ensured compatibility with existing functionality while enhancing clarity and maintainability of the code. Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -12,7 +12,8 @@ update as the project evolves:
|
||||
- `gateway_core/`: boot profile and top-level role bootstrap.
|
||||
- `dali/`: vendored ESP-IDF DALI HAL/backend reused from LuatOS, including native raw receive fan-out.
|
||||
- `dali_domain/`: native DALI domain facade over `dali_cpp` and raw frame sinks.
|
||||
- `gateway_cache/`: DALI scene/group/settings/runtime cache used by controller reconciliation and protocol bridges.
|
||||
- `gateway_cache/`: ESP-IDF NVS adapter for the portable `dali_cpp` cache,
|
||||
plus gateway-internal scene/group definitions.
|
||||
- `gateway_bridge/`: per-channel bridge provisioning, command execution, protocol startup, and HTTP bridge actions.
|
||||
- `openknx_idf/`: ESP-IDF port layer for the OpenKNX `gateway/knx` and `gateway/tpuart` submodules, including NVS-backed OpenKNX memory, development KNX security storage, ETS cEMI programming support, UDP multicast/unicast plumbing, and a native TP-UART interface without the Arduino framework.
|
||||
- `gateway_modbus/`: gateway-owned Modbus TCP/RTU/ASCII config, generated DALI point tables, and provisioned Modbus model override dispatch.
|
||||
@@ -29,18 +30,25 @@ update as the project evolves:
|
||||
|
||||
## Gateway DALI cache
|
||||
|
||||
The gateway owns the shared DALI cache for multi-user deployments. App, BLE,
|
||||
IP, Modbus, BACnet, KNX, and local control paths should treat the gateway cache
|
||||
as the shared read surface instead of maintaining separate app-side device-state
|
||||
caches. Transparent/setup raw forwarding paths remain bypass-oriented, but raw
|
||||
DALI bus observation still feeds the passive decoder when frames are visible to
|
||||
the gateway.
|
||||
`dali_cpp::DaliGatewayCache` owns the shared DALI cache and is the authoritative
|
||||
read surface for App, BLE, IP, Modbus, BACnet, KNX, and local control paths. It
|
||||
interprets direct, group, broadcast, scene, DTR, and settings commands; owns
|
||||
presence and reconciliation state; versions persisted address snapshots; and
|
||||
emits platform-neutral `DaliGatewayStatusUpdate` callbacks.
|
||||
|
||||
`gateway_cache` stores internal scene/group data and per-short-address DALI
|
||||
state. Device settings, group masks, scene levels, known flags, and the last
|
||||
runtime status are batched to NVS using `GATEWAY_CACHE_FLUSH_INTERVAL_MS`, which
|
||||
defaults to 10000 ms. Runtime status loaded from disk is marked stale until the
|
||||
gateway observes a bus command or the background refresher verifies it again.
|
||||
The ESP-IDF `gateway_cache` component no longer contains DALI cache behavior.
|
||||
It binds the portable cache persistence callbacks to NVS and continues to own
|
||||
only gateway-internal scene/group definitions. Device settings, group masks,
|
||||
scene levels, known flags, and the last runtime status are batched through the
|
||||
portable cache using `GATEWAY_CACHE_FLUSH_INTERVAL_MS`, which defaults to
|
||||
10000 ms. Runtime status loaded from disk is marked stale until a bus command
|
||||
or the background refresher verifies it again.
|
||||
|
||||
Protocol adapters register for semantic status updates instead of decoding raw
|
||||
DALI commands independently. The current KNX adapter maps the callback target,
|
||||
status, and affected short-address list into its group-object status updates.
|
||||
Transparent/setup raw forwarding paths remain bypass-oriented, while visible
|
||||
raw DALI bus traffic still feeds the portable cache.
|
||||
|
||||
`GATEWAY_CACHE_REFRESH_INTERVAL_MS` defaults to 120000 ms. When nonzero, the
|
||||
controller maintenance loop refreshes direct short-address actual levels one
|
||||
|
||||
@@ -511,11 +511,11 @@ constexpr bool kCacheFullStateMirrorEnabled = false;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_GATEWAY_CACHE_LOCAL_GATEWAY_FIRST
|
||||
constexpr gateway::GatewayCachePriorityMode kCachePriorityMode =
|
||||
gateway::GatewayCachePriorityMode::kLocalGatewayFirst;
|
||||
constexpr DaliGatewayCachePriorityMode kCachePriorityMode =
|
||||
DaliGatewayCachePriorityMode::localGatewayFirst;
|
||||
#else
|
||||
constexpr gateway::GatewayCachePriorityMode kCachePriorityMode =
|
||||
gateway::GatewayCachePriorityMode::kOutsideBusFirst;
|
||||
constexpr DaliGatewayCachePriorityMode kCachePriorityMode =
|
||||
DaliGatewayCachePriorityMode::outsideBusFirst;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_GATEWAY_DALI_103_APPLICATION_CONTROLLER_ENABLED
|
||||
@@ -1097,14 +1097,15 @@ extern "C" void app_main(void) {
|
||||
|
||||
gateway::GatewayCacheConfig cache_config;
|
||||
cache_config.cache_enabled = kCacheSupported && kCacheStartupEnabled && s_runtime->cacheEnabled();
|
||||
cache_config.reconciliation_enabled = cache_config.cache_enabled && kCacheReconciliationEnabled;
|
||||
cache_config.full_state_mirror_enabled = cache_config.reconciliation_enabled &&
|
||||
kCacheFullStateMirrorEnabled;
|
||||
cache_config.flush_interval_ms = static_cast<uint32_t>(CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS);
|
||||
cache_config.refresh_interval_ms =
|
||||
static_cast<uint32_t>(CONFIG_GATEWAY_CACHE_REFRESH_INTERVAL_MS);
|
||||
cache_config.default_priority_mode = kCachePriorityMode;
|
||||
s_cache = std::make_unique<gateway::GatewayCache>(cache_config);
|
||||
const bool reconciliation_enabled =
|
||||
cache_config.cache_enabled && kCacheReconciliationEnabled;
|
||||
s_dali_domain->gatewayCache().configure(
|
||||
DaliGatewayCacheConfig{cache_config.cache_enabled, reconciliation_enabled,
|
||||
reconciliation_enabled && kCacheFullStateMirrorEnabled,
|
||||
kCachePriorityMode});
|
||||
s_cache = std::make_unique<gateway::GatewayCache>(s_dali_domain->gatewayCache(),
|
||||
cache_config);
|
||||
ESP_ERROR_CHECK(s_cache->start());
|
||||
|
||||
gateway::GatewayControllerConfig controller_config;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "dali_gateway.hpp"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
@@ -137,6 +138,8 @@ class DaliDomainService {
|
||||
void setApplicationControllerIdentitySink(ApplicationControllerIdentitySink sink);
|
||||
void setApplicationControllerShortAddressProvider(ApplicationControllerShortAddressProvider provider);
|
||||
void setApplicationControllerShortAddressSink(ApplicationControllerShortAddressSink sink);
|
||||
DaliGatewayCache& gatewayCache();
|
||||
const DaliGatewayCache& gatewayCache() const;
|
||||
|
||||
bool resetBus(uint8_t gateway_id) const;
|
||||
bool pulseBusLow(uint8_t gateway_id, uint32_t duration_ms) const;
|
||||
@@ -263,6 +266,7 @@ class DaliDomainService {
|
||||
ApplicationControllerIdentitySink application_controller_identity_sink_;
|
||||
ApplicationControllerShortAddressProvider application_controller_short_address_provider_;
|
||||
ApplicationControllerShortAddressSink application_controller_short_address_sink_;
|
||||
DaliGatewayCache gateway_cache_;
|
||||
QueueHandle_t raw_frame_dispatch_queue_{nullptr};
|
||||
TaskHandle_t raw_frame_dispatch_task_handle_{nullptr};
|
||||
TaskHandle_t raw_frame_task_handle_{nullptr};
|
||||
|
||||
@@ -481,6 +481,14 @@ DaliDomainService::~DaliDomainService() {
|
||||
}
|
||||
}
|
||||
|
||||
DaliGatewayCache& DaliDomainService::gatewayCache() {
|
||||
return gateway_cache_;
|
||||
}
|
||||
|
||||
const DaliGatewayCache& DaliDomainService::gatewayCache() const {
|
||||
return gateway_cache_;
|
||||
}
|
||||
|
||||
bool DaliDomainService::bindTransport(const DaliChannelConfig& config, DaliTransportHooks hooks) {
|
||||
if (!hooks.send) {
|
||||
return false;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "dali_gateway.hpp"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -19,7 +20,6 @@
|
||||
namespace gateway {
|
||||
|
||||
class DaliDomainService;
|
||||
struct DaliRawFrame;
|
||||
class GatewayCache;
|
||||
|
||||
struct GatewayBridgeHttpResponse {
|
||||
@@ -86,7 +86,7 @@ class GatewayBridgeService {
|
||||
size_t len);
|
||||
DaliBridgeResult routeKnxGroupObjectWrite(uint16_t group_object_number,
|
||||
const uint8_t* data, size_t len);
|
||||
void handleDaliRawFrame(const DaliRawFrame& frame);
|
||||
void handleDaliStatusUpdate(const DaliGatewayStatusUpdate& update);
|
||||
void collectUsedRuntimeResources(uint8_t except_gateway_id,
|
||||
std::set<uint16_t>* modbus_tcp_ports,
|
||||
std::set<uint16_t>* knx_udp_ports,
|
||||
|
||||
@@ -103,11 +103,6 @@ struct BridgeDiscoveryEntry {
|
||||
DaliDomainSnapshot discovery;
|
||||
};
|
||||
|
||||
struct DaliKnxStatusUpdate {
|
||||
GatewayKnxDaliTarget target;
|
||||
uint8_t actual_level{0};
|
||||
};
|
||||
|
||||
using BridgeDiscoveryInventory = std::map<int, BridgeDiscoveryEntry>;
|
||||
|
||||
extern "C" uint8_t knx_platform_copy_security_failures(uint8_t* counters, size_t countersLen,
|
||||
@@ -472,54 +467,6 @@ bool ValidDaliAddress(int address) {
|
||||
return address >= 0 && address <= 127;
|
||||
}
|
||||
|
||||
std::optional<GatewayKnxDaliTarget> DecodeKnxDaliTarget(uint8_t raw_addr) {
|
||||
if (raw_addr <= 0x7F) {
|
||||
return GatewayKnxDaliTarget{GatewayKnxDaliTargetKind::kShortAddress,
|
||||
static_cast<int>(raw_addr >> 1)};
|
||||
}
|
||||
if (raw_addr >= kDaliGroupRawMin && raw_addr <= kDaliGroupRawMax) {
|
||||
return GatewayKnxDaliTarget{GatewayKnxDaliTargetKind::kGroup,
|
||||
static_cast<int>((raw_addr - kDaliGroupRawMin) >> 1)};
|
||||
}
|
||||
if (raw_addr == 0xFE || raw_addr == 0xFF) {
|
||||
return GatewayKnxDaliTarget{GatewayKnxDaliTargetKind::kBroadcast, 127};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<DaliKnxStatusUpdate> DecodeDaliKnxStatusUpdate(const DaliRawFrame& frame) {
|
||||
if (frame.data.size() != 2 && frame.data.size() != 3) {
|
||||
return std::nullopt;
|
||||
}
|
||||
uint8_t raw_addr = 0;
|
||||
uint8_t command = 0;
|
||||
if (frame.data.size() == 2) {
|
||||
raw_addr = frame.data[0];
|
||||
command = frame.data[1];
|
||||
if (raw_addr == 0xBE) {
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
raw_addr = frame.data[1];
|
||||
command = frame.data[2];
|
||||
}
|
||||
auto target = DecodeKnxDaliTarget(raw_addr);
|
||||
if (!target.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if ((raw_addr & 0x01U) == 0) {
|
||||
if (command > 254) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return DaliKnxStatusUpdate{*target, command};
|
||||
}
|
||||
if (command == kDaliCmdOff || command == kDaliCmdRecallMax) {
|
||||
return DaliKnxStatusUpdate{*target,
|
||||
static_cast<uint8_t>(command == kDaliCmdOff ? 0 : 254)};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool ValidShortAddress(int address) {
|
||||
return address >= 0 && address <= kMaxDaliShortAddress;
|
||||
}
|
||||
@@ -1583,6 +1530,7 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
GatewayBridgeServiceConfig service_config)
|
||||
: service(service),
|
||||
domain(domain),
|
||||
dali_cache(domain.gatewayCache()),
|
||||
cache(cache),
|
||||
channel(std::move(channel)),
|
||||
service_config(service_config),
|
||||
@@ -1603,6 +1551,7 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
|
||||
GatewayBridgeService& service;
|
||||
DaliDomainService& domain;
|
||||
DaliGatewayCache& dali_cache;
|
||||
GatewayCache& cache;
|
||||
DaliChannelInfo channel;
|
||||
GatewayBridgeServiceConfig service_config;
|
||||
@@ -3141,7 +3090,7 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
}
|
||||
|
||||
const auto* discovery = findDiscoveryEntryLocked(point.short_address);
|
||||
const auto state = cache.daliAddressState(channel.gateway_id,
|
||||
const auto state = dali_cache.addressState(channel.gateway_id,
|
||||
static_cast<uint8_t>(point.short_address));
|
||||
switch (point.generated_kind) {
|
||||
case GatewayModbusGeneratedKind::kShortDiscovered:
|
||||
@@ -3159,11 +3108,11 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
case GatewayModbusGeneratedKind::kShortSupportsDt8:
|
||||
return discovery != nullptr && SnapshotHasDeviceType(discovery->discovery, 8);
|
||||
case GatewayModbusGeneratedKind::kShortGroupMaskKnown:
|
||||
return state.group_mask_known;
|
||||
return state.groupMaskKnown;
|
||||
case GatewayModbusGeneratedKind::kShortActualLevelKnown:
|
||||
return state.status.actual_level.has_value();
|
||||
return state.status.actualLevel.has_value();
|
||||
case GatewayModbusGeneratedKind::kShortSceneKnown:
|
||||
return state.status.scene_id.has_value();
|
||||
return state.status.sceneID.has_value();
|
||||
case GatewayModbusGeneratedKind::kShortSettingsKnown:
|
||||
return state.settings.anyKnown();
|
||||
case GatewayModbusGeneratedKind::kShortControlGearPresent:
|
||||
@@ -3195,7 +3144,7 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
}
|
||||
|
||||
const auto* discovery = findDiscoveryEntryLocked(point.short_address);
|
||||
const auto state = cache.daliAddressState(channel.gateway_id,
|
||||
const auto state = dali_cache.addressState(channel.gateway_id,
|
||||
static_cast<uint8_t>(point.short_address));
|
||||
switch (point.generated_kind) {
|
||||
case GatewayModbusGeneratedKind::kShortInventoryState:
|
||||
@@ -3216,12 +3165,12 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
return discovery == nullptr ? kModbusUnknownRegister : DeviceTypeMask(discovery->discovery);
|
||||
case GatewayModbusGeneratedKind::kShortBrightness:
|
||||
case GatewayModbusGeneratedKind::kShortActualLevel:
|
||||
return state.status.actual_level.has_value()
|
||||
? static_cast<uint16_t>(state.status.actual_level.value())
|
||||
return state.status.actualLevel.has_value()
|
||||
? static_cast<uint16_t>(state.status.actualLevel.value())
|
||||
: kModbusUnknownRegister;
|
||||
case GatewayModbusGeneratedKind::kShortSceneId:
|
||||
return state.status.scene_id.has_value()
|
||||
? static_cast<uint16_t>(state.status.scene_id.value())
|
||||
return state.status.sceneID.has_value()
|
||||
? static_cast<uint16_t>(state.status.sceneID.value())
|
||||
: kModbusUnknownRegister;
|
||||
case GatewayModbusGeneratedKind::kShortRawStatus: {
|
||||
const auto snapshot = diagnosticSnapshotLocked(point.short_address, "base_status");
|
||||
@@ -3233,30 +3182,30 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
return kModbusUnknownRegister;
|
||||
}
|
||||
case GatewayModbusGeneratedKind::kShortGroupMask:
|
||||
return state.group_mask_known ? state.group_mask : kModbusUnknownRegister;
|
||||
return state.groupMaskKnown ? state.groupMask : kModbusUnknownRegister;
|
||||
case GatewayModbusGeneratedKind::kShortPowerOnLevel:
|
||||
return state.settings.power_on_level.has_value()
|
||||
? static_cast<uint16_t>(state.settings.power_on_level.value())
|
||||
return state.settings.powerOnLevel.has_value()
|
||||
? static_cast<uint16_t>(state.settings.powerOnLevel.value())
|
||||
: kModbusUnknownRegister;
|
||||
case GatewayModbusGeneratedKind::kShortSystemFailureLevel:
|
||||
return state.settings.system_failure_level.has_value()
|
||||
? static_cast<uint16_t>(state.settings.system_failure_level.value())
|
||||
return state.settings.systemFailureLevel.has_value()
|
||||
? static_cast<uint16_t>(state.settings.systemFailureLevel.value())
|
||||
: kModbusUnknownRegister;
|
||||
case GatewayModbusGeneratedKind::kShortMinLevel:
|
||||
return state.settings.min_level.has_value()
|
||||
? static_cast<uint16_t>(state.settings.min_level.value())
|
||||
return state.settings.minLevel.has_value()
|
||||
? static_cast<uint16_t>(state.settings.minLevel.value())
|
||||
: kModbusUnknownRegister;
|
||||
case GatewayModbusGeneratedKind::kShortMaxLevel:
|
||||
return state.settings.max_level.has_value()
|
||||
? static_cast<uint16_t>(state.settings.max_level.value())
|
||||
return state.settings.maxLevel.has_value()
|
||||
? static_cast<uint16_t>(state.settings.maxLevel.value())
|
||||
: kModbusUnknownRegister;
|
||||
case GatewayModbusGeneratedKind::kShortFadeTime:
|
||||
return state.settings.fade_time.has_value()
|
||||
? static_cast<uint16_t>(state.settings.fade_time.value())
|
||||
return state.settings.fadeTime.has_value()
|
||||
? static_cast<uint16_t>(state.settings.fadeTime.value())
|
||||
: kModbusUnknownRegister;
|
||||
case GatewayModbusGeneratedKind::kShortFadeRate:
|
||||
return state.settings.fade_rate.has_value()
|
||||
? static_cast<uint16_t>(state.settings.fade_rate.value())
|
||||
return state.settings.fadeRate.has_value()
|
||||
? static_cast<uint16_t>(state.settings.fadeRate.value())
|
||||
: kModbusUnknownRegister;
|
||||
case GatewayModbusGeneratedKind::kShortColorTemperature:
|
||||
return kModbusUnknownRegister;
|
||||
@@ -3297,7 +3246,7 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
return false;
|
||||
}
|
||||
if (sent) {
|
||||
cache.mirrorDaliCommand(channel.gateway_id, raw_command_address, mirrored_command);
|
||||
dali_cache.mirrorForwardFrame(channel.gateway_id, raw_command_address, mirrored_command);
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
@@ -3315,7 +3264,7 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
domain.markHostCommandFrame(channel.gateway_id, RawArcAddressFromDec(point.short_address),
|
||||
static_cast<uint8_t>(value));
|
||||
if (domain.setBright(channel.gateway_id, point.short_address, value)) {
|
||||
cache.mirrorDaliCommand(channel.gateway_id, RawArcAddressFromDec(point.short_address),
|
||||
dali_cache.mirrorForwardFrame(channel.gateway_id, RawArcAddressFromDec(point.short_address),
|
||||
static_cast<uint8_t>(value));
|
||||
return true;
|
||||
}
|
||||
@@ -3326,7 +3275,7 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
case GatewayModbusGeneratedKind::kShortGroupMask:
|
||||
domain.markHostActivity(channel.gateway_id);
|
||||
if (domain.applyGroupMask(channel.gateway_id, point.short_address, value)) {
|
||||
cache.setDaliGroupMask(channel.gateway_id, static_cast<uint8_t>(point.short_address),
|
||||
dali_cache.setGroupMask(channel.gateway_id, static_cast<uint8_t>(point.short_address),
|
||||
value);
|
||||
return true;
|
||||
}
|
||||
@@ -3340,40 +3289,40 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
if (value > 255) {
|
||||
return false;
|
||||
}
|
||||
auto current = cache.daliAddressState(channel.gateway_id,
|
||||
auto current = dali_cache.addressState(channel.gateway_id,
|
||||
static_cast<uint8_t>(point.short_address)).settings;
|
||||
switch (point.generated_kind) {
|
||||
case GatewayModbusGeneratedKind::kShortPowerOnLevel:
|
||||
current.power_on_level = static_cast<uint8_t>(value);
|
||||
current.powerOnLevel = static_cast<uint8_t>(value);
|
||||
break;
|
||||
case GatewayModbusGeneratedKind::kShortSystemFailureLevel:
|
||||
current.system_failure_level = static_cast<uint8_t>(value);
|
||||
current.systemFailureLevel = static_cast<uint8_t>(value);
|
||||
break;
|
||||
case GatewayModbusGeneratedKind::kShortMinLevel:
|
||||
current.min_level = static_cast<uint8_t>(value);
|
||||
current.minLevel = static_cast<uint8_t>(value);
|
||||
break;
|
||||
case GatewayModbusGeneratedKind::kShortMaxLevel:
|
||||
current.max_level = static_cast<uint8_t>(value);
|
||||
current.maxLevel = static_cast<uint8_t>(value);
|
||||
break;
|
||||
case GatewayModbusGeneratedKind::kShortFadeTime:
|
||||
current.fade_time = static_cast<uint8_t>(value);
|
||||
current.fadeTime = static_cast<uint8_t>(value);
|
||||
break;
|
||||
case GatewayModbusGeneratedKind::kShortFadeRate:
|
||||
current.fade_rate = static_cast<uint8_t>(value);
|
||||
current.fadeRate = static_cast<uint8_t>(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DaliAddressSettingsSnapshot domain_settings;
|
||||
domain_settings.power_on_level = current.power_on_level;
|
||||
domain_settings.system_failure_level = current.system_failure_level;
|
||||
domain_settings.min_level = current.min_level;
|
||||
domain_settings.max_level = current.max_level;
|
||||
domain_settings.fade_time = current.fade_time;
|
||||
domain_settings.fade_rate = current.fade_rate;
|
||||
domain_settings.power_on_level = current.powerOnLevel;
|
||||
domain_settings.system_failure_level = current.systemFailureLevel;
|
||||
domain_settings.min_level = current.minLevel;
|
||||
domain_settings.max_level = current.maxLevel;
|
||||
domain_settings.fade_time = current.fadeTime;
|
||||
domain_settings.fade_rate = current.fadeRate;
|
||||
domain.markHostActivity(channel.gateway_id);
|
||||
if (domain.applyAddressSettings(channel.gateway_id, point.short_address, domain_settings)) {
|
||||
cache.setDaliSettings(channel.gateway_id, static_cast<uint8_t>(point.short_address),
|
||||
dali_cache.setSettings(channel.gateway_id, static_cast<uint8_t>(point.short_address),
|
||||
current);
|
||||
return true;
|
||||
}
|
||||
@@ -4318,7 +4267,9 @@ GatewayBridgeService::GatewayBridgeService(DaliDomainService& dali_domain,
|
||||
GatewayBridgeServiceConfig config)
|
||||
: dali_domain_(dali_domain), cache_(cache), config_(config) {}
|
||||
|
||||
GatewayBridgeService::~GatewayBridgeService() = default;
|
||||
GatewayBridgeService::~GatewayBridgeService() {
|
||||
dali_domain_.gatewayCache().setStatusUpdateCallback({});
|
||||
}
|
||||
|
||||
esp_err_t GatewayBridgeService::start() {
|
||||
ConfigureDaliCppLogging();
|
||||
@@ -4343,8 +4294,8 @@ esp_err_t GatewayBridgeService::start() {
|
||||
runtimes_.push_back(std::move(runtime));
|
||||
}
|
||||
|
||||
dali_domain_.addRawFrameSink(
|
||||
[this](const DaliRawFrame& frame) { handleDaliRawFrame(frame); });
|
||||
dali_domain_.gatewayCache().setStatusUpdateCallback(
|
||||
[this](const DaliGatewayStatusUpdate& update) { handleDaliStatusUpdate(update); });
|
||||
|
||||
std::set<int> used_serial_uarts;
|
||||
if (config_.modbus_enabled && config_.modbus_startup_enabled) {
|
||||
@@ -4583,14 +4534,13 @@ DaliBridgeResult GatewayBridgeService::routeKnxGroupObjectWrite(uint16_t group_o
|
||||
return runtime->knx->handleGroupObjectWrite(group_object_number, data, len);
|
||||
}
|
||||
|
||||
void GatewayBridgeService::handleDaliRawFrame(const DaliRawFrame& frame) {
|
||||
const auto update = DecodeDaliKnxStatusUpdate(frame);
|
||||
if (!update.has_value()) {
|
||||
void GatewayBridgeService::handleDaliStatusUpdate(const DaliGatewayStatusUpdate& update) {
|
||||
if (!update.status.actualLevel.has_value()) {
|
||||
return;
|
||||
}
|
||||
auto* owner = knx_endpoint_runtime_ != nullptr ? knx_endpoint_runtime_
|
||||
: selectKnxEndpointRuntime();
|
||||
if (owner == nullptr || owner->channel.gateway_id != frame.gateway_id) {
|
||||
if (owner == nullptr || owner->channel.gateway_id != update.channel) {
|
||||
return;
|
||||
}
|
||||
LockGuard guard(owner->lock);
|
||||
@@ -4600,32 +4550,29 @@ void GatewayBridgeService::handleDaliRawFrame(const DaliRawFrame& frame) {
|
||||
|
||||
auto publish_target = [&](GatewayKnxDaliTargetKind kind, int address) {
|
||||
owner->knx_router->publishDaliStatus(GatewayKnxDaliTarget{kind, address},
|
||||
update->actual_level);
|
||||
*update.status.actualLevel);
|
||||
};
|
||||
|
||||
publish_target(update->target.kind, update->target.address);
|
||||
GatewayKnxDaliTargetKind target_kind = GatewayKnxDaliTargetKind::kShortAddress;
|
||||
int target_address = update.target.value;
|
||||
if (update.target.kind == DaliGatewayTargetKind::group) {
|
||||
target_kind = GatewayKnxDaliTargetKind::kGroup;
|
||||
} else if (update.target.kind == DaliGatewayTargetKind::broadcast) {
|
||||
target_kind = GatewayKnxDaliTargetKind::kBroadcast;
|
||||
target_address = 127;
|
||||
}
|
||||
publish_target(target_kind, target_address);
|
||||
|
||||
if (update->target.kind == GatewayKnxDaliTargetKind::kGroup &&
|
||||
update->target.address >= 0 && update->target.address < 16) {
|
||||
const uint16_t group_bit = static_cast<uint16_t>(1U << update->target.address);
|
||||
for (int short_address = 0; short_address <= kMaxDaliShortAddress; ++short_address) {
|
||||
const auto state = owner->cache.daliAddressState(frame.gateway_id,
|
||||
static_cast<uint8_t>(short_address));
|
||||
if (!state.group_mask_known || (state.group_mask & group_bit) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (update.target.kind != DaliGatewayTargetKind::shortAddress) {
|
||||
for (const uint8_t short_address : update.affectedShortAddresses) {
|
||||
publish_target(GatewayKnxDaliTargetKind::kShortAddress, short_address);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (update->target.kind == GatewayKnxDaliTargetKind::kBroadcast) {
|
||||
if (update.target.kind == DaliGatewayTargetKind::broadcast) {
|
||||
for (int group = 0; group < 16; ++group) {
|
||||
publish_target(GatewayKnxDaliTargetKind::kGroup, group);
|
||||
}
|
||||
for (int short_address = 0; short_address <= kMaxDaliShortAddress; ++short_address) {
|
||||
publish_target(GatewayKnxDaliTargetKind::kShortAddress, short_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,88 +12,17 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#include "nvs.h"
|
||||
#include "dali_gateway.hpp"
|
||||
|
||||
class DaliGatewayCache;
|
||||
|
||||
namespace gateway {
|
||||
|
||||
enum class GatewayCachePriorityMode : uint8_t {
|
||||
kOutsideBusFirst = 0,
|
||||
kLocalGatewayFirst = 1,
|
||||
};
|
||||
|
||||
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{10000};
|
||||
uint32_t refresh_interval_ms{120000};
|
||||
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,
|
||||
};
|
||||
|
||||
enum class GatewayCacheDaliTargetKind : uint8_t {
|
||||
kShortAddress = 0,
|
||||
kGroup = 1,
|
||||
kBroadcast = 2,
|
||||
};
|
||||
|
||||
enum class GatewayCacheDaliPresence : uint8_t {
|
||||
kUnknown = 0,
|
||||
kOnline = 1,
|
||||
kOffline = 2,
|
||||
};
|
||||
|
||||
struct GatewayCacheDaliTarget {
|
||||
GatewayCacheDaliTargetKind kind{GatewayCacheDaliTargetKind::kShortAddress};
|
||||
uint8_t value{0};
|
||||
};
|
||||
|
||||
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 GatewayCacheDaliRuntimeStatus {
|
||||
std::optional<uint8_t> actual_level;
|
||||
std::optional<uint8_t> scene_id;
|
||||
bool use_min_level{false};
|
||||
bool stale{false};
|
||||
uint32_t revision{0};
|
||||
|
||||
bool anyKnown() const {
|
||||
return actual_level.has_value() || scene_id.has_value() || use_min_level;
|
||||
}
|
||||
};
|
||||
|
||||
struct GatewayCacheDaliAddressState {
|
||||
bool group_mask_known{false};
|
||||
uint16_t group_mask{0};
|
||||
std::array<std::optional<uint8_t>, 16> scene_levels{};
|
||||
GatewayCacheDaliSettingsSnapshot settings;
|
||||
GatewayCacheDaliRuntimeStatus status;
|
||||
};
|
||||
|
||||
class GatewayCache {
|
||||
@@ -118,11 +47,10 @@ class GatewayCache {
|
||||
using SceneStore = std::array<SceneEntry, 16>;
|
||||
using GroupStore = std::array<GroupEntry, 16>;
|
||||
|
||||
explicit GatewayCache(GatewayCacheConfig config = {});
|
||||
GatewayCache(DaliGatewayCache& dali_cache, GatewayCacheConfig config = {});
|
||||
~GatewayCache();
|
||||
|
||||
esp_err_t start();
|
||||
void preloadChannel(uint8_t gateway_id);
|
||||
|
||||
SceneStore scenes(uint8_t gateway_id);
|
||||
GroupStore groups(uint8_t gateway_id);
|
||||
@@ -143,48 +71,10 @@ class GatewayCache {
|
||||
bool deleteGroup(uint8_t gateway_id, uint8_t group_id);
|
||||
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);
|
||||
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,
|
||||
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 setDaliActualLevel(uint8_t gateway_id, uint8_t short_address,
|
||||
std::optional<uint8_t> level);
|
||||
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 setCacheEnabled(bool enabled);
|
||||
bool reconciliationEnabled() const;
|
||||
bool fullStateMirrorEnabled() const;
|
||||
bool mirrorDaliCommand(uint8_t gateway_id, uint8_t raw_addr, uint8_t command);
|
||||
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();
|
||||
@@ -193,63 +83,22 @@ class GatewayCache {
|
||||
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 persistDaliAddressStateLocked(uint8_t gateway_id, uint8_t short_address,
|
||||
const GatewayCacheDaliAddressState& state);
|
||||
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);
|
||||
void applyDaliTargetRuntimeStatusLocked(uint8_t gateway_id,
|
||||
const GatewayCacheDaliTarget& target,
|
||||
const GatewayCacheDaliRuntimeStatus& status);
|
||||
void applyDaliRuntimeStatusToAddressLocked(GatewayCacheDaliAddressState& state,
|
||||
const GatewayCacheDaliRuntimeStatus& status);
|
||||
void applyDaliTargetGroupMutationLocked(uint8_t gateway_id,
|
||||
const GatewayCacheDaliTarget& target, uint8_t group_id,
|
||||
bool add_to_group);
|
||||
void applyDaliTargetSceneLevelLocked(uint8_t gateway_id,
|
||||
const GatewayCacheDaliTarget& target, uint8_t scene_id,
|
||||
std::optional<uint8_t> level);
|
||||
void applyDaliTargetSettingsLocked(uint8_t gateway_id,
|
||||
const GatewayCacheDaliTarget& target, uint8_t command,
|
||||
uint8_t value);
|
||||
void refreshDaliAddressAggregateStatusLocked(uint8_t gateway_id,
|
||||
GatewayCacheDaliAddressState& state);
|
||||
GatewayCacheDaliAddressState& ensureDaliAddressStateLocked(uint8_t gateway_id,
|
||||
uint8_t short_address);
|
||||
GatewayCacheDaliRuntimeStatus& ensureDaliGroupStatusLocked(uint8_t gateway_id,
|
||||
uint8_t group_id);
|
||||
GatewayCacheDaliRuntimeStatus& ensureDaliBroadcastStatusLocked(uint8_t gateway_id);
|
||||
SceneStore& ensureSceneStoreLocked(uint8_t gateway_id);
|
||||
GroupStore& ensureGroupStoreLocked(uint8_t gateway_id);
|
||||
void loadSceneStoreLocked(uint8_t gateway_id, SceneStore& scenes);
|
||||
void loadGroupStoreLocked(uint8_t gateway_id, GroupStore& groups);
|
||||
void loadDaliStateStoreLocked(uint8_t gateway_id,
|
||||
std::array<GatewayCacheDaliAddressState, 64>& states);
|
||||
std::string readStringLocked(std::string_view key);
|
||||
bool writeStringLocked(std::string_view key, std::string_view value);
|
||||
bool eraseKeyLocked(std::string_view key);
|
||||
void syncDaliStatesFromCoreLocked(uint8_t gateway_id);
|
||||
|
||||
DaliGatewayCache& dali_cache_;
|
||||
GatewayCacheConfig config_;
|
||||
GatewayCachePriorityMode priority_mode_;
|
||||
DaliGatewayCache dali_gateway_cache_;
|
||||
TaskHandle_t task_handle_{nullptr};
|
||||
SemaphoreHandle_t lock_{nullptr};
|
||||
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, 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_;
|
||||
std::map<uint8_t, GatewayCacheChannelFlags> channel_flags_;
|
||||
uint32_t dali_runtime_revision_{0};
|
||||
bool dirty_{false};
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "dali_gateway.hpp"
|
||||
#include "gateway_cache.hpp"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -148,9 +149,9 @@ class GatewayController {
|
||||
kSettings = 3,
|
||||
};
|
||||
|
||||
GatewayCacheChannelFlags flags{};
|
||||
DaliGatewayChannelFlags flags{};
|
||||
Phase phase{Phase::kReloadFlags};
|
||||
std::optional<GatewayCacheDaliTarget> target;
|
||||
std::optional<DaliGatewayTarget> target;
|
||||
std::vector<uint8_t> addresses;
|
||||
size_t address_index{0};
|
||||
uint8_t scene_id{0};
|
||||
@@ -210,7 +211,7 @@ class GatewayController {
|
||||
void runOperationTask(GatewayOperationTaskContext* context);
|
||||
void dispatchCommand(const std::vector<uint8_t>& command);
|
||||
void scheduleReconciliation(uint8_t gateway_id,
|
||||
std::optional<GatewayCacheDaliTarget> target = std::nullopt);
|
||||
std::optional<DaliGatewayTarget> target = std::nullopt);
|
||||
bool hasPendingReconciliation() const;
|
||||
bool cacheRefreshEnabled() const;
|
||||
bool cacheMaintenanceSnoozed(uint8_t gateway_id) const;
|
||||
@@ -303,6 +304,7 @@ class GatewayController {
|
||||
|
||||
GatewayRuntime& runtime_;
|
||||
DaliDomainService& dali_domain_;
|
||||
DaliGatewayCache& dali_cache_;
|
||||
GatewayCache& cache_;
|
||||
GatewayBridgeService* bridge_service_{nullptr};
|
||||
GatewayControllerConfig config_;
|
||||
|
||||
@@ -206,12 +206,12 @@ class LockGuard {
|
||||
SemaphoreHandle_t lock_;
|
||||
};
|
||||
|
||||
bool AnyFlagSet(const GatewayCacheChannelFlags& flags) {
|
||||
return flags.need_update_group || flags.need_update_scene || flags.need_update_settings;
|
||||
bool AnyFlagSet(const DaliGatewayChannelFlags& flags) {
|
||||
return flags.needUpdateGroup || flags.needUpdateScene || flags.needUpdateSettings;
|
||||
}
|
||||
|
||||
bool SameTarget(const std::optional<GatewayCacheDaliTarget>& lhs,
|
||||
const std::optional<GatewayCacheDaliTarget>& rhs) {
|
||||
bool SameTarget(const std::optional<DaliGatewayTarget>& lhs,
|
||||
const std::optional<DaliGatewayTarget>& rhs) {
|
||||
if (lhs.has_value() != rhs.has_value()) {
|
||||
return false;
|
||||
}
|
||||
@@ -453,15 +453,15 @@ uint8_t CacheByte(std::optional<uint8_t> value) {
|
||||
return value.value_or(0xFF);
|
||||
}
|
||||
|
||||
uint16_t CacheRuntimeFlags(const GatewayCacheDaliRuntimeStatus& status) {
|
||||
uint16_t CacheRuntimeFlags(const DaliGatewayRuntimeStatus& status) {
|
||||
uint16_t flags = 0;
|
||||
if (status.actual_level.has_value()) {
|
||||
if (status.actualLevel.has_value()) {
|
||||
flags |= kCacheFlagActualKnown;
|
||||
}
|
||||
if (status.scene_id.has_value()) {
|
||||
if (status.sceneID.has_value()) {
|
||||
flags |= kCacheFlagSceneKnown;
|
||||
}
|
||||
if (status.use_min_level) {
|
||||
if (status.useMinLevel) {
|
||||
flags |= kCacheFlagUseMinLevel;
|
||||
}
|
||||
if (status.stale) {
|
||||
@@ -470,36 +470,36 @@ uint16_t CacheRuntimeFlags(const GatewayCacheDaliRuntimeStatus& status) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
uint16_t CacheAddressFlags(const GatewayCacheDaliAddressState& state) {
|
||||
uint16_t CacheAddressFlags(const DaliGatewayAddressState& state) {
|
||||
uint16_t flags = CacheRuntimeFlags(state.status);
|
||||
if (state.group_mask_known) {
|
||||
if (state.groupMaskKnown) {
|
||||
flags |= kCacheFlagGroupMaskKnown;
|
||||
}
|
||||
if (state.settings.power_on_level.has_value()) {
|
||||
if (state.settings.powerOnLevel.has_value()) {
|
||||
flags |= kCacheFlagPowerOnKnown;
|
||||
}
|
||||
if (state.settings.system_failure_level.has_value()) {
|
||||
if (state.settings.systemFailureLevel.has_value()) {
|
||||
flags |= kCacheFlagSystemFailureKnown;
|
||||
}
|
||||
if (state.settings.min_level.has_value()) {
|
||||
if (state.settings.minLevel.has_value()) {
|
||||
flags |= kCacheFlagMinKnown;
|
||||
}
|
||||
if (state.settings.max_level.has_value()) {
|
||||
if (state.settings.maxLevel.has_value()) {
|
||||
flags |= kCacheFlagMaxKnown;
|
||||
}
|
||||
if (state.settings.fade_time.has_value()) {
|
||||
if (state.settings.fadeTime.has_value()) {
|
||||
flags |= kCacheFlagFadeTimeKnown;
|
||||
}
|
||||
if (state.settings.fade_rate.has_value()) {
|
||||
if (state.settings.fadeRate.has_value()) {
|
||||
flags |= kCacheFlagFadeRateKnown;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
uint16_t CacheSceneKnownMask(const GatewayCacheDaliAddressState& state) {
|
||||
uint16_t CacheSceneKnownMask(const DaliGatewayAddressState& state) {
|
||||
uint16_t mask = 0;
|
||||
for (size_t index = 0; index < state.scene_levels.size(); ++index) {
|
||||
if (state.scene_levels[index].has_value()) {
|
||||
for (size_t index = 0; index < state.sceneLevels.size(); ++index) {
|
||||
if (state.sceneLevels[index].has_value()) {
|
||||
mask |= static_cast<uint16_t>(1U << index);
|
||||
}
|
||||
}
|
||||
@@ -546,6 +546,7 @@ GatewayController::GatewayController(GatewayRuntime& runtime, DaliDomainService&
|
||||
GatewayCache& cache, GatewayControllerConfig config)
|
||||
: runtime_(runtime),
|
||||
dali_domain_(dali_domain),
|
||||
dali_cache_(dali_domain.gatewayCache()),
|
||||
cache_(cache),
|
||||
config_(config),
|
||||
maintenance_lock_(xSemaphoreCreateMutex()),
|
||||
@@ -577,7 +578,7 @@ esp_err_t GatewayController::start() {
|
||||
dali_domain_.addRawFrameSink([this](const DaliRawFrame& frame) { handleDaliRawFrame(frame); });
|
||||
|
||||
for (const auto& channel : dali_domain_.channelInfo()) {
|
||||
cache_.preloadChannel(channel.gateway_id);
|
||||
dali_cache_.preloadChannel(channel.gateway_id);
|
||||
dali_domain_.resetBus(channel.gateway_id);
|
||||
publishPayload(channel.gateway_id, {0x02, channel.gateway_id, 0x88});
|
||||
}
|
||||
@@ -746,19 +747,23 @@ bool GatewayController::setBleEnabled(bool enabled) {
|
||||
}
|
||||
|
||||
bool GatewayController::cacheEnabled() const {
|
||||
return cache_.cacheEnabled();
|
||||
return dali_cache_.enabled();
|
||||
}
|
||||
|
||||
bool GatewayController::setCacheEnabled(bool enabled) {
|
||||
if (!config_.cache_supported || !runtime_.setCacheEnabled(enabled)) {
|
||||
return false;
|
||||
}
|
||||
if (cache_.setCacheEnabled(enabled)) {
|
||||
if (!enabled && !cache_.setCacheEnabled(false)) {
|
||||
runtime_.setCacheEnabled(dali_cache_.enabled());
|
||||
return false;
|
||||
}
|
||||
if (dali_cache_.setEnabled(enabled) && (enabled ? cache_.setCacheEnabled(true) : true)) {
|
||||
return true;
|
||||
}
|
||||
// Keep the persisted setting aligned with the live cache when the worker
|
||||
// cannot be started or stopped.
|
||||
runtime_.setCacheEnabled(cache_.cacheEnabled());
|
||||
runtime_.setCacheEnabled(dali_cache_.enabled());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -880,7 +885,7 @@ bool GatewayController::setChannelGatewayId(uint8_t channel_index, uint8_t gatew
|
||||
dali_domain_.updateChannelGatewayId(channel_index, current_gateway_id.value());
|
||||
return false;
|
||||
}
|
||||
cache_.preloadChannel(gateway_id);
|
||||
dali_cache_.preloadChannel(gateway_id);
|
||||
{
|
||||
LockGuard guard(maintenance_lock_);
|
||||
reconciliation_jobs_.erase(current_gateway_id.value());
|
||||
@@ -952,13 +957,13 @@ void GatewayController::taskLoop() {
|
||||
}
|
||||
|
||||
void GatewayController::scheduleReconciliation(uint8_t gateway_id,
|
||||
std::optional<GatewayCacheDaliTarget> target) {
|
||||
if (!cache_.reconciliationEnabled()) {
|
||||
std::optional<DaliGatewayTarget> target) {
|
||||
if (!dali_cache_.reconciliationEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto flags = cache_.pendingChannelFlags(gateway_id);
|
||||
if (cache_.fullStateMirrorEnabled() && AnyFlagSet(flags)) {
|
||||
auto flags = dali_cache_.pendingChannelFlags(gateway_id);
|
||||
if (dali_cache_.fullStateMirrorEnabled() && AnyFlagSet(flags)) {
|
||||
flags = {true, true, true};
|
||||
}
|
||||
if (!AnyFlagSet(flags)) {
|
||||
@@ -990,7 +995,7 @@ bool GatewayController::hasPendingReconciliation() const {
|
||||
}
|
||||
|
||||
bool GatewayController::cacheRefreshEnabled() const {
|
||||
return config_.cache_supported && cache_.cacheEnabled() &&
|
||||
return config_.cache_supported && dali_cache_.enabled() &&
|
||||
config_.cache_refresh_interval_ms > 0;
|
||||
}
|
||||
|
||||
@@ -1000,7 +1005,7 @@ bool GatewayController::cacheMaintenanceSnoozed(uint8_t gateway_id) const {
|
||||
}
|
||||
|
||||
bool GatewayController::runMaintenanceStep() {
|
||||
if (cache_.reconciliationEnabled()) {
|
||||
if (dali_cache_.reconciliationEnabled()) {
|
||||
bool has_job = false;
|
||||
uint8_t gateway_id = 0;
|
||||
ReconciliationJob job;
|
||||
@@ -1045,24 +1050,24 @@ bool GatewayController::runMaintenanceStep() {
|
||||
|
||||
bool GatewayController::runReconciliationStep(uint8_t gateway_id, ReconciliationJob& job) {
|
||||
if (job.phase == ReconciliationJob::Phase::kReloadFlags) {
|
||||
job.flags = cache_.pendingChannelFlags(gateway_id);
|
||||
if (cache_.fullStateMirrorEnabled() && AnyFlagSet(job.flags)) {
|
||||
job.flags = dali_cache_.pendingChannelFlags(gateway_id);
|
||||
if (dali_cache_.fullStateMirrorEnabled() && AnyFlagSet(job.flags)) {
|
||||
job.flags = {true, true, true};
|
||||
}
|
||||
if (!AnyFlagSet(job.flags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
job.addresses = cache_.reconciliationAddresses(gateway_id, job.target);
|
||||
job.addresses = dali_cache_.reconciliationAddresses(gateway_id, job.target);
|
||||
job.address_index = 0;
|
||||
job.scene_id = 0;
|
||||
if (job.addresses.empty()) {
|
||||
cache_.clearChannelFlagsIfMatched(gateway_id, job.flags);
|
||||
dali_cache_.clearChannelFlagsIfMatched(gateway_id, job.flags);
|
||||
return false;
|
||||
}
|
||||
if (job.flags.need_update_group) {
|
||||
if (job.flags.needUpdateGroup) {
|
||||
job.phase = ReconciliationJob::Phase::kGroups;
|
||||
} else if (job.flags.need_update_scene) {
|
||||
} else if (job.flags.needUpdateScene) {
|
||||
job.phase = ReconciliationJob::Phase::kScenes;
|
||||
} else {
|
||||
job.phase = ReconciliationJob::Phase::kSettings;
|
||||
@@ -1074,11 +1079,11 @@ bool GatewayController::runReconciliationStep(uint8_t gateway_id, Reconciliation
|
||||
reconcileGroupStep(gateway_id, job.addresses[job.address_index++]);
|
||||
if (job.address_index >= job.addresses.size()) {
|
||||
job.address_index = 0;
|
||||
if (job.flags.need_update_scene) {
|
||||
if (job.flags.needUpdateScene) {
|
||||
job.phase = ReconciliationJob::Phase::kScenes;
|
||||
} else if (job.flags.need_update_settings) {
|
||||
} else if (job.flags.needUpdateSettings) {
|
||||
job.phase = ReconciliationJob::Phase::kSettings;
|
||||
} else if (!cache_.clearChannelFlagsIfMatched(gateway_id, job.flags)) {
|
||||
} else if (!dali_cache_.clearChannelFlagsIfMatched(gateway_id, job.flags)) {
|
||||
job.phase = ReconciliationJob::Phase::kReloadFlags;
|
||||
} else {
|
||||
return false;
|
||||
@@ -1087,8 +1092,8 @@ bool GatewayController::runReconciliationStep(uint8_t gateway_id, Reconciliation
|
||||
return true;
|
||||
case ReconciliationJob::Phase::kScenes: {
|
||||
const uint8_t short_address = job.addresses[job.address_index];
|
||||
if (cache_.daliAddressPresence(gateway_id, short_address) ==
|
||||
GatewayCacheDaliPresence::kOffline) {
|
||||
if (dali_cache_.addressPresence(gateway_id, short_address) ==
|
||||
DaliGatewayPresence::offline) {
|
||||
job.scene_id = 0;
|
||||
++job.address_index;
|
||||
} else {
|
||||
@@ -1101,9 +1106,9 @@ bool GatewayController::runReconciliationStep(uint8_t gateway_id, Reconciliation
|
||||
}
|
||||
if (job.address_index >= job.addresses.size()) {
|
||||
job.address_index = 0;
|
||||
if (job.flags.need_update_settings) {
|
||||
if (job.flags.needUpdateSettings) {
|
||||
job.phase = ReconciliationJob::Phase::kSettings;
|
||||
} else if (!cache_.clearChannelFlagsIfMatched(gateway_id, job.flags)) {
|
||||
} else if (!dali_cache_.clearChannelFlagsIfMatched(gateway_id, job.flags)) {
|
||||
job.phase = ReconciliationJob::Phase::kReloadFlags;
|
||||
} else {
|
||||
return false;
|
||||
@@ -1113,13 +1118,13 @@ bool GatewayController::runReconciliationStep(uint8_t gateway_id, Reconciliation
|
||||
}
|
||||
case ReconciliationJob::Phase::kSettings: {
|
||||
const uint8_t short_address = job.addresses[job.address_index++];
|
||||
if (cache_.daliAddressPresence(gateway_id, short_address) !=
|
||||
GatewayCacheDaliPresence::kOffline) {
|
||||
if (dali_cache_.addressPresence(gateway_id, short_address) !=
|
||||
DaliGatewayPresence::offline) {
|
||||
reconcileSettingsStep(gateway_id, short_address);
|
||||
}
|
||||
if (job.address_index >= job.addresses.size()) {
|
||||
job.address_index = 0;
|
||||
if (!cache_.clearChannelFlagsIfMatched(gateway_id, job.flags)) {
|
||||
if (!dali_cache_.clearChannelFlagsIfMatched(gateway_id, job.flags)) {
|
||||
job.phase = ReconciliationJob::Phase::kReloadFlags;
|
||||
} else {
|
||||
return false;
|
||||
@@ -1170,8 +1175,8 @@ bool GatewayController::runCacheRefreshStep() {
|
||||
}
|
||||
};
|
||||
|
||||
if (cache_.daliAddressPresence(channel.gateway_id, job.short_address) ==
|
||||
GatewayCacheDaliPresence::kOffline) {
|
||||
if (dali_cache_.addressPresence(channel.gateway_id, job.short_address) ==
|
||||
DaliGatewayPresence::offline) {
|
||||
advance_job();
|
||||
return true;
|
||||
}
|
||||
@@ -1179,11 +1184,11 @@ bool GatewayController::runCacheRefreshStep() {
|
||||
maintenance_activity_gateway_.store(channel.gateway_id);
|
||||
const auto actual_level = dali_domain_.queryActualLevel(channel.gateway_id, job.short_address);
|
||||
maintenance_activity_gateway_.store(-1);
|
||||
cache_.markDaliAddressPresence(channel.gateway_id, job.short_address,
|
||||
dali_cache_.markAddressPresence(channel.gateway_id, job.short_address,
|
||||
actual_level.has_value()
|
||||
? GatewayCacheDaliPresence::kOnline
|
||||
: GatewayCacheDaliPresence::kOffline);
|
||||
cache_.setDaliActualLevel(channel.gateway_id, job.short_address, actual_level);
|
||||
? DaliGatewayPresence::online
|
||||
: DaliGatewayPresence::offline);
|
||||
dali_cache_.setActualLevel(channel.gateway_id, job.short_address, actual_level);
|
||||
advance_job();
|
||||
return true;
|
||||
}
|
||||
@@ -1192,19 +1197,19 @@ bool GatewayController::runCacheRefreshStep() {
|
||||
}
|
||||
|
||||
void GatewayController::reconcileGroupStep(uint8_t gateway_id, uint8_t short_address) {
|
||||
const auto policy = cache_.priorityMode();
|
||||
const auto state = cache_.daliAddressState(gateway_id, short_address);
|
||||
const auto policy = dali_cache_.priorityMode();
|
||||
const auto state = dali_cache_.addressState(gateway_id, short_address);
|
||||
|
||||
if (policy == GatewayCachePriorityMode::kLocalGatewayFirst && state.group_mask_known) {
|
||||
if (policy == DaliGatewayCachePriorityMode::localGatewayFirst && state.groupMaskKnown) {
|
||||
maintenance_activity_gateway_.store(gateway_id);
|
||||
const bool applied = dali_domain_.applyGroupMask(gateway_id, short_address, state.group_mask);
|
||||
const bool applied = dali_domain_.applyGroupMask(gateway_id, short_address, state.groupMask);
|
||||
maintenance_activity_gateway_.store(-1);
|
||||
const auto verified_mask = dali_domain_.queryGroupMask(gateway_id, short_address);
|
||||
cache_.markDaliAddressPresence(gateway_id, short_address,
|
||||
dali_cache_.markAddressPresence(gateway_id, short_address,
|
||||
verified_mask.has_value()
|
||||
? GatewayCacheDaliPresence::kOnline
|
||||
: GatewayCacheDaliPresence::kOffline);
|
||||
cache_.setDaliGroupMask(gateway_id, short_address, verified_mask);
|
||||
? DaliGatewayPresence::online
|
||||
: DaliGatewayPresence::offline);
|
||||
dali_cache_.setGroupMask(gateway_id, short_address, verified_mask);
|
||||
if (!applied && verified_mask.has_value()) {
|
||||
ESP_LOGW(kTag, "group reconcile fallback gateway=%u short=%u", gateway_id, short_address);
|
||||
}
|
||||
@@ -1212,62 +1217,62 @@ void GatewayController::reconcileGroupStep(uint8_t gateway_id, uint8_t short_add
|
||||
}
|
||||
|
||||
const auto group_mask = dali_domain_.queryGroupMask(gateway_id, short_address);
|
||||
cache_.markDaliAddressPresence(gateway_id, short_address,
|
||||
group_mask.has_value() ? GatewayCacheDaliPresence::kOnline
|
||||
: GatewayCacheDaliPresence::kOffline);
|
||||
cache_.setDaliGroupMask(gateway_id, short_address, group_mask);
|
||||
dali_cache_.markAddressPresence(gateway_id, short_address,
|
||||
group_mask.has_value() ? DaliGatewayPresence::online
|
||||
: DaliGatewayPresence::offline);
|
||||
dali_cache_.setGroupMask(gateway_id, short_address, group_mask);
|
||||
}
|
||||
|
||||
void GatewayController::reconcileSceneStep(uint8_t gateway_id, uint8_t short_address,
|
||||
uint8_t scene_id) {
|
||||
const auto policy = cache_.priorityMode();
|
||||
const auto state = cache_.daliAddressState(gateway_id, short_address);
|
||||
const auto policy = dali_cache_.priorityMode();
|
||||
const auto state = dali_cache_.addressState(gateway_id, short_address);
|
||||
|
||||
if (policy == GatewayCachePriorityMode::kLocalGatewayFirst &&
|
||||
state.scene_levels[scene_id].has_value()) {
|
||||
if (policy == DaliGatewayCachePriorityMode::localGatewayFirst &&
|
||||
state.sceneLevels[scene_id].has_value()) {
|
||||
maintenance_activity_gateway_.store(gateway_id);
|
||||
dali_domain_.applySceneLevel(gateway_id, short_address, scene_id, state.scene_levels[scene_id]);
|
||||
dali_domain_.applySceneLevel(gateway_id, short_address, scene_id, state.sceneLevels[scene_id]);
|
||||
maintenance_activity_gateway_.store(-1);
|
||||
}
|
||||
|
||||
const auto level = dali_domain_.querySceneLevel(gateway_id, short_address, scene_id);
|
||||
cache_.markDaliAddressPresence(gateway_id, short_address,
|
||||
level.has_value() ? GatewayCacheDaliPresence::kOnline
|
||||
: GatewayCacheDaliPresence::kOffline);
|
||||
cache_.setDaliSceneLevel(gateway_id, short_address, scene_id, level);
|
||||
dali_cache_.markAddressPresence(gateway_id, short_address,
|
||||
level.has_value() ? DaliGatewayPresence::online
|
||||
: DaliGatewayPresence::offline);
|
||||
dali_cache_.setSceneLevel(gateway_id, short_address, scene_id, level);
|
||||
}
|
||||
|
||||
void GatewayController::reconcileSettingsStep(uint8_t gateway_id, uint8_t short_address) {
|
||||
const auto policy = cache_.priorityMode();
|
||||
const auto state = cache_.daliAddressState(gateway_id, short_address);
|
||||
const auto policy = dali_cache_.priorityMode();
|
||||
const auto state = dali_cache_.addressState(gateway_id, short_address);
|
||||
|
||||
if (policy == GatewayCachePriorityMode::kLocalGatewayFirst && state.settings.anyKnown()) {
|
||||
if (policy == DaliGatewayCachePriorityMode::localGatewayFirst && state.settings.anyKnown()) {
|
||||
maintenance_activity_gateway_.store(gateway_id);
|
||||
dali_domain_.applyAddressSettings(gateway_id, short_address, {
|
||||
state.settings.power_on_level,
|
||||
state.settings.system_failure_level,
|
||||
state.settings.min_level,
|
||||
state.settings.max_level,
|
||||
state.settings.fade_time,
|
||||
state.settings.fade_rate,
|
||||
state.settings.powerOnLevel,
|
||||
state.settings.systemFailureLevel,
|
||||
state.settings.minLevel,
|
||||
state.settings.maxLevel,
|
||||
state.settings.fadeTime,
|
||||
state.settings.fadeRate,
|
||||
});
|
||||
maintenance_activity_gateway_.store(-1);
|
||||
}
|
||||
|
||||
const auto settings = dali_domain_.queryAddressSettings(gateway_id, short_address);
|
||||
cache_.markDaliAddressPresence(gateway_id, short_address,
|
||||
settings.has_value() ? GatewayCacheDaliPresence::kOnline
|
||||
: GatewayCacheDaliPresence::kOffline);
|
||||
dali_cache_.markAddressPresence(gateway_id, short_address,
|
||||
settings.has_value() ? DaliGatewayPresence::online
|
||||
: DaliGatewayPresence::offline);
|
||||
if (settings.has_value()) {
|
||||
cache_.setDaliSettings(gateway_id, short_address,
|
||||
GatewayCacheDaliSettingsSnapshot{settings->power_on_level,
|
||||
dali_cache_.setSettings(gateway_id, short_address,
|
||||
DaliGatewaySettingsSnapshot{settings->power_on_level,
|
||||
settings->system_failure_level,
|
||||
settings->min_level,
|
||||
settings->max_level,
|
||||
settings->fade_time,
|
||||
settings->fade_rate});
|
||||
} else {
|
||||
cache_.setDaliSettings(gateway_id, short_address, std::nullopt);
|
||||
dali_cache_.setSettings(gateway_id, short_address, std::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1932,12 +1937,13 @@ void GatewayController::handleDaliRawFrame(const DaliRawFrame& frame) {
|
||||
dali_domain_.hasRecentHostActivity(frame.gateway_id, config_.cache_host_echo_ms);
|
||||
const bool local_activity = maintenance_activity || runtime_.hasActiveCommand(frame.gateway_id) ||
|
||||
host_echo_activity || dali_domain_.isAllocAddr(frame.gateway_id);
|
||||
const bool flagged = cache_.observeDaliCommand(frame.gateway_id, addr, data,
|
||||
local_activity
|
||||
? GatewayCacheRawFrameOrigin::kLocalGateway
|
||||
: GatewayCacheRawFrameOrigin::kOutsideBus);
|
||||
const bool flagged =
|
||||
local_activity
|
||||
? (dali_cache_.mirrorForwardFrame(frame.gateway_id, addr, data), false)
|
||||
: dali_cache_.observeForwardFrame(frame.gateway_id, addr, data,
|
||||
DaliGatewayFrameOrigin::outsideBus);
|
||||
if (flagged) {
|
||||
scheduleReconciliation(frame.gateway_id, cache_.decodeDaliTarget(addr));
|
||||
scheduleReconciliation(frame.gateway_id, dali_cache_.decodeTarget(addr));
|
||||
}
|
||||
|
||||
if (setup_mode_ || dali_domain_.isAllocAddr(frame.gateway_id) || maintenance_activity ||
|
||||
@@ -1952,7 +1958,7 @@ void GatewayController::handleDaliRawFrame(const DaliRawFrame& frame) {
|
||||
bool GatewayController::sendRawAndMirror(uint8_t gateway_id, uint8_t raw_addr, uint8_t command) {
|
||||
const bool sent = dali_domain_.sendRaw(gateway_id, raw_addr, command);
|
||||
if (sent) {
|
||||
cache_.mirrorDaliCommand(gateway_id, raw_addr, command);
|
||||
dali_cache_.mirrorForwardFrame(gateway_id, raw_addr, command);
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
@@ -1961,7 +1967,7 @@ bool GatewayController::sendExtRawAndMirror(uint8_t gateway_id, uint8_t raw_addr
|
||||
uint8_t command) {
|
||||
const bool sent = dali_domain_.sendExtRaw(gateway_id, raw_addr, command);
|
||||
if (sent) {
|
||||
cache_.mirrorDaliCommand(gateway_id, raw_addr, command);
|
||||
dali_cache_.mirrorForwardFrame(gateway_id, raw_addr, command);
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
@@ -1971,7 +1977,7 @@ bool GatewayController::setBrightAndMirror(uint8_t gateway_id, int dec_address,
|
||||
dali_domain_.markHostCommandFrame(gateway_id, raw_addr, level);
|
||||
const bool sent = dali_domain_.setBright(gateway_id, dec_address, level);
|
||||
if (sent) {
|
||||
cache_.mirrorDaliCommand(gateway_id, raw_addr, level);
|
||||
dali_cache_.mirrorForwardFrame(gateway_id, raw_addr, level);
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
@@ -1981,7 +1987,7 @@ bool GatewayController::offAndMirror(uint8_t gateway_id, int dec_address) {
|
||||
dali_domain_.markHostCommandFrame(gateway_id, raw_addr, kDaliCmdOff);
|
||||
const bool sent = dali_domain_.off(gateway_id, dec_address);
|
||||
if (sent) {
|
||||
cache_.mirrorDaliCommand(gateway_id, raw_addr, kDaliCmdOff);
|
||||
dali_cache_.mirrorForwardFrame(gateway_id, raw_addr, kDaliCmdOff);
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
@@ -1991,7 +1997,7 @@ bool GatewayController::onAndMirror(uint8_t gateway_id, int dec_address) {
|
||||
dali_domain_.markHostCommandFrame(gateway_id, raw_addr, kDaliCmdRecallMax);
|
||||
const bool sent = dali_domain_.on(gateway_id, dec_address);
|
||||
if (sent) {
|
||||
cache_.mirrorDaliCommand(gateway_id, raw_addr, kDaliCmdRecallMax);
|
||||
dali_cache_.mirrorForwardFrame(gateway_id, raw_addr, kDaliCmdRecallMax);
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
@@ -2311,7 +2317,7 @@ void GatewayController::handleGatewaySerialCommand(uint8_t channel_number,
|
||||
{channel_number, new_gateway_id});
|
||||
return;
|
||||
}
|
||||
cache_.preloadChannel(new_gateway_id);
|
||||
dali_cache_.preloadChannel(new_gateway_id);
|
||||
reconciliation_jobs_.erase(old_gateway_id);
|
||||
cache_refresh_jobs_.erase(old_gateway_id);
|
||||
refreshRuntimeGatewayNames();
|
||||
@@ -3393,11 +3399,11 @@ void GatewayController::handleGatewayCacheCommand(uint8_t gateway_id,
|
||||
const std::vector<uint8_t>& command) {
|
||||
const uint8_t op = command.size() > 4 ? command[4] : kGatewayCacheOpSummary;
|
||||
const uint8_t arg = command.size() > 5 ? command[5] : 0;
|
||||
const bool enabled = config_.cache_supported && cache_.cacheEnabled();
|
||||
const bool enabled = config_.cache_supported && dali_cache_.enabled();
|
||||
|
||||
if (op == kGatewayCacheOpSummary) {
|
||||
const uint8_t flags = static_cast<uint8_t>((config_.cache_supported ? 0x01 : 0x00) |
|
||||
(cache_.cacheEnabled() ? 0x02 : 0x00) |
|
||||
(dali_cache_.enabled() ? 0x02 : 0x00) |
|
||||
(cacheRefreshEnabled() ? 0x04 : 0x00));
|
||||
std::vector<uint8_t> payload{kGatewayCacheOpcode,
|
||||
gateway_id,
|
||||
@@ -3423,21 +3429,21 @@ void GatewayController::handleGatewayCacheCommand(uint8_t gateway_id,
|
||||
kGatewayCacheStatusInvalidArgument, arg});
|
||||
return;
|
||||
}
|
||||
const auto state = cache_.daliAddressState(gateway_id, arg);
|
||||
const auto state = dali_cache_.addressState(gateway_id, arg);
|
||||
std::vector<uint8_t> payload{kGatewayCacheOpcode, gateway_id, op, kGatewayCacheStatusOk, arg};
|
||||
AppendLe16(payload, CacheAddressFlags(state));
|
||||
payload.push_back(CacheByte(state.status.actual_level));
|
||||
payload.push_back(CacheByte(state.status.scene_id));
|
||||
AppendLe16(payload, state.group_mask_known ? state.group_mask : 0);
|
||||
payload.push_back(CacheByte(state.settings.power_on_level));
|
||||
payload.push_back(CacheByte(state.settings.system_failure_level));
|
||||
payload.push_back(CacheByte(state.settings.min_level));
|
||||
payload.push_back(CacheByte(state.settings.max_level));
|
||||
payload.push_back(CacheByte(state.settings.fade_time));
|
||||
payload.push_back(CacheByte(state.settings.fade_rate));
|
||||
payload.push_back(CacheByte(state.status.actualLevel));
|
||||
payload.push_back(CacheByte(state.status.sceneID));
|
||||
AppendLe16(payload, state.groupMaskKnown ? state.groupMask : 0);
|
||||
payload.push_back(CacheByte(state.settings.powerOnLevel));
|
||||
payload.push_back(CacheByte(state.settings.systemFailureLevel));
|
||||
payload.push_back(CacheByte(state.settings.minLevel));
|
||||
payload.push_back(CacheByte(state.settings.maxLevel));
|
||||
payload.push_back(CacheByte(state.settings.fadeTime));
|
||||
payload.push_back(CacheByte(state.settings.fadeRate));
|
||||
AppendLe32(payload, state.status.revision);
|
||||
AppendLe16(payload, CacheSceneKnownMask(state));
|
||||
for (const auto& level : state.scene_levels) {
|
||||
for (const auto& level : state.sceneLevels) {
|
||||
payload.push_back(CacheByte(level));
|
||||
}
|
||||
publishPayload(gateway_id, payload);
|
||||
@@ -3450,22 +3456,22 @@ void GatewayController::handleGatewayCacheCommand(uint8_t gateway_id,
|
||||
kGatewayCacheStatusInvalidArgument, arg});
|
||||
return;
|
||||
}
|
||||
const auto status = cache_.daliGroupStatus(gateway_id, arg);
|
||||
const auto status = dali_cache_.groupStatus(gateway_id, arg);
|
||||
std::vector<uint8_t> payload{kGatewayCacheOpcode, gateway_id, op, kGatewayCacheStatusOk, arg};
|
||||
AppendLe16(payload, CacheRuntimeFlags(status));
|
||||
payload.push_back(CacheByte(status.actual_level));
|
||||
payload.push_back(CacheByte(status.scene_id));
|
||||
payload.push_back(CacheByte(status.actualLevel));
|
||||
payload.push_back(CacheByte(status.sceneID));
|
||||
AppendLe32(payload, status.revision);
|
||||
publishPayload(gateway_id, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
if (op == kGatewayCacheOpBroadcast) {
|
||||
const auto status = cache_.daliBroadcastStatus(gateway_id);
|
||||
const auto status = dali_cache_.broadcastStatus(gateway_id);
|
||||
std::vector<uint8_t> payload{kGatewayCacheOpcode, gateway_id, op, kGatewayCacheStatusOk, 0};
|
||||
AppendLe16(payload, CacheRuntimeFlags(status));
|
||||
payload.push_back(CacheByte(status.actual_level));
|
||||
payload.push_back(CacheByte(status.scene_id));
|
||||
payload.push_back(CacheByte(status.actualLevel));
|
||||
payload.push_back(CacheByte(status.sceneID));
|
||||
AppendLe32(payload, status.revision);
|
||||
publishPayload(gateway_id, payload);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user