246 lines
7.9 KiB
C++
246 lines
7.9 KiB
C++
|
|
#include "ConfigMonitor.h"
|
||
|
|
#include "VrLog.h"
|
||
|
|
#include "VrError.h"
|
||
|
|
#include <cstring>
|
||
|
|
#include <chrono>
|
||
|
|
|
||
|
|
ConfigMonitor::ConfigMonitor()
|
||
|
|
: m_pShareMem(nullptr)
|
||
|
|
, m_pCommandHandler(nullptr)
|
||
|
|
, m_bMonitorRunning(false)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
ConfigMonitor::~ConfigMonitor()
|
||
|
|
{
|
||
|
|
Stop();
|
||
|
|
}
|
||
|
|
|
||
|
|
void ConfigMonitor::SetCommandHandler(IConfigCommandHandler* handler)
|
||
|
|
{
|
||
|
|
m_pCommandHandler = handler;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ConfigMonitor::Start(const std::string& sharedMemName)
|
||
|
|
{
|
||
|
|
if (m_bMonitorRunning) {
|
||
|
|
LOG_WARNING("[ConfigMonitor] Monitor is already running\n");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!m_pCommandHandler) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Command handler not set\n");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
m_sharedMemName = sharedMemName;
|
||
|
|
|
||
|
|
if (!InitializeSharedMemory(sharedMemName)) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Failed to initialize shared memory\n");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 启动监控线程
|
||
|
|
m_bMonitorRunning = true;
|
||
|
|
m_monitorThread = std::thread(&ConfigMonitor::MonitorThreadFunc, this);
|
||
|
|
|
||
|
|
LOG_INFO("[ConfigMonitor] Shared memory monitor started (name: %s)\n", sharedMemName.c_str());
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ConfigMonitor::Stop()
|
||
|
|
{
|
||
|
|
if (!m_bMonitorRunning) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
LOG_INFO("[ConfigMonitor] Stopping shared memory monitor...\n");
|
||
|
|
|
||
|
|
m_bMonitorRunning = false;
|
||
|
|
|
||
|
|
// 等待线程结束
|
||
|
|
if (m_monitorThread.joinable()) {
|
||
|
|
m_monitorThread.join();
|
||
|
|
}
|
||
|
|
|
||
|
|
// 清理共享内存
|
||
|
|
CleanupSharedMemory();
|
||
|
|
|
||
|
|
LOG_INFO("[ConfigMonitor] Shared memory monitor stopped\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
void ConfigMonitor::MonitorThreadFunc()
|
||
|
|
{
|
||
|
|
LOG_INFO("[ConfigMonitor] Monitor thread started\n");
|
||
|
|
|
||
|
|
ConfigCmdSharedData lastData;
|
||
|
|
memset(&lastData, 0, sizeof(ConfigCmdSharedData));
|
||
|
|
|
||
|
|
while (m_bMonitorRunning) {
|
||
|
|
try {
|
||
|
|
// 锁定共享内存并读取数据
|
||
|
|
int ret = m_pShareMem->Lock(1000); // 1秒超时
|
||
|
|
if (ret != SUCCESS) {
|
||
|
|
if (ret != SHAREMEM_ERR_TIMEOUT) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Failed to lock shared memory, error: %d\n", ret);
|
||
|
|
}
|
||
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
ConfigCmdSharedData currentData;
|
||
|
|
ret = m_pShareMem->ReadData(0, ¤tData, sizeof(ConfigCmdSharedData));
|
||
|
|
m_pShareMem->Unlock();
|
||
|
|
|
||
|
|
if (ret < 0) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Failed to read shared memory, error: %d\n", ret);
|
||
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 检查魔数和版本
|
||
|
|
if (strcmp(currentData.header.magic, "VRCFG001") != 0 || currentData.header.version != 1) {
|
||
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 检查是否有新数据
|
||
|
|
if (!currentData.header.hasNewData) {
|
||
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 验证校验和
|
||
|
|
if (!currentData.ValidateChecksum()) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Config command data checksum validation failed\n");
|
||
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 检查是否是新的命令(与上次不同)
|
||
|
|
if (memcmp(&lastData.data, ¤tData.data, sizeof(ConfigCmdData)) == 0) {
|
||
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 应用配置命令
|
||
|
|
LOG_INFO("[ConfigMonitor] Received new config command, type: %d, timestamp: %s\n",
|
||
|
|
currentData.data.cmdType, currentData.data.timestamp);
|
||
|
|
|
||
|
|
if (ApplyConfigCommand(currentData.data)) {
|
||
|
|
LOG_INFO("[ConfigMonitor] Config command applied successfully\n");
|
||
|
|
} else {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Failed to apply config command\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
// 更新最后处理的数据
|
||
|
|
lastData = currentData;
|
||
|
|
|
||
|
|
// 标记数据已处理(清除新数据标志)
|
||
|
|
ret = m_pShareMem->Lock(1000);
|
||
|
|
if (ret == SUCCESS) {
|
||
|
|
ConfigCmdSharedData clearData = currentData;
|
||
|
|
clearData.header.hasNewData = false;
|
||
|
|
m_pShareMem->WriteData(0, &clearData, sizeof(ConfigCmdSharedData));
|
||
|
|
m_pShareMem->Unlock();
|
||
|
|
}
|
||
|
|
|
||
|
|
} catch (const std::exception& e) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Exception in monitor thread: %s\n", e.what());
|
||
|
|
}
|
||
|
|
|
||
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||
|
|
}
|
||
|
|
|
||
|
|
LOG_INFO("[ConfigMonitor] Monitor thread stopped\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ConfigMonitor::InitializeSharedMemory(const std::string& sharedMemName)
|
||
|
|
{
|
||
|
|
if (m_pShareMem) {
|
||
|
|
return true; // 已经初始化
|
||
|
|
}
|
||
|
|
|
||
|
|
m_pShareMem = CreateShareMemInstance();
|
||
|
|
if (!m_pShareMem) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Failed to create shared memory instance\n");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 尝试打开已存在的共享内存,如果不存在则创建
|
||
|
|
int ret = m_pShareMem->CreateOrOpen(sharedMemName, CONFIG_CMD_SHARED_MEM_SIZE, false);
|
||
|
|
if (ret != SUCCESS) {
|
||
|
|
// 如果打开失败,尝试创建新的
|
||
|
|
ret = m_pShareMem->CreateOrOpen(sharedMemName, CONFIG_CMD_SHARED_MEM_SIZE, true);
|
||
|
|
if (ret != SUCCESS) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Failed to create or open shared memory, error: %d\n", ret);
|
||
|
|
CleanupSharedMemory();
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 映射内存
|
||
|
|
void* mappedAddr = m_pShareMem->MapView();
|
||
|
|
if (!mappedAddr) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Failed to map shared memory view\n");
|
||
|
|
CleanupSharedMemory();
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
LOG_INFO("[ConfigMonitor] Shared memory initialized successfully (name: %s, size: %zu)\n",
|
||
|
|
sharedMemName.c_str(), CONFIG_CMD_SHARED_MEM_SIZE);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ConfigMonitor::CleanupSharedMemory()
|
||
|
|
{
|
||
|
|
if (m_pShareMem) {
|
||
|
|
m_pShareMem->UnmapView();
|
||
|
|
m_pShareMem->Close();
|
||
|
|
DestroyShareMemInstance(m_pShareMem);
|
||
|
|
m_pShareMem = nullptr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ConfigMonitor::ApplyConfigCommand(const ConfigCmdData& configData)
|
||
|
|
{
|
||
|
|
if (!m_pCommandHandler) {
|
||
|
|
LOG_ERROR("[ConfigMonitor] Command handler not set\n");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (configData.cmdType) {
|
||
|
|
case CONFIG_CMD_CAMERA_EXPOSE:
|
||
|
|
return m_pCommandHandler->OnCameraExposeCommand(configData.cameraParam);
|
||
|
|
|
||
|
|
case CONFIG_CMD_CAMERA_GAIN:
|
||
|
|
return m_pCommandHandler->OnCameraGainCommand(configData.cameraParam);
|
||
|
|
|
||
|
|
case CONFIG_CMD_CAMERA_FRAMERATE:
|
||
|
|
return m_pCommandHandler->OnCameraFrameRateCommand(configData.cameraParam);
|
||
|
|
|
||
|
|
case CONFIG_CMD_CAMERA_SWING:
|
||
|
|
return m_pCommandHandler->OnCameraSwingCommand(configData.swingParam);
|
||
|
|
|
||
|
|
case CONFIG_CMD_ALGO_PARAM:
|
||
|
|
return m_pCommandHandler->OnAlgoParamCommand(configData.algoParam);
|
||
|
|
|
||
|
|
case CONFIG_CMD_CALIB_PARAM:
|
||
|
|
return m_pCommandHandler->OnCalibParamCommand(configData.calibParam);
|
||
|
|
|
||
|
|
case CONFIG_CMD_FULL_CONFIG:
|
||
|
|
return m_pCommandHandler->OnFullConfigCommand(configData.fullConfigParam);
|
||
|
|
|
||
|
|
case CONFIG_CMD_SWITCH_WORKPOSITION:
|
||
|
|
return m_pCommandHandler->OnSwitchWorkPositionCommand(configData.switchWorkPositionParam);
|
||
|
|
|
||
|
|
case CONFIG_CMD_SWITCH_PACKAGETYPE:
|
||
|
|
return m_pCommandHandler->OnSwitchPackageTypeCommand(configData.switchPackageTypeParam);
|
||
|
|
|
||
|
|
default:
|
||
|
|
LOG_ERROR("[ConfigMonitor] Unknown config command type: %d\n", configData.cmdType);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|