886bda43a4
- Updated `CMakeLists.txt` to require `dali_cpp` for the gateway cache component. - Enhanced `GatewayCache` class to include DALI state synchronization and management, including new methods for handling DALI address states, settings, and runtime statuses. - Removed legacy application controller handling from `GatewayController`, simplifying the frame handling logic. - Introduced `identify` method in `GatewayNetworkService` for Part 103 identity indication, along with task management for LED signaling. - Added methods in `GatewaySettingsStore` and `GatewayRuntime` for managing application controller short addresses, improving configuration handling. Signed-off-by: Tony <tonylu@tony-cloud.com>
243 lines
8.8 KiB
C++
243 lines
8.8 KiB
C++
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <deque>
|
|
#include <functional>
|
|
#include <map>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
#include "esp_err.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/semphr.h"
|
|
#include "gateway_core.hpp"
|
|
#include "nvs.h"
|
|
|
|
namespace gateway {
|
|
|
|
esp_err_t InitializeRuntimeNvs();
|
|
std::string ReadRuntimeSerialId();
|
|
|
|
class DaliDomainService;
|
|
|
|
struct WirelessInfo {
|
|
std::string ssid;
|
|
std::string password;
|
|
std::string mac;
|
|
std::string ip;
|
|
};
|
|
|
|
struct EthernetInfo {
|
|
std::string mac;
|
|
std::string ip;
|
|
};
|
|
|
|
struct EthernetConfig {
|
|
std::string ip;
|
|
std::string mask;
|
|
std::string gateway;
|
|
std::string dns;
|
|
};
|
|
|
|
/// Boot-only USB personalities. The selected value is persisted in NVS so a
|
|
/// remote configuration survives reboot, but changing it cannot re-enumerate
|
|
/// an already-running USB device.
|
|
enum class GatewayUsbMode : uint8_t {
|
|
kDebug = 0,
|
|
kSetup = 1,
|
|
kTridonic = 2,
|
|
};
|
|
|
|
const char* GatewayUsbModeToString(GatewayUsbMode mode);
|
|
std::optional<GatewayUsbMode> GatewayUsbModeFromString(std::string_view value);
|
|
|
|
struct GatewayRuntimeConfig {
|
|
std::string_view project_name;
|
|
std::string_view version;
|
|
std::string serial_id;
|
|
bool default_ble_enabled{true};
|
|
bool default_cache_enabled{true};
|
|
GatewayUsbMode default_usb_mode{GatewayUsbMode::kDebug};
|
|
uint8_t default_usb_channel_index{0};
|
|
size_t command_queue_capacity{16};
|
|
};
|
|
|
|
struct GatewayDeviceInfo {
|
|
std::string serial_id;
|
|
std::string type;
|
|
std::string project;
|
|
std::string version;
|
|
size_t dali_gateway_count{0};
|
|
bool ble_enabled{false};
|
|
std::optional<WirelessInfo> wlan;
|
|
std::optional<EthernetInfo> eth;
|
|
};
|
|
|
|
class GatewaySettingsStore {
|
|
public:
|
|
GatewaySettingsStore();
|
|
~GatewaySettingsStore();
|
|
|
|
esp_err_t open();
|
|
void close();
|
|
|
|
bool getBleEnabled(bool default_value = false) const;
|
|
bool setBleEnabled(bool enabled);
|
|
|
|
bool getCacheEnabled(bool default_value = true) const;
|
|
bool setCacheEnabled(bool enabled);
|
|
|
|
std::optional<std::string> getWifiSsid() const;
|
|
std::optional<std::string> getWifiPassword() const;
|
|
bool setWifiCredentials(std::string_view ssid, std::string_view password);
|
|
bool clearWifiCredentials();
|
|
std::optional<EthernetConfig> getEthernetConfig() const;
|
|
bool setEthernetConfig(const EthernetConfig& config);
|
|
bool clearEthernetConfig();
|
|
|
|
GatewayUsbMode getUsbMode(GatewayUsbMode default_value) const;
|
|
bool setUsbMode(GatewayUsbMode mode);
|
|
uint8_t getUsbChannelIndex(uint8_t default_value) const;
|
|
bool setUsbChannelIndex(uint8_t channel_index);
|
|
|
|
std::string getDeviceName(std::string_view fallback) const;
|
|
bool setDeviceName(std::string_view name);
|
|
std::string getGatewayName(uint8_t gateway_id, std::string_view fallback) const;
|
|
bool setGatewayName(uint8_t gateway_id, std::string_view name);
|
|
uint8_t getChannelGatewayId(uint8_t channel_index, uint8_t fallback) const;
|
|
bool setChannelGatewayId(uint8_t channel_index, uint8_t gateway_id);
|
|
uint8_t getChannelGatewayGroup(uint8_t channel_index, uint8_t fallback) const;
|
|
bool setChannelGatewayGroup(uint8_t channel_index, uint8_t gateway_group);
|
|
std::optional<uint8_t> getApplicationControllerShortAddress(uint8_t channel_index,
|
|
uint8_t fallback) const;
|
|
bool setApplicationControllerShortAddress(uint8_t channel_index,
|
|
std::optional<uint8_t> short_address);
|
|
|
|
private:
|
|
std::optional<std::string> readString(std::string_view key) const;
|
|
bool writeString(std::string_view key, std::string_view value);
|
|
std::string makeGatewayNameKey(uint8_t gateway_id) const;
|
|
std::string makeChannelGatewayIdKey(uint8_t channel_index) const;
|
|
std::string makeChannelGatewayGroupKey(uint8_t channel_index) const;
|
|
std::string makeApplicationControllerShortAddressKey(uint8_t channel_index) const;
|
|
|
|
mutable nvs_handle_t handle_{0};
|
|
};
|
|
|
|
class GatewayRuntime {
|
|
public:
|
|
enum class CommandDropReason {
|
|
kNone,
|
|
kDuplicate,
|
|
kQueueFull,
|
|
};
|
|
|
|
enum class CommandPriority : uint8_t {
|
|
kControl = 0,
|
|
kNormal = 1,
|
|
kMaintenance = 2,
|
|
};
|
|
|
|
GatewayRuntime(BootProfile profile, GatewayRuntimeConfig config,
|
|
DaliDomainService* dali_domain);
|
|
~GatewayRuntime();
|
|
|
|
esp_err_t start();
|
|
|
|
static std::vector<uint8_t> checksum(std::vector<uint8_t> frame);
|
|
static bool hasValidChecksum(const std::vector<uint8_t>& frame);
|
|
static bool isGatewayCommandFrame(const std::vector<uint8_t>& frame);
|
|
static std::vector<uint8_t> buildNotificationFrame(const std::vector<uint8_t>& payload);
|
|
static CommandPriority classifyCommandPriority(const std::vector<uint8_t>& command);
|
|
|
|
bool enqueueCommand(std::vector<uint8_t> command,
|
|
CommandPriority priority = CommandPriority::kNormal);
|
|
std::optional<std::vector<uint8_t>> popNextCommand();
|
|
void completeCurrentCommand();
|
|
bool hasPendingQueryCommand(const std::vector<uint8_t>& command) const;
|
|
bool hasPendingControlCommand(uint8_t gateway_id) const;
|
|
bool shouldYieldMaintenance(uint8_t gateway_id) const;
|
|
bool hasActiveCommand(uint8_t gateway_id) const;
|
|
bool hasActiveQueryCommand(uint8_t gateway_id) const;
|
|
CommandDropReason lastEnqueueDropReason() const;
|
|
|
|
void setGatewayCount(size_t gateway_count);
|
|
void setWirelessInfo(WirelessInfo info);
|
|
bool clearWirelessInfo();
|
|
void setEthernetInfo(EthernetInfo info);
|
|
void clearEthernetInfo();
|
|
void clearEthernetIp();
|
|
std::optional<EthernetConfig> ethernetConfig() const;
|
|
bool setEthernetConfig(const EthernetConfig& config);
|
|
bool clearEthernetConfig();
|
|
GatewayUsbMode usbMode() const;
|
|
bool setUsbMode(GatewayUsbMode mode);
|
|
uint8_t usbChannelIndex() const;
|
|
bool setUsbChannelIndex(uint8_t channel_index);
|
|
void setCommandAddressResolver(std::function<uint8_t(uint8_t gw, uint8_t raw_addr)> resolver);
|
|
|
|
GatewayDeviceInfo deviceInfo() const;
|
|
bool bleEnabled() const;
|
|
bool setBleEnabled(bool enabled);
|
|
bool cacheEnabled() const;
|
|
bool setCacheEnabled(bool enabled);
|
|
uint8_t gatewayIdForChannel(uint8_t channel_index, uint8_t fallback) const;
|
|
bool setGatewayIdForChannel(uint8_t channel_index, uint8_t gateway_id);
|
|
uint8_t gatewayGroupForChannel(uint8_t channel_index, uint8_t fallback = 0) const;
|
|
bool setGatewayGroupForChannel(uint8_t channel_index, uint8_t gateway_group);
|
|
std::optional<uint8_t> applicationControllerShortAddressForChannel(uint8_t channel_index,
|
|
uint8_t fallback) const;
|
|
bool setApplicationControllerShortAddressForChannel(
|
|
uint8_t channel_index, std::optional<uint8_t> short_address);
|
|
std::string deviceName() const;
|
|
bool setDeviceName(std::string_view name);
|
|
std::string gatewayName(uint8_t gateway_id) const;
|
|
bool setGatewayName(uint8_t gateway_id, std::string_view name);
|
|
std::vector<uint8_t> serialNumberBytes() const;
|
|
std::string gatewaySerialHex(uint8_t gateway_id) const;
|
|
std::string bleMacHex() const;
|
|
std::string bleGatewayName(uint8_t gateway_id, std::string_view gateway_name) const;
|
|
std::string defaultBleGatewayName() const;
|
|
|
|
private:
|
|
bool isQueryCommand(const std::vector<uint8_t>& command) const;
|
|
size_t pendingCommandCountLocked() const;
|
|
std::deque<std::vector<uint8_t>>& queueForPriorityLocked(CommandPriority priority);
|
|
const std::deque<std::vector<uint8_t>>& queueForPriorityLocked(CommandPriority priority) const;
|
|
std::optional<std::string> queryCommandKey(const std::vector<uint8_t>& command) const;
|
|
std::string defaultDeviceName() const;
|
|
std::string defaultGatewayName(uint8_t gateway_id) const;
|
|
std::vector<uint8_t> serialBytes() const;
|
|
static std::string toHex(const std::vector<uint8_t>& bytes);
|
|
|
|
BootProfile profile_;
|
|
GatewayRuntimeConfig config_;
|
|
DaliDomainService* dali_domain_;
|
|
GatewaySettingsStore settings_;
|
|
std::optional<std::vector<uint8_t>> current_command_;
|
|
CommandPriority current_command_priority_{CommandPriority::kNormal};
|
|
std::deque<std::vector<uint8_t>> control_commands_;
|
|
std::deque<std::vector<uint8_t>> normal_commands_;
|
|
std::deque<std::vector<uint8_t>> maintenance_commands_;
|
|
mutable std::optional<std::string> device_name_;
|
|
mutable std::map<uint8_t, std::string> gateway_names_;
|
|
mutable std::map<uint8_t, uint8_t> channel_gateway_ids_;
|
|
mutable std::map<uint8_t, uint8_t> channel_gateway_groups_;
|
|
mutable std::map<uint8_t, std::optional<uint8_t>> application_controller_short_addresses_;
|
|
size_t gateway_count_{0};
|
|
bool ble_enabled_{false};
|
|
bool cache_enabled_{true};
|
|
GatewayUsbMode usb_mode_{GatewayUsbMode::kDebug};
|
|
uint8_t usb_channel_index_{0};
|
|
CommandDropReason last_enqueue_drop_reason_{CommandDropReason::kNone};
|
|
std::function<uint8_t(uint8_t gw, uint8_t raw_addr)> command_address_resolver_;
|
|
std::optional<WirelessInfo> wireless_info_;
|
|
std::optional<EthernetInfo> ethernet_info_;
|
|
SemaphoreHandle_t command_lock_{nullptr};
|
|
};
|
|
|
|
} // namespace gateway
|