kunlang_tbox/include/config/TboxConfigManager.h

159 lines
5.3 KiB
C
Raw Permalink Normal View History

2026-02-06 09:03:24 +08:00
#pragma once
#include <chrono>
#include <memory>
#include <mutex>
#include <string>
#include <string_view>
#include "TboxConfigClient.h"
#include "TboxConfigSemantic.h"
// =======================================================
// TboxConfigManager
// - 表驱动生成 getter / setter
// - 支持多项修改 + commit
// - 自动 version 检测 + reload
// =======================================================
class TboxConfigManager
{
public:
static TboxConfigManager& instance()
{
static TboxConfigManager inst;
return inst;
}
// ================= 初始化 =================
bool init(const std::string& server = "127.0.0.1", int port = 18080)
{
std::lock_guard<std::mutex> lock(mtx_);
client_ = std::make_unique<TboxConfigClient>(server, port);
bool ok = client_->fetch();
last_check_ = std::chrono::steady_clock::now();
return ok;
}
uint64_t version()
{
ensure();
return client_ ? client_->version() : 0;
}
// ===================================================
// 🔑 配置字段定义表(唯一维护点)
// type, Name, semantic, default
// ===================================================
#define TBOX_CONFIG_FIELDS(X) \
/* -------- 基础身份 -------- */ \
X(std::string, DeviceNo, tbox::semantic::DEVICE_NO, "KL001") \
X(std::string, VehicleId, tbox::semantic::VEHICLE_ID, "V010001") \
X(std::string, Vin, tbox::semantic::VIN, "") \
\
/* -------- 云平台 -------- */ \
X(std::string, PlatformIp, tbox::semantic::PLATFORM_IP, "") \
X(int, PlatformPort, tbox::semantic::PLATFORM_PORT, 0) \
X(std::string, MqttIp, tbox::semantic::MQTT_IP, "") \
X(int, MqttPort, tbox::semantic::MQTT_PORT, 1883) \
X(std::string, MqttUsername, tbox::semantic::MQTT_USERNAME, "") \
X(std::string, MqttPassword, tbox::semantic::MQTT_PASSWORD, "") \
\
/* -------- 驾驶舱 -------- */ \
X(std::string, CockpitMqttIp, tbox::semantic::COCKPIT_MQTT_IP, "") \
X(int, CockpitMqttPort, tbox::semantic::COCKPIT_MQTT_PORT, 1883) \
\
/* -------- 协议相关 -------- */ \
X(int, LoginSeq, tbox::semantic::LOGIN_SEQ, 1) \
X(std::string, LoginSeqDate, tbox::semantic::LOGIN_SEQ_DATE, "000000") \
X(int, HeartbeatInterval, tbox::semantic::HEARTBEAT_INTERVAL, 60)
// ================= Getter 自动生成 =================
#define GEN_GET(type, name, semantic, def) \
type get##name() { return getValue<type>(semantic, def); }
TBOX_CONFIG_FIELDS(GEN_GET)
#undef GEN_GET
// ================= Setter写入缓存不立即提交 =================
#define GEN_SET(type, name, semantic, def) \
void set##name(const type& v) { setValue<type>(semantic, v); }
TBOX_CONFIG_FIELDS(GEN_SET)
#undef GEN_SET
// ================= 统一提交 =================
bool commit()
{
ensure();
return client_->commitAndFetch();
}
private:
TboxConfigManager() = default;
~TboxConfigManager() = default;
TboxConfigManager(const TboxConfigManager&) = delete;
TboxConfigManager& operator=(const TboxConfigManager&) = delete;
// ================= 自动刷新机制 =================
void ensureFresh()
{
auto now = std::chrono::steady_clock::now();
if (now - last_check_ < check_interval_) return;
last_check_ = now;
// 简单粗暴,但稳定:直接 fetch
client_->fetch();
}
void ensure()
{
if (!client_)
{
client_ = std::make_unique<TboxConfigClient>();
client_->fetch();
}
ensureFresh();
}
// ================= 泛型访问 =================
template <typename T>
T getValue(std::string_view semantic, const T& def)
{
ensure();
if constexpr (std::is_same_v<T, int>)
{
auto v = client_->getInt(semantic);
return v ? *v : def;
}
else if constexpr (std::is_same_v<T, bool>)
{
auto v = client_->getBool(semantic);
return v ? *v : def;
}
else
{
auto v = client_->getString(semantic);
return v ? *v : def;
}
}
template <typename T>
void setValue(std::string_view semantic, const T& v)
{
ensure();
if constexpr (std::is_same_v<T, int>)
client_->setInt(semantic, v);
else if constexpr (std::is_same_v<T, bool>)
client_->setBool(semantic, v);
else
client_->setString(semantic, v);
}
private:
std::mutex mtx_;
std::unique_ptr<TboxConfigClient> client_;
std::chrono::steady_clock::time_point last_check_{};
const std::chrono::seconds check_interval_{30};
};