// config_manager.cc (修改后) #include "config_manager.h" #include ConfigManager &ConfigManager::getInstance() { static ConfigManager instance; return instance; } json ConfigManager::createDefaultConfig() { // --- 修改: 添加新的 video_service 和 video_streams 默认值 --- return json{ {"device_id", "default-edge-proxy-01"}, {"config_base_path", "/app/config/"}, {"mqtt_broker", "tcp://localhost:1883"}, {"mqtt_client_id_prefix", "edge-proxy-"}, {"data_storage_db_path", "edge_proxy_data.db"}, {"data_cache_db_path", "edge_data_cache.db"}, {"tcp_server_ports", {12345}}, {"web_server_port", 8080}, {"log_level", "debug"}, {"alarm_rules_path", "alarms.json"}, {"piper_executable_path", "/usr/bin/piper"}, {"piper_model_path", "/app/models/model.onnx"}, // --- 新增: 视频服务配置 --- {"video_config_path", "/app/config/video_config.json"}, }; } bool ConfigManager::save_unlocked() { std::ofstream ofs(m_configFilePath); if (!ofs.is_open()) { spdlog::error("Failed to open config file '{}' for writing.", m_configFilePath); return false; } try { ofs << m_config_json.dump(4); return true; } catch (const json::exception &e) { spdlog::error("Failed to serialize config. Error: {}", e.what()); return false; } } bool ConfigManager::load(const std::string &configFilePath) { std::unique_lock lock(m_mutex); m_configFilePath = configFilePath; std::ifstream ifs(m_configFilePath); if (!ifs.is_open()) { spdlog::warn("Config file '{}' not found. Creating with default values.", m_configFilePath); m_config_json = createDefaultConfig(); if (save_unlocked()) { spdlog::info("Default config file created at '{}'.", m_configFilePath); return true; } else { spdlog::error("Failed to create default config file."); return false; } } try { ifs >> m_config_json; // **重要**:合并默认值。 json defaults = createDefaultConfig(); defaults.merge_patch( m_config_json); // <-- 关键: m_config_json 会覆盖 defaults m_config_json = defaults; // 将合并后的结果存回 spdlog::info("Successfully loaded config from '{}'. Device ID: {}", m_configFilePath, m_config_json.value("device_id", "N/A")); if (save_unlocked()) { spdlog::debug("Config file updated with new default keys if any."); } return true; } catch (const json::exception &e) { spdlog::error( "Failed to parse config file '{}'. Error: {}. Using default values.", m_configFilePath, e.what()); m_config_json = createDefaultConfig(); return false; } } // ... (save, getDeviceID, ... getPiperModelPath 保持不变) ... bool ConfigManager::save() { std::unique_lock lock(m_mutex); return save_unlocked(); } std::string ConfigManager::getDeviceID() { return get("device_id", "default-edge-proxy-01"); } std::string ConfigManager::getConfigBasePath() { return get("config_base_path", "/app/config/"); } std::string ConfigManager::getMqttBroker() { return get("mqtt_broker", "tcp://localhost:1883"); } std::string ConfigManager::getMqttClientID() { return get("mqtt_client_id_prefix", "edge-proxy-") + getDeviceID(); } std::string ConfigManager::getDataStorageDbPath() { return getConfigBasePath() + get("data_storage_db_path", "edge_proxy_data.db"); } std::string ConfigManager::getDataCacheDbPath() { return getConfigBasePath() + get("data_cache_db_path", "edge_data_cache.db"); } std::string ConfigManager::getDevicesConfigPath() { return getConfigBasePath() + "devices.json"; } int ConfigManager::getWebServerPort() { return get("web_server_port", 8080); } std::vector ConfigManager::getTcpServerPorts() { return get>("tcp_server_ports", {12345}); } std::string ConfigManager::getLogLevel() { return get("log_level", "debug"); } std::string ConfigManager::getAlarmRulesPath() { return getConfigBasePath() + get("alarm_rules_path", "alarms.json"); } std::string ConfigManager::getPiperExecutablePath() { return get("piper_executable_path", "/usr/bin/piper"); } std::string ConfigManager::getPiperModelPath() { return get("piper_model_path", "/app/models/model.onnx"); } std::string ConfigManager::getVideoConfigPath() { return getConfigBasePath() + get("video_config_path", "video_config.json"); } std::string ConfigManager::getConfigFilePath() const { std::shared_lock lock(m_mutex); return m_configFilePath; }