kunlang_video/include/app_config.hpp
2026-01-05 13:46:03 +08:00

192 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// app_config.hpp
#pragma once
#include <limits.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <map>
#include <nlohmann/json.hpp>
#include <stdexcept>
#include <string>
#include "logger.hpp"
using json = nlohmann::json;
using ordered_json = nlohmann::ordered_json;
// ------------------- 摄像头结构体 -------------------
enum class StreamType
{
MAIN,
SUB
};
struct Camera
{
std::string device;
std::string name;
int width, height, fps;
int bitrate;
bool enabled;
StreamType stream_type; // 新增字段
};
// ------------------- MQTT Topic -------------------
struct VehicleMQTTTopics
{
std::string heartbeat_up;
std::string video_down;
std::string record_query;
std::string record_play;
std::string vehicle_ctrl;
void fill_with_veh_id(const std::string& vehId)
{
heartbeat_up = "/zxwl/vehicle/video/status/" + vehId;
video_down = "/zxwl/vehicle/video/request/" + vehId;
record_query = "/zxwl/vehicle/video/record/query/" + vehId;
record_play = "/zxwl/vehicle/video/record/play/" + vehId;
vehicle_ctrl = "/zxwl/vehicle/ctrl/" + vehId;
}
};
// ------------------- MQTT 配置 -------------------
struct MQTTConfig
{
std::string vehicle_id;
std::string server_ip;
int server_port;
bool need_username_pwd;
std::string client_id;
std::string username;
std::string password;
int keep_alive;
int qos = 1; // 默认 QoS 级别
bool clean_session = true; // 默认 clean session
VehicleMQTTTopics topics;
};
// ------------------- 总配置 -------------------
struct AppConfig
{
std::vector<Camera> cameras;
MQTTConfig mqtt;
// ⭐ 运行期从 orin 获取的 VID优先生效
std::string runtime_vid;
static AppConfig load_from_file(const std::string& filepath)
{
AppConfig cfg;
std::ifstream ifs(filepath);
if (!ifs.is_open())
{
LOG_ERROR("[Config] Failed to open config file: " + filepath);
throw std::runtime_error("Failed to open config file: " + filepath);
}
json j;
ifs >> j;
// 读取摄像头
if (j.contains("cameras"))
{
for (auto& c : j["cameras"])
{
Camera cam;
cam.device = c.value("device", "");
cam.name = c.value("name", "");
cam.width = c.value("width", 1280);
cam.height = c.value("height", 720);
cam.fps = c.value("fps", 30);
cam.bitrate = c.value("bitrate", 2000000);
cam.enabled = c.value("enabled", false);
cfg.cameras.push_back(cam);
LOG_INFO("[Config] Loaded camera: " + cam.name + " (" + cam.device +
"), enabled=" + std::to_string(cam.enabled) + ", bitrate=" + std::to_string(cam.bitrate));
}
}
// 读取 MQTT
if (!j.contains("mqtt_server"))
{
LOG_ERROR("[Config] Missing 'mqtt_server' section");
throw std::runtime_error("Config file missing 'mqtt_server'");
}
auto& m = j["mqtt_server"];
if (m.contains("veh_id"))
{
if (m["veh_id"].is_string())
{
cfg.mqtt.vehicle_id = m["veh_id"].get<std::string>();
}
else if (m["veh_id"].is_number_integer())
{
cfg.mqtt.vehicle_id = std::to_string(m["veh_id"].get<int>());
}
else
{
throw std::runtime_error("mqtt_server.veh_id must be string or integer");
}
}
else
{
throw std::runtime_error("mqtt_server.veh_id missing");
}
cfg.mqtt.server_ip = m.value("address", "");
cfg.mqtt.server_port = m.value("port", 1883);
cfg.mqtt.need_username_pwd = m.value("need_username_pwd", true);
cfg.mqtt.client_id = m.value("client_id", "");
cfg.mqtt.username = m.value("username", "");
cfg.mqtt.password = m.value("password", "");
cfg.mqtt.keep_alive = m.value("mqtt_heart_threshold", 2000);
cfg.mqtt.topics.fill_with_veh_id(cfg.mqtt.vehicle_id);
LOG_INFO("[Config] Loaded MQTT server: " + cfg.mqtt.server_ip + ":" + std::to_string(cfg.mqtt.server_port));
LOG_INFO("[Config] MQTT client ID: " + cfg.mqtt.client_id);
LOG_INFO("[Config] MQTT Credentials - username: " + cfg.mqtt.username + ", password: " + cfg.mqtt.password);
LOG_INFO("[Config] MQTT Topics: " + cfg.mqtt.topics.heartbeat_up + ", " + cfg.mqtt.topics.video_down);
LOG_INFO("[Config] MQTT keepAlive: " + std::to_string(cfg.mqtt.keep_alive));
return cfg;
}
};
// ------------------- 辅助函数 -------------------
inline std::string get_executable_dir()
{
char result[PATH_MAX] = {0};
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
if (count == -1)
{
LOG_ERROR("[Config] Failed to read /proc/self/exe");
throw std::runtime_error("Failed to read /proc/self/exe");
}
std::string full_path(result, count);
auto pos = full_path.find_last_of('/');
if (pos == std::string::npos)
{
LOG_ERROR("[Config] Failed to find executable directory");
throw std::runtime_error("Failed to find executable directory");
}
return full_path.substr(0, pos);
}
inline std::string get_executable_dir_file_path(const std::string& filename)
{
std::string dir = get_executable_dir();
if (dir.back() != '/') dir += '/';
return dir + filename;
}
// 全局配置变量
extern AppConfig g_app_config;