config.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include "config.h"
  2. #include <fstream>
  3. #include <iostream>
  4. #include <sstream>
  5. #include <boost/filesystem.hpp>
  6. namespace jtjai_media {
  7. bool ConfigManager::load_from_file(const std::string& config_file) {
  8. try {
  9. std::ifstream file(config_file);
  10. if (!file.is_open()) {
  11. std::cerr << "无法打开配置文件: " << config_file << std::endl;
  12. return false;
  13. }
  14. std::stringstream buffer;
  15. buffer << file.rdbuf();
  16. file.close();
  17. return load_from_json(buffer.str());
  18. } catch (const std::exception& e) {
  19. std::cerr << "加载配置文件时发生异常: " << e.what() << std::endl;
  20. return false;
  21. }
  22. }
  23. bool ConfigManager::load_from_json(const std::string& json_str) {
  24. try {
  25. auto json_value = boost::json::parse(json_str);
  26. auto json_obj = json_value.as_object();
  27. // 加载全局配置
  28. if (json_obj.contains("global_config")) {
  29. global_config_ = global_config_from_json(json_obj["global_config"].as_object());
  30. }
  31. // 加载流配置
  32. stream_configs_.clear();
  33. if (json_obj.contains("streams")) {
  34. auto streams_array = json_obj["streams"].as_array();
  35. for (const auto& stream_json : streams_array) {
  36. stream_configs_.push_back(stream_config_from_json(stream_json.as_object()));
  37. }
  38. }
  39. return validate();
  40. } catch (const std::exception& e) {
  41. std::cerr << "解析JSON配置时发生异常: " << e.what() << std::endl;
  42. return false;
  43. }
  44. }
  45. bool ConfigManager::save_to_file(const std::string& config_file) const {
  46. try {
  47. boost::json::object root;
  48. // 保存全局配置
  49. root["global_config"] = global_config_to_json(global_config_);
  50. // 保存流配置
  51. boost::json::array streams_array;
  52. for (const auto& stream : stream_configs_) {
  53. streams_array.push_back(stream_config_to_json(stream));
  54. }
  55. root["streams"] = streams_array;
  56. std::ofstream file(config_file);
  57. if (!file.is_open()) {
  58. std::cerr << "无法创建配置文件: " << config_file << std::endl;
  59. return false;
  60. }
  61. file << boost::json::serialize(root) << std::endl;
  62. file.close();
  63. return true;
  64. } catch (const std::exception& e) {
  65. std::cerr << "保存配置文件时发生异常: " << e.what() << std::endl;
  66. return false;
  67. }
  68. }
  69. bool ConfigManager::validate() const {
  70. // 检查全局配置
  71. if (global_config_.total_poll_duration_seconds <= 0) {
  72. std::cerr << "总轮询时长必须大于0秒" << std::endl;
  73. return false;
  74. }
  75. if (global_config_.max_concurrent_streams <= 0) {
  76. std::cerr << "最大并发流数必须大于0" << std::endl;
  77. return false;
  78. }
  79. if (global_config_.output_directory.empty()) {
  80. std::cerr << "输出目录不能为空" << std::endl;
  81. return false;
  82. }
  83. // 检查流配置
  84. if (stream_configs_.empty()) {
  85. std::cerr << "至少需要配置一个RTSP流" << std::endl;
  86. return false;
  87. }
  88. for (size_t i = 0; i < stream_configs_.size(); ++i) {
  89. const auto& stream = stream_configs_[i];
  90. if (stream.rtsp_url.empty()) {
  91. std::cerr << "第 " << (i + 1) << " 个流的RTSP地址不能为空" << std::endl;
  92. return false;
  93. }
  94. if (stream.duration_seconds <= 0) {
  95. std::cerr << "第 " << (i + 1) << " 个流的访问时长必须大于0秒" << std::endl;
  96. return false;
  97. }
  98. if (stream.weight <= 0) {
  99. std::cerr << "第 " << (i + 1) << " 个流的权重必须大于0" << std::endl;
  100. return false;
  101. }
  102. if (stream.output_filename.empty()) {
  103. std::cerr << "第 " << (i + 1) << " 个流的输出文件名不能为空" << std::endl;
  104. return false;
  105. }
  106. }
  107. return true;
  108. }
  109. std::string ConfigManager::to_string() const {
  110. std::stringstream ss;
  111. ss << "全局配置:\\n";
  112. ss << " 总轮询时长: " << global_config_.total_poll_duration_seconds << " 秒\\n";
  113. ss << " 最大并发流数: " << global_config_.max_concurrent_streams << "\\n";
  114. ss << " 输出目录: " << global_config_.output_directory << "\\n";
  115. ss << " 报告文件名: " << global_config_.report_filename << "\\n";
  116. ss << " 连接超时: " << global_config_.connection_timeout_seconds << " 秒\\n";
  117. ss << " 读取超时: " << global_config_.read_timeout_seconds << " 秒\\n";
  118. ss << " 轮询周期数: " << (global_config_.poll_cycles == -1 ? "无限循环" : std::to_string(global_config_.poll_cycles)) << "\n";
  119. ss << " 周期间隔: " << global_config_.cycle_interval_seconds << " 秒\n";
  120. ss << "\\n流配置 (" << stream_configs_.size() << " 个):\\n";
  121. for (size_t i = 0; i < stream_configs_.size(); ++i) {
  122. const auto& stream = stream_configs_[i];
  123. ss << " [" << (i + 1) << "] " << stream.rtsp_url << "\\n";
  124. ss << " 时长: " << stream.duration_seconds << " 秒, ";
  125. ss << "权重: " << stream.weight << ", ";
  126. ss << "输出: " << stream.output_filename << "\\n";
  127. }
  128. return ss.str();
  129. }
  130. boost::json::object ConfigManager::stream_config_to_json(const StreamConfig& config) const {
  131. boost::json::object obj;
  132. obj["rtsp_url"] = config.rtsp_url;
  133. obj["duration_seconds"] = config.duration_seconds;
  134. obj["weight"] = config.weight;
  135. obj["output_filename"] = config.output_filename;
  136. return obj;
  137. }
  138. StreamConfig ConfigManager::stream_config_from_json(const boost::json::object& json_obj) const {
  139. StreamConfig config;
  140. if (json_obj.contains("rtsp_url")) {
  141. config.rtsp_url = json_obj.at("rtsp_url").as_string().c_str();
  142. }
  143. if (json_obj.contains("duration_seconds")) {
  144. config.duration_seconds = static_cast<int>(json_obj.at("duration_seconds").as_int64());
  145. }
  146. if (json_obj.contains("weight")) {
  147. config.weight = json_obj.at("weight").as_double();
  148. }
  149. if (json_obj.contains("output_filename")) {
  150. config.output_filename = json_obj.at("output_filename").as_string().c_str();
  151. }
  152. return config;
  153. }
  154. boost::json::object ConfigManager::global_config_to_json(const GlobalConfig& config) const {
  155. boost::json::object obj;
  156. obj["total_poll_duration_seconds"] = config.total_poll_duration_seconds;
  157. obj["max_concurrent_streams"] = config.max_concurrent_streams;
  158. obj["output_directory"] = config.output_directory;
  159. obj["report_filename"] = config.report_filename;
  160. obj["connection_timeout_seconds"] = config.connection_timeout_seconds;
  161. obj["read_timeout_seconds"] = config.read_timeout_seconds;
  162. obj["poll_cycles"] = config.poll_cycles;
  163. obj["cycle_interval_seconds"] = config.cycle_interval_seconds;
  164. return obj;
  165. }
  166. GlobalConfig ConfigManager::global_config_from_json(const boost::json::object& json_obj) const {
  167. GlobalConfig config;
  168. if (json_obj.contains("total_poll_duration_seconds")) {
  169. config.total_poll_duration_seconds = static_cast<int>(json_obj.at("total_poll_duration_seconds").as_int64());
  170. }
  171. if (json_obj.contains("max_concurrent_streams")) {
  172. config.max_concurrent_streams = static_cast<int>(json_obj.at("max_concurrent_streams").as_int64());
  173. }
  174. if (json_obj.contains("output_directory")) {
  175. config.output_directory = json_obj.at("output_directory").as_string().c_str();
  176. }
  177. if (json_obj.contains("report_filename")) {
  178. config.report_filename = json_obj.at("report_filename").as_string().c_str();
  179. }
  180. if (json_obj.contains("connection_timeout_seconds")) {
  181. config.connection_timeout_seconds = static_cast<int>(json_obj.at("connection_timeout_seconds").as_int64());
  182. }
  183. if (json_obj.contains("read_timeout_seconds")) {
  184. config.read_timeout_seconds = static_cast<int>(json_obj.at("read_timeout_seconds").as_int64());
  185. }
  186. if (json_obj.contains("poll_cycles")) {
  187. config.poll_cycles = static_cast<int>(json_obj.at("poll_cycles").as_int64());
  188. }
  189. if (json_obj.contains("cycle_interval_seconds")) {
  190. config.cycle_interval_seconds = static_cast<int>(json_obj.at("cycle_interval_seconds").as_int64());
  191. }
  192. return config;
  193. }
  194. } // namespace jtjai_media