feat: implement device name handling and update gateway name features
Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -49,10 +49,14 @@ DALI bus activity from another master until the bus has been idle. Group and
|
|||||||
broadcast targets are never queried for refresh.
|
broadcast targets are never queried for refresh.
|
||||||
|
|
||||||
Gateway feature opcode `0x06` keeps the Lua-compatible low-byte feature bits,
|
Gateway feature opcode `0x06` keeps the Lua-compatible low-byte feature bits,
|
||||||
advertises cache support with bit `0x40`, and advertises the native C++ gateway
|
advertises cache support with bit `0x40`, advertises gateway/channel name
|
||||||
type with bit `0x0100`. Gateway opcode `0x39` returns cache summary and target
|
support with bit `0x80`, and advertises the native C++ gateway type with bit
|
||||||
snapshots so frontend clients can read cached state without issuing live DALI
|
`0x0100`. Gateway opcode `0x05` reads and writes user-facing gateway identity:
|
||||||
queries on supported gateways.
|
operation `0x00` reads the channel name, `0x01` writes the channel name,
|
||||||
|
`0x02` reads the physical gateway device name, and `0x03` writes the physical
|
||||||
|
gateway device name. Empty writes reset to the default name. Gateway opcode
|
||||||
|
`0x39` returns cache summary and target snapshots so frontend clients can read
|
||||||
|
cached state without issuing live DALI queries on supported gateways.
|
||||||
|
|
||||||
Gateway opcode `0x09` with address/data `0x00/0x00` is a chip-level channel-id
|
Gateway opcode `0x09` with address/data `0x00/0x00` is a chip-level channel-id
|
||||||
report. It returns the enabled DALI channel ids so clients do not need to probe
|
report. It returns the enabled DALI channel ids so clients do not need to probe
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifndef CONFIG_GATEWAY_CHANNEL_COUNT
|
#ifndef CONFIG_GATEWAY_CHANNEL_COUNT
|
||||||
#define CONFIG_GATEWAY_CHANNEL_COUNT 2
|
#define CONFIG_GATEWAY_CHANNEL_COUNT 2
|
||||||
@@ -1144,9 +1145,17 @@ extern "C" void app_main(void) {
|
|||||||
static_cast<uint32_t>(CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE);
|
static_cast<uint32_t>(CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE);
|
||||||
bridge_config.knx_task_priority =
|
bridge_config.knx_task_priority =
|
||||||
static_cast<UBaseType_t>(CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY);
|
static_cast<UBaseType_t>(CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY);
|
||||||
|
bridge_config.gateway_device_name_provider = []() {
|
||||||
|
return s_runtime == nullptr ? std::string() : s_runtime->deviceName();
|
||||||
|
};
|
||||||
s_bridge = std::make_unique<gateway::GatewayBridgeService>(*s_dali_domain, *s_cache,
|
s_bridge = std::make_unique<gateway::GatewayBridgeService>(*s_dali_domain, *s_cache,
|
||||||
bridge_config);
|
bridge_config);
|
||||||
s_controller->setBridgeService(s_bridge.get());
|
s_controller->setBridgeService(s_bridge.get());
|
||||||
|
s_controller->addGatewayNameSink([](uint8_t gateway_id) {
|
||||||
|
if (s_bridge != nullptr) {
|
||||||
|
s_bridge->handleGatewayNameChanged(gateway_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profile.enable_wifi || profile.enable_eth) {
|
if (profile.enable_wifi || profile.enable_eth) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace gateway {
|
|||||||
struct GatewayBacnetServerConfig {
|
struct GatewayBacnetServerConfig {
|
||||||
uint32_t device_instance{4194303};
|
uint32_t device_instance{4194303};
|
||||||
std::string device_name{"DALI Gateway"};
|
std::string device_name{"DALI Gateway"};
|
||||||
|
std::string channel_name;
|
||||||
std::string local_address;
|
std::string local_address;
|
||||||
uint16_t udp_port{47808};
|
uint16_t udp_port{47808};
|
||||||
uint32_t task_stack_size{8192};
|
uint32_t task_stack_size{8192};
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ bool gateway_bacnet_stack_start(
|
|||||||
|
|
||||||
void gateway_bacnet_stack_cleanup(void);
|
void gateway_bacnet_stack_cleanup(void);
|
||||||
|
|
||||||
|
bool gateway_bacnet_stack_set_device_name(const char* device_name);
|
||||||
|
|
||||||
bool gateway_bacnet_stack_upsert_object(
|
bool gateway_bacnet_stack_upsert_object(
|
||||||
gateway_bacnet_object_kind_t object_kind,
|
gateway_bacnet_object_kind_t object_kind,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
|
|||||||
@@ -251,6 +251,11 @@ esp_err_t GatewayBacnetServer::registerChannel(
|
|||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GatewayBacnetServerConfig effective_config = config;
|
||||||
|
if (effective_config.device_name.empty()) {
|
||||||
|
effective_config.device_name = "DALI Gateway";
|
||||||
|
}
|
||||||
|
|
||||||
bindings.erase(std::remove_if(bindings.begin(), bindings.end(), [](const auto& binding) {
|
bindings.erase(std::remove_if(bindings.begin(), bindings.end(), [](const auto& binding) {
|
||||||
return !IsSupportedObjectType(binding.object_type) ||
|
return !IsSupportedObjectType(binding.object_type) ||
|
||||||
binding.object_instance > kMaxBacnetInstance;
|
binding.object_instance > kMaxBacnetInstance;
|
||||||
@@ -258,7 +263,7 @@ esp_err_t GatewayBacnetServer::registerChannel(
|
|||||||
bindings.end());
|
bindings.end());
|
||||||
|
|
||||||
LockGuard guard(lock_);
|
LockGuard guard(lock_);
|
||||||
if (started_ && !configCompatible(config)) {
|
if (started_ && !configCompatible(effective_config)) {
|
||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +273,15 @@ esp_err_t GatewayBacnetServer::registerChannel(
|
|||||||
if (bindings.empty() && !started_ && channel == channels_.end()) {
|
if (bindings.empty() && !started_ && channel == channels_.end()) {
|
||||||
return ESP_ERR_NOT_FOUND;
|
return ESP_ERR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
ChannelRegistration registration{gateway_id, config, std::move(bindings),
|
if (started_ && active_config_.device_name != effective_config.device_name) {
|
||||||
|
if (!gateway_bacnet_stack_set_device_name(effective_config.device_name.c_str())) {
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
active_config_.device_name = effective_config.device_name;
|
||||||
|
gateway_bacnet_stack_send_i_am();
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelRegistration registration{gateway_id, effective_config, std::move(bindings),
|
||||||
std::move(write_callback), std::move(read_callback)};
|
std::move(write_callback), std::move(read_callback)};
|
||||||
if (channel == channels_.end()) {
|
if (channel == channels_.end()) {
|
||||||
channels_.push_back(std::move(registration));
|
channels_.push_back(std::move(registration));
|
||||||
@@ -276,7 +289,7 @@ esp_err_t GatewayBacnetServer::registerChannel(
|
|||||||
*channel = std::move(registration);
|
*channel = std::move(registration);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t err = startStackLocked(config);
|
esp_err_t err = startStackLocked(effective_config);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -341,9 +354,16 @@ esp_err_t GatewayBacnetServer::rebuildObjectsLocked() {
|
|||||||
used_objects.insert(key);
|
used_objects.insert(key);
|
||||||
|
|
||||||
const std::string name = ObjectName(binding);
|
const std::string name = ObjectName(binding);
|
||||||
|
std::string description = channel.config.channel_name;
|
||||||
|
if (!binding.model_id.empty()) {
|
||||||
|
if (!description.empty()) {
|
||||||
|
description += " / ";
|
||||||
|
}
|
||||||
|
description += binding.model_id;
|
||||||
|
}
|
||||||
if (!gateway_bacnet_stack_upsert_object(ToBacnetKind(binding.object_type),
|
if (!gateway_bacnet_stack_upsert_object(ToBacnetKind(binding.object_type),
|
||||||
binding.object_instance, name.c_str(),
|
binding.object_instance, name.c_str(),
|
||||||
binding.model_id.c_str(),
|
description.c_str(),
|
||||||
binding.out_of_service,
|
binding.out_of_service,
|
||||||
binding.reliability)) {
|
binding.reliability)) {
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
|
|||||||
@@ -410,6 +410,14 @@ void gateway_bacnet_stack_cleanup(void)
|
|||||||
Write_Callback_Context = NULL;
|
Write_Callback_Context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool gateway_bacnet_stack_set_device_name(const char* device_name)
|
||||||
|
{
|
||||||
|
if (!device_name || device_name[0] == '\0') {
|
||||||
|
device_name = "DALI Gateway";
|
||||||
|
}
|
||||||
|
return Device_Object_Name_ANSI_Init(device_name);
|
||||||
|
}
|
||||||
|
|
||||||
bool gateway_bacnet_stack_upsert_object(
|
bool gateway_bacnet_stack_upsert_object(
|
||||||
gateway_bacnet_object_kind_t object_kind,
|
gateway_bacnet_object_kind_t object_kind,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -41,6 +42,7 @@ struct GatewayBridgeServiceConfig {
|
|||||||
uint32_t knx_task_stack_size{12288};
|
uint32_t knx_task_stack_size{12288};
|
||||||
UBaseType_t knx_task_priority{5};
|
UBaseType_t knx_task_priority{5};
|
||||||
std::optional<GatewayKnxConfig> default_knx_config;
|
std::optional<GatewayKnxConfig> default_knx_config;
|
||||||
|
std::function<std::string()> gateway_device_name_provider;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GatewayBridgeHttpResponse {
|
struct GatewayBridgeHttpResponse {
|
||||||
@@ -62,6 +64,7 @@ class GatewayBridgeService {
|
|||||||
GatewayBridgeHttpResponse handlePost(const std::string& action, int gateway_id,
|
GatewayBridgeHttpResponse handlePost(const std::string& action, int gateway_id,
|
||||||
const std::string& body);
|
const std::string& body);
|
||||||
std::string handleTransportRequest(uint8_t gateway_id, std::string_view request);
|
std::string handleTransportRequest(uint8_t gateway_id, std::string_view request);
|
||||||
|
void handleGatewayNameChanged(uint8_t gateway_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ChannelRuntime;
|
struct ChannelRuntime;
|
||||||
|
|||||||
@@ -2100,8 +2100,17 @@ struct GatewayBridgeService::ChannelRuntime {
|
|||||||
#if defined(CONFIG_GATEWAY_BACNET_BRIDGE_SUPPORTED)
|
#if defined(CONFIG_GATEWAY_BACNET_BRIDGE_SUPPORTED)
|
||||||
GatewayBacnetServerConfig bacnetServerConfigLocked() const {
|
GatewayBacnetServerConfig bacnetServerConfigLocked() const {
|
||||||
GatewayBacnetServerConfig config;
|
GatewayBacnetServerConfig config;
|
||||||
config.device_name = channel.name.empty() ? "DALI Gateway " + std::to_string(channel.gateway_id)
|
config.channel_name = channel.name.empty()
|
||||||
|
? "Gateway " + std::to_string(channel.gateway_id)
|
||||||
: channel.name;
|
: channel.name;
|
||||||
|
if (service_config.gateway_device_name_provider) {
|
||||||
|
config.device_name = service_config.gateway_device_name_provider();
|
||||||
|
}
|
||||||
|
if (config.device_name.empty()) {
|
||||||
|
config.device_name = channel.name.empty()
|
||||||
|
? "DALI Gateway " + std::to_string(channel.gateway_id)
|
||||||
|
: channel.name;
|
||||||
|
}
|
||||||
config.task_stack_size = service_config.bacnet_task_stack_size;
|
config.task_stack_size = service_config.bacnet_task_stack_size;
|
||||||
config.task_priority = service_config.bacnet_task_priority;
|
config.task_priority = service_config.bacnet_task_priority;
|
||||||
if (bacnet_server_config.has_value()) {
|
if (bacnet_server_config.has_value()) {
|
||||||
@@ -2320,6 +2329,21 @@ struct GatewayBridgeService::ChannelRuntime {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void updateChannelInfo(DaliChannelInfo next_channel) {
|
||||||
|
LockGuard guard(lock);
|
||||||
|
channel = std::move(next_channel);
|
||||||
|
#if defined(CONFIG_GATEWAY_BACNET_BRIDGE_SUPPORTED)
|
||||||
|
if (bacnet_started) {
|
||||||
|
const esp_err_t err = syncBacnetServerLocked();
|
||||||
|
if (err != ESP_OK && err != ESP_ERR_NOT_FOUND) {
|
||||||
|
ESP_LOGW(kTag, "gateway=%u BACnet name refresh failed: %s", channel.gateway_id,
|
||||||
|
esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
bacnet_started = err == ESP_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t startKnx(std::set<uint16_t>* used_ports = nullptr,
|
esp_err_t startKnx(std::set<uint16_t>* used_ports = nullptr,
|
||||||
std::set<int>* used_uarts = nullptr) {
|
std::set<int>* used_uarts = nullptr) {
|
||||||
LockGuard guard(lock);
|
LockGuard guard(lock);
|
||||||
@@ -4379,6 +4403,24 @@ const GatewayBridgeService::ChannelRuntime* GatewayBridgeService::findRuntime(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GatewayBridgeService::handleGatewayNameChanged(uint8_t gateway_id) {
|
||||||
|
const auto channels = dali_domain_.channelInfo();
|
||||||
|
for (const auto& runtime : runtimes_) {
|
||||||
|
if (gateway_id != 0xff && runtime->channel.gateway_id != gateway_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const uint8_t runtime_gateway = runtime->channel.gateway_id;
|
||||||
|
const auto channel =
|
||||||
|
std::find_if(channels.begin(), channels.end(), [runtime_gateway](
|
||||||
|
const DaliChannelInfo& item) {
|
||||||
|
return item.gateway_id == runtime_gateway;
|
||||||
|
});
|
||||||
|
if (channel != channels.end()) {
|
||||||
|
runtime->updateChannelInfo(*channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GatewayBridgeService::ChannelRuntime* GatewayBridgeService::selectKnxEndpointRuntime() {
|
GatewayBridgeService::ChannelRuntime* GatewayBridgeService::selectKnxEndpointRuntime() {
|
||||||
auto eligible = [](ChannelRuntime* runtime) {
|
auto eligible = [](ChannelRuntime* runtime) {
|
||||||
if (runtime == nullptr) {
|
if (runtime == nullptr) {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ constexpr uint8_t kDali103QueryResponseOpcode = 0x63;
|
|||||||
constexpr uint8_t kDali103NoResponseOpcode = 0x64;
|
constexpr uint8_t kDali103NoResponseOpcode = 0x64;
|
||||||
constexpr uint8_t kDali103RawFrameOpcode = 0x65;
|
constexpr uint8_t kDali103RawFrameOpcode = 0x65;
|
||||||
constexpr uint16_t kGatewayFeatureCache = 0x0040;
|
constexpr uint16_t kGatewayFeatureCache = 0x0040;
|
||||||
|
constexpr uint16_t kGatewayFeatureNames = 0x0080;
|
||||||
constexpr uint16_t kGatewayFeatureNativeCpp = 0x0100;
|
constexpr uint16_t kGatewayFeatureNativeCpp = 0x0100;
|
||||||
constexpr uint8_t kGatewayCacheOpcode = 0x39;
|
constexpr uint8_t kGatewayCacheOpcode = 0x39;
|
||||||
constexpr uint8_t kGatewayCacheProtocolVersion = 1;
|
constexpr uint8_t kGatewayCacheProtocolVersion = 1;
|
||||||
@@ -252,6 +253,15 @@ void AppendPaddedName(std::vector<uint8_t>& out, std::string_view name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppendGatewayNameResponse(std::vector<uint8_t>& out, std::string_view name) {
|
||||||
|
const auto normalized = NormalizeName(name);
|
||||||
|
out.push_back(static_cast<uint8_t>(normalized.size()));
|
||||||
|
AppendStringBytes(out, normalized);
|
||||||
|
while (out.size() < 4 + kMaxNameBytes) {
|
||||||
|
out.push_back(0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* PhyKindToString(DaliPhyKind phy_kind) {
|
const char* PhyKindToString(DaliPhyKind phy_kind) {
|
||||||
switch (phy_kind) {
|
switch (phy_kind) {
|
||||||
case DaliPhyKind::kNativeHardware:
|
case DaliPhyKind::kNativeHardware:
|
||||||
@@ -865,6 +875,7 @@ void GatewayController::dispatchCommand(const std::vector<uint8_t>& command) {
|
|||||||
if (config_.cache_supported) {
|
if (config_.cache_supported) {
|
||||||
feature |= kGatewayFeatureCache;
|
feature |= kGatewayFeatureCache;
|
||||||
}
|
}
|
||||||
|
feature |= kGatewayFeatureNames;
|
||||||
std::vector<uint8_t> payload{0x03, gateway_id};
|
std::vector<uint8_t> payload{0x03, gateway_id};
|
||||||
AppendFeatureBits(payload, feature);
|
AppendFeatureBits(payload, feature);
|
||||||
publishPayload(gateway_id, payload);
|
publishPayload(gateway_id, payload);
|
||||||
@@ -1624,13 +1635,19 @@ void GatewayController::handleGatewayNameCommand(uint8_t gateway_id,
|
|||||||
const uint8_t op = command[4];
|
const uint8_t op = command[4];
|
||||||
if (op == 0x00) {
|
if (op == 0x00) {
|
||||||
const auto name = gatewayName(gateway_id);
|
const auto name = gatewayName(gateway_id);
|
||||||
std::vector<uint8_t> payload{0x05, gateway_id, op,
|
std::vector<uint8_t> payload{0x05, gateway_id, op};
|
||||||
static_cast<uint8_t>(std::min(name.size(), kMaxNameBytes))};
|
AppendGatewayNameResponse(payload, name);
|
||||||
AppendStringBytes(payload, NormalizeName(name));
|
|
||||||
publishPayload(gateway_id, payload);
|
publishPayload(gateway_id, payload);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (op != 0x01) {
|
if (op == 0x02) {
|
||||||
|
const auto name = runtime_.deviceName();
|
||||||
|
std::vector<uint8_t> payload{0x05, gateway_id, op};
|
||||||
|
AppendGatewayNameResponse(payload, name);
|
||||||
|
publishPayload(gateway_id, payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (op != 0x01 && op != 0x03) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1647,10 +1664,12 @@ void GatewayController::handleGatewayNameCommand(uint8_t gateway_id,
|
|||||||
for (size_t index = 0; index < actual_len; ++index) {
|
for (size_t index = 0; index < actual_len; ++index) {
|
||||||
name.push_back(static_cast<char>(command[6 + index]));
|
name.push_back(static_cast<char>(command[6 + index]));
|
||||||
}
|
}
|
||||||
if (runtime_.setGatewayName(gateway_id, name)) {
|
const bool saved = op == 0x03 ? runtime_.setDeviceName(name)
|
||||||
|
: runtime_.setGatewayName(gateway_id, name);
|
||||||
|
if (saved) {
|
||||||
refreshRuntimeGatewayNames();
|
refreshRuntimeGatewayNames();
|
||||||
for (const auto& sink : gateway_name_sinks_) {
|
for (const auto& sink : gateway_name_sinks_) {
|
||||||
sink(gateway_id);
|
sink(op == 0x03 ? 0xff : gateway_id);
|
||||||
}
|
}
|
||||||
publishPayload(gateway_id, {0x05, gateway_id, op, 0x01});
|
publishPayload(gateway_id, {0x05, gateway_id, op, 0x01});
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ class GatewaySettingsStore {
|
|||||||
bool setWifiCredentials(std::string_view ssid, std::string_view password);
|
bool setWifiCredentials(std::string_view ssid, std::string_view password);
|
||||||
bool clearWifiCredentials();
|
bool clearWifiCredentials();
|
||||||
|
|
||||||
|
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;
|
std::string getGatewayName(uint8_t gateway_id, std::string_view fallback) const;
|
||||||
bool setGatewayName(uint8_t gateway_id, std::string_view name);
|
bool setGatewayName(uint8_t gateway_id, std::string_view name);
|
||||||
uint8_t getChannelGatewayId(uint8_t channel_index, uint8_t fallback) const;
|
uint8_t getChannelGatewayId(uint8_t channel_index, uint8_t fallback) const;
|
||||||
@@ -140,6 +142,8 @@ class GatewayRuntime {
|
|||||||
bool setCacheEnabled(bool enabled);
|
bool setCacheEnabled(bool enabled);
|
||||||
uint8_t gatewayIdForChannel(uint8_t channel_index, uint8_t fallback) const;
|
uint8_t gatewayIdForChannel(uint8_t channel_index, uint8_t fallback) const;
|
||||||
bool setGatewayIdForChannel(uint8_t channel_index, uint8_t gateway_id);
|
bool setGatewayIdForChannel(uint8_t channel_index, uint8_t gateway_id);
|
||||||
|
std::string deviceName() const;
|
||||||
|
bool setDeviceName(std::string_view name);
|
||||||
std::string gatewayName(uint8_t gateway_id) const;
|
std::string gatewayName(uint8_t gateway_id) const;
|
||||||
bool setGatewayName(uint8_t gateway_id, std::string_view name);
|
bool setGatewayName(uint8_t gateway_id, std::string_view name);
|
||||||
std::vector<uint8_t> serialNumberBytes() const;
|
std::vector<uint8_t> serialNumberBytes() const;
|
||||||
@@ -154,6 +158,7 @@ class GatewayRuntime {
|
|||||||
std::deque<std::vector<uint8_t>>& queueForPriorityLocked(CommandPriority priority);
|
std::deque<std::vector<uint8_t>>& queueForPriorityLocked(CommandPriority priority);
|
||||||
const std::deque<std::vector<uint8_t>>& queueForPriorityLocked(CommandPriority priority) const;
|
const std::deque<std::vector<uint8_t>>& queueForPriorityLocked(CommandPriority priority) const;
|
||||||
std::optional<std::string> queryCommandKey(const std::vector<uint8_t>& command) 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::string defaultGatewayName(uint8_t gateway_id) const;
|
||||||
std::vector<uint8_t> serialBytes() const;
|
std::vector<uint8_t> serialBytes() const;
|
||||||
static std::string toHex(const std::vector<uint8_t>& bytes);
|
static std::string toHex(const std::vector<uint8_t>& bytes);
|
||||||
@@ -167,6 +172,7 @@ class GatewayRuntime {
|
|||||||
std::deque<std::vector<uint8_t>> control_commands_;
|
std::deque<std::vector<uint8_t>> control_commands_;
|
||||||
std::deque<std::vector<uint8_t>> normal_commands_;
|
std::deque<std::vector<uint8_t>> normal_commands_;
|
||||||
std::deque<std::vector<uint8_t>> maintenance_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, std::string> gateway_names_;
|
||||||
mutable std::map<uint8_t, uint8_t> channel_gateway_ids_;
|
mutable std::map<uint8_t, uint8_t> channel_gateway_ids_;
|
||||||
size_t gateway_count_{0};
|
size_t gateway_count_{0};
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ constexpr const char* kTag = "gateway_runtime";
|
|||||||
constexpr const char* kNamespace = "gateway_rt";
|
constexpr const char* kNamespace = "gateway_rt";
|
||||||
constexpr const char* kBleEnabledKey = "ble_enabled";
|
constexpr const char* kBleEnabledKey = "ble_enabled";
|
||||||
constexpr const char* kCacheEnabledKey = "cache_enabled";
|
constexpr const char* kCacheEnabledKey = "cache_enabled";
|
||||||
|
constexpr const char* kDeviceNameKey = "device_name";
|
||||||
constexpr const char* kWifiSsidKey = "wifi_ssid";
|
constexpr const char* kWifiSsidKey = "wifi_ssid";
|
||||||
constexpr const char* kWifiPasswordKey = "wifi_passwd";
|
constexpr const char* kWifiPasswordKey = "wifi_passwd";
|
||||||
constexpr size_t kMaxGatewayNameBytes = 32;
|
constexpr size_t kMaxGatewayNameBytes = 32;
|
||||||
@@ -174,6 +175,19 @@ bool GatewaySettingsStore::clearWifiCredentials() {
|
|||||||
return ssid_err == ESP_OK && password_err == ESP_OK && nvs_commit(handle_) == ESP_OK;
|
return ssid_err == ESP_OK && password_err == ESP_OK && nvs_commit(handle_) == ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GatewaySettingsStore::getDeviceName(std::string_view fallback) const {
|
||||||
|
const auto value = readString(kDeviceNameKey);
|
||||||
|
if (!value.has_value() || value->empty()) {
|
||||||
|
return std::string(fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GatewaySettingsStore::setDeviceName(std::string_view name) {
|
||||||
|
return writeString(kDeviceNameKey, name);
|
||||||
|
}
|
||||||
|
|
||||||
std::string GatewaySettingsStore::getGatewayName(uint8_t gateway_id,
|
std::string GatewaySettingsStore::getGatewayName(uint8_t gateway_id,
|
||||||
std::string_view fallback) const {
|
std::string_view fallback) const {
|
||||||
const auto value = readString(makeGatewayNameKey(gateway_id));
|
const auto value = readString(makeGatewayNameKey(gateway_id));
|
||||||
@@ -584,6 +598,41 @@ bool GatewayRuntime::setGatewayIdForChannel(uint8_t channel_index, uint8_t gatew
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GatewayRuntime::deviceName() const {
|
||||||
|
LockGuard guard(command_lock_);
|
||||||
|
if (device_name_.has_value()) {
|
||||||
|
return device_name_.value();
|
||||||
|
}
|
||||||
|
auto name = settings_.getDeviceName(defaultDeviceName());
|
||||||
|
if (name.size() > kMaxGatewayNameBytes) {
|
||||||
|
name.resize(kMaxGatewayNameBytes);
|
||||||
|
}
|
||||||
|
device_name_ = name;
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GatewayRuntime::setDeviceName(std::string_view name) {
|
||||||
|
std::string normalized(name);
|
||||||
|
if (normalized.size() > kMaxGatewayNameBytes) {
|
||||||
|
normalized.resize(kMaxGatewayNameBytes);
|
||||||
|
}
|
||||||
|
if (normalized.empty()) {
|
||||||
|
normalized = defaultDeviceName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceName() == normalized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!settings_.setDeviceName(normalized)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LockGuard guard(command_lock_);
|
||||||
|
device_name_ = normalized;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GatewayRuntime::gatewayName(uint8_t gateway_id) const {
|
std::string GatewayRuntime::gatewayName(uint8_t gateway_id) const {
|
||||||
LockGuard guard(command_lock_);
|
LockGuard guard(command_lock_);
|
||||||
const auto cached = gateway_names_.find(gateway_id);
|
const auto cached = gateway_names_.find(gateway_id);
|
||||||
@@ -640,11 +689,13 @@ std::string GatewayRuntime::bleMacHex() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GatewayRuntime::bleGatewayName(uint8_t gateway_id, std::string_view gateway_name) const {
|
std::string GatewayRuntime::bleGatewayName(uint8_t gateway_id, std::string_view gateway_name) const {
|
||||||
std::string normalized(gateway_name);
|
std::string normalized(deviceName());
|
||||||
if (normalized.size() > kMaxGatewayNameBytes) {
|
if (normalized.size() > kMaxGatewayNameBytes) {
|
||||||
normalized.resize(kMaxGatewayNameBytes);
|
normalized.resize(kMaxGatewayNameBytes);
|
||||||
}
|
}
|
||||||
if (!normalized.empty() && normalized != defaultGatewayName(gateway_id)) {
|
(void)gateway_id;
|
||||||
|
(void)gateway_name;
|
||||||
|
if (!normalized.empty() && normalized != defaultDeviceName()) {
|
||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
return defaultBleGatewayName();
|
return defaultBleGatewayName();
|
||||||
@@ -718,7 +769,7 @@ std::optional<std::string> GatewayRuntime::queryCommandKey(
|
|||||||
return std::string(key);
|
return std::string(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GatewayRuntime::defaultGatewayName(uint8_t) const {
|
std::string GatewayRuntime::defaultDeviceName() const {
|
||||||
const std::string serial_hex = bleMacHex();
|
const std::string serial_hex = bleMacHex();
|
||||||
if (serial_hex.size() <= 6) {
|
if (serial_hex.size() <= 6) {
|
||||||
return "DALIGW_" + serial_hex;
|
return "DALIGW_" + serial_hex;
|
||||||
@@ -726,6 +777,10 @@ std::string GatewayRuntime::defaultGatewayName(uint8_t) const {
|
|||||||
return "DALIGW_" + serial_hex.substr(serial_hex.size() - 6);
|
return "DALIGW_" + serial_hex.substr(serial_hex.size() - 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GatewayRuntime::defaultGatewayName(uint8_t gateway_id) const {
|
||||||
|
return "Channel " + std::to_string(gateway_id);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> GatewayRuntime::serialBytes() const {
|
std::vector<uint8_t> GatewayRuntime::serialBytes() const {
|
||||||
std::vector<uint8_t> bytes;
|
std::vector<uint8_t> bytes;
|
||||||
const std::string& serial = config_.serial_id;
|
const std::string& serial = config_.serial_id;
|
||||||
|
|||||||
Reference in New Issue
Block a user