kunlang_tbox/include/config/config.h

241 lines
8.3 KiB
C++

#pragma once
#include <algorithm>
#include <cctype>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <vector>
#include "INIReader.h"
// ------------------------
// 线程安全配置管理单例类
// ------------------------
class ConfigManager
{
public:
// 获取单例
static ConfigManager& instance()
{
static ConfigManager inst;
return inst;
}
// 加载 INI 文件
bool load(const std::string& path)
{
std::lock_guard<std::mutex> lock(mtx);
file_path = path;
auto r = std::make_unique<INIReader>(path);
if (r->ParseError() < 0)
{
std::cerr << "Can't load config file: " << path << ", will create default on save\n";
reader.reset();
buildMapFromReader(); // 用 schema 默认值初始化
return false;
}
reader = std::move(r);
buildMapFromReader();
return true;
}
// ==================== Vehicle ====================
std::string getVin() { return getValue("vehicle", "vin", "LSV1234567890KUNL"); }
std::string getVehicleId() { return getValue("vehicle", "vehicle_id", "V010001"); }
void setVin(const std::string& vin) { setValue("vehicle", "vin", vin); }
void setVehicleId(const std::string& vid) { setValue("vehicle", "vehicle_id", vid); }
// ==================== Cloud ====================
std::string getDeviceNo() { return getValue("cloud", "device_no", "KL001"); }
std::string getPlatformIp() { return getValue("cloud", "platform_ip", "192.168.1.100"); }
int getPlatformPort() { return getInt("cloud", "platform_port", 8888); }
std::string getMqttIp() { return getValue("cloud", "mqtt_ip", "192.168.1.101"); }
int getMqttPort() { return getInt("cloud", "mqtt_port", 1883); }
// ✅ 新增
std::string getMqttUsername() { return getValue("cloud", "mqtt_username", ""); }
std::string getMqttPassword() { return getValue("cloud", "mqtt_password", ""); }
int getHeartbeatInterval() { return getInt("cloud", "heartbeat_interval", 60); }
void setDeviceNo(const std::string& v) { setValue("cloud", "device_no", v); }
void setPlatformIp(const std::string& v) { setValue("cloud", "platform_ip", v); }
void setPlatformPort(int v) { setValue("cloud", "platform_port", std::to_string(v)); }
void setMqttIp(const std::string& v) { setValue("cloud", "mqtt_ip", v); }
void setMqttPort(int v) { setValue("cloud", "mqtt_port", std::to_string(v)); }
// ✅ 新增
void setMqttUsername(const std::string& v) { setValue("cloud", "mqtt_username", v); }
void setMqttPassword(const std::string& v) { setValue("cloud", "mqtt_password", v); }
void setHeartbeatInterval(int interval) { setValue("cloud", "heartbeat_interval", std::to_string(interval)); }
// ==================== Cockpit ====================
std::string getCockpitId() { return getValue("cockpit", "cockpit_id", "C010001"); }
std::string getCockpitMqttIp() { return getValue("cockpit", "mqtt_ip", "192.168.1.110"); }
int getCockpitMqttPort() { return getInt("cockpit", "mqtt_port", 1883); }
void setCockpitId(const std::string& v) { setValue("cockpit", "cockpit_id", v); }
void setCockpitMqttIp(const std::string& v) { setValue("cockpit", "mqtt_ip", v); }
void setCockpitMqttPort(int v) { setValue("cockpit", "mqtt_port", std::to_string(v)); }
// ==================== Serial ====================
std::string getSerialDev() { return getValue("serial", "dev_name", "/dev/ttyUSB3"); }
int getSerialBaudrate() { return getInt("serial", "baudrate", 115200); }
void setSerialDev(const std::string& v) { setValue("serial", "dev_name", v); }
void setSerialBaudrate(int v) { setValue("serial", "baudrate", std::to_string(v)); }
// ==================== TBox ====================
int getLoginSeq() { return getInt("tbox", "login_seq", 1); }
std::string getLoginSeqDate() { return getValue("tbox", "login_seq_date", "000000"); }
void setLoginSeq(int v) { setValue("tbox", "login_seq", std::to_string(v)); }
void setLoginSeqDate(const std::string& v) { setValue("tbox", "login_seq_date", v); }
// 保存当前内存 map 到文件
bool save()
{
std::lock_guard<std::mutex> lock(mtx);
std::ofstream ofs(file_path);
if (!ofs.is_open()) return false;
for (const auto& [section, items] : schema)
{
ofs << "[" << section << "]\n";
for (const auto& item : items)
{
ofs << item.key << "=" << getValueUnlocked(section, item.key, item.default_value) << "\n";
}
ofs << "\n";
}
return true;
}
private:
ConfigManager() = default;
~ConfigManager() = default;
ConfigManager(const ConfigManager&) = delete;
ConfigManager& operator=(const ConfigManager&) = delete;
struct ConfigItem
{
std::string key;
std::string default_value;
};
const std::vector<std::pair<std::string, std::vector<ConfigItem>>> schema = {
{"vehicle",
{
{"vin", "LSV1234567890KUNL"},
{"vehicle_id", "V010001"},
}},
{"cloud",
{
{"device_no", "KL001"},
{"platform_ip", "192.168.1.100"},
{"platform_port", "8888"},
{"mqtt_ip", "192.168.1.101"},
{"mqtt_port", "1883"},
{"mqtt_username", ""}, // ✅ 新增
{"mqtt_password", ""}, // ✅ 新增
{"heartbeat_interval", "60"},
}},
{"cockpit",
{
{"cockpit_id", "C010001"},
{"mqtt_ip", "192.168.1.110"},
{"mqtt_port", "1883"},
}},
{"serial",
{
{"dev_name", "/dev/ttyUSB3"},
{"baudrate", "115200"},
}},
{"tbox",
{
{"login_seq", "1"},
{"login_seq_date", "000000"},
}},
};
std::unique_ptr<INIReader> reader;
std::string file_path;
std::map<std::string, std::map<std::string, std::string>> sections;
std::mutex mtx; // 多线程保护
// 根据 INIReader 初始化 map
void buildMapFromReader()
{
sections.clear();
for (const auto& [section, items] : schema)
{
for (const auto& item : items)
{
if (reader) { sections[section][item.key] = reader->Get(section, item.key, item.default_value); }
else
{
sections[section][item.key] = item.default_value;
}
}
}
}
int getInt(const std::string& section, const std::string& key, int def)
{
std::string v = getValue(section, key, std::to_string(def));
try
{
size_t idx = 0;
int result = std::stoi(v, &idx);
if (idx != v.size()) throw std::invalid_argument("trailing chars");
return result;
}
catch (...)
{
// 自动纠错 + 修复配置
setValue(section, key, std::to_string(def));
return def;
}
}
bool getBool(const std::string& section, const std::string& key, bool def)
{
std::string v = getValue(section, key, def ? "1" : "0");
std::string lv = v;
std::transform(lv.begin(), lv.end(), lv.begin(), [](unsigned char c) { return std::tolower(c); });
if (lv == "1" || lv == "true" || lv == "yes") return true;
if (lv == "0" || lv == "false" || lv == "no") return false;
setValue(section, key, def ? "1" : "0");
return def;
}
std::string getValueUnlocked(const std::string& section, const std::string& key, const std::string& def)
{
auto& sec = sections[section];
auto it = sec.find(key);
if (it != sec.end()) return it->second;
sec[key] = def;
return def;
}
// 从 map 获取值
std::string getValue(const std::string& section, const std::string& key, const std::string& def)
{
std::lock_guard<std::mutex> lock(mtx);
return getValueUnlocked(section, key, def);
}
// 写入 map
void setValue(const std::string& section, const std::string& key, const std::string& value)
{
std::lock_guard<std::mutex> lock(mtx);
sections[section][key] = value;
}
};