#pragma once #include #include #include #include #include #include #include #include #include #include #include "INIReader.h" // ------------------------ // 线程安全配置管理单例类 // ------------------------ class ConfigManager { public: // 获取单例 static ConfigManager& instance() { static ConfigManager inst; return inst; } // 加载 INI 文件 bool load(const std::string& path) { std::lock_guard lock(mtx); file_path = path; auto r = std::make_unique(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 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>> 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 reader; std::string file_path; std::map> 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 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 lock(mtx); sections[section][key] = value; } };