增加机械臂ModbusTCP的协议交互;重构相机对话框,添加设备参数初始化和应用功能,增强错误处理,更新UI控件名称以提高可读性; 增加相机扫描逻辑
This commit is contained in:
parent
533e068a01
commit
89a8d050f5
@ -19,7 +19,7 @@ inline std::string WorkStatusToString(WorkStatus status) {
|
||||
switch (status) {
|
||||
case WorkStatus::Ready: return "准备就绪";
|
||||
case WorkStatus::Working: return "正在工作";
|
||||
case WorkStatus::Completed: return "监测完成";
|
||||
case WorkStatus::Completed: return "检测完成";
|
||||
case WorkStatus::Error: return "设备异常";
|
||||
default: return "未知状态";
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "IVrEyeDevice.h"
|
||||
#include "IYGrabBagStatus.h"
|
||||
#include "RobotProtocol.h"
|
||||
#include "VZNL_Types.h"
|
||||
|
||||
class GrabBagPresenter
|
||||
{
|
||||
@ -24,6 +25,8 @@ public:
|
||||
// 停止检测
|
||||
int StopDetection();
|
||||
|
||||
IVrEyeDevice* GetEyeDevice(int index);
|
||||
|
||||
private:
|
||||
// 机械臂协议相关方法
|
||||
int InitRobotProtocol();
|
||||
@ -32,19 +35,43 @@ private:
|
||||
void OnRobotConnectionChanged(bool connected);
|
||||
void OnRobotWorkSignal(bool startWork);
|
||||
|
||||
// 连接状态检查和更新
|
||||
void CheckAndUpdateWorkStatus();
|
||||
|
||||
// 静态回调函数,用于传递给SDK
|
||||
static void _StaticCameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam);
|
||||
|
||||
// 实例方法,处理回调
|
||||
void _CameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam);
|
||||
|
||||
// 检测数据回调函数
|
||||
static void _StaticDetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint, void* pParam);
|
||||
void _DetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint);
|
||||
|
||||
// 算法检测线程
|
||||
void _AlgoDetectThread();
|
||||
|
||||
int _DetectTask();
|
||||
|
||||
private:
|
||||
IVrConfig* m_vrConfig = nullptr;
|
||||
IVrEyeDevice* m_vrEyeDevice = nullptr;
|
||||
IYGrabBagStatus* m_pStatus = nullptr;
|
||||
IVrConfig* m_vrConfig = nullptr;
|
||||
std::vector<IVrEyeDevice*> m_vrEyeDeviceList;
|
||||
IYGrabBagStatus* m_pStatus = nullptr;
|
||||
|
||||
RobotProtocol* m_pRobotProtocol = nullptr;
|
||||
RobotProtocol* m_pRobotProtocol = nullptr;
|
||||
|
||||
// 连接状态标志
|
||||
bool m_bCameraConnected = false; // 相机连接状态
|
||||
bool m_bRobotConnected = false; // 机械臂连接状态
|
||||
WorkStatus m_currentWorkStatus = WorkStatus::Error; // 当前工作状态
|
||||
|
||||
std::atomic<bool> m_bAlgoDetectThreadRunning = false;
|
||||
std::mutex m_algoDetectMutex;
|
||||
std::condition_variable m_algoDetectCondition;
|
||||
|
||||
// 检测数据缓存
|
||||
std::vector<SVzLaserLineData*> m_detectionDataCache;
|
||||
std::mutex m_detectionDataMutex;
|
||||
};
|
||||
|
||||
#endif // GRABBAGPRESENTER_H
|
||||
|
||||
@ -107,6 +107,12 @@ private:
|
||||
*/
|
||||
void StopModbusTCPServer();
|
||||
|
||||
/**
|
||||
* @brief 处理ModbusTCP连接状态变化
|
||||
* @param connected true-连接,false-断开
|
||||
*/
|
||||
void OnModbusTCPConnectionChanged(bool connected);
|
||||
|
||||
/**
|
||||
* @brief 处理线圈写入请求(工作信号)
|
||||
* @param unitId 单元ID
|
||||
@ -155,6 +161,7 @@ private:
|
||||
WorkSignalCallback m_workSignalCallback; // 工作信号回调
|
||||
|
||||
// Modbus地址映射
|
||||
|
||||
static const uint16_t COORD_X_ADDR = 0x0000; // X坐标地址
|
||||
static const uint16_t COORD_Y_ADDR = 0x0002; // Y坐标地址
|
||||
static const uint16_t COORD_Z_ADDR = 0x0004; // Z坐标地址
|
||||
|
||||
@ -7,9 +7,11 @@
|
||||
|
||||
GrabBagPresenter::GrabBagPresenter()
|
||||
: m_vrConfig(nullptr)
|
||||
, m_vrEyeDevice(nullptr)
|
||||
, m_pStatus(nullptr)
|
||||
, m_pRobotProtocol(nullptr)
|
||||
, m_bCameraConnected(false)
|
||||
, m_bRobotConnected(false)
|
||||
, m_currentWorkStatus(WorkStatus::Error)
|
||||
{
|
||||
|
||||
}
|
||||
@ -24,14 +26,22 @@ GrabBagPresenter::~GrabBagPresenter()
|
||||
}
|
||||
|
||||
// 释放其他资源
|
||||
if (m_vrEyeDevice) {
|
||||
// 关闭设备
|
||||
m_vrEyeDevice->CloseDevice();
|
||||
for(auto it = m_vrEyeDeviceList.begin(); it != m_vrEyeDeviceList.end(); it++)
|
||||
{
|
||||
(*it)->CloseDevice();
|
||||
delete (*it);
|
||||
}
|
||||
m_vrEyeDeviceList.clear();
|
||||
|
||||
}
|
||||
|
||||
int GrabBagPresenter::Init()
|
||||
{
|
||||
// 初始化连接状态
|
||||
m_bCameraConnected = false;
|
||||
m_bRobotConnected = false;
|
||||
m_currentWorkStatus = WorkStatus::Error;
|
||||
|
||||
// 初始化VrConfig模块
|
||||
IVrConfig::CreateInstance(&m_vrConfig);
|
||||
|
||||
@ -43,19 +53,12 @@ int GrabBagPresenter::Init()
|
||||
|
||||
// 读取IP列表
|
||||
ConfigResult configResult = m_vrConfig->LoadConfig(configPath.toStdString());
|
||||
if (configResult.cameraList.size() == 0) {
|
||||
m_pStatus->OnStatusUpdate("读取配置信息列表失败");
|
||||
m_pStatus->OnCamera1StatusChanged(false);
|
||||
m_pStatus->OnCamera2StatusChanged(false);
|
||||
m_pStatus->OnCameraCountChanged(0);
|
||||
return ERR_CODE(DEV_CONFIG_ERR);
|
||||
}
|
||||
|
||||
// 初始化机械臂协议
|
||||
int nRet = InitRobotProtocol();
|
||||
if (nRet != 0) {
|
||||
m_pStatus->OnStatusUpdate("机械臂服务初始化失败");
|
||||
m_pStatus->OnWorkStatusChanged(WorkStatus::Error);
|
||||
m_bRobotConnected = false;
|
||||
} else {
|
||||
m_pStatus->OnStatusUpdate("机械臂服务初始化成功");
|
||||
}
|
||||
@ -63,49 +66,90 @@ int GrabBagPresenter::Init()
|
||||
// 通知UI相机个数
|
||||
int cameraCount = configResult.cameraList.size();
|
||||
m_pStatus->OnCameraCountChanged(cameraCount);
|
||||
|
||||
// 初始化VrEyeDevice模块
|
||||
IVrEyeDevice::CreateObject(&m_vrEyeDevice);
|
||||
|
||||
nRet = m_vrEyeDevice->InitDevice();
|
||||
ERR_CODE_RETURN(nRet);
|
||||
|
||||
if(cameraCount > 0){
|
||||
if (cameraCount >= 1) {
|
||||
// 尝试打开相机1
|
||||
// 初始化VrEyeDevice模块
|
||||
IVrEyeDevice* pDevice = nullptr;
|
||||
IVrEyeDevice::CreateObject(&pDevice);
|
||||
|
||||
nRet = pDevice->InitDevice();
|
||||
ERR_CODE_RETURN(nRet);
|
||||
|
||||
if (configResult.cameraList.size() >= 1) {
|
||||
nRet = pDevice->OpenDevice(configResult.cameraList[0].ip.c_str(), &GrabBagPresenter::_StaticCameraNotify, this);
|
||||
// 通过回调更新相机1状态
|
||||
bool camera1Connected = (SUCCESS == nRet);
|
||||
if(camera1Connected)
|
||||
{
|
||||
m_vrEyeDeviceList.push_back(pDevice);
|
||||
}
|
||||
m_pStatus->OnCamera1StatusChanged(camera1Connected);
|
||||
m_pStatus->OnStatusUpdate(camera1Connected ? "相机一连接成功" : "相机一连接失败");
|
||||
m_bCameraConnected = camera1Connected;
|
||||
}
|
||||
else {
|
||||
m_pStatus->OnCamera1StatusChanged(false);
|
||||
m_bCameraConnected = false;
|
||||
}
|
||||
ERR_CODE_RETURN(nRet);
|
||||
|
||||
if (cameraCount >= 2) {
|
||||
IVrEyeDevice* pDevice = nullptr;
|
||||
IVrEyeDevice::CreateObject(&pDevice);
|
||||
nRet = pDevice->InitDevice();
|
||||
ERR_CODE_RETURN(nRet);
|
||||
// 尝试打开相机2
|
||||
nRet = pDevice->OpenDevice(configResult.cameraList[1].ip.c_str(), &GrabBagPresenter::_StaticCameraNotify, this);
|
||||
// 通过回调更新相机2状态
|
||||
bool camera2Connected = (SUCCESS == nRet);
|
||||
if(camera2Connected)
|
||||
{
|
||||
m_vrEyeDeviceList.push_back(pDevice);
|
||||
}
|
||||
m_pStatus->OnCamera2StatusChanged(camera2Connected);
|
||||
m_pStatus->OnStatusUpdate(camera2Connected ? "相机二连接成功" : "相机二连接失败");
|
||||
// 只要有一个相机连接成功就认为相机连接正常
|
||||
if (camera2Connected) {
|
||||
m_bCameraConnected = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 如果只有一个相机,则将相机2状态设为未连接
|
||||
m_pStatus->OnCamera2StatusChanged(false);
|
||||
}
|
||||
ERR_CODE_RETURN(nRet);
|
||||
} else {
|
||||
IVrEyeDevice* pDevice = nullptr;
|
||||
IVrEyeDevice::CreateObject(&pDevice);
|
||||
nRet = pDevice->InitDevice();
|
||||
ERR_CODE_RETURN(nRet);
|
||||
// 尝试打开相机1
|
||||
nRet = m_vrEyeDevice->OpenDevice(configResult.cameraList[0].ip.c_str(), &GrabBagPresenter::_StaticCameraNotify, this);
|
||||
nRet = pDevice->OpenDevice(nullptr, &GrabBagPresenter::_StaticCameraNotify, this);
|
||||
// 通过回调更新相机1状态
|
||||
m_pStatus->OnCamera1StatusChanged(SUCCESS == nRet);
|
||||
m_pStatus->OnStatusUpdate(SUCCESS == nRet ? "相机1连接成功" : "相机1连接失败");
|
||||
bool camera1Connected = (SUCCESS == nRet);
|
||||
if(camera1Connected)
|
||||
{
|
||||
m_vrEyeDeviceList.push_back(pDevice);
|
||||
}
|
||||
m_pStatus->OnCamera1StatusChanged(camera1Connected);
|
||||
m_pStatus->OnStatusUpdate(camera1Connected ? "相机一连接成功" : "相机一连接失败");
|
||||
m_bCameraConnected = camera1Connected;
|
||||
}
|
||||
else {
|
||||
m_pStatus->OnCamera1StatusChanged(false);
|
||||
}
|
||||
m_pStatus->OnWorkStatusChanged(SUCCESS == nRet ? WorkStatus::Ready : WorkStatus::Error);
|
||||
ERR_CODE_RETURN(nRet);
|
||||
|
||||
if (configResult.cameraList.size() >= 2) {
|
||||
// 尝试打开相机2
|
||||
nRet = m_vrEyeDevice->OpenDevice(configResult.cameraList[1].ip.c_str(), &GrabBagPresenter::_StaticCameraNotify, this);
|
||||
// 通过回调更新相机2状态
|
||||
m_pStatus->OnCamera2StatusChanged(SUCCESS == nRet);
|
||||
m_pStatus->OnStatusUpdate(SUCCESS == nRet ? "相机2连接成功" : "相机2连接失败");
|
||||
}
|
||||
else {
|
||||
// 如果只有一个相机,则将相机2状态设为未连接
|
||||
m_pStatus->OnCamera2StatusChanged(false);
|
||||
}
|
||||
ERR_CODE_RETURN(nRet);
|
||||
|
||||
m_bAlgoDetectThreadRunning = true;
|
||||
std::thread algoDetectThread(&GrabBagPresenter::_AlgoDetectThread, this);
|
||||
algoDetectThread.detach();
|
||||
|
||||
m_pStatus->OnStatusUpdate("设备初始化完成");
|
||||
m_pStatus->OnWorkStatusChanged(SUCCESS == nRet ? WorkStatus::Ready : WorkStatus::Error);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// 初始化机械臂协议
|
||||
int GrabBagPresenter::InitRobotProtocol()
|
||||
{
|
||||
LOG_DEBUG("GrabBagPresenter::InitRobotProtocol - 开始初始化机械臂协议\n");
|
||||
LOG_DEBUG("Start initializing robot protocol\n");
|
||||
|
||||
// 创建RobotProtocol实例
|
||||
if(nullptr == m_pRobotProtocol){
|
||||
@ -126,7 +170,7 @@ int GrabBagPresenter::InitRobotProtocol()
|
||||
int nRet = m_pRobotProtocol->Initialize();
|
||||
ERR_CODE_RETURN(nRet);
|
||||
|
||||
LOG_INFO("GrabBagPresenter::InitRobotProtocol - 机械臂协议初始化成功\n");
|
||||
LOG_INFO("Robot protocol initialization successful\n");
|
||||
return SUCCESS;
|
||||
|
||||
}
|
||||
@ -134,17 +178,23 @@ int GrabBagPresenter::InitRobotProtocol()
|
||||
// 机械臂协议回调函数实现
|
||||
void GrabBagPresenter::OnRobotConnectionChanged(bool connected)
|
||||
{
|
||||
LOG_INFO("GrabBagPresenter::OnRobotConnectionChanged - 机械臂连接状态变化:%s\n", (connected ? "已连接" : "已断开"));
|
||||
LOG_INFO("Robot connection status changed: %s\n", (connected ? "connected" : "disconnected"));
|
||||
|
||||
// 更新机械臂连接状态
|
||||
m_bRobotConnected = connected;
|
||||
|
||||
if (m_pStatus) {
|
||||
m_pStatus->OnRobotConnectionChanged(connected);
|
||||
m_pStatus->OnStatusUpdate(connected ? "机械臂已连接" : "机械臂连接断开");
|
||||
}
|
||||
|
||||
// 检查并更新工作状态
|
||||
CheckAndUpdateWorkStatus();
|
||||
}
|
||||
|
||||
void GrabBagPresenter::OnRobotWorkSignal(bool startWork)
|
||||
{
|
||||
LOG_INFO("GrabBagPresenter::OnRobotWorkSignal - 收到机械臂工作信号:%s\n", (startWork ? "开始工作" : "停止工作"));
|
||||
LOG_INFO("Received robot work signal: %s\n", (startWork ? "start work" : "stop work"));
|
||||
|
||||
if (nullptr == m_pStatus) {
|
||||
return;
|
||||
@ -166,13 +216,233 @@ void GrabBagPresenter::SetStatusCallback(IYGrabBagStatus* status)
|
||||
// 模拟检测函数,用于演示
|
||||
int GrabBagPresenter::StartDetection()
|
||||
{
|
||||
LOG_INFO("GrabBagPresenter::StartDetection - 开始检测\n");
|
||||
LOG_INFO("Start detection\n");
|
||||
|
||||
// 检查设备状态是否准备就绪
|
||||
if (m_currentWorkStatus != WorkStatus::Ready) {
|
||||
LOG_INFO("Device not ready, cannot start detection\n");
|
||||
if (m_pStatus) {
|
||||
m_pStatus->OnStatusUpdate("设备未准备就绪,无法开始检测");
|
||||
}
|
||||
return ERR_CODE(DEV_BUSY);
|
||||
}
|
||||
|
||||
// 通知UI工作状态变更为"正在工作"
|
||||
if (m_pStatus) {
|
||||
m_currentWorkStatus = WorkStatus::Working;
|
||||
m_pStatus->OnWorkStatusChanged(WorkStatus::Working);
|
||||
}
|
||||
|
||||
if(m_vrEyeDeviceList.empty())
|
||||
{
|
||||
LOG_ERROR("No camera device found\n");
|
||||
return ERR_CODE(DEV_NOT_FIND);
|
||||
}
|
||||
|
||||
// 清空检测数据缓存
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_detectionDataMutex);
|
||||
m_detectionDataCache.clear();
|
||||
}
|
||||
|
||||
// 启动所有相机的检测
|
||||
for (size_t i = 0; i < m_vrEyeDeviceList.size(); ++i) {
|
||||
IVrEyeDevice* pDevice = m_vrEyeDeviceList[i];
|
||||
if (pDevice) {
|
||||
int ret = pDevice->StartDetect(&GrabBagPresenter::_StaticDetectionCallback, this);
|
||||
if (ret == 0) {
|
||||
LOG_INFO("Camera %zu start detection successfully\n", i + 1);
|
||||
} else {
|
||||
LOG_WARNING("Camera %zu start detection failed, error code: %d\n", i + 1, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GrabBagPresenter::StopDetection()
|
||||
{
|
||||
LOG_INFO("Stop detection\n");
|
||||
|
||||
// 停止所有相机的检测
|
||||
for (size_t i = 0; i < m_vrEyeDeviceList.size(); ++i) {
|
||||
IVrEyeDevice* pDevice = m_vrEyeDeviceList[i];
|
||||
if (pDevice) {
|
||||
int ret = pDevice->StopDetect();
|
||||
if (ret == 0) {
|
||||
LOG_INFO("Camera %zu stop detection successfully\n", i + 1);
|
||||
} else {
|
||||
LOG_WARNING("Camera %zu stop detection failed, error code: %d\n", i + 1, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 通知UI工作状态变更为"就绪"(如果设备连接正常)
|
||||
if (m_pStatus) {
|
||||
// 检查设备连接状态,决定停止后的状态
|
||||
if (m_bCameraConnected && m_bRobotConnected) {
|
||||
m_currentWorkStatus = WorkStatus::Ready;
|
||||
m_pStatus->OnWorkStatusChanged(WorkStatus::Ready);
|
||||
} else {
|
||||
m_currentWorkStatus = WorkStatus::Error;
|
||||
m_pStatus->OnWorkStatusChanged(WorkStatus::Error);
|
||||
}
|
||||
m_pStatus->OnStatusUpdate("检测已停止");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IVrEyeDevice *GrabBagPresenter::GetEyeDevice(int index)
|
||||
{
|
||||
if(m_vrEyeDeviceList.size() <= index) return nullptr;
|
||||
return m_vrEyeDeviceList[index];
|
||||
}
|
||||
|
||||
// 静态回调函数实现
|
||||
void GrabBagPresenter::_StaticCameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam)
|
||||
{
|
||||
// 从pInfoParam获取this指针,转换回GrabBagPresenter*类型
|
||||
GrabBagPresenter* pThis = reinterpret_cast<GrabBagPresenter*>(pInfoParam);
|
||||
if (pThis)
|
||||
{
|
||||
// 调用实例的非静态成员函数
|
||||
pThis->_CameraNotify(eStatus, pExtData, nDataLength, pInfoParam);
|
||||
}
|
||||
}
|
||||
|
||||
void GrabBagPresenter::_CameraNotify(EVzDeviceWorkStatus eStatus, void *pExtData, unsigned int nDataLength, void *pInfoParam)
|
||||
{
|
||||
LOG_DEBUG("Camera notify received: status=%d, dataLength=%u\n", (int)eStatus, nDataLength);
|
||||
|
||||
switch (eStatus) {
|
||||
case EVzDeviceWorkStatus::keDeviceWorkStatus_Offline:
|
||||
{
|
||||
LOG_WARNING("Camera device offline/disconnected\n");
|
||||
|
||||
// 更新相机连接状态
|
||||
m_bCameraConnected = false;
|
||||
|
||||
// 通知UI相机状态变更
|
||||
if (m_pStatus) {
|
||||
// 这里需要判断是哪个相机离线,暂时更新相机1状态
|
||||
// 实际应用中可能需要通过pInfoParam或其他方式区分具体哪个相机
|
||||
m_pStatus->OnCamera1StatusChanged(false);
|
||||
m_pStatus->OnStatusUpdate("相机设备离线");
|
||||
}
|
||||
|
||||
// 检查并更新工作状态
|
||||
CheckAndUpdateWorkStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
case EVzDeviceWorkStatus::keDeviceWorkStatus_Eye_Reconnect:
|
||||
{
|
||||
LOG_INFO("Camera device online/connected\n");
|
||||
|
||||
// 更新相机连接状态
|
||||
m_bCameraConnected = true;
|
||||
|
||||
// 通知UI相机状态变更
|
||||
if (m_pStatus) {
|
||||
m_pStatus->OnCamera1StatusChanged(true);
|
||||
m_pStatus->OnStatusUpdate("相机设备已连接");
|
||||
}
|
||||
|
||||
// 检查并更新工作状态
|
||||
CheckAndUpdateWorkStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
case EVzDeviceWorkStatus::keDeviceWorkStatus_Device_Swing_Finish:
|
||||
{
|
||||
LOG_INFO("Received scan/trigger signal from camera\n");
|
||||
|
||||
// 如果当前状态为就绪,通知检测线程开始处理
|
||||
if (m_currentWorkStatus == WorkStatus::Ready) {
|
||||
LOG_INFO("Notifying detection thread to start processing\n");
|
||||
|
||||
// 通知算法检测线程
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_algoDetectMutex);
|
||||
// 这里可以设置一个标志位,或者直接通知条件变量
|
||||
}
|
||||
m_algoDetectCondition.notify_one();
|
||||
|
||||
if (m_pStatus) {
|
||||
m_pStatus->OnStatusUpdate("收到扫描信号,开始检测处理");
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("Received scan signal but device not ready, current status: %d\n", (int)m_currentWorkStatus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG_DEBUG("Unhandled camera status: %d\n", (int)eStatus);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 检测数据回调函数静态版本
|
||||
void GrabBagPresenter::_StaticDetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint, void* pUserData)
|
||||
{
|
||||
GrabBagPresenter* pThis = reinterpret_cast<GrabBagPresenter*>(pUserData);
|
||||
if (pThis && pLaserLinePoint) {
|
||||
pThis->_DetectionCallback(eDataType, pLaserLinePoint);
|
||||
}
|
||||
}
|
||||
|
||||
// 检测数据回调函数实例版本
|
||||
void GrabBagPresenter::_DetectionCallback(EVzResultDataType eDataType, SVzLaserLineData* pLaserLinePoint)
|
||||
{
|
||||
if (!pLaserLinePoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 将检测数据保存到缓存中
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_detectionDataMutex);
|
||||
m_detectionDataCache.push_back(pLaserLinePoint);
|
||||
|
||||
// LOG_DEBUG("Detection data cached: Frame %llu, Points: %d\n",
|
||||
// pLaserLinePoint->sLineData.llFrameIdx,
|
||||
// pLaserLinePoint->sLineData.nPointCount);
|
||||
}
|
||||
}
|
||||
|
||||
void GrabBagPresenter::CheckAndUpdateWorkStatus()
|
||||
{
|
||||
if (m_bCameraConnected && m_bRobotConnected) {
|
||||
m_currentWorkStatus = WorkStatus::Ready;
|
||||
m_pStatus->OnWorkStatusChanged(WorkStatus::Ready);
|
||||
m_pStatus->OnStatusUpdate("设备已准备好");
|
||||
} else {
|
||||
m_currentWorkStatus = WorkStatus::Error;
|
||||
m_pStatus->OnWorkStatusChanged(WorkStatus::Error);
|
||||
m_pStatus->OnStatusUpdate("设备未准备好");
|
||||
}
|
||||
}
|
||||
|
||||
void GrabBagPresenter::_AlgoDetectThread()
|
||||
{
|
||||
while(m_bAlgoDetectThreadRunning)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_algoDetectMutex);
|
||||
m_algoDetectCondition.wait(lock, [this]() {
|
||||
return m_currentWorkStatus == WorkStatus::Ready;
|
||||
});
|
||||
|
||||
// 检查设备状态是否准备就绪
|
||||
|
||||
_DetectTask();
|
||||
}
|
||||
}
|
||||
|
||||
int GrabBagPresenter::_DetectTask()
|
||||
{
|
||||
// 创建测试图像
|
||||
QImage image(":/resource/result_image.jpg");
|
||||
|
||||
@ -229,6 +499,7 @@ int GrabBagPresenter::StartDetection()
|
||||
|
||||
// 检测完成后,将工作状态更新为"完成"
|
||||
if (m_pStatus) {
|
||||
m_currentWorkStatus = WorkStatus::Completed;
|
||||
m_pStatus->OnWorkStatusChanged(WorkStatus::Completed);
|
||||
}
|
||||
|
||||
@ -247,41 +518,11 @@ int GrabBagPresenter::StartDetection()
|
||||
detectedCoord.rz = firstPos.yaw;
|
||||
m_pRobotProtocol->SetRobotCoordinate(detectedCoord);
|
||||
|
||||
LOG_INFO("GrabBagPresenter::StartDetection - 更新检测结果坐标: X=%.2f, Y=%.2f, Z=%.2f\n",
|
||||
LOG_INFO("Update detection result coordinates: X=%.2f, Y=%.2f, Z=%.2f\n",
|
||||
detectedCoord.x, detectedCoord.y, detectedCoord.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GrabBagPresenter::StopDetection()
|
||||
{
|
||||
LOG_INFO("GrabBagPresenter::StopDetection - 停止检测\n");
|
||||
|
||||
// 通知UI工作状态变更为"就绪"
|
||||
if (m_pStatus) {
|
||||
m_pStatus->OnWorkStatusChanged(WorkStatus::Ready);
|
||||
m_pStatus->OnStatusUpdate("检测已停止");
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 静态回调函数实现
|
||||
void GrabBagPresenter::_StaticCameraNotify(EVzDeviceWorkStatus eStatus, void* pExtData, unsigned int nDataLength, void* pInfoParam)
|
||||
{
|
||||
// 从pInfoParam获取this指针,转换回GrabBagPresenter*类型
|
||||
GrabBagPresenter* pThis = reinterpret_cast<GrabBagPresenter*>(pInfoParam);
|
||||
if (pThis)
|
||||
{
|
||||
// 调用实例的非静态成员函数
|
||||
pThis->_CameraNotify(eStatus, pExtData, nDataLength, pInfoParam);
|
||||
}
|
||||
}
|
||||
|
||||
void GrabBagPresenter::_CameraNotify(EVzDeviceWorkStatus eStatus, void *pExtData, unsigned int nDataLength, void *pInfoParam)
|
||||
{
|
||||
|
||||
m_currentWorkStatus = WorkStatus::Ready;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ RobotProtocol::~RobotProtocol()
|
||||
int RobotProtocol::Initialize(uint16_t port)
|
||||
{
|
||||
if (m_bServerRunning) {
|
||||
LOG_WARNING("RobotProtocol::Initialize - 服务已经在运行中\n");
|
||||
LOG_WARNING("Server is already running\n");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -29,20 +29,40 @@ int RobotProtocol::Initialize(uint16_t port)
|
||||
|
||||
// 创建ModbusTCP服务器实例
|
||||
bool bRet = IYModbusTCPServer::CreateInstance(&m_pModbusServer);
|
||||
LOG_ERRO("RobotProtocol::%s - 创建ModbusTCP服务器%s \n", __func__, bRet ? "失败" : "成功");
|
||||
LOG_ERRO("Create ModbusTCP server %s \n", bRet ? "success" : "failed");
|
||||
m_bServerRunning = bRet;
|
||||
ERR_CODE_RETURN(NET_ERR_CREAT_INIT);
|
||||
|
||||
|
||||
// 设置ModbusTCP回调函数
|
||||
if (m_pModbusServer) {
|
||||
// 设置写线圈回调
|
||||
m_pModbusServer->setWriteCoilsCallback([this](uint8_t unitId, uint16_t startAddress, uint16_t quantity, const uint8_t* values) {
|
||||
return this->OnWriteCoils(unitId, startAddress, quantity, values);
|
||||
});
|
||||
|
||||
// 设置写寄存器回调
|
||||
m_pModbusServer->setWriteRegistersCallback([this](uint8_t unitId, uint16_t startAddress, uint16_t quantity, const uint16_t* values) {
|
||||
return this->OnWriteRegisters(unitId, startAddress, quantity, values);
|
||||
});
|
||||
|
||||
// 设置连接状态回调
|
||||
m_pModbusServer->setConnectionStatusCallback([this](bool connected) {
|
||||
this->OnModbusTCPConnectionChanged(connected);
|
||||
});
|
||||
}
|
||||
|
||||
int nRet = m_pModbusServer->start();
|
||||
ERR_CODE_RETURN(nRet);
|
||||
|
||||
// 设置初始状态
|
||||
m_robotStatus = STATUS_CONNECTED;
|
||||
|
||||
LOG_INFO("RobotProtocol::Initialize - ModbusTCP服务初始化完成\n");
|
||||
return 0;
|
||||
LOG_INFO("ModbusTCP service initialization completed\n");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void RobotProtocol::Deinitialize()
|
||||
{
|
||||
LOG_DEBUG("RobotProtocol::Deinitialize - 停止ModbusTCP服务\n");
|
||||
LOG_DEBUG("Stop ModbusTCP service\n");
|
||||
|
||||
// 停止ModbusTCP服务器
|
||||
StopModbusTCPServer();
|
||||
@ -51,14 +71,14 @@ void RobotProtocol::Deinitialize()
|
||||
m_robotStatus = STATUS_DISCONNECTED;
|
||||
m_bServerRunning = false;
|
||||
|
||||
LOG_INFO("RobotProtocol::Deinitialize - ModbusTCP服务已停止\n");
|
||||
LOG_INFO("ModbusTCP service stopped\n");
|
||||
}
|
||||
|
||||
int RobotProtocol::SetRobotCoordinate(const RobotCoordinate& coordinate)
|
||||
{
|
||||
LOG_DEBUG("RobotProtocol::SetRobotCoordinate - 设置机械臂坐标\n");
|
||||
LOG_DEBUG("坐标: X=%.2f, Y=%.2f, Z=%.2f\n", coordinate.x, coordinate.y, coordinate.z);
|
||||
LOG_DEBUG("旋转: RX=%.2f, RY=%.2f, RZ=%.2f\n", coordinate.rx, coordinate.ry, coordinate.rz);
|
||||
LOG_DEBUG("Set robot arm coordinates\n");
|
||||
LOG_DEBUG("Coordinates: X=%.2f, Y=%.2f, Z=%.2f\n", coordinate.x, coordinate.y, coordinate.z);
|
||||
LOG_DEBUG("Rotation: RX=%.2f, RY=%.2f, RZ=%.2f\n", coordinate.rx, coordinate.ry, coordinate.rz);
|
||||
|
||||
m_robotCoordinate = coordinate;
|
||||
|
||||
@ -93,7 +113,7 @@ bool RobotProtocol::IsRunning() const
|
||||
|
||||
void RobotProtocol::StopModbusTCPServer()
|
||||
{
|
||||
LOG_DEBUG("RobotProtocol::StopModbusTCPServer - 停止ModbusTCP服务器\n");
|
||||
LOG_DEBUG("Stop ModbusTCP server\n");
|
||||
|
||||
if (m_pModbusServer) {
|
||||
// 释放资源
|
||||
@ -102,22 +122,20 @@ void RobotProtocol::StopModbusTCPServer()
|
||||
}
|
||||
|
||||
m_bServerRunning = false;
|
||||
LOG_INFO("RobotProtocol::StopModbusTCPServer - ModbusTCP服务器已停止\n");
|
||||
LOG_INFO("ModbusTCP server stopped\n");
|
||||
}
|
||||
|
||||
IYModbusTCPServer::ErrorCode RobotProtocol::OnWriteCoils(uint8_t unitId, uint16_t startAddress,
|
||||
uint16_t quantity, const uint8_t* values)
|
||||
{
|
||||
LOG_DEBUG("RobotProtocol::OnWriteCoils - 单元ID:%d, 起始地址:%d, 数量:%d\n",
|
||||
unitId, startAddress, quantity);
|
||||
LOG_DEBUG("Write coils - UnitID:%d, StartAddress:%d, Quantity:%d\n", unitId, startAddress, quantity);
|
||||
|
||||
// 处理工作信号线圈
|
||||
if (startAddress <= WORK_SIGNAL_COIL && startAddress + quantity > WORK_SIGNAL_COIL) {
|
||||
uint16_t coilIndex = WORK_SIGNAL_COIL - startAddress;
|
||||
bool workSignal = (values[coilIndex / 8] >> (coilIndex % 8)) & 0x01;
|
||||
|
||||
LOG_INFO("RobotProtocol::OnWriteCoils - 收到工作信号:%s\n",
|
||||
(workSignal ? "开始工作" : "停止工作"));
|
||||
LOG_INFO("Received work signal: %s\n", (workSignal ? "start work" : "stop work"));
|
||||
|
||||
// 触发工作信号回调
|
||||
if (m_workSignalCallback) {
|
||||
@ -131,8 +149,7 @@ IYModbusTCPServer::ErrorCode RobotProtocol::OnWriteCoils(uint8_t unitId, uint16_
|
||||
IYModbusTCPServer::ErrorCode RobotProtocol::OnWriteRegisters(uint8_t unitId, uint16_t startAddress,
|
||||
uint16_t quantity, const uint16_t* values)
|
||||
{
|
||||
LOG_DEBUG("RobotProtocol::OnWriteRegisters - 单元ID:%d, 起始地址:%d, 数量:%d\n",
|
||||
unitId, startAddress, quantity);
|
||||
LOG_DEBUG("Write registers - UnitID:%d, StartAddress:%d, Quantity:%d\n", unitId, startAddress, quantity);
|
||||
|
||||
// 处理坐标寄存器更新
|
||||
if (startAddress >= COORD_X_ADDR && startAddress < STATUS_ADDR) {
|
||||
@ -168,7 +185,7 @@ IYModbusTCPServer::ErrorCode RobotProtocol::OnWriteRegisters(uint8_t unitId, uin
|
||||
IYModbusTCPServer::ErrorCode RobotProtocol::OnReadHoldingRegisters(uint8_t unitId, uint16_t startAddress,
|
||||
uint16_t quantity, uint16_t* values)
|
||||
{
|
||||
LOG_DEBUG("RobotProtocol::OnReadHoldingRegisters - 单元ID:%d, 起始地址:%d, 数量:%d\n",
|
||||
LOG_DEBUG("Read holding registers - UnitID:%d, StartAddress:%d, Quantity:%d\n",
|
||||
unitId, startAddress, quantity);
|
||||
|
||||
for (uint16_t i = 0; i < quantity; i++) {
|
||||
@ -202,4 +219,20 @@ IYModbusTCPServer::ErrorCode RobotProtocol::OnReadHoldingRegisters(uint8_t unitI
|
||||
}
|
||||
|
||||
return IYModbusTCPServer::ErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
void RobotProtocol::OnModbusTCPConnectionChanged(bool connected)
|
||||
{
|
||||
if (connected) {
|
||||
LOG_INFO("ModbusTCP connection established\n");
|
||||
m_robotStatus = STATUS_CONNECTED;
|
||||
} else {
|
||||
LOG_INFO("ModbusTCP connection lost\n");
|
||||
m_robotStatus = STATUS_DISCONNECTED;
|
||||
}
|
||||
|
||||
// 触发上层连接状态回调
|
||||
if (m_connectionCallback) {
|
||||
m_connectionCallback(connected);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,165 @@
|
||||
#include "dialogcamera.h"
|
||||
#include "ui_dialogcamera.h"
|
||||
#include <QMessageBox>
|
||||
#include "VrSimpleLog.h"
|
||||
|
||||
DialogCamera::DialogCamera(QWidget *parent) :
|
||||
DialogCamera::DialogCamera(IVrEyeDevice* pDevice, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::DialogCamera)
|
||||
ui(new Ui::DialogCamera),
|
||||
m_pDevice(pDevice)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
// 检查设备是否有效
|
||||
if (!m_pDevice) {
|
||||
setWindowTitle("相机参数配置 - 设备错误");
|
||||
// 禁用所有控件
|
||||
setEnabled(false);
|
||||
return;
|
||||
} else {
|
||||
setWindowTitle("相机参数配置");
|
||||
}
|
||||
|
||||
// 初始化界面数据
|
||||
InitCameraParameters();
|
||||
}
|
||||
|
||||
DialogCamera::~DialogCamera()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void DialogCamera::on_btn_camer_ok_clicked()
|
||||
{
|
||||
if (!m_pDevice) {
|
||||
QMessageBox::warning(this, "错误", "设备未初始化");
|
||||
return;
|
||||
}
|
||||
|
||||
// 应用参数配置
|
||||
if (ApplyCameraParameters()) {
|
||||
QMessageBox::information(this, "成功", "相机参数配置成功!");
|
||||
accept(); // 关闭对话框并返回Accepted
|
||||
} else {
|
||||
QMessageBox::warning(this, "失败", "相机参数配置失败,请检查设备连接!");
|
||||
}
|
||||
}
|
||||
|
||||
void DialogCamera::on_btn_camer_cancel_clicked()
|
||||
{
|
||||
// 直接关闭窗口,不保存任何更改
|
||||
reject();
|
||||
}
|
||||
|
||||
void DialogCamera::InitCameraParameters()
|
||||
{
|
||||
if (!m_pDevice) return;
|
||||
|
||||
try {
|
||||
// 获取曝光时间
|
||||
unsigned int exposeTime = 0;
|
||||
if (m_pDevice->GetEyeExpose(exposeTime) == 0) {
|
||||
// 假设UI中有一个名为spinBox_expose的控件
|
||||
ui->lineEdit_export->setText(QString::number(exposeTime));
|
||||
LOG_DEBUG("Current expose time: %u\n", exposeTime);
|
||||
}
|
||||
|
||||
// 获取增益
|
||||
unsigned int gain = 0;
|
||||
if (m_pDevice->GetEyeGain(gain) == 0) {
|
||||
// 假设UI中有一个名为spinBox_gain的控件
|
||||
ui->lineEdit_gain->setText(QString::number(gain));
|
||||
LOG_DEBUG("Current gain: %u\n", gain);
|
||||
}
|
||||
|
||||
// 获取帧率
|
||||
int frame = 0;
|
||||
if (m_pDevice->GetFrame(frame) == 0) {
|
||||
// 假设UI中有一个名为spinBox_frame的控件
|
||||
ui->lineEdit_frame->setText(QString::number(frame));
|
||||
LOG_DEBUG("Current frame rate: %d\n", frame);
|
||||
}
|
||||
|
||||
// 获取摆动速度
|
||||
float swingSpeed = 0.0f;
|
||||
if (m_pDevice->GetSwingSpeed(swingSpeed) == 0) {
|
||||
// 假设UI中有一个名为doubleSpinBox_swing_speed的控件
|
||||
ui->lineEdit_swing_speed->setText(QString::number(swingSpeed));
|
||||
LOG_DEBUG("Swing speed: %.3f\n", swingSpeed);
|
||||
}
|
||||
|
||||
// 获取工作角度
|
||||
float minAngle = 0.0f, maxAngle = 0.0f;
|
||||
if (m_pDevice->GetSwingAngle(minAngle, maxAngle) == 0) {
|
||||
// 假设UI中有角度相关的控件
|
||||
ui->lineEdit_swing_start->setText(QString::number(minAngle));
|
||||
ui->lineEdit_swing_stop->setText(QString::number(maxAngle));
|
||||
LOG_DEBUG("Swing angle range: %.3f to %.3f\n", minAngle, maxAngle);
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
QMessageBox::warning(this, "错误", "读取相机参数时发生异常");
|
||||
}
|
||||
}
|
||||
|
||||
bool DialogCamera::ApplyCameraParameters()
|
||||
{
|
||||
if (!m_pDevice) return false;
|
||||
|
||||
try {
|
||||
bool success = true;
|
||||
|
||||
// 设置曝光时间
|
||||
unsigned int exposeTime = ui->lineEdit_export->text().toUInt();
|
||||
if (m_pDevice->SetEyeExpose(exposeTime) != 0) {
|
||||
LOG_WARNING("Failed to set expose time: %u\n", exposeTime);
|
||||
success = false;
|
||||
} else {
|
||||
LOG_INFO("Set expose time: %u\n", exposeTime);
|
||||
}
|
||||
|
||||
// 设置增益
|
||||
unsigned int gain = ui->lineEdit_gain->text().toUInt();
|
||||
if (m_pDevice->SetEyeGain(gain) != 0) {
|
||||
LOG_WARNING("Failed to set gain: %u\n", gain);
|
||||
success = false;
|
||||
} else {
|
||||
LOG_INFO("Set gain: %u\n", gain);
|
||||
}
|
||||
|
||||
// 设置帧率
|
||||
int frame = ui->lineEdit_frame->text().toInt();
|
||||
if (m_pDevice->SetFrame(frame) != 0) {
|
||||
LOG_WARNING("Failed to set frame rate: %d\n", frame);
|
||||
success = false;
|
||||
} else {
|
||||
LOG_INFO("Set frame rate: %d\n", frame);
|
||||
}
|
||||
|
||||
// 设置摆动速度
|
||||
float swingSpeed = ui->lineEdit_swing_speed->text().toFloat();
|
||||
if (m_pDevice->SetSwingSpeed(swingSpeed) != 0) {
|
||||
LOG_WARNING("Failed to set swing speed: %.3f\n", swingSpeed);
|
||||
success = false;
|
||||
} else {
|
||||
LOG_INFO("Set swing speed: %.3f\n", swingSpeed);
|
||||
}
|
||||
|
||||
// 设置工作角度
|
||||
float minAngle = ui->lineEdit_swing_start->text().toFloat();
|
||||
float maxAngle = ui->lineEdit_swing_stop->text().toFloat();
|
||||
if (m_pDevice->SetSwingAngle(minAngle, maxAngle) != 0) {
|
||||
LOG_WARNING("Failed to set swing angle: %.3f to %.3f\n", minAngle, maxAngle);
|
||||
success = false;
|
||||
} else {
|
||||
LOG_INFO("Set swing angle: %.3f to %.3f\n", minAngle, maxAngle);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
} catch (...) {
|
||||
QMessageBox::warning(this, "错误", "应用相机参数时发生异常");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define DIALOGCAMERA_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <IVrEyeDevice.h>
|
||||
|
||||
namespace Ui {
|
||||
class DialogCamera;
|
||||
@ -12,11 +13,23 @@ class DialogCamera : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DialogCamera(QWidget *parent = nullptr);
|
||||
explicit DialogCamera(IVrEyeDevice* pDevice, QWidget *parent = nullptr);
|
||||
~DialogCamera();
|
||||
|
||||
private slots:
|
||||
void on_btn_camer_ok_clicked();
|
||||
void on_btn_camer_cancel_clicked();
|
||||
|
||||
private:
|
||||
// 初始化相机参数到界面
|
||||
void InitCameraParameters();
|
||||
|
||||
// 应用界面参数到相机
|
||||
bool ApplyCameraParameters();
|
||||
|
||||
private:
|
||||
Ui::DialogCamera *ui;
|
||||
IVrEyeDevice* m_pDevice = nullptr;
|
||||
};
|
||||
|
||||
#endif // DIALOGCAMERA_H
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<property name="windowTitle">
|
||||
<string>相机配置</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="label_camera_title">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
@ -51,7 +51,7 @@
|
||||
<property name="title">
|
||||
<string>基本参数</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="">
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
@ -81,7 +81,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<widget class="QLineEdit" name="lineEdit_export">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
@ -106,7 +106,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_2">
|
||||
<widget class="QLineEdit" name="lineEdit_gain">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
@ -131,7 +131,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_3">
|
||||
<widget class="QLineEdit" name="lineEdit_frame">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
@ -191,7 +191,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_4">
|
||||
<widget class="QLineEdit" name="lineEdit_swing_speed">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
@ -216,7 +216,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_5">
|
||||
<widget class="QLineEdit" name="lineEdit_swing_start">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
@ -241,7 +241,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_6">
|
||||
<widget class="QLineEdit" name="lineEdit_swing_stop">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
@ -254,7 +254,7 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<widget class="QPushButton" name="btn_camer_ok">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>120</x>
|
||||
@ -272,7 +272,7 @@
|
||||
<string>应用</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<widget class="QPushButton" name="btn_camer_cancel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>280</x>
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>0</y>
|
||||
<width>651</width>
|
||||
<y>20</y>
|
||||
<width>601</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -28,7 +28,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>区域标定</string>
|
||||
<string>区域框定</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
@ -97,7 +97,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
<string>mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -134,7 +134,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
<string>mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -171,7 +171,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
<string>mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -243,7 +243,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
<string>mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -280,7 +280,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
<string>mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -317,7 +317,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
<string>mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -389,7 +389,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
<string>mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -426,7 +426,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
<string>mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -463,7 +463,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
<string>mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QBrush>
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
@ -36,11 +36,17 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
setStatusDot(ui->label_camera_1_status, false); // 在线绿色
|
||||
setStatusDot(ui->label_camera_2_status, false); // 在线绿色
|
||||
setStatusDot(ui->label_robot_status, false); // 在线绿色
|
||||
|
||||
|
||||
// 连接菜单信号
|
||||
connect(ui->menu_camera, &QMenu::aboutToShow, this, &MainWindow::on_menu_camera_triggered);
|
||||
connect(ui->menu_config, &QMenu::aboutToShow, this, &MainWindow::on_menu_config_triggered);
|
||||
connect(ui->menu_camera_adjust, &QMenu::aboutToShow, this, &MainWindow::on_menu_camera_adjust_triggered);
|
||||
// connect(ui->menu_camera, &QMenu::aboutToShow, this, &MainWindow::on_menu_camera_triggered);
|
||||
// connect(ui->menu_config, &QMenu::aboutToShow, this, &MainWindow::on_menu_config_triggered);
|
||||
// connect(ui->menu_camera_adjust, &QMenu::aboutToShow, this, &MainWindow::on_menu_camera_adjust_triggered);
|
||||
|
||||
// 连接工作状态更新信号槽
|
||||
connect(this, &MainWindow::workStatusUpdateRequested, this, &MainWindow::updateWorkStatusLabel);
|
||||
|
||||
// 连接检测结果更新信号槽
|
||||
connect(this, &MainWindow::detectionResultUpdateRequested, this, &MainWindow::updateDetectionResultDisplay);
|
||||
|
||||
updateStatusLog(tr("就绪"));
|
||||
|
||||
@ -140,10 +146,10 @@ void MainWindow::setStatusDot(QLabel* label, bool isOnline) {
|
||||
|
||||
void MainWindow::on_btn_camera_clicked()
|
||||
{
|
||||
if(nullptr == ui_dialogCamera){
|
||||
ui_dialogCamera = new DialogCamera;
|
||||
}
|
||||
ui_dialogCamera->show();
|
||||
// if(nullptr == ui_dialogCamera){
|
||||
// ui_dialogCamera = new DialogCamera;
|
||||
// }
|
||||
// ui_dialogCamera->show();
|
||||
}
|
||||
|
||||
void MainWindow::on_btn_config_clicked()
|
||||
@ -154,16 +160,13 @@ void MainWindow::on_btn_config_clicked()
|
||||
ui_dialogConfig->show();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_btn_flow_clicked()
|
||||
{
|
||||
// 机械臂连接/断开
|
||||
static bool isConnected = false;
|
||||
isConnected = !isConnected;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_btn_start_clicked()
|
||||
{
|
||||
// 使用Presenter启动检测
|
||||
@ -172,7 +175,6 @@ void MainWindow::on_btn_start_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_btn_stop_clicked()
|
||||
{
|
||||
if (m_presenter) {
|
||||
@ -180,25 +182,19 @@ void MainWindow::on_btn_stop_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_menu_camera_triggered()
|
||||
{
|
||||
qDebug() << __func__ ;
|
||||
if(nullptr == ui_dialogCamera){
|
||||
ui_dialogCamera = new DialogCamera(this);
|
||||
}
|
||||
ui_dialogCamera->show();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_menu_config_triggered()
|
||||
{
|
||||
qDebug() << __func__ ;
|
||||
if(nullptr == ui_dialogConfig){
|
||||
ui_dialogConfig = new DialogConfig(this);
|
||||
}
|
||||
ui_dialogConfig->show();
|
||||
}
|
||||
//void MainWindow::on_menu_camera_triggered()
|
||||
//{
|
||||
// qDebug() << __func__ ;
|
||||
//}
|
||||
|
||||
//void MainWindow::on_menu_config_triggered()
|
||||
//{
|
||||
// qDebug() << __func__ ;
|
||||
// if(nullptr == ui_dialogConfig){
|
||||
// ui_dialogConfig = new DialogConfig(this);
|
||||
// }
|
||||
// ui_dialogConfig->show();
|
||||
//}
|
||||
|
||||
void MainWindow::on_menu_camera_adjust_triggered()
|
||||
{
|
||||
@ -213,11 +209,8 @@ void MainWindow::OnStatusUpdate(const std::string& statusMessage)
|
||||
|
||||
void MainWindow::OnDetectionResult(const DetectionResult& result)
|
||||
{
|
||||
// 显示检测结果图像
|
||||
displayImage(result.image);
|
||||
|
||||
// 添加检测结果到列表
|
||||
addDetectionResult(result);
|
||||
// 通过信号槽机制更新UI(确保在主线程中执行)
|
||||
emit detectionResultUpdateRequested(result);
|
||||
}
|
||||
|
||||
void MainWindow::OnCamera1StatusChanged(bool isConnected)
|
||||
@ -226,7 +219,7 @@ void MainWindow::OnCamera1StatusChanged(bool isConnected)
|
||||
setStatusDot(ui->label_camera_1_status, isConnected);
|
||||
|
||||
// 更新状态消息
|
||||
QString statusMsg = isConnected ? tr("相机1已连接") : tr("相机1已断开");
|
||||
QString statusMsg = isConnected ? tr("相机一已连接") : tr("相机一已断开");
|
||||
ui->label_camera_1_txt->setText(statusMsg);
|
||||
updateStatusLog(statusMsg);
|
||||
}
|
||||
@ -238,7 +231,7 @@ void MainWindow::OnCamera2StatusChanged(bool isConnected)
|
||||
setStatusDot(ui->label_camera_2_status, isConnected);
|
||||
|
||||
// 更新状态消息
|
||||
QString statusMsg = isConnected ? tr("相机2已连接") : tr("相机2已断开");
|
||||
QString statusMsg = isConnected ? tr("相机二已连接") : tr("相机二已断开");
|
||||
ui->label_camera_2_txt->setText(statusMsg);
|
||||
updateStatusLog(statusMsg);
|
||||
}
|
||||
@ -272,11 +265,17 @@ void MainWindow::OnRobotConnectionChanged(bool isConnected)
|
||||
|
||||
// 更新状态消息
|
||||
QString statusMsg = isConnected ? tr("机械臂已连接") : tr("机械臂已断开");
|
||||
updateStatusLog(statusMsg);
|
||||
updateStatusLog(statusMsg);
|
||||
}
|
||||
|
||||
// 工作状态更新槽函数
|
||||
void MainWindow::OnWorkStatusChanged(WorkStatus status)
|
||||
{
|
||||
// 通过信号槽机制更新UI(确保在主线程中执行)
|
||||
emit workStatusUpdateRequested(status);
|
||||
}
|
||||
|
||||
void MainWindow::updateWorkStatusLabel(WorkStatus status)
|
||||
{
|
||||
// 获取状态对应的显示文本
|
||||
QString statusText = QString::fromStdString(WorkStatusToString(status));
|
||||
@ -309,6 +308,40 @@ void MainWindow::OnWorkStatusChanged(WorkStatus status)
|
||||
updateStatusLog(statusText);
|
||||
}
|
||||
|
||||
void MainWindow::updateDetectionResultDisplay(const DetectionResult& result)
|
||||
{
|
||||
// 实现检测结果显示的逻辑
|
||||
displayImage(result.image);
|
||||
addDetectionResult(result);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_action_camera_1_triggered()
|
||||
{
|
||||
IVrEyeDevice* pDevice = m_presenter->GetEyeDevice(0);
|
||||
if(nullptr == pDevice){
|
||||
QMessageBox::warning(this, "设备错误", "相机设备未正确初始化!");
|
||||
return;
|
||||
}
|
||||
if(nullptr == ui_dialogCamera){
|
||||
ui_dialogCamera = new DialogCamera(pDevice, this);
|
||||
}
|
||||
ui_dialogCamera->show();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_action_camera_2_triggered()
|
||||
{
|
||||
IVrEyeDevice* pDevice = m_presenter->GetEyeDevice(1);
|
||||
if(nullptr == pDevice){
|
||||
QMessageBox::warning(this, "设备错误", "相机设备未正确初始化!");
|
||||
return;
|
||||
}
|
||||
if(nullptr == ui_dialogCamera){
|
||||
ui_dialogCamera = new DialogCamera(pDevice, this);
|
||||
}
|
||||
ui_dialogCamera->show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
@ -36,6 +36,13 @@ public:
|
||||
virtual void OnCameraCountChanged(int cameraCount) override;
|
||||
virtual void OnWorkStatusChanged(WorkStatus status) override;
|
||||
|
||||
signals:
|
||||
// 工作状态更新信号
|
||||
void workStatusUpdateRequested(WorkStatus status);
|
||||
|
||||
// 检测结果更新信号
|
||||
void detectionResultUpdateRequested(const DetectionResult& result);
|
||||
|
||||
private slots:
|
||||
// UI操作相关槽
|
||||
void on_btn_camera_clicked();
|
||||
@ -43,9 +50,19 @@ private slots:
|
||||
void on_btn_flow_clicked();
|
||||
void on_btn_start_clicked();
|
||||
void on_btn_stop_clicked();
|
||||
void on_menu_camera_triggered();
|
||||
void on_menu_config_triggered();
|
||||
// void on_menu_camera_triggered();
|
||||
// void on_menu_config_triggered();
|
||||
void on_menu_camera_adjust_triggered();
|
||||
|
||||
// 工作状态更新槽函数
|
||||
void updateWorkStatusLabel(WorkStatus status);
|
||||
|
||||
// 检测结果更新槽函数
|
||||
void updateDetectionResultDisplay(const DetectionResult& result);
|
||||
|
||||
void on_action_camera_1_triggered();
|
||||
|
||||
void on_action_camera_2_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
@ -197,6 +197,8 @@
|
||||
<property name="title">
|
||||
<string>相机配置</string>
|
||||
</property>
|
||||
<addaction name="action_camera_1"/>
|
||||
<addaction name="action_camera_2"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_config">
|
||||
<property name="title">
|
||||
@ -219,6 +221,16 @@
|
||||
<addaction name="menu_4"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="action_camera_1">
|
||||
<property name="text">
|
||||
<string>相机一配置</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_camera_2">
|
||||
<property name="text">
|
||||
<string>相机二配置</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@ -32,6 +32,9 @@ public:
|
||||
|
||||
// 写保持寄存器回调函数:unitId, startAddress, quantity, values -> ErrorCode
|
||||
using WriteRegistersCallback = std::function<ErrorCode(uint8_t, uint16_t, uint16_t, const uint16_t*)>;
|
||||
|
||||
// 连接状态回调函数:isConnected -> void
|
||||
using ConnectionStatusCallback = std::function<void(bool)>;
|
||||
|
||||
public:
|
||||
virtual ~IYModbusTCPServer() = default;
|
||||
@ -39,12 +42,13 @@ public:
|
||||
static bool CreateInstance(IYModbusTCPServer** ppModbusTCPServer);
|
||||
|
||||
// 启动/停止服务器
|
||||
virtual bool start(int port = 502, int maxConnections = 10) = 0;
|
||||
virtual int start(int port = 502, int maxConnections = 10) = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
// 设置回调函数
|
||||
virtual void setWriteCoilsCallback(WriteCoilsCallback callback) = 0;
|
||||
virtual void setWriteRegistersCallback(WriteRegistersCallback callback) = 0;
|
||||
virtual void setConnectionStatusCallback(ConnectionStatusCallback callback) = 0;
|
||||
|
||||
// 更新数据接口 - 线程安全
|
||||
virtual void updateCoil(uint16_t address, bool value) = 0;
|
||||
|
||||
@ -19,6 +19,10 @@ DEFINES += DLLBUILD
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
|
||||
|
||||
INCLUDEPATH += ../../VrCommon/Inc
|
||||
INCLUDEPATH += ../../VrUtils/Inc
|
||||
|
||||
INCLUDEPATH += ./Inc
|
||||
INCLUDEPATH += ./_Inc
|
||||
|
||||
|
||||
@ -3,6 +3,9 @@
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "VrError.h"
|
||||
#include "VrSimpleLog.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
@ -32,11 +35,11 @@ ModbusTCPServer::~ModbusTCPServer()
|
||||
stop();
|
||||
}
|
||||
|
||||
bool ModbusTCPServer::start(int port, int maxConnections)
|
||||
int ModbusTCPServer::start(int port, int maxConnections)
|
||||
{
|
||||
if (m_isRunning.load()) {
|
||||
setLastError("服务器已在运行");
|
||||
return true;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
m_port = port;
|
||||
@ -46,7 +49,7 @@ bool ModbusTCPServer::start(int port, int maxConnections)
|
||||
m_modbusCtx = modbus_new_tcp("0.0.0.0", port);
|
||||
if (m_modbusCtx == nullptr) {
|
||||
setLastError("创建Modbus TCP上下文失败");
|
||||
return false;
|
||||
return ERR_CODE(NET_ERR_CREAT_INIT);
|
||||
}
|
||||
|
||||
// 创建数据映射 - 分配足够的空间
|
||||
@ -56,7 +59,7 @@ bool ModbusTCPServer::start(int port, int maxConnections)
|
||||
setLastError("创建数据映射失败");
|
||||
modbus_free(m_modbusCtx);
|
||||
m_modbusCtx = nullptr;
|
||||
return false;
|
||||
return ERR_CODE(NET_ERR_CONFIG);
|
||||
}
|
||||
|
||||
// 监听连接
|
||||
@ -67,7 +70,7 @@ bool ModbusTCPServer::start(int port, int maxConnections)
|
||||
m_mapping = nullptr;
|
||||
modbus_free(m_modbusCtx);
|
||||
m_modbusCtx = nullptr;
|
||||
return false;
|
||||
return ERR_CODE(NET_ERR_CREAT_LISTEN);
|
||||
}
|
||||
|
||||
m_isRunning.store(true);
|
||||
@ -76,7 +79,12 @@ bool ModbusTCPServer::start(int port, int maxConnections)
|
||||
// 启动服务器线程
|
||||
m_serverThread = std::make_unique<std::thread>(&ModbusTCPServer::serverLoop, this);
|
||||
|
||||
return true;
|
||||
// 初始状态:服务器启动但没有客户端连接
|
||||
if (m_connectionStatusCallback) {
|
||||
m_connectionStatusCallback(false);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModbusTCPServer::stop()
|
||||
@ -154,7 +162,7 @@ void ModbusTCPServer::serverLoop()
|
||||
|
||||
if (selectResult == -1) {
|
||||
if (!m_shouldStop.load()) {
|
||||
std::cerr << "select错误: " << strerror(errno) << std::endl;
|
||||
LOG_WARNING("select error: %s\n", strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -198,7 +206,7 @@ void ModbusTCPServer::handleNewConnection()
|
||||
int clientSocket = modbus_tcp_accept(m_modbusCtx, &m_serverSocket);
|
||||
if (clientSocket == -1) {
|
||||
if (!m_shouldStop.load()) {
|
||||
std::cerr << "接受连接失败: " << modbus_strerror(errno) << std::endl;
|
||||
LOG_ERRO("Accept connection failed: %s\n", modbus_strerror(errno));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -206,7 +214,7 @@ void ModbusTCPServer::handleNewConnection()
|
||||
// 创建新的modbus context用于此客户端
|
||||
modbus_t* clientCtx = modbus_new_tcp("0.0.0.0", m_port);
|
||||
if (clientCtx == nullptr) {
|
||||
std::cerr << "为客户端创建Modbus上下文失败" << std::endl;
|
||||
LOG_ERRO("Create Modbus context for client failed\n");
|
||||
#ifdef _WIN32
|
||||
closesocket(clientSocket);
|
||||
#else
|
||||
@ -227,7 +235,12 @@ void ModbusTCPServer::handleNewConnection()
|
||||
m_clients[clientSocket] = client;
|
||||
}
|
||||
|
||||
std::cout << "新客户端连接: socket=" << clientSocket << std::endl;
|
||||
LOG_INFO("New client connected: socket=%d\n", clientSocket);
|
||||
|
||||
// 触发连接状态回调
|
||||
if (m_connectionStatusCallback) {
|
||||
m_connectionStatusCallback(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ModbusTCPServer::handleClientData(std::shared_ptr<ClientConnection> client)
|
||||
@ -240,9 +253,9 @@ void ModbusTCPServer::handleClientData(std::shared_ptr<ClientConnection> client)
|
||||
if (bytesReceived <= 0) {
|
||||
// 连接断开或错误
|
||||
if (bytesReceived == 0) {
|
||||
std::cout << "客户端断开连接: socket=" << client->socket << std::endl;
|
||||
LOG_VERBOSE("Client disconnected: socket=%d\n", client->socket);
|
||||
} else {
|
||||
std::cerr << "接收数据错误: " << strerror(errno) << std::endl;
|
||||
LOG_ERRO("Receive data error: %s\n", strerror(errno));
|
||||
}
|
||||
throw std::runtime_error("客户端连接错误");
|
||||
}
|
||||
@ -256,8 +269,13 @@ void ModbusTCPServer::removeClient(int socket)
|
||||
std::lock_guard<std::mutex> lock(m_clientsMutex);
|
||||
auto it = m_clients.find(socket);
|
||||
if (it != m_clients.end()) {
|
||||
std::cout << "移除客户端连接: socket=" << socket << std::endl;
|
||||
LOG_INFO("Remove client connection: socket=%d\n", socket);
|
||||
m_clients.erase(it);
|
||||
|
||||
// 如果没有客户端连接了,触发断开回调
|
||||
if (m_clients.empty() && m_connectionStatusCallback) {
|
||||
m_connectionStatusCallback(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,42 +286,134 @@ void ModbusTCPServer::processModbusRequest(std::shared_ptr<ClientConnection> cli
|
||||
int responseRc = modbus_reply(client->modbusCtx, query, queryLength, m_mapping);
|
||||
|
||||
if (responseRc == -1) {
|
||||
std::cerr << "发送响应失败: " << modbus_strerror(errno) << std::endl;
|
||||
LOG_WARNING("Send response failed: %s\n", modbus_strerror(errno));
|
||||
throw std::runtime_error("发送响应失败");
|
||||
}
|
||||
|
||||
// 检查是否是写操作,如果是则调用回调
|
||||
if (queryLength >= 8) { // 确保有足够的字节
|
||||
uint8_t function = query[7]; // 功能码在TCP ADU的第8字节
|
||||
uint16_t address = (query[8] << 8) | query[9];
|
||||
uint16_t quantity = (query[10] << 8) | query[11];
|
||||
uint8_t unitId = query[6];
|
||||
// 解析ModbusTCP ADU - 最小长度检查
|
||||
if (queryLength < 8) {
|
||||
LOG_DEBUG("Query too short: %d bytes\n", queryLength);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (function) {
|
||||
case MODBUS_FC_WRITE_SINGLE_COIL:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_COILS:
|
||||
if (m_writeCoilsCallback) {
|
||||
const uint8_t* values = &query[12]; // 数据从第13字节开始
|
||||
ErrorCode result = m_writeCoilsCallback(unitId, address, quantity, values);
|
||||
if (result != ErrorCode::SUCCESS) {
|
||||
// 发送异常响应
|
||||
modbus_reply_exception(client->modbusCtx, query, static_cast<unsigned int>(result));
|
||||
// ModbusTCP ADU格式: [Transaction ID(2)] [Protocol ID(2)] [Length(2)] [Unit ID(1)] [Function Code(1)] [Data...]
|
||||
uint16_t transactionId = (query[0] << 8) | query[1]; // Transaction ID
|
||||
uint16_t protocolId = (query[2] << 8) | query[3]; // Protocol ID (should be 0 for ModbusTCP)
|
||||
uint16_t length = (query[4] << 8) | query[5]; // Length field
|
||||
uint8_t unitId = query[6]; // Unit ID
|
||||
uint8_t function = query[7]; // Function Code
|
||||
|
||||
// 验证协议ID
|
||||
if (protocolId != 0) {
|
||||
LOG_DEBUG("Invalid protocol ID: %d\n", protocolId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证长度字段
|
||||
if (length != (queryLength - 6)) {
|
||||
LOG_DEBUG("Length mismatch: expected %d, got %d\n", length, queryLength - 6);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("ModbusTCP request - TransID:%d, UnitID:%d, Function:0x%02X\n",
|
||||
transactionId, unitId, function);
|
||||
|
||||
// 根据功能码解析数据
|
||||
switch (function) {
|
||||
case MODBUS_FC_WRITE_SINGLE_COIL:
|
||||
{
|
||||
if (queryLength >= 12) {
|
||||
uint16_t address = (query[8] << 8) | query[9];
|
||||
uint16_t value = (query[10] << 8) | query[11];
|
||||
|
||||
LOG_DEBUG("Write single coil - Address:%d, Value:%d\n", address, value);
|
||||
|
||||
if (m_writeCoilsCallback) {
|
||||
uint8_t coilValue = (value == 0xFF00) ? 1 : 0;
|
||||
ErrorCode result = m_writeCoilsCallback(unitId, address, 1, &coilValue);
|
||||
if (result != ErrorCode::SUCCESS) {
|
||||
LOG_DEBUG("Write coil callback returned error: %d\n", (int)result);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODBUS_FC_WRITE_SINGLE_REGISTER:
|
||||
case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
|
||||
if (m_writeRegistersCallback) {
|
||||
const uint16_t* values = reinterpret_cast<const uint16_t*>(&query[12]);
|
||||
ErrorCode result = m_writeRegistersCallback(unitId, address, quantity, values);
|
||||
if (result != ErrorCode::SUCCESS) {
|
||||
// 发送异常响应
|
||||
modbus_reply_exception(client->modbusCtx, query, static_cast<unsigned int>(result));
|
||||
}
|
||||
break;
|
||||
|
||||
case MODBUS_FC_WRITE_MULTIPLE_COILS:
|
||||
{
|
||||
if (queryLength >= 13) {
|
||||
uint16_t address = (query[8] << 8) | query[9];
|
||||
uint16_t quantity = (query[10] << 8) | query[11];
|
||||
uint8_t byteCount = query[12];
|
||||
|
||||
if (queryLength >= (13 + byteCount)) {
|
||||
LOG_DEBUG("Write multiple coils - Address:%d, Quantity:%d, Bytes:%d\n",
|
||||
address, quantity, byteCount);
|
||||
|
||||
if (m_writeCoilsCallback) {
|
||||
const uint8_t* values = &query[13];
|
||||
ErrorCode result = m_writeCoilsCallback(unitId, address, quantity, values);
|
||||
if (result != ErrorCode::SUCCESS) {
|
||||
LOG_DEBUG("Write coils callback returned error: %d\n", (int)result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODBUS_FC_WRITE_SINGLE_REGISTER:
|
||||
{
|
||||
if (queryLength >= 12) {
|
||||
uint16_t address = (query[8] << 8) | query[9];
|
||||
uint16_t value = (query[10] << 8) | query[11];
|
||||
|
||||
LOG_DEBUG("Write single register - Address:%d, Value:%d\n", address, value);
|
||||
|
||||
if (m_writeRegistersCallback) {
|
||||
ErrorCode result = m_writeRegistersCallback(unitId, address, 1, &value);
|
||||
if (result != ErrorCode::SUCCESS) {
|
||||
LOG_DEBUG("Write register callback returned error: %d\n", (int)result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
|
||||
{
|
||||
if (queryLength >= 13) {
|
||||
uint16_t address = (query[8] << 8) | query[9];
|
||||
uint16_t quantity = (query[10] << 8) | query[11];
|
||||
uint8_t byteCount = query[12];
|
||||
|
||||
if (queryLength >= (13 + byteCount) && byteCount == (quantity * 2)) {
|
||||
LOG_DEBUG("Write multiple registers - Address:%d, Quantity:%d, Bytes:%d\n",
|
||||
address, quantity, byteCount);
|
||||
|
||||
if (m_writeRegistersCallback) {
|
||||
// 解析寄存器值(注意字节序)
|
||||
std::vector<uint16_t> values;
|
||||
values.reserve(quantity);
|
||||
|
||||
for (int i = 0; i < quantity; i++) {
|
||||
uint16_t value = (query[13 + i*2] << 8) | query[13 + i*2 + 1];
|
||||
values.push_back(value);
|
||||
}
|
||||
|
||||
ErrorCode result = m_writeRegistersCallback(unitId, address, quantity, values.data());
|
||||
if (result != ErrorCode::SUCCESS) {
|
||||
LOG_DEBUG("Write registers callback returned error: %d\n", (int)result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_DEBUG("Unhandled function code: 0x%02X\n", function);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,4 +509,4 @@ bool IYModbusTCPServer::CreateInstance(IYModbusTCPServer** ppModbusTCPServer)
|
||||
|
||||
*ppModbusTCPServer = new ModbusTCPServer();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,13 +47,14 @@ public:
|
||||
|
||||
// 实现IYModbusTCPServer接口
|
||||
// 启动/停止服务器
|
||||
virtual bool start(int port = 502, int maxConnections = 10) override;
|
||||
virtual int start(int port = 502, int maxConnections = 10) override;
|
||||
virtual void stop() override;
|
||||
bool isRunning() const { return m_isRunning.load(); }
|
||||
|
||||
// 设置回调函数
|
||||
virtual void setWriteCoilsCallback(WriteCoilsCallback callback) override { m_writeCoilsCallback = callback; }
|
||||
virtual void setWriteRegistersCallback(WriteRegistersCallback callback) override { m_writeRegistersCallback = callback; }
|
||||
virtual void setConnectionStatusCallback(ConnectionStatusCallback callback) override { m_connectionStatusCallback = callback; }
|
||||
|
||||
// 数据更新接口 - 线程安全
|
||||
virtual void updateCoil(uint16_t address, bool value) override;
|
||||
@ -111,6 +112,7 @@ private:
|
||||
// 回调函数
|
||||
WriteCoilsCallback m_writeCoilsCallback;
|
||||
WriteRegistersCallback m_writeRegistersCallback;
|
||||
ConnectionStatusCallback m_connectionStatusCallback;
|
||||
|
||||
// 错误信息
|
||||
mutable std::mutex m_errorMutex;
|
||||
@ -120,4 +122,4 @@ private:
|
||||
void setLastError(const std::string& error);
|
||||
};
|
||||
|
||||
#endif // MODBUS_TCP_SERVER_H
|
||||
#endif // MODBUS_TCP_SERVER_H
|
||||
|
||||
@ -17,9 +17,14 @@ CVrEyeCommon* CVrEyeCommon::GetInstance()
|
||||
int CVrEyeCommon::InitDevice()
|
||||
{
|
||||
int nErrCode = SUCCESS;
|
||||
if(m_bInit) return nErrCode;
|
||||
|
||||
// 初始化SDK
|
||||
SVzNLConfigParam sVzNlConfigParam;
|
||||
nErrCode = VzNL_Init(&sVzNlConfigParam);
|
||||
|
||||
m_bInit = (SUCCESS == nErrCode);
|
||||
|
||||
return nErrCode;
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#ifndef VREYECOMMON_H
|
||||
#define VREYECOMMON_H
|
||||
|
||||
#include <atomic>
|
||||
|
||||
class CVrEyeCommon
|
||||
{
|
||||
@ -12,6 +12,9 @@ public:
|
||||
|
||||
int InitDevice();
|
||||
|
||||
private:
|
||||
std::atomic<bool> m_bInit = false;
|
||||
|
||||
};
|
||||
|
||||
#endif // VREYECOMMON_H
|
||||
|
||||
@ -54,7 +54,6 @@
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
////定义Log�
|
||||
///******************************************************************************************************************/
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
@ -65,28 +64,6 @@
|
||||
#define LOG_ERRO(...) __android_log_print(ANDROID_LOG_ERROR, "VrAPPE", ##__VA_ARGS__)
|
||||
#else
|
||||
|
||||
//#ifdef QT_CORE_LIB
|
||||
|
||||
|
||||
//#define LOG_TIME do { \
|
||||
//std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); \
|
||||
// std::time_t timestamp = std::chrono::system_clock::to_time_t(now); \
|
||||
// std::tm local_time; \
|
||||
// localtime_s(&local_time, ×tamp); \
|
||||
// long long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count(); \
|
||||
// char varTime[128] = { 0 }; \
|
||||
// sprintf_s(varTime, "%d-%02d-%02d %02d:%02d:%02d.%03lld", local_time.tm_year + 1900 , local_time.tm_mon + 1, local_time.tm_mday, local_time.tm_hour, local_time.tm_min, local_time.tm_sec, milliseconds % 1000); \
|
||||
// _LOG_OUTPUT << varTime; \
|
||||
//} while(0)
|
||||
|
||||
//#define LOG_VERBOSE(level,fmt, ...) do { if(level <= 1) { _EchoLog( true, "V", logfilename(__FILE__), __LINE__, fmt ); }} while(0)
|
||||
//#define LOG_DEBUG(level,fmt, ...) do { if(level <= 2) { _EchoLog( true, "D", logfilename(__FILE__), __LINE__, fmt ); }} while(0)
|
||||
//#define LOG_DEBUG_NOLINE(level,fmt, ...) do { if(level <= 3) { _EchoLog( false, "D", logfilename(__FILE__), __LINE__, fmt ); }} while(0)
|
||||
//#define LOG_INFO(level,fmt, ...) do { if(level <= 3) { _EchoLog( true, "I", logfilename(__FILE__), __LINE__, fmt ); }} while(0)
|
||||
//#define LOG_WARNING(level,fmt, ...) do { if(level <= 4) { _EchoLog( true, "W", logfilename(__FILE__), __LINE__, fmt ); }} while(0)
|
||||
//#define LOG_ERRO(level,fmt, ...) do { if(level <= 5) { _EchoLog( true, "E", logfilename(__FILE__), __LINE__, fmt ); }} while(0)
|
||||
//#define LOG_ERR(level,fmt, ...) do { if(level <= 5) { _EchoLog( true, "E", logfilename(__FILE__), __LINE__, fmt ); }} while(0)
|
||||
//#else
|
||||
|
||||
#if 0
|
||||
#include <qdebug.h>
|
||||
@ -105,48 +82,14 @@ std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOG_VERBOSE(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" V[%s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); }} while(0)
|
||||
#define LOG_DEBUG(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" D[%s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); }} while(0)
|
||||
#define LOG_DEBUG_NOLINE(fmt, ...) do { { printf(fmt, ##__VA_ARGS__); }} while(0)
|
||||
#define LOG_INFO(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" I[%s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); }} while(0)
|
||||
#define LOG_WARNING(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" W[%s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); }} while(0)
|
||||
#define LOG_ERRO(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" E[%s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); }} while(0)
|
||||
#define LOG_ERR(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" E[%s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); }} while(0)
|
||||
//#endif
|
||||
#define LOG_VERBOSE(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" V[%20s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); } fflush(stdout); } while(0)
|
||||
#define LOG_DEBUG(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" D[%20s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); } fflush(stdout); } while(0)
|
||||
#define LOG_DEBUG_NOLINE(fmt, ...) do { { printf(fmt, ##__VA_ARGS__); } fflush(stdout); } while(0)
|
||||
#define LOG_INFO(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" I[%20s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); } fflush(stdout);} while(0)
|
||||
#define LOG_WARNING(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" W[%20s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); } fflush(stdout); } while(0)
|
||||
#define LOG_ERROR(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" E[%20s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); } fflush(stdout); } while(0)
|
||||
#define LOG_ERRO(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" E[%20s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); } fflush(stdout); } while(0)
|
||||
#define LOG_ERR(fmt, ...) do { { LOG_TIME; _LOG_OUTPUT(" E[%20s : %4u] " fmt"", logfilename(__FILE__), __LINE__ ,##__VA_ARGS__); } fflush(stdout); } while(0)
|
||||
|
||||
#endif
|
||||
///******************************************************************************************************************/
|
||||
|
||||
#if 0
|
||||
|
||||
static void _EchoLog(const bool bLogHead, const char* sTag, const char* fileName, const int nLenNo, const char* sFormat, ...)
|
||||
{
|
||||
// load log info
|
||||
va_list args;
|
||||
va_start(args, sFormat);
|
||||
char szLogInfo[1024] = { 0 };
|
||||
#ifdef _WIN32
|
||||
vsprintf_s(szLogInfo, sFormat, args);
|
||||
#else
|
||||
vsprintf(szLogInfo, sFormat, args);
|
||||
#endif
|
||||
va_end(args);
|
||||
|
||||
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
||||
std::time_t timestamp = std::chrono::system_clock::to_time_t(now);
|
||||
std::tm local_time;
|
||||
localtime_s(&local_time, ×tamp);
|
||||
long long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
|
||||
char varTime[128] = { 0 };
|
||||
sprintf_s(varTime, "%d-%02d-%02d %02d:%02d:%02d.%03lld", local_time.tm_year + 1900 , local_time.tm_mon + 1, local_time.tm_mday, local_time.tm_hour, local_time.tm_min, local_time.tm_sec, milliseconds % 1000);
|
||||
|
||||
if(bLogHead)
|
||||
{
|
||||
_LOG_OUTPUT << varTime << "[" << sTag << fileName << ":" << nLenNo << "]" << szLogInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
_LOG_OUTPUT << szLogInfo;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user