571 lines
18 KiB
C++
571 lines
18 KiB
C++
#ifndef BASECONFIGMANAGER_H
|
||
#define BASECONFIGMANAGER_H
|
||
|
||
#include "ConfigMonitor.h"
|
||
#include <mutex>
|
||
#include <vector>
|
||
#include <functional>
|
||
#include <memory>
|
||
#include <string>
|
||
#include <algorithm>
|
||
#include <cstring>
|
||
#include <QtCore/QCoreApplication>
|
||
|
||
#include "VrLog.h"
|
||
|
||
// 前置声明,具体定义由各应用的 IVrConfig.h 提供
|
||
class IVrConfig;
|
||
struct ConfigResult;
|
||
struct VrAlgorithmParams;
|
||
struct DeviceInfo;
|
||
|
||
/**
|
||
* @brief 扩展的相机UI参数
|
||
*/
|
||
struct CameraUIParam
|
||
{
|
||
int cameraIndex = 1; // 相机索引
|
||
double exposeTime = 100.0; // 曝光时间 (微秒)
|
||
double gain = 1.0; // 增益值
|
||
double frameRate = 30.0; // 帧率
|
||
double swingSpeed = 10.0; // 摆动速度
|
||
double swingStartAngle = 0.0; // 开始角度
|
||
double swingStopAngle = 180.0; // 结束角度
|
||
};
|
||
|
||
/**
|
||
* @brief 完整的系统配置数据
|
||
*/
|
||
struct SystemConfig
|
||
{
|
||
ConfigResult configResult; // VrConfig配置结果
|
||
std::vector<CameraUIParam> cameraUIParams; // 相机UI参数
|
||
|
||
// 获取指定相机的UI参数
|
||
CameraUIParam* GetCameraUIParam(int cameraIndex)
|
||
{
|
||
for (auto& param : cameraUIParams) {
|
||
if (param.cameraIndex == cameraIndex) {
|
||
return ¶m;
|
||
}
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
const CameraUIParam* GetCameraUIParam(int cameraIndex) const
|
||
{
|
||
for (const auto& param : cameraUIParams) {
|
||
if (param.cameraIndex == cameraIndex) {
|
||
return ¶m;
|
||
}
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
// 设置或更新指定相机的UI参数
|
||
void SetCameraUIParam(const CameraUIParam& param)
|
||
{
|
||
for (auto& existingParam : cameraUIParams) {
|
||
if (existingParam.cameraIndex == param.cameraIndex) {
|
||
existingParam = param;
|
||
return;
|
||
}
|
||
}
|
||
// 如果不存在,则添加新的
|
||
cameraUIParams.push_back(param);
|
||
}
|
||
|
||
// 确保指定相机的参数存在
|
||
void EnsureCameraUIParam(int cameraIndex)
|
||
{
|
||
for (const auto& param : cameraUIParams) {
|
||
if (param.cameraIndex == cameraIndex) {
|
||
return; // 已存在
|
||
}
|
||
}
|
||
|
||
// 不存在,创建默认参数
|
||
CameraUIParam defaultParam;
|
||
defaultParam.cameraIndex = cameraIndex;
|
||
cameraUIParams.push_back(defaultParam);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* @brief 配置变化监听器接口
|
||
*/
|
||
class IConfigChangeListener
|
||
{
|
||
public:
|
||
virtual ~IConfigChangeListener() = default;
|
||
|
||
/**
|
||
* @brief 配置变化通知
|
||
* @param config 新的配置数据
|
||
*/
|
||
virtual void OnSystemConfigChanged(const SystemConfig& config) = 0;
|
||
|
||
/**
|
||
* @brief 相机参数变化通知
|
||
* @param cameraIndex 相机索引
|
||
* @param cameraParam 相机参数
|
||
*/
|
||
virtual void OnCameraParamChanged(int cameraIndex, const CameraUIParam& cameraParam) = 0;
|
||
|
||
/**
|
||
* @brief 算法参数变化通知
|
||
* @param algorithmParams 算法参数
|
||
*/
|
||
virtual void OnAlgorithmParamChanged(const VrAlgorithmParams& algorithmParams) = 0;
|
||
};
|
||
|
||
/**
|
||
* @brief 配置管理器基类
|
||
*
|
||
* Header-only 实现,避免编译依赖问题
|
||
* 提供通用的配置管理功能
|
||
*/
|
||
class BaseConfigManager : public IConfigCommandHandler
|
||
{
|
||
public:
|
||
BaseConfigManager()
|
||
: m_pVrConfig(nullptr)
|
||
{
|
||
}
|
||
|
||
virtual ~BaseConfigManager()
|
||
{
|
||
Shutdown();
|
||
}
|
||
|
||
// 基本配置管理
|
||
virtual bool Initialize(const std::string& configFilePath = "")
|
||
{
|
||
LOG_INFO("BaseConfigManager initializing...\n");
|
||
|
||
// 保存配置文件路径
|
||
if (configFilePath.empty()) {
|
||
QString defaultPath = QCoreApplication::applicationDirPath() + "/config.json";
|
||
m_configFilePath = defaultPath.toStdString();
|
||
} else {
|
||
m_configFilePath = configFilePath;
|
||
}
|
||
|
||
// 创建VrConfig实例
|
||
if (!IVrConfig::CreateInstance(&m_pVrConfig) || !m_pVrConfig) {
|
||
LOG_ERROR("Failed to create VrConfig instance\n");
|
||
return false;
|
||
}
|
||
|
||
// 加载配置文件
|
||
if (!LoadConfigFromFile(m_configFilePath)) {
|
||
LOG_WARNING("Failed to load config file, using default config\n");
|
||
_InitializeDefaultConfig();
|
||
}
|
||
|
||
// 启动 ConfigMonitor
|
||
m_configMonitor.SetCommandHandler(this);
|
||
if (!m_configMonitor.Start()) {
|
||
LOG_WARNING("Failed to start ConfigMonitor, config updates from shared memory will not work\n");
|
||
}
|
||
|
||
LOG_INFO("BaseConfigManager initialized successfully\n");
|
||
return true;
|
||
}
|
||
|
||
virtual void Shutdown()
|
||
{
|
||
LOG_INFO("BaseConfigManager shutting down...\n");
|
||
|
||
// 停止 ConfigMonitor
|
||
m_configMonitor.Stop();
|
||
|
||
// 清理监听器
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_listenersMutex);
|
||
m_listeners.clear();
|
||
}
|
||
|
||
// 释放VrConfig实例
|
||
if (m_pVrConfig) {
|
||
delete m_pVrConfig;
|
||
m_pVrConfig = nullptr;
|
||
}
|
||
|
||
LOG_INFO("BaseConfigManager shutdown completed\n");
|
||
}
|
||
|
||
// 配置访问(线程安全)
|
||
SystemConfig GetConfig() const
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
return m_systemConfig;
|
||
}
|
||
|
||
CameraUIParam GetCameraUIParam(int cameraIndex) const
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
const CameraUIParam* param = m_systemConfig.GetCameraUIParam(cameraIndex);
|
||
if (param) {
|
||
return *param;
|
||
}
|
||
|
||
// 返回默认参数
|
||
CameraUIParam defaultParam;
|
||
defaultParam.cameraIndex = cameraIndex;
|
||
return defaultParam;
|
||
}
|
||
|
||
VrAlgorithmParams GetAlgorithmParams() const
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
return m_systemConfig.configResult.algorithmParams;
|
||
}
|
||
|
||
ConfigResult GetConfigResult() const
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
return m_systemConfig.configResult;
|
||
}
|
||
|
||
IVrConfig* GetVrConfigInstance() const { return m_pVrConfig; }
|
||
|
||
// 配置更新
|
||
bool UpdateCameraUIParam(int cameraIndex, const CameraUIParam& param)
|
||
{
|
||
bool changed = false;
|
||
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
|
||
CameraUIParam* existingParam = m_systemConfig.GetCameraUIParam(cameraIndex);
|
||
if (!existingParam || memcmp(existingParam, ¶m, sizeof(CameraUIParam)) != 0) {
|
||
m_systemConfig.SetCameraUIParam(param);
|
||
changed = true;
|
||
}
|
||
}
|
||
|
||
if (changed) {
|
||
_NotifyCameraParamChanged(cameraIndex);
|
||
LOG_INFO("Camera %d UI parameters updated\n", cameraIndex);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool UpdateAlgorithmParams(const VrAlgorithmParams& params)
|
||
{
|
||
bool changed = false;
|
||
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
|
||
if (memcmp(&m_systemConfig.configResult.algorithmParams, ¶ms, sizeof(VrAlgorithmParams)) != 0) {
|
||
m_systemConfig.configResult.algorithmParams = params;
|
||
changed = true;
|
||
}
|
||
}
|
||
|
||
if (changed) {
|
||
_NotifyAlgorithmParamChanged();
|
||
LOG_INFO("Algorithm parameters updated\n");
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool UpdateFullConfig(const SystemConfig& config)
|
||
{
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
m_systemConfig = config;
|
||
}
|
||
|
||
_NotifyConfigChanged();
|
||
LOG_INFO("Full configuration updated\n");
|
||
|
||
return true;
|
||
}
|
||
|
||
// 配置文件操作(纯虚函数,子类必须实现以适配不同的 IVrConfig API)
|
||
virtual bool LoadConfigFromFile(const std::string& filePath) = 0;
|
||
|
||
bool SaveConfigToFile(const std::string& filePath)
|
||
{
|
||
if (!m_pVrConfig) {
|
||
LOG_ERROR("VrConfig instance not available\n");
|
||
return false;
|
||
}
|
||
|
||
try {
|
||
ConfigResult configResult;
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
configResult = m_systemConfig.configResult;
|
||
}
|
||
|
||
bool result = m_pVrConfig->SaveConfig(filePath, configResult);
|
||
if (result) {
|
||
LOG_INFO("Configuration saved to file: %s\n", filePath.c_str());
|
||
} else {
|
||
LOG_ERROR("Failed to save configuration to file: %s\n", filePath.c_str());
|
||
}
|
||
|
||
return result;
|
||
|
||
} catch (const std::exception& e) {
|
||
LOG_ERROR("Exception while saving configuration to file %s: %s\n", filePath.c_str(), e.what());
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 监听器管理
|
||
void AddConfigChangeListener(std::shared_ptr<IConfigChangeListener> listener)
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_listenersMutex);
|
||
m_listeners.push_back(listener);
|
||
|
||
LOG_DEBUG("Config change listener added, total listeners: %zu\n", m_listeners.size());
|
||
}
|
||
|
||
void RemoveConfigChangeListener(std::shared_ptr<IConfigChangeListener> listener)
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_listenersMutex);
|
||
|
||
auto it = std::find_if(m_listeners.begin(), m_listeners.end(),
|
||
[&listener](const std::weak_ptr<IConfigChangeListener>& weak_listener) {
|
||
return weak_listener.lock() == listener;
|
||
});
|
||
|
||
if (it != m_listeners.end()) {
|
||
m_listeners.erase(it);
|
||
LOG_DEBUG("Config change listener removed, remaining listeners: %zu\n", m_listeners.size());
|
||
}
|
||
}
|
||
|
||
// IConfigCommandHandler 接口实现
|
||
bool OnCameraExposeCommand(const CameraConfigParam& param) override
|
||
{
|
||
LOG_INFO("Received camera expose command: camera=%d, exposeTime=%f\n", param.cameraIndex, param.exposeTime);
|
||
|
||
CameraUIParam cameraParam = GetCameraUIParam(param.cameraIndex);
|
||
cameraParam.exposeTime = param.exposeTime;
|
||
|
||
return UpdateCameraUIParam(param.cameraIndex, cameraParam);
|
||
}
|
||
|
||
bool OnCameraGainCommand(const CameraConfigParam& param) override
|
||
{
|
||
LOG_INFO("Received camera gain command: camera=%d, gain=%f\n", param.cameraIndex, param.gain);
|
||
|
||
CameraUIParam cameraParam = GetCameraUIParam(param.cameraIndex);
|
||
cameraParam.gain = param.gain;
|
||
|
||
return UpdateCameraUIParam(param.cameraIndex, cameraParam);
|
||
}
|
||
|
||
bool OnCameraFrameRateCommand(const CameraConfigParam& param) override
|
||
{
|
||
LOG_INFO("Received camera framerate command: camera=%d, frameRate=%f\n", param.cameraIndex, param.frameRate);
|
||
|
||
CameraUIParam cameraParam = GetCameraUIParam(param.cameraIndex);
|
||
cameraParam.frameRate = param.frameRate;
|
||
|
||
return UpdateCameraUIParam(param.cameraIndex, cameraParam);
|
||
}
|
||
|
||
bool OnCameraSwingCommand(const SwingConfigParam& param) override
|
||
{
|
||
LOG_INFO("Received camera swing command: camera=%d, swingSpeed=%f, start=%f, stop=%f\n",
|
||
param.cameraIndex, param.swingSpeed, param.startAngle, param.stopAngle);
|
||
|
||
CameraUIParam cameraParam = GetCameraUIParam(param.cameraIndex);
|
||
cameraParam.swingSpeed = param.swingSpeed;
|
||
cameraParam.swingStartAngle = param.startAngle;
|
||
cameraParam.swingStopAngle = param.stopAngle;
|
||
|
||
return UpdateCameraUIParam(param.cameraIndex, cameraParam);
|
||
}
|
||
|
||
bool OnAlgoParamCommand(const AlgoConfigParam& param) override
|
||
{
|
||
LOG_INFO("Received algorithm param command: %s=%f\n", param.paramName, param.paramValue);
|
||
|
||
VrAlgorithmParams algoParams = GetAlgorithmParams();
|
||
|
||
// 根据 param 中的数据更新算法参数
|
||
// 这里需要根据实际的 AlgoConfigParam 结构来映射
|
||
// 暂时简单处理
|
||
|
||
return UpdateAlgorithmParams(algoParams);
|
||
}
|
||
|
||
bool OnFullConfigCommand(const FullConfigParam& param) override
|
||
{
|
||
LOG_INFO("Received full config command\n");
|
||
|
||
// 重新加载配置文件
|
||
if (!m_configFilePath.empty()) {
|
||
return LoadConfigFromFile(m_configFilePath);
|
||
}
|
||
|
||
LOG_WARNING("Config file path not set, cannot reload full config\n");
|
||
return false;
|
||
}
|
||
|
||
// 应用特定的命令处理(默认实现)
|
||
bool OnCalibParamCommand(const CalibConfigParam& param) override
|
||
{
|
||
LOG_INFO("Received calibration param command: camera=%d\n", param.cameraIndex);
|
||
LOG_INFO("Calibration command received but not implemented in base class\n");
|
||
return true;
|
||
}
|
||
|
||
bool OnSwitchWorkPositionCommand(const SwitchWorkPositionParam& param) override
|
||
{
|
||
LOG_INFO("Received switch work position command: workPositionId=%s\n", param.workPositionId);
|
||
LOG_INFO("Switch work position command received but not implemented in base class\n");
|
||
return true;
|
||
}
|
||
|
||
bool OnSwitchPackageTypeCommand(const SwitchPackageTypeParam& param) override
|
||
{
|
||
LOG_INFO("Received switch package type command: packageTypeId=%s\n", param.packageTypeId);
|
||
LOG_INFO("Switch package type command received but not implemented in base class\n");
|
||
return true;
|
||
}
|
||
|
||
protected:
|
||
// 配置数据
|
||
mutable std::mutex m_configMutex;
|
||
SystemConfig m_systemConfig;
|
||
std::string m_configFilePath;
|
||
|
||
// VrConfig实例
|
||
IVrConfig* m_pVrConfig;
|
||
|
||
// 监听器管理
|
||
mutable std::mutex m_listenersMutex;
|
||
std::vector<std::weak_ptr<IConfigChangeListener>> m_listeners;
|
||
|
||
// ConfigMonitor 实例
|
||
ConfigMonitor m_configMonitor;
|
||
|
||
// 通知相关
|
||
void _NotifyConfigChanged()
|
||
{
|
||
SystemConfig currentConfig = GetConfig();
|
||
|
||
std::lock_guard<std::mutex> lock(m_listenersMutex);
|
||
_CleanupExpiredListeners();
|
||
|
||
for (auto& weakListener : m_listeners) {
|
||
if (auto listener = weakListener.lock()) {
|
||
try {
|
||
listener->OnSystemConfigChanged(currentConfig);
|
||
} catch (const std::exception& e) {
|
||
LOG_ERROR("Exception in config change listener: %s\n", e.what());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void _NotifyCameraParamChanged(int cameraIndex)
|
||
{
|
||
CameraUIParam cameraParam = GetCameraUIParam(cameraIndex);
|
||
|
||
std::lock_guard<std::mutex> lock(m_listenersMutex);
|
||
_CleanupExpiredListeners();
|
||
|
||
for (auto& weakListener : m_listeners) {
|
||
if (auto listener = weakListener.lock()) {
|
||
try {
|
||
listener->OnCameraParamChanged(cameraIndex, cameraParam);
|
||
} catch (const std::exception& e) {
|
||
LOG_ERROR("Exception in camera param change listener: %s\n", e.what());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void _NotifyAlgorithmParamChanged()
|
||
{
|
||
VrAlgorithmParams algorithmParams = GetAlgorithmParams();
|
||
|
||
std::lock_guard<std::mutex> lock(m_listenersMutex);
|
||
_CleanupExpiredListeners();
|
||
|
||
for (auto& weakListener : m_listeners) {
|
||
if (auto listener = weakListener.lock()) {
|
||
try {
|
||
listener->OnAlgorithmParamChanged(algorithmParams);
|
||
} catch (const std::exception& e) {
|
||
LOG_ERROR("Exception in algorithm param change listener: %s\n", e.what());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void _CleanupExpiredListeners()
|
||
{
|
||
// 移除已过期的weak_ptr
|
||
m_listeners.erase(
|
||
std::remove_if(m_listeners.begin(), m_listeners.end(),
|
||
[](const std::weak_ptr<IConfigChangeListener>& weak_listener) {
|
||
return weak_listener.expired();
|
||
}),
|
||
m_listeners.end());
|
||
}
|
||
|
||
// 初始化相关(子类可重写以提供自定义默认配置)
|
||
virtual bool _InitializeDefaultConfig()
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
|
||
// 初始化默认ConfigResult
|
||
m_systemConfig.configResult = ConfigResult();
|
||
|
||
// 添加默认相机配置
|
||
DeviceInfo defaultCamera;
|
||
defaultCamera.name = "Camera1";
|
||
defaultCamera.ip = "192.168.1.100";
|
||
m_systemConfig.configResult.cameraList.push_back(defaultCamera);
|
||
|
||
// 初始化默认相机UI参数
|
||
m_systemConfig.cameraUIParams.clear();
|
||
CameraUIParam defaultCameraUI;
|
||
defaultCameraUI.cameraIndex = 1;
|
||
m_systemConfig.cameraUIParams.push_back(defaultCameraUI);
|
||
|
||
LOG_INFO("Default configuration initialized\n");
|
||
return true;
|
||
}
|
||
|
||
// 应用加载的配置(提取公共逻辑)
|
||
bool _ApplyLoadedConfig(const ConfigResult& configResult, const std::string& filePath)
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_configMutex);
|
||
m_systemConfig.configResult = configResult;
|
||
|
||
// 初始化默认的相机UI参数
|
||
m_systemConfig.cameraUIParams.clear();
|
||
for (size_t i = 0; i < configResult.cameraList.size(); ++i) {
|
||
CameraUIParam cameraParam;
|
||
cameraParam.cameraIndex = static_cast<int>(i + 1);
|
||
m_systemConfig.cameraUIParams.push_back(cameraParam);
|
||
}
|
||
|
||
// 如果没有相机配置,至少添加一个默认相机
|
||
if (m_systemConfig.cameraUIParams.empty()) {
|
||
CameraUIParam defaultCamera;
|
||
defaultCamera.cameraIndex = 1;
|
||
m_systemConfig.cameraUIParams.push_back(defaultCamera);
|
||
}
|
||
|
||
LOG_INFO("Configuration loaded from file: %s\n", filePath.c_str());
|
||
return true;
|
||
}
|
||
};
|
||
|
||
#endif // BASECONFIGMANAGER_H
|