#include "stdafx.h" #include #include "TrixellCtrl.h" #include "common_api.h" #include "MyPingip.h" #include "CiniFile.h" #include "DeviceConf_Api.h" //加载、处理固件升级、shock信息的配置 extern Log4CPP::Logger* gLogger; TrixellCtrl* g_pDetector = nullptr; const string str3543EZINI = "\\Detector3543EZe.ini"; const string str3543DRCINI = "\\Detector3543DRcs.ini"; const string str2430EZINI = "\\Detector2430EZ.ini"; const string str3543EZINI_BK = "\\Detector3543EZe_bk.ini"; const string str3543DRCINI_BK = "\\Detector3543DRcs_bk.ini"; const string str2430EZINI_BK = "\\Detector2430EZ_bk.ini"; const string STR_FXDFILE = "_DefectMapRef_DetMode1_0.fxd"; const string STR_GainFILE = "_GainLinRef_DetMode1_0.fxd"; const string STR_Manual_DefectFILE = "_DefectMapManual_DetMode1.fxd"; const string STR_FXDFILEL = "_DefectMapRef_DetMode2_0.fxd"; //长曝光模式 defect文件名 const string STR_GainFILEL = "_GainLinRef_DetMode2_0.fxd"; //长曝光模式 gain文件名 const string STR_Manual_DefectFILEL = "_DefectMapManual_DetMode2.fxd"; //长曝光模式 defect文件名 const string STR_FIRMWARE_HISTORY = "C:\\Addon\\IC\\Detectortools\\"; //SDK采集模式的宏定义,和DetectorXXXX.ini中modes.application.X.Y中的X对应 //一般顺序:rad、aed、rad_lte、tomo const int g_nRADmode = 1; const int g_nAEDmode = 2; const int g_nRADLTEmode = 3; const int g_nTOMOmode = 4; const int g_nRespondTimeout = 5000; const int g_nConnectTimeout = 20000; const int g_nRespondTimeoutLong = 30000; #define MAX_STRING 1024 TrixellCtrl::TrixellCtrl() { m_nPanelCount = 0; m_nCurrentPanelID = 0; m_pDPC2PanelID = new map(); m_pPanelID2DPC = new map(); m_hTrixellModule = NULL; m_strPanelType = ""; m_strWorkPath = ""; m_strPanelIP = ""; m_strCfgPath = ""; m_bOpened = false; m_bConnected = false; m_bLoaded = false; m_eAppStatus = APP_STATUS_IDLE; m_nCurrentMode = -1; m_nCurrentOmMode = -1; m_nCurrentAppMode = -1; m_bWorkMode = false; m_nImageWidth = 0; m_nImageHeight = 0; m_nRawImgWidth = 0; m_nRawImgHeight = 0; m_nWidthOffset = 0; m_nHeightOffset = 0; m_pImgBuffer = NULL; m_pPreImgBuffer = NULL; m_pRawImgBuffer = NULL; m_nImgBits = 16; m_nPixelPitch = 148; m_bPreviewEnable = false; m_nPreviewWidth = 0; m_nPreviewHeight = 0; m_eCaliType = CCOS_CALIBRATION_TYPE_NONE; m_fDose = 0; m_fCurrentDose = 0; m_eStatus = DetStatus_NotIni; m_nXwinOnIndex = 0; m_nTomoImgIndex = 0; m_nTomoImgCount = 30; m_nCaliFailedCount = 0; m_bGainPreparing = false; m_bGainProcess = false; m_bConfirmCaliRst = false; m_bAutoContinueCal = false; m_nSaveRaw = PIX_IMG_NONE; m_bPreviewImg = false; m_bExpEnable = false; m_eImgType = PIX_IMG_FULL; m_bWaitAcqEnd = false; m_bPrepShot = false; //m_nGainNodeCount = 0; //m_nGainNodeIndex = 0; //m_nGainExpCount = 0; //m_nGainExpIndex = 0; m_eCorrectionType = CT_OFFSET; m_eCurrentCT = CT_NONE; m_bAbortRefreshOft = false; m_nOftRefreshTimer = 0; //缺省2分钟 m_nAngle = 0; m_nIgnoreImgCount = 0; m_nIgnoreImgNum = 0; InitializeCriticalSection(&m_cs); m_nDetectorID = 0; //目前只支持单板,此处缺省0即可 m_bAttaching = false; m_bModuleConnecting = false; m_bModulePresent = false; m_bModuleEnable = true; m_bUpdateFirmwareDirect = false; m_bNeedFeedback = false; m_bLTEenable = false; m_eSyncMode = SYNC_SOFTWARE; m_bTransImageSuccess = true; //缺省true,曝光后置为false //m_nTotalShockNumber = -1; m_nAttachFPDID = -1; m_nUpdateFPDID = -1; m_strAttachFPD = ""; m_nAttachFPDID = -1; m_nShockFPDID = -1; //m_nInitFPDCount = 0; m_bExitShockCheck = false; m_nRefreshOftMode = 0; m_bIsImageRecovering = false; m_nRequireHWType = 0; m_nStatusTimeout = 600; m_nPollingTimes = 0; m_nStopPollingIndex = -1; m_bIsExpInAuto = true; //缺省true 如果没有开始aed流程就退出检查,这样不会调用stopacq m_bRefreshing = false; m_bReInitialize = false; m_hModuleThread = NULL; m_hFPDScanThread = NULL; m_hFPDStatusThread = NULL; m_hCheckShockThread = NULL; m_hRespondEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hShareEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hCheckShockEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hToggleEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hQuitAdaptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hQuitStatusEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hStopScanEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hProcessImgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hXWinOnEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hXWinOffEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hEndCalibEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hDarkEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hClosePollingEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hArrayEvent[0] = m_hStopScanEvent; m_hArrayEvent[1] = m_hProcessImgEvent; m_hArrayEvent[2] = m_hXWinOnEvent; m_hArrayEvent[3] = m_hXWinOffEvent; m_hArrayEvent[4] = m_hEndCalibEvent; m_hArrayEvent[5] = m_hDarkEndEvent; m_hArrayEvent[6] = m_hClosePollingEvent; m_nCfgCalibPrepare = 0; m_bAutonumousMode = false; m_strAutonumousMetaData = ""; m_nAutonumousImageIndex = 0; m_nCalibrationMode = CCOS_CALIBRATION_MODE_ZSKK; m_pZSKKCalib = nullptr; m_nCalibCurrentCalibrationRound = 0; m_nCalibrationRounds = 0; m_nCalibCurrentExposureIndex = 0; m_nExposureNumCurrentRound = 0; m_bSaveCalibrationRaw = true; } TrixellCtrl::~TrixellCtrl() { if (m_pImgBuffer) { delete[] m_pImgBuffer; m_pImgBuffer = nullptr; } if (m_hRespondEvent) { CloseHandle(m_hRespondEvent); m_hRespondEvent = nullptr; } if (m_hShareEvent) { CloseHandle(m_hShareEvent); m_hShareEvent = nullptr; } if (m_hProcessImgEvent) { CloseHandle(m_hProcessImgEvent); m_hProcessImgEvent = nullptr; } if (m_hXWinOnEvent) { CloseHandle(m_hXWinOnEvent); m_hXWinOnEvent = nullptr; } if (m_hXWinOffEvent) { CloseHandle(m_hXWinOffEvent); m_hXWinOffEvent = nullptr; } if (m_hStopScanEvent) { CloseHandle(m_hStopScanEvent); m_hStopScanEvent = nullptr; } if (m_hDarkEndEvent) { CloseHandle(m_hDarkEndEvent); m_hDarkEndEvent = nullptr; } if (m_hEndCalibEvent) { CloseHandle(m_hEndCalibEvent); m_hEndCalibEvent = nullptr; } if (m_hCheckShockEvent) { CloseHandle(m_hCheckShockEvent); m_hCheckShockEvent = nullptr; } if (m_hToggleEvent) { CloseHandle(m_hToggleEvent); m_hToggleEvent = nullptr; } if (m_hQuitAdaptEvent) { CloseHandle(m_hQuitAdaptEvent); m_hQuitAdaptEvent = nullptr; } if (m_nPanelCount != 0) { for (int i = 0; i < m_nPanelCount; i++) { delete[] m_pStPanelStatus[i]; } } if (m_pZSKKCalib) { delete m_pZSKKCalib; m_pZSKKCalib = nullptr; } delete m_pDPC2PanelID; m_pDPC2PanelID = NULL; delete m_pPanelID2DPC; m_pPanelID2DPC = NULL; } #define LOAD_PROC_ADDRESS(handle,func) \ if ((func = (CB_##func)GetProcAddress(handle, #func)) == NULL) { printf("Error occurs while loading entry point!!! \n'%s'\n", #func); }\ bool TrixellCtrl::AddDPCs(FPDDeviceTrixell* pDrvDPC, ResDataObject& Configuration, DeviceIndexStruct& DeviceStruct) { map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { Warn("TrixellCtrl::AddDPCs This DPC already exist\n"); return false; } Info("--Func-- AddDPCs {$}", pDrvDPC); //拿到当前探测器的配置 m_stDeviceIndex[m_nPanelCount] = DeviceStruct; m_ModeConfig = Configuration; ResDataObject objFPDInfo; //拿到当前探测器的配置 try { CPanelStatus* p = new CPanelStatus[1]; m_pStPanelStatus[m_nPanelCount] = p; if (m_nPanelCount == 0) { m_ObjFPDsInfo.add("FPDNum", 1); } else { m_ObjFPDsInfo["FPDNum"] = m_nPanelCount + 1; } objFPDInfo.add("FPD", Configuration[DetectorDescription]); m_pStPanelStatus[m_nPanelCount]->strPanelType = (string)Configuration[DetectorDescription]; if (m_pStPanelStatus[m_nPanelCount]->strPanelType == "3543DRgx") { m_pStPanelStatus[m_nPanelCount]->bHaveAutonumousMode = true; } m_pStPanelStatus[m_nPanelCount]->objPanelConfig = Configuration; if (m_ObjFPDsInfo.GetFirstOf("FPDs") >= 0) { m_ObjFPDsInfo["FPDs"].add("FPD", Configuration[DetectorDescription]); } else { m_ObjFPDsInfo.add("FPDs", objFPDInfo); } } catch (ResDataObjectExption& e) { Error("Get detector configuration failed: {$}", e.what()); return false; } m_pDPC2PanelID->insert(pair(pDrvDPC, m_nPanelCount)); m_pPanelID2DPC->insert(pair(m_nPanelCount, pDrvDPC)); m_nPanelCount++; Info("TrixellCtrl::AddDPCs ok {$}\n", m_nPanelCount); return true; } bool TrixellCtrl::DelDPCs(FPDDeviceTrixell* pDrvDPC) { map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { map::iterator PanelIdIter = m_pPanelID2DPC->find(DPCsIter->second); if (PanelIdIter != m_pPanelID2DPC->end()) { m_pPanelID2DPC->erase(PanelIdIter); //删掉相应的探测器配置,用于修改SDK ResDataObject objFPDsInfo = m_ObjFPDsInfo; ResDataObject objFPDInfo; int nCount = (int)objFPDsInfo["FPDs"].GetKeyCount("FPD"); if (nCount > 0) { m_ObjFPDsInfo.clear(); m_ObjFPDsInfo.add("FPDNum", m_nPanelCount - 1); for (int i = 0; i < nCount; i++) { if (i != DPCsIter->second) { objFPDInfo.add("FPD", objFPDsInfo["FPDNum"][i]); } } m_ObjFPDsInfo.add("FPDs", objFPDInfo); } } m_pDPC2PanelID->erase(DPCsIter); m_nPanelCount--; Info("TrixellCtrl::DelDPCs ok {$}\n", m_nPanelCount); } return true; } bool TrixellCtrl::SwitchPanel(int nPanelId) { //切换前动作 //1.图像恢复过程,不能切换 - 恢复流程不执行完毕,应该不会走到切换流程,暂不处理 //2.使能状态,需要先停止采集 - 切换时应该也到不了FramePrep阶段,暂不处理 //3.停止当前板的状态反馈 - 现在多板状态都交由SDK反馈,这里不用停 //4.重置图像宽高等参数 - selectexammode去处理 if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); return false; } else { Info("Set Quiet State OK"); } if (!SetActiveDetector(nPanelId)) { Error("Active detector Failed"); return false; } return true; } bool TrixellCtrl::ActivePanel(FPDDeviceTrixell* pDrvDPC) { Info("ActivePanel start: {$}, m_nCurrentPanelID {$}", pDrvDPC, m_nCurrentPanelID); map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { if (m_nCurrentPanelID != DPCsIter->second) { Info("m_nCurrentPanelID {$} != DPCsIter->second {$}", m_nCurrentPanelID, DPCsIter->second); if (!SwitchPanel(DPCsIter->second)) { return false; } m_nCurrentPanelID = DPCsIter->second; m_pCurrentDPC = pDrvDPC; m_nCurrentMode = -1; Info("ActivePanel over: {$}, m_nCurrentPanelID {$}", pDrvDPC, m_nCurrentPanelID); } else { Info("m_nCurrentPanelID {$} == DPCsIter->second {$}", m_nCurrentPanelID, DPCsIter->second); } } else { return false; } return true; } bool TrixellCtrl::EnterExam(APP_STATUS eStatus) { string strLog = ""; switch (eStatus) { case APP_STATUS_IDLE: strLog = "APP_STATUS_IDLE"; break; case APP_STATUS_WORK_BEGIN: strLog = "APP_STATUS_WORK_BEGIN"; break; case APP_STATUS_WORK_END: strLog = "APP_STATUS_WORK_END"; break; case APP_STATUS_DETSHARE_BEGIN: strLog = "APP_STATUS_DETSHARE_BEGIN"; break; case APP_STATUS_DETSHAR_END: strLog = "APP_STATUS_DETSHAR_END"; break; case APP_STATUS_CAL_BEGIN: strLog = "APP_STATUS_CAL_BEGIN"; break; case APP_STATUS_CAL_END: strLog = "APP_STATUS_CAL_END"; break; case APP_STATUS_WORK_IN_SENSITIVITY: strLog = "APP_STATUS_WORK_IN_SENSITIVITY"; break; default: break; } Info("Enter exam: {$}", strLog.c_str()); m_eAppStatus = eStatus; if (APP_STATUS_WORK_BEGIN == eStatus) //如果红外对接后再进检查,也要进行attach { if (m_pStPanelStatus[0]->bConnectStatus == false) { Info("Panel status connect status false"); ErrorFeedback(EVT_ERR_COMMUNICATE, "true", 0); } } else if (APP_STATUS_WORK_END == eStatus) { if (PIX_OM_AED == m_nCurrentOmMode) { if (!m_bIsExpInAuto) { m_bWaitAcqEnd = true; LockPixrad("StopAcquisition"); Info("Calling StopAcquisition"); error_status ErrorStatus = TED_PixRad_StopAcquisition(); //EVT_END_ACQUISITION if (TestError(ErrorStatus)) { Info("Stop acquisition command OK"); LockPixrad(); //等待回调(stop操作执行完毕) UnlockPixrad("StopAcquisition"); } else { Error("Stop acuqisition command failed"); UnlockPixrad("StopAcquisition"); } } } } return true; } int TrixellCtrl::GetDPCsCount() { return m_nPanelCount; } /*** ** 说明:连接 ** 加载SDK,初始化SDK,连接探测器等初始化操作 ** 参数:strWorkPath,初始化SDK必须的conf路径 ***/ bool TrixellCtrl::Connect(string strWorkPath, FPDDeviceTrixell* pDrvDPC) { Info("--Func-- Connect"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Debug("Not current DPC, return true"); return true; } m_strWorkPath = strWorkPath; Info("Current work path: {$}", m_strWorkPath); if (!m_pZSKKCalib) { m_pZSKKCalib = new CZSKKCalibrationCtrl(); } int nRet = InitDetector(); if (INIT_SUCCESS == nRet) { StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_CONNECT_OK, "", m_nCurrentPanelID); } else if (INIT_FIRMWARE == nRet) { } else if (INIT_CONNECT_ERR == nRet) { Error("TrixellCtrl::Connect INIT_CONNECT_ERR"); } else { Error("Connect detector failed"); StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_CONNECT_ERROR, "", m_nCurrentPanelID); return false; } DWORD dwThreadId; if (NULL == m_hFPDScanThread) { m_hFPDScanThread = CreateThread(NULL, 0, onFPDScanThread, this, 0, &dwThreadId); //启动辅助线程 } if (NULL == m_hFPDStatusThread) { m_hFPDStatusThread = CreateThread(NULL, 0, onFPDStatusThread, this, 0, &dwThreadId); } if (m_hCheckShockThread == NULL) { m_hCheckShockThread = CreateThread(NULL, 0, onCheckShockThread, this, 0, &dwThreadId); } m_eStatus = DetStatus_Standby; //初始化完毕,置为Standby Info("=== Connect detector OK ==="); return true; } /*** ** 说明:退出 ** 释放SDK ***/ void TrixellCtrl::DisConnect(FPDDeviceTrixell* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Info("Not current DPC, return"); return; } Info("--Func-- DisConnect"); //先退出自动重连线程,避免和接下来的退出流程冲突 if (m_hFPDStatusThread != NULL) { ResetEvent(m_hToggleEvent); SetEvent(m_hQuitStatusEvent); DWORD result = WaitForSingleObject(m_hToggleEvent, 65000); if (result == WAIT_OBJECT_0) { Info("Leave Thread Over"); } else if (result == WAIT_TIMEOUT) { Warn("Till time out"); } m_hFPDStatusThread = NULL; } //退出SDK try { if (!SetSystemState(STATE_QUIET)) { Warn("Set Quiet State Failed"); } else { Info("Set Quiet State OK"); } Info("Calling close"); error_status ErrorStatus = TED_PixRad_Close(); if (TestError(ErrorStatus)) { Info("Close detector ok"); } else { Warn("Close detector failed"); } Info("DisConnect Call PixRad_UnregisterEventCallback"); TED_PixRad_UnregisterEventCallback(EventCallback); m_bOpened = false; } catch (...) { Fatal("Close detector crash"); } //退出线程 StopThread(); Info("DisConnect Over"); } /*** ** 说明:DPC下发要attach的探测器信息 ** 参数:strFPDType,探测器类型 ** nDetectorID,该探测器对应的subDPC ID ***/ void TrixellCtrl::SetAttachFPDInfo(string strFPDType, int nDetectorID) { Info("The {$}({$}) is ready to be attached", strFPDType, nDetectorID); m_strAttachFPD = strFPDType; m_nAttachFPDID = nDetectorID; } /*** ** 说明:用户确认要连接当前attach的探测器 ***/ bool TrixellCtrl::AttachDetector(FPDDeviceTrixell* pDrvDPC) { map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { int nDetectorID = m_nAttachFPDID; Info("--Func-- AttachDetector(ID:{$})", nDetectorID); m_bModuleConnecting = true; m_bAttaching = false; //ping通探测器,修改配置 begin string strSetIP = ""; string strConfHostIP = ""; try { strConfHostIP = (string)m_pStPanelStatus[m_nAttachFPDID]->objPanelConfig["connections"]["LocalIP"] + R"(/24)"; } catch (ResDataObjectExption& exp) { Error("Get configuration failed, {$}", exp.what()); m_bModuleConnecting = false; StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_CONNECT_ERROR, "", nDetectorID); return false; } strSetIP = m_pStPanelStatus[m_nAttachFPDID]->strModuleIP; int nPingTotalTime = 30;//ping不通,一次约6s,共30次,4分钟左右超时 int nPingTimes = 0; Info("AttachDetector strSetIP:{$}", strSetIP); for (; nPingTimes < nPingTotalTime; nPingTimes++) { bool bConnect = IsConnected(strSetIP); //有ping权限么? if (bConnect) { Info("Ping Detector successfully"); break; } Sleep(2000); if (!InDetectorShare()) //如果退出Share界面了,返回false { m_bModuleConnecting = false; return false; } } if (nPingTotalTime == nPingTimes) //如果没有ping通探测器,不连接 { //UnlockPixrad(); Error("Cannot Ping Detector IP Failed"); m_bModuleConnecting = false; StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_CONNECT_ERROR, "", nDetectorID); return false; } if (ModifyModuleFPDConf(strSetIP, strConfHostIP)) { ConfFeedback(EVT_CONF_MODULE_IP, m_nAttachFPDID, strSetIP.c_str()); //把配置文件中的反馈上去 m_pStPanelStatus[m_nAttachFPDID]->objPanelConfig["SerialNumber"] = m_strModuleSN.c_str(); } else { StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_CONNECT_ERROR, "", nDetectorID); m_bModuleConnecting = false; return false; } //end //修改连接配置,使接下来调用API,执行连接过程 SetConnectConf(true, nDetectorID); CloseDetector(); m_bModulePresent = false;//防止:释放SDK后,红外断开,无法拿到红外断开状态,影响后面attach其他探测器进入share界面弹错误窗 int nRet = InitDetector(true, nDetectorID); if (nRet != INIT_FIRMWARE) { if (m_pStPanelStatus[nDetectorID]->bConnectStatus) { Info("Attach succeed"); UpdatePanelSerialFile(m_strModuleType, m_strModuleSN, m_pStPanelStatus[m_nAttachFPDID]->strModuleIP, "", true); StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_CONNECT_OK, "", nDetectorID); m_bModuleConnecting = false; return true; } else { Info("Attach failed"); DisconnectDetector(nDetectorID); StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_CONNECT_ERROR, "", nDetectorID); m_bModuleConnecting = false; return false; } } else if (m_pStPanelStatus[nDetectorID]->bNeedUpdateFW) { Info("Attach pending"); m_nUpdateFPDID = nDetectorID; //启动线程,升级固件 HANDLE hUpdateThread; DWORD unThreadID; hUpdateThread = CreateThread(NULL, 0, onUpdateFWThread, this, 0, &unThreadID); if (hUpdateThread == NULL) { Error("Start Update Firmware Thread Error"); } } } return true; } /*** ** 说明:用户确认不连接当前attach的探测器 ***/ void TrixellCtrl::CancelAttach() { Info("Cancel the attach process"); m_bAttaching = false; } RET_STATUS TrixellCtrl::SetSyncMode(SYNC_MODE nSyncMode, HARDWARE_TRIGGER_MODE TriggerMode) { m_eSyncMode = nSyncMode; return RET_STATUS::RET_SUCCEED; } /*** ** 说明:设置当前的曝光模式 ** 参数:nLogicMode,从配置文件读取,与SDK配置application mode对应 ***/ bool TrixellCtrl::SelectExamMode(int nLogicMode, FPDDeviceTrixell* pDrvDPC) { Info("TrixellCtrl::SelectExamMode start"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Info("Not current DPC {$}, {$} != {$} ,return", pDrvDPC, (*m_pDPC2PanelID)[pDrvDPC], m_nCurrentPanelID); return false; } Info("SelectExamMode({$})", nLogicMode); if (m_nCurrentAppMode == nLogicMode) //同样appmode下没必要再次走下面的流程 { Info("Same appmode, return true"); return true; } m_nRawImgWidth = m_stDeviceIndex[m_nCurrentPanelID].nRawWidth; m_nRawImgHeight = m_stDeviceIndex[m_nCurrentPanelID].nRawHeight; m_nImageWidth = m_stDeviceIndex[m_nCurrentPanelID].nFullImageWidth; m_nImageHeight = m_stDeviceIndex[m_nCurrentPanelID].nFullImageHeight; m_nWidthOffset = m_stDeviceIndex[m_nCurrentPanelID].nImageLeftOffset; m_nHeightOffset = m_stDeviceIndex[m_nCurrentPanelID].nImageTopffset; m_nImgBits = m_stDeviceIndex[m_nCurrentPanelID].nImageBits; m_nPixelPitch = m_stDeviceIndex[m_nCurrentPanelID].nPixelSpace; m_nSaveRaw = m_stDeviceIndex[m_nCurrentPanelID].nSaveRaw; m_nTomoImgCount = m_stDeviceIndex[m_nCurrentPanelID].nFrameCount; if (m_pImgBuffer) { delete m_pImgBuffer; m_pImgBuffer = NULL; } m_pImgBuffer = new WORD[m_nImageHeight * m_nImageWidth]; if (m_pRawImgBuffer) { delete m_pRawImgBuffer; m_pRawImgBuffer = NULL; } m_pRawImgBuffer = new WORD[m_nRawImgHeight * m_nRawImgWidth]; Info("Image size(W*H), Raw({$}*{$}), Effective({$}*{$}), Offset({$} {$}), Bits({$}), PixelPitch({$}), SaveRaw({$}), FrameCount({$})", m_nRawImgWidth, m_nRawImgHeight, m_nImageWidth, m_nImageHeight, m_nWidthOffset, m_nHeightOffset, m_nImgBits, m_nPixelPitch, m_nSaveRaw, m_nTomoImgCount); m_bPreviewEnable = m_stDeviceIndex[m_nCurrentPanelID].bPreviewEnable; m_nPreviewWidth = m_stDeviceIndex[m_nCurrentPanelID].nPreviewWidth; m_nPreviewHeight = m_stDeviceIndex[m_nCurrentPanelID].nPreviewHeight; Info("Preview size(W*H {$}*{$}), PreviewEnable({$})", m_nPreviewWidth, m_nPreviewHeight, m_bPreviewEnable); if (m_bPreviewEnable) { if (m_pPreImgBuffer) { delete m_pPreImgBuffer; m_pPreImgBuffer = NULL; } m_pPreImgBuffer = new WORD[m_nPreviewHeight * m_nPreviewWidth]; } ConfFeedback(EVT_CONF_RAW_WIDTH, m_nCurrentPanelID, "", m_nImageWidth); ConfFeedback(EVT_CONF_RAW_HIGHT, m_nCurrentPanelID, "", m_nImageHeight); ConfFeedback(EVT_CONF_RAW_BITS, m_nCurrentPanelID, "", m_nImgBits); ConfFeedback(EVT_CONF_PIXELSPACE, m_nCurrentPanelID, "", 0, (float)m_nPixelPitch); ConfFeedback(EVT_CONF_PREVIEW_WIDTH, m_nCurrentPanelID, "", m_nPreviewWidth); ConfFeedback(EVT_CONF_PREVIEW_HIGHT, m_nCurrentPanelID, "", m_nPreviewHeight); eDetOperationMode nOmMode = (eDetOperationMode)m_nCurrentOmMode; /*if (SYNC_AED == m_stDeviceIndex[m_nCurrentPanelID].nSyncMode) { nOmMode = PIX_OM_AED; }*/ if (!SetFpdExamMode("", nOmMode, nLogicMode, true)) { return false; } m_nCurrentAppMode = nLogicMode; //加载校正文件,暂时先放到初始化流程中,同探测器多模式还需要考虑 return true; } RET_STATUS TrixellCtrl::SetFrameRate(FLOAT frameRate, FPDDeviceTrixell* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Info("Not current DPC, return"); return RET_STATUS::RET_FAILED; } return RET_STATUS::RET_SUCCEED; } bool TrixellCtrl::GetCalibrationStep(int nCalibCurrentCalibrationRound, int nCalibrationRounds, int nCalibCurrentExposureIndex, int nExposureNumCurrentRound) { m_nCalibCurrentCalibrationRound = nCalibCurrentCalibrationRound; m_nCalibrationRounds = nCalibrationRounds; m_nCalibCurrentExposureIndex = nCalibCurrentExposureIndex; m_nExposureNumCurrentRound = nExposureNumCurrentRound; Info("Calibration Step===Round: {$}/{$}, ExposureNum: {$}/{$}", nCalibCurrentCalibrationRound, nCalibrationRounds, nCalibCurrentExposureIndex, nExposureNumCurrentRound); return true; } /*** ** 说明:曝光前的准备流程 ***/ RET_STATUS TrixellCtrl::PrepareAcquisition(FPDDeviceTrixell* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Info("Not current DPC, return"); return RET_STATUS::RET_FAILED; } if (m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus == false) { Info("Current detector is not connect, return"); return RET_STATUS::RET_FAILED; } RET_STATUS Ret = RET_STATUS::RET_FAILED; //设置到工作模式 if (!SetSystemState(STATE_PATIENT)) { Error("Set patient state failed"); return Ret; } StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_START); /*** ** tomo采集,根据和子系统沟通,机架反馈曝光次数后,子系统才给探测器设置曝光次数, ** 对应到状态机中的FrameReady之后 FrameStart之前, ** 因此,将非aed模式的SetParam放到FrameStart调用, ** aed模式到ready状态耗时比较久,所以在此处单独处理, ** 将SetParam放到aed判断里面调用 ***/ //SetApplicationParam(m_nCurrentMode); if (PIX_OM_AED == m_nCurrentOmMode) //AED模式需要提前到ready状态(耗时约1.8s) { if (DetStatus_Acquire == m_eStatus && !m_bIsExpInAuto) //重复使能直接返回 { return RET_STATUS::RET_SUCCEED; } SetApplicationParam(m_nCurrentMode); try { application_mode applicationMode = application_mode(m_nCurrentMode - 1); LockPixrad("ApplicationAcquisition"); Info("Calling ApplicationAcquisition(appmode:{$} acqmode:AED)", (int)applicationMode); error_status ErrorStatus = TED_PixRad_ApplicationAcquisition(applicationMode); //EVT_START_ACQUISITION->EVT_READY if (TestError(ErrorStatus)) { Info("Application acquisition command OK"); Ret = RET_STATUS::RET_SUCCEED; m_nXwinOnIndex = 0; //开始采集,置为初值 m_nTomoImgIndex = 0; //开始采集,置为初值 m_nIgnoreImgNum = 0; //开始采集,置为初值 m_eStatus = DetStatus_Acquire; LockPixrad(); //等待回调 UnlockPixrad("ApplicationAcquisition"); StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP); } else { StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_END_ERROR); UnlockPixrad("ApplicationAcquisition"); //执行失败,解锁 } } catch (...) { Error("Start acq crash!"); StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_END_ERROR); UnlockPixrad("ApplicationAcquisition"); //执行崩溃,解锁 } } else { StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP); Ret = RET_STATUS::RET_SUCCEED; } return Ret; } RET_STATUS TrixellCtrl::StartAcquisition(FPDDeviceTrixell* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Info("Not current DPC, return"); return RET_STATUS::RET_FAILED; } RET_STATUS Ret = RET_STATUS::RET_FAILED; if (-1 == m_nCurrentMode) { Warn("Current mode({$}) is illegal, may not select exam mode successfully, return failed", m_nCurrentMode); return Ret; } if (m_nCurrentOmMode == PIX_OM_AED) { Info("AED return"); return RET_STATUS::RET_SUCCEED; } if (m_eStatus == DetStatus_Acquire) { Error("Already in acquire state, forbid start acquisition"); return Ret; } if (m_nCurrentOmMode != PIX_OM_AED) //aed模式采集命令在FramePrep下发 { /*** ** tomo采集,根据和子系统沟通,机架反馈曝光次数后,子系统才给探测器设置曝光次数, ** 对应到状态机中的FrameReady之后 FrameStart之前, ** 因此,将非aed模式的SetParam放到此处调用 ***/ SetApplicationParam(m_nCurrentMode); try { application_mode applicationMode = application_mode(m_nCurrentMode - 1); if (m_bLTEenable && m_nCurrentOmMode == PIX_OM_RAD) //软同步 长曝光 { applicationMode = application_mode(g_nRADLTEmode - 1); } string strTemp = "unknown"; if (PIX_OM_AED == m_nCurrentOmMode) { strTemp = "aed"; } else if (PIX_OM_RAD == m_nCurrentOmMode) { strTemp = "rad"; } else if (PIX_OM_TOMO == m_nCurrentOmMode) { strTemp = "tomo"; } LockPixrad("ApplicationAcquisition"); //等待上一步操作执行完毕 Info("Calling ApplicationAcquisition(appmode:{$} acqmode:{$})", (int)applicationMode, strTemp.c_str()); error_status ErrorStatus = TED_PixRad_ApplicationAcquisition(applicationMode); //EVT_START_ACQUISITION if (TestError(ErrorStatus)) { Info("Application acquisition command OK"); Ret = RET_STATUS::RET_SUCCEED; m_eStatus = DetStatus_Acquire; m_nXwinOnIndex = 0; //开始采集,置为初值 m_nTomoImgIndex = 0; //开始采集,置为初值 m_nIgnoreImgNum = 0; //开始采集,置为初值 Info("m_nIgnoreImgCount:{$}", m_nIgnoreImgCount); if (m_nIgnoreImgCount != 0) { Info("m_nIgnoreImgCount != 0"); LockPixrad("ApplicationAcquisition"); } } else { StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_END_ERROR); } } catch (...) { Error("Start acq crash!"); StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_END_ERROR); } UnlockPixrad("ApplicationAcquisition"); } else { m_eStatus = DetStatus_Acquire; Ret = RET_STATUS::RET_SUCCEED; } if (Ret == RET_STATUS::RET_SUCCEED) { StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_END_OK); } return Ret; } RET_STATUS TrixellCtrl::StopAcquisition(FPDDeviceTrixell* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Info("Not current DPC, return"); return RET_STATUS::RET_FAILED; } RET_STATUS Ret = RET_STATUS::RET_FAILED; if (m_eStatus != DetStatus_Acquire) { Warn("Not in acq state, does not need stop acquisition"); m_eStatus = DetStatus_Standby; //停止采集,置回Standby return RET_STATUS::RET_SUCCEED; } //可以调用TED_PixRad_StopAcquisition的情况 //1.AED没曝光 //2.序列采集过程 //3.收到preview还没收到full image //不可以调用TED_PixRad_StopAcquisition的情况 //1.Tomo传图过程 if (m_eStatus == DetStatus_Acquire && PIX_OM_TOMO == m_nCurrentOmMode && m_nXwinOnIndex == m_nTomoImgCount) { //tomo模式,已经曝光完毕,正在传图,这时如果调用TED_PixRad_StopAcquisition会终止传图,所以需要等待传图完毕 m_bWaitAcqEnd = true; //已经收到回调,没必要再调用TED_PixRad_StopAcquisition m_eStatus = DetStatus_Standby; //停止采集,置回Standby return RET_STATUS::RET_SUCCEED; } //2.非Tomo传图过程 if (m_eStatus == DetStatus_Acquire && m_nCurrentOmMode != PIX_OM_TOMO && m_nXwinOnIndex != 0) { //rad/aed模式,已经曝光完毕,正在传图,这时如果调用TED_PixRad_StopAcquisition会终止传图,所以需要等待传图完毕 m_bWaitAcqEnd = true; //已经收到回调,没必要再调用TED_PixRad_StopAcquisition m_eStatus = DetStatus_Standby; //停止采集,置回Standby return RET_STATUS::RET_SUCCEED; } if (m_eStatus == DetStatus_Acquire) { //m_bWaitAcqEnd = true; Info("Calling StopAcquisition"); error_status ErrorStatus = TED_PixRad_StopAcquisition(); //EVT_END_ACQUISITION if (TestError(ErrorStatus)) { Info("Stop acquisition command OK"); Ret = RET_STATUS::RET_SUCCEED; } else { Error("Stop acuqisition command failed"); return Ret; } m_eStatus = DetStatus_Standby; //停止采集,置回Standby } else { Info("Not in acquire state, return"); Ret = RET_STATUS::RET_SUCCEED; } return Ret; } /*** * 设置校正点数 ***/ bool TrixellCtrl::SetReferenceNum(int nReferenceNum) { m_nCalibrationRounds = nReferenceNum; Info("Set reference number: {$}", m_nCalibrationRounds); return true; } /*** ** 说明:激活校正 ** 增益校正(探测器采用post-offset,暗场校正基本没用了)时拿到dose回调,算作执行完毕 ***/ RET_STATUS TrixellCtrl::ActiveCalibration(CCOS_CALIBRATION_TYPE Type) { RET_STATUS Ret = RET_STATUS::RET_FAILED; StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_START); if (CCOS_CALIBRATION_TYPE_DARK == Type) { Info("ActiveDarkCalibration"); Ret = RET_STATUS::RET_SUCCEED; } else if (CCOS_CALIBRATION_TYPE_XRAY == Type) { Info("ActiveXrayCalibration"); m_eStatus = DetStatus_XrayCalibration; /* * Tomo增益校正流程 * S1. 调用TED_PixRad_XRayCalibration,收到EVT_START_XRAY_CALIBRATION等(没啥用),EVT_DOSE_PARAM_REQUEST -- Active结束 * S2. 调用TED_PixRad_ResumeSequence,收到EVT_WAIT_STOP_XRAY * S3. 调用TED_PixRad_ResumeSequence,收到一些列回调,EVT_WAIT_START_XRAY -- PrepareCalibration(FramePrep)结束 * S4. 调用TED_PixRad_ResumeSequence,收到 25组窗口回调 ,EVT_WAIT_STOP_XRAY * S5. 调用TED_PixRad_ResumeSequence,收到EVT_DOSE_PARAM_REQUEST * 循环 -> S2 总共收到4次EVT_DOSE_PARAM_REQUEST,2.5, 0.25, 0.5, 5ugy * 最后一组曝光完毕后 S5 收到EVT_END_XRAY_CALIBRATION -- 校正结束 */ if (m_nCalibrationMode) //Trixell 校正 { if (ActiveGainCalibration()) { Ret = RET_STATUS::RET_SUCCEED; m_nCaliFailedCount = 0; //开始增益校正,置为初值 } } else //ZSKK校正 { //设置到工作状态 if (!SetSystemState(STATE_PATIENT)) //需要在PATIENT状态执行gain { Error("Set quiet state failed"); Ret = RET_STATUS::RET_FAILED; } if (!m_pZSKKCalib) { Error("ZSKK Calibration object is undefined"); Ret = RET_STATUS::RET_FAILED; } else { //反馈Dose信息 DataFeedback(EVT_DATA_DOSEPARAM, NULL, 0, 2.5); //加载ZSKK的校正文件 m_pZSKKCalib->m_strRawImgPath = m_strWorkPath + "\\rawdata\\"; m_pZSKKCalib->m_strRefFilePath = m_strWorkPath + "\\references\\"; m_pZSKKCalib->m_nFullImgWidth = m_stDeviceIndex[m_nCurrentPanelID].nFullImageWidth; m_pZSKKCalib->m_nFullImgHeight = m_stDeviceIndex[m_nCurrentPanelID].nFullImageHeight; m_pZSKKCalib->m_nReferenceNum = m_nCalibrationRounds; m_pZSKKCalib->m_nSaturationValue = 50000; m_pZSKKCalib->LoadZSKKGainMap(false, m_strPanelType); m_pZSKKCalib->LoadZSKKPixelMap(false, m_strPanelType); Info("Load ZSKK map successful"); Info("References: {$}", m_pZSKKCalib->m_strRefFilePath); Ret = RET_STATUS::RET_SUCCEED; } } } else { Error("Active not supported calibration({$}), return! \n", (int)Type); Ret = RET_STATUS::RET_NOSUPPORT; return Ret; } m_eCaliType = Type; return Ret; } /*** ** 说明:准备校正(状态机FramePrep) ** 曝光使能过程,使探测器开窗 ***/ RET_STATUS TrixellCtrl::PrepareCalibration(FPDDeviceTrixell* pDrvDPC) { if (m_eStatus != DetStatus_XrayCalibration) //offset校正直接返回 { Warn("Not in xraycalibration state, return"); return RET_STATUS::RET_SUCCEED; } RET_STATUS Ret = RET_STATUS::RET_FAILED; if (m_nCalibrationMode) //Trixell校正 { Info("Manual trigger next calibration exposure"); if (ResumeSequence(true)) { Ret = RET_STATUS::RET_SUCCEED; } } else //ZSKK校正 { //1.切换到工作模式 if (!SetSystemState(STATE_PATIENT)) { Error("Set quiet state failed"); Ret = RET_STATUS::RET_FAILED; } //2.设置参数 if (!SetApplicationParam(m_nCurrentMode)) { Error("Set application parameter failed"); Ret = RET_STATUS::RET_FAILED; } if (PIX_OM_AED == m_nCurrentOmMode) { ApplicationAcquireSequence(); } Ret = RET_STATUS::RET_SUCCEED; } Info("PrepareCalibration Over"); return Ret; } /*** ** 说明:开始校正(状态机FrameStart) ***/ RET_STATUS TrixellCtrl::StartCalibration(FPDDeviceTrixell* pDrvDPC) { RET_STATUS Ret = RET_STATUS::RET_FAILED; if (CCOS_CALIBRATION_TYPE_DARK == m_eCaliType) { Info("StartDarkCalibration \n"); m_eStatus = DetStatus_Offset; //开始offset if (RefreshOffset(m_bPreviewEnable, m_nCurrentOmMode, m_nCurrentMode, false)) { Ret = RET_STATUS::RET_SUCCEED; } else { m_eStatus = DetStatus_Standby; //开始offset执行失败,置回Standby } } else { Info("StartXrayCalibration \n"); if (m_nCurrentOmMode == PIX_OM_TOMO) //非Tomo模式,由于ResumeSequence()耗时较长,在FramePrep中完成触发 { if (!ResumeSequence(false)) //Tomo增益,使SDK返回开窗回调 { return Ret; } } if (m_nCalibrationMode)//Trixell校正 { } else //ZSKK校正 { if (PIX_OM_RAD == m_nCurrentOmMode) { ApplicationAcquireSequence(); } } Ret = RET_STATUS::RET_SUCCEED; m_nXwinOnIndex = 0; //开始校正,置为初值 } return Ret; } /*** * 接受曝光图像 ***/ bool TrixellCtrl::AcceptCalibration() { Info("Accept calibration exposure result"); if (m_nCalibrationMode)//Trixell校正 { //不做处理 } else //ZSKK校正 { if (m_nCalibCurrentExposureIndex == 1) { m_pZSKKCalib->AddImageToPixMap(m_pImgBuffer); m_pZSKKCalib->AverageZSKKGainMap(m_pImgBuffer, m_nCalibCurrentCalibrationRound - 1, true); } else { m_pZSKKCalib->AverageZSKKGainMap(m_pImgBuffer, m_nCalibCurrentCalibrationRound - 1, false); //曝光第几轮 } } Info("Accept calibration exposure over"); return true; } /*** * 拒绝曝光图像 ***/ bool TrixellCtrl::RejectCalibration() { Info("Reject calibration exposure result"); //不做处理 return true; } //Salmon项目中DPC等待dose反馈,不会再拿dose,所以用不到了 RET_STATUS TrixellCtrl::GetDoseRequest(float& DoseReq, FPDDeviceTrixell* pDrvDPC) { Info("GetDoseRequest \n"); if (CCOS_CALIBRATION_TYPE_XRAY == m_eCaliType) { DoseReq = (float)m_fDose; } else { DoseReq = 0; } m_fCurrentDose = DoseReq; Info("Dose request : {$}", DoseReq); return RET_STATUS::RET_SUCCEED; } /*** ** 说明:终止校正 ***/ RET_STATUS TrixellCtrl::AbortCalibration(FPDDeviceTrixell* pDrvDPC) { Info("AbortCalibration \n"); m_eCaliType = CCOS_CALIBRATION_TYPE_NONE; //恢复初值 m_bConfirmCaliRst = false; //终止校正,恢复初值 m_bAutoContinueCal = false; //终止校正,恢复初值 RET_STATUS Ret = RET_STATUS::RET_FAILED; if (m_nCalibrationMode) //Trixell校正 { Info("Calling CancelingSequence"); error_status ErrorStatus = TED_PixRad_CancelSequence(); if (!TestError(ErrorStatus)) { Error("CancelSequence Command Failed"); } else { Info("CancelSequence Command OK"); Ret = RET_STATUS::RET_SUCCEED; } } else { Info("Abort ZSKK calibration"); m_pZSKKCalib->LoadZSKKGainMap(true, m_strPanelType); //重新加载增益校正文件 m_pZSKKCalib->AbortZSKKPixMap(m_strPanelType); //放弃坏点校正并重新加载原来的坏点校正文件 } m_eStatus = DetStatus_Standby; return Ret; } /*** ** 说明:增益校正时响应上层调用的FramePost ** 曝光结束后在此等到当前的曝光结果:OK,剂量高/低,有物体。避免状态机被其它设备拉入下一次流程 ** Salmon系统中没有其它驱动触发跳转,所以用不到了 ***/ RET_STATUS TrixellCtrl::PostCalibration(FPDDeviceTrixell* pDrvDPC) { //if (m_eStatus != DetStatus_XrayCalibration) //{ // Warn( "Not in xraycalibration state, return"); // return RET_STATUS::RET_SUCCEED; //} //if (m_bGainProcess) //{ // LockPixrad("WaitGainRst"); // LockPixrad(); //等待当前增益曝光结束 // UnlockPixrad("WaitGainRst"); //} ////当前节点曝光结束,需要等到dose回调再让FramePost结束 //if (m_nGainExpIndex == m_nGainExpCount) //{ // if (m_fCurrentDose == m_fDose) //当前节点曝光结束,如果这两个值还相等,说明SDK还没回调Dose,需要等待 // { // LockPixrad("WaitDose"); // LockPixrad(); //等待下一次dose回调 // UnlockPixrad("WaitDose"); // } // m_bAutoContinueCal = false; //剂量改变后,不能自动进行下一次增益 // m_nGainNodeIndex++; // m_nGainExpCount = (int)m_ModeConfig["ModeTable"][m_nCurrentMode - 1]["CalibConfig"][m_nGainNodeIndex]["ImgCount"]; // Info( "Gain node index: %d, current node exp count: %d, exp index: %d", m_nGainNodeIndex, m_nGainExpCount, m_nGainExpIndex); //} //Info( "Over, Gain calibration already exposure %d times, need %d times", m_nGainExpIndex, m_nGainExpCount); //m_nGainExpIndex = 0; //恢复初值 return RET_STATUS::RET_SUCCEED; } bool TrixellCtrl::SaveCalibrationFile() { Info("Save Calibration File"); if (m_nCalibrationMode)//Trixell校正 { //不做处理 } else { Info("Save ZSKK Calibration File"); m_pZSKKCalib->StoreZSKKGainMap(m_strPanelType); m_pZSKKCalib->StoreZSKKPixMap(m_strPanelType); } //修改探测器状态,否则校正完成后进入检查页面不能正常ready m_eStatus = DetStatus_Standby; //更新配置文件中校正日期和时间 SYSTEMTIME stCurrentTime = { 0 }; GetLocalTime(&stCurrentTime); //Info("Current time: %04d/%02d/%02d %02d:%02d:%02d:%03d", Info("Current time: {$d04}/{$d02}/{$d02} {$d02}:{$d02}:{$d02}:{$d02}", stCurrentTime.wYear, stCurrentTime.wMonth, stCurrentTime.wDay, stCurrentTime.wHour, stCurrentTime.wMinute, stCurrentTime.wSecond, stCurrentTime.wMilliseconds); Info("Save Calibration File over"); return true; } /*** ** 说明:结束校正 ** DPC处理完校正报告后调用,此处上传map、报告等文件 ***/ RET_STATUS TrixellCtrl::CompleteCalibration(FPDDeviceTrixell* pDrvDPC) { Info("CompleteCalibration"); SetEvent(m_hEndCalibEvent); return RET_STATUS::RET_SUCCEED; } /*** ** 说明:设置长短曝光模式 ***/ bool TrixellCtrl::SetLTEMode(bool bEnable) { Info("{$} LTE mode", bEnable ? "Enable" : "Disable"); m_bLTEenable = bEnable; return true; } bool TrixellCtrl::RecoverLastImage() { Info("Recover Last Image"); if (m_bIsImageRecovering) { Warn("Recover Image is processing, return"); return false; } LockPixrad("RecoverLastImage"); m_bIsImageRecovering = true; error_status eErr = TED_PixRad_RecoverLastImage(true); if (!TestError(eErr)) { Error("Recover Last Image Failed"); UnlockPixrad("RecoverLastImage"); return false; } LockPixrad("RecoverLastImage"); UnlockPixrad("RecoverLastImage"); return true; } bool TrixellCtrl::WakeupDetector(int nDetectorID) { Info("WakeupDetector SetDetectorStatusPolling == true"); SetDetectorStatusPolling(nDetectorID, true); Sleep(50); //确保开启polling StatusFeedback(EVT_STATUS_SLEEP, 0, "false", nDetectorID); return true; } bool TrixellCtrl::LoadDLL(string strWorkPath) { string workpath = strWorkPath + "\\"; try { workpath += (string)m_ModeConfig["SDKPath"]; m_strCfgPath = (string)m_ModeConfig["CFGPath"]; } catch (ResDataObjectExption &e) { Error("Read configuration failed, Error code: {$}", e.what()); return false; } string drvpath = workpath + "\\pixrad.dll"; Debug("{$}", drvpath.c_str()); DWORD PathLen = 32768; char* pszPath = new char[PathLen]; DWORD Len = GetEnvironmentVariable("Path", pszPath, PathLen); if (Len > PathLen) { delete[] pszPath; return false; } std::string::size_type pos = 0; string EnvPath = pszPath; delete[] pszPath; EnvPath.find(workpath, 0); if ((pos = EnvPath.find(workpath, pos)) == std::string::npos) { string NewPath = EnvPath; NewPath += ";"; NewPath += workpath; if (SetEnvironmentVariable("Path", NewPath.c_str()) == FALSE) { return false; } else { //Info("pathvar = {$} \n\n", NewPath.c_str()); } } Info("Load Trixell API module"); //int nTemp = putenv(strPath.c_str()); //if (nTemp != 0) //{ // DWORD dw = GetLastError(); // //printf("Add dll failed: %d \n", dw); // return false; //} //pathvar = getenv("Path"); ////printf("pathvar = %s \n\n", pathvar); //m_hTrixellModule = LoadLibrary(drvpath.c_str()); m_hTrixellModule = LoadLibraryEx(drvpath.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH/*LOAD_LIBRARY_SEARCH_USER_DIRS*/); if (m_hTrixellModule == NULL) { DWORD dw = GetLastError(); Error("Load {$} failed: {$} \n", drvpath.c_str(), dw); return false; } LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_RegisterEventCallback); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_UnregisterEventCallback); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_RegisterOutputMsgCallback); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_UnregisterOutputMsgCallback); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_SwitchSSID); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_Open); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_Close); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_ResetDetector); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_StartAcquisition); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_StopAcquisition); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetConfigParameters); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetHardwareStatus); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetDetectorHardwareStatus); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetSystemStatus); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetSystemState); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_DarkCalibration); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_XRayCalibration); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_CancelSequence); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_SetActiveDetector); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetActiveDetector); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_PerformDetectorSelfTest); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_SwitchSSID); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_SetSystemState); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_ResumeSequence); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetWifiStatus); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetDetectorWifiStatus); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_ModulePolling); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_ModuleSetIpConfig); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_ModuleSwitchSSID); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_ModuleSetNetworkConfig); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_Connect); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_Disconnect); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_RecoverLastImage); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_DetectorControl); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_LoadReferences); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetLastAcquisitionData); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_SetImageMetadata); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetStoredImageList); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetStoredImage); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_RemoveStoredImage); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_ApplicationControl); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_RemoveAllStoredImages); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetSystemCalibrationTimeStatus); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_DetectorStatusPolling); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetVoltage); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_ModuleGetInfo); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_SetApplicationParameters); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_ApplicationAcquisition); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_GetDetectorInformation); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_OpenRemoteStorageSession); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_CloseRemoteStorageSession); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_RemoteStorageUploadFile); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_RemoteStorageDownloadFile); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_RemoteStorageCreateDirectory); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_SaveImage); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_LoadImage); LOAD_PROC_ADDRESS(m_hTrixellModule, TED_PixRad_TransferStoredImages); Info("Load Trixell API module over"); return true; } /*** ** 说明:验证返回是否有错误 ** 返回值:true,没有错误;false,有错误 ***/ bool TrixellCtrl::TestError(error_status err, int nFpdID, string strFuncName) { if (-1 == nFpdID) { nFpdID = m_nCurrentPanelID; } if (nFpdID != 0 && nFpdID != 1 && nFpdID != 2) //按最大三板处理 { //如果是SDK不反馈ID的错误,则置为-1,避免下面数组越界 nFpdID = -1; } switch (err) { //general error case ERR_SUCCESS: Debug("{$} There is no error", strFuncName.c_str()); return true; case ERR_UNKNOWN: Error("TestError {$} ERR_UNKNOWN", strFuncName.c_str()); break; //system error 1000+ case ERR_BAD_STATE: Error("TestError {$} ERR_BAD_STATE", strFuncName.c_str()); break; case ERR_BAD_PARAMETER: Error("TestError {$} ERR_BAD_PARAMETER", strFuncName.c_str()); break; case ERR_CONFIG_PARAMETER: Error("TestError {$} ERR_CONFIG_PARAMETER", strFuncName.c_str()); break; case ERR_REFERENCE_MISSING: Error("TestError {$} ERR_REFERENCE_MISSING", strFuncName.c_str()); break; case ERR_CONFIG_FILE_NOT_FOUND: Error("TestError {$} ERR_CONFIG_FILE_NOT_FOUND", strFuncName.c_str()); break; case ERR_CALLBACK_ALREADY_REGISTERED: Error("TestError {$} ERR_CALLBACK_ALREADY_REGISTERED", strFuncName.c_str()); break; case ERR_DETECTOR_OPERATION_NOT_ALLOWED: Error("TestError {$} ERR_DETECTOR_OPERATION_NOT_ALLOWED", strFuncName.c_str()); break; //hw error 2000+ case ERR_ACQ_NOT_END: Error("TestError {$} ERR_ACQ_NOT_END", strFuncName.c_str()); break; case ERR_DETECTOR_INIT_FAILED: Error("TestError {$} ERR_DETECTOR_INIT_FAILED", strFuncName.c_str()); if (nFpdID != -1) { m_pStPanelStatus[nFpdID]->bConnectStatus = false; ErrorFeedback(EVT_ERR_COMMUNICATE, "true", nFpdID); } break; case ERR_DETECTOR_REQUEST: Error("TestError {$} ERR_DETECTOR_REQUEST", strFuncName.c_str()); break; case ERR_DETECTOR_COMMUNICATION: Error("TestError {$} ERR_DETECTOR_COMMUNICATION({$})", strFuncName.c_str(), nFpdID); if (nFpdID != -1) { m_pStPanelStatus[nFpdID]->bConnectStatus = false; ErrorFeedback(EVT_ERR_COMMUNICATE, "true", nFpdID); } break; case ERR_DETECTOR_BATTERY_LOW_LEVEL: Error("TestError {$} ERR_DETECTOR_BATTERY_LOW_LEVEL", strFuncName.c_str()); break; case ERR_DETECTOR_CONFIGURATION: Error("TestError {$} ERR_DETECTOR_CONFIGURATION", strFuncName.c_str()); break; case ERR_DETECTOR_UNREACHABLE: Error("TestError {$} ERR_DETECTOR_UNREACHABLE Fpd({$})", strFuncName.c_str(), nFpdID); if (nFpdID != -1) { m_pStPanelStatus[nFpdID]->bConnectStatus = false; ErrorFeedback(EVT_ERR_COMMUNICATE, "true", nFpdID); } break; case ERR_DETECTOR_IMAGE_PENDING: Error("TestError {$} ERR_DETECTOR_IMAGE_PENDING Fpd({$})", strFuncName.c_str(), nFpdID); //需要考虑图像恢复机制 ys break; case ERR_MODULE_INIT_FAILED: Error("TestError {$} ERR_MODULE_INIT_FAILED", strFuncName.c_str()); break; case ERR_MODULE_COMMUNICATION: Error("TestError {$} ERR_MODULE_COMMUNICATION Fpd({$})", strFuncName.c_str(), nFpdID); break; //acq error 3000+ case ERR_ACQUISITION_CANCELED: Error("TestError {$} ERR_ACQUISITION_CANCELED", strFuncName.c_str()); break; case ERR_BAD_DETECTOR_HOST_SYNCHRO: Error("TestError {$} ERR_BAD_DETECTOR_HOST_SYNCHRO", strFuncName.c_str()); break; //cali error 4000+ case ERR_CALIBRATION_ACQUISITION: Error("TestError {$} ERR_CALIBRATION_ACQUISITION", strFuncName.c_str()); break; //load error 5000+ case LOAD_ERROR: Error("TestError {$} LOAD_ERROR", strFuncName.c_str()); break; case ERR_LOAD_GAIN: Error("{$} ERR_LOAD_GAIN", strFuncName.c_str()); break; case ERR_LOAD_DEFECTMAP: Error("TestError {$} ERR_LOAD_DEFECTMAP", strFuncName.c_str()); break; //sequence error 6000+ case ERR_SEQUENCE_CANCELED: Error("TestError {$} ERR_SEQUENCE_CANCELED", strFuncName.c_str()); break; case ERR_RESUME_TIMEOUT: Error("TestError {$} ERR_RESUME_TIMEOUT", strFuncName.c_str()); break; default: Error("TestError {$} Unknown Error: {$}", strFuncName.c_str(), (int)err); break; } return false; } /*** ** 说明:验证返回是否有错误 ** 返回值:true,没有错误;false,有错误 ***/ bool TrixellCtrl::TestRSError(rs_error_status err, int nFpdID, string strFuncName) { switch (err) { case RS_ERR_SUCCESS: Debug("{$} There is no error", strFuncName.c_str()); return true; case RS_ERR_UNKNOWN: Error("{$} ERR_UNKNOWN", strFuncName.c_str()); break; case RS_ERR_SESSION_DISABLED: Error("{$} ERR_SESSION_DISABLED", strFuncName.c_str()); break; case RS_ERR_OPERATION_FAILED: Error("{$} ERR_OPERATION_FAILED", strFuncName.c_str()); break; default: Error("{$} Unknown Error: {$}", strFuncName.c_str(), (int)err); break; } return false; } /*** ** 说明:修改SDK配置Pixrad.ini ** 参数:ResConfig 探测器类型配置 ** 例 { "FPDNum": 2, //探测器数量 "FPDs": { "FPD": "2430EZ", "FPD": "3543EZh" } } ** 此函数的逻辑是按最多三块泰雷兹平板设计的,超过限制代码和配置文件都需要调整!! ***/ bool TrixellCtrl::ConfigPixradSDK(ResDataObject ResConfig) { Info("Reset Pixrad ini, {$}", ResConfig.encode()); int nFPDNum = 0; bool bRet = true; if (ResConfig.GetFirstOf("FPDNum") >= 0) { nFPDNum = (int)ResConfig["FPDNum"]; if (nFPDNum > 0) { string strIniPath = m_strWorkPath + "\\" + m_strCfgPath + "\\PixRad.ini"; string strPanelType = ""; //存储探测器类型,e.g. 3543EZh string strConfigPath = ""; //存储探测器配置文件名称,e.g. Detector3543EZe string strConfigItem = ""; //要修改的ini文件配置项 Info("{$}", strIniPath.c_str()); //输出ini文件全路径 bRet = CIniFileCreat(strIniPath.c_str()); if (bRet) { int i = 0; for (i = 0; i < nFPDNum; i++) { strPanelType = (string)ResConfig["FPDs"][i]; int nPanelID = 0; //轮询已轮询过的探测器类型,看和当前的是否重复,重复则nPanelID自增 for (int j = 0; j < i; j++) { if ((string)ResConfig["FPDs"][j] == strPanelType) { nPanelID++; } } if (strPanelType.find("3543EZh") != string::npos && strPanelType.find("3543EZhd") == string::npos) { //3543EZh探测器在SDK中的类型是3543EZe strPanelType = "3543EZe"; } strConfigPath = "Detector" + strPanelType; if (nPanelID == 1) { strConfigPath += "_A"; } else if (nPanelID == 2) { strConfigPath += "_B"; } strConfigPath += ".ini"; if (i == 0) { strConfigItem = "configfile.detector.0"; } else if (i == 1) { strConfigItem = "configfile.detector.1"; } else { strConfigItem = "configfile.detector.2"; } //修改配置项 bool bFind = CIniFileGetValueByKey2(strConfigItem.c_str(), strConfigPath.c_str()); if (bFind) { Info("Same configfile.detector setting"); } else { strConfigPath = strConfigItem + " = " + strConfigPath; Info("Set configuration ({$}) \n", strConfigPath.c_str()); bRet = CIniFileSetItemByKey("configuration", strConfigItem.c_str(), strConfigPath.c_str()); if (bRet) { Info("Set {$} Success \n", strConfigItem.c_str()); } else { Error("Set {$} failed", strConfigItem.c_str()); } } } //将用不到的配置项删掉 for (int j = i; j < 3; j++) //临时写成3,按最大3板处理 { std::ostringstream ostrKey; string strKey = ""; ostrKey << "configfile.detector." << j; strKey = ostrKey.str(); std::ostringstream ostrValue; string strValue = ""; bool bFind = false; char tem[200]; bFind = CIniFileGetValueByKey(strKey.c_str(), tem); if (bFind) { ostrValue << ";" << strKey << " = " << "Detector3543EZe.ini"; strValue = ostrValue.str(); Info("Set configuration ({$}) \n", strValue.c_str()); if (CIniFileSetItemByKey("configuration", strKey.c_str(), strValue.c_str())) { Info("Set {$} success", strValue.c_str()); } else { Warn("Set {$} failed", strValue.c_str()); } } } CIniFileClose(); } else { Error("Read Pixrad.ini file failed"); CIniFileCloseWithoutWrite(); return bRet; } } else { Error("There is no fpd(FPDNum: {$})", nFPDNum); //printf("There is no fpd(FPDNum: %d) \n", nFPDNum); bRet = false; } } else { Error("The configuration is illegal"); bRet = false; } Info("Reset Pixrad ini Over"); return bRet; } void TrixellCtrl::EventCallback(const event_id eventID, const Event* eventData, void* customData) { TrixellCtrl* pOpr = static_cast(customData); if (NULL == pOpr) { Fatal("EventCallback is NULL"); } else { pOpr->ProcessEvent(eventID, eventData); } } /*** ** 说明:探测器上传下载文件的进度回调 ***/ void TrixellCtrl::RsprogressCallback(const unsigned int unTransferred_bytes, const unsigned int unTotal_bytes, void* pCustomData) { TrixellCtrl* pLib = static_cast(pCustomData); Info("Transferred Bytes:{$},Total Bytes:{$}", unTransferred_bytes, unTotal_bytes); } /*** ** 说明:调用API,初始化SDK ** 参数:bAttachProcess 是否在attach流程 ** 返回值:0,失败;1,成功;2,成功 但需要升级固件 ***/ int TrixellCtrl::InitDetector(bool bAttachProcess, int nDetectorID) { Info("Begin OpenDetector"); if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } if (m_bOpened) { Info("Already opened, skip this step"); //return true; } else { if (!m_bLoaded) //确保加载dll操作只进行一次 { if (!LoadDLL(m_strWorkPath)) { return INIT_FAILED; //失败 } m_bLoaded = true; } //modify20210908配置失败后,将备份恢复,然后尝试再次配置一次 string strIniPath = m_strWorkPath + "\\OEMDrivers\\Detector\\Trixell\\TrixellDRDetector\\config_Pixrad\\PixRad.ini"; string strSrcPath = m_strWorkPath + "\\OEMDrivers\\Detector\\Trixell\\TrixellDRDetector\\config_Pixrad\\PixRad_bk.ini"; if (!ConfigPixradSDK(m_ObjFPDsInfo)) { Warn("ConfigPixradSDK Failed, try again"); CopyFile2Folder(strSrcPath, strIniPath); if (!ConfigPixradSDK(m_ObjFPDsInfo)) { Error("ConfigPixradSDK Failed"); return INIT_FAILED; } } CopyFile2Folder(strIniPath, strSrcPath); Info("Calling RegisterEventCallback"); error_status ErrorStatus = TED_PixRad_RegisterEventCallback(EventCallback, this); if (!TestError(ErrorStatus)) { Error("Register event callback failed"); return INIT_FAILED; } string strConfigPath = m_strWorkPath + "\\" + m_strCfgPath; Info("Call Open: {$}", strConfigPath.c_str()); error_status Err = TED_PixRad_Open(strConfigPath.c_str()); //没有EVT_DETECTOR_INIT if (!TestError(Err)) { Info("InitDetector Call PixRad_UnregisterEventCallback"); TED_PixRad_UnregisterEventCallback(EventCallback); return INIT_FAILED; } Sleep(50); //Open执行结束会有EVT_ACTIVE_STATE回调 m_bOpened = true; } ConnectDetector(bAttachProcess, nDetectorID); if (m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { Info("Connect detector over"); } else { ErrorFeedback(EVT_ERR_COMMUNICATE, "true", m_nCurrentPanelID); return INIT_FAILED; } Info("OpenDetector Over"); return INIT_SUCCESS; } /*** ** 说明:调用API,释放SDK ***/ bool TrixellCtrl::CloseDetector() { Info("Closing Detector and API"); if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); } else { Info("Set Quiet State OK"); } for (int nID = 0; nID < m_nPanelCount; nID++) { SetStatusPolling(nID, false); } try { Info("Calling close"); error_status ErrorStatus = TED_PixRad_Close(); if (TestError(ErrorStatus)) { Info("Close detector ok"); } else { Warn("Close detector failed"); } Info("CloseDetector Call PixRad_UnregisterEventCallback"); TED_PixRad_UnregisterEventCallback(EventCallback); } catch (...) { Fatal("Close detector crash"); } m_bOpened = false; for (int nID = 0; nID < m_nPanelCount; nID++) { m_pStPanelStatus[nID]->bInitOK = false; //close执行结束,恢复初值 } return true; } /*** ** 说明:调用API,连接探测器 ** nDetectorID: 探测器ID ** bAttachProcess: true表示是attach过程 ***/ bool TrixellCtrl::ConnectDetector(bool bAttachProcess, int nDetectorID) { Info("ConnectDetector nDetectorID:{$}", nDetectorID); if (!SetSystemState(STATE_QUIET)) { Error("Set Quite State Failed"); return false; } else { Info("Set Quite State OK"); } for (int nID = 0; nID < m_nPanelCount; ++nID) { Info("Call Connect({$})", nID); error_status ErrorStatus = TED_PixRad_Connect(nID, ""); //EVT_DETECTOR_INIT if (!TestError(ErrorStatus, nID, "Connect")) { Error("Connect detector API failed"); continue; } if (!WaitRespond(g_nConnectTimeout, "Connect")) //设置一个10秒的连接超时 { Error("Connect detector timeout"); continue; } if (m_pStPanelStatus[nID]->bConnectStatus) { Info("Connect {$} Detector success", nID); } else { Warn("Connect {$} Detector failed", nID); continue; } if (!SetActiveDetector(nID)) { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_ERROR, "", nID); continue; } if (m_pStPanelStatus[nID]->bConnectStatus) { if (!m_pStPanelStatus[nID]->bDarkCalibDone) { Info("ConnectDetector synctype == SYNC_SOFTWARE"); m_nRefreshOftMode = g_nRADmode; m_bRefreshing = true; RefreshOffset(true, PIX_OM_RAD, g_nRADmode); m_bRefreshing = false; } /*if (!m_pStPanelStatus[nID]->bAEDDarkCalibDone) { Info("ConnectDetector synctype == SYNC_AED"); m_nRefreshOftMode = g_nAEDmode; m_bRefreshing = true; RefreshOffset(true, PIX_OM_AED, g_nAEDmode); m_bRefreshing = false; }*/ } FactoryCorrectionActive(bAttachProcess, nID); m_strPanelType = m_stDeviceIndex[m_nCurrentPanelID].strDeviceName; if (m_nCalibrationMode)//Trixell校正 { } else { Info("Load ZSKK Reference file"); m_pZSKKCalib->m_strRawImgPath = m_strWorkPath + "\\rawdata\\"; m_pZSKKCalib->m_strRefFilePath = m_strWorkPath + "\\references\\"; m_pZSKKCalib->m_nFullImgWidth = m_stDeviceIndex[m_nCurrentPanelID].nFullImageWidth; m_pZSKKCalib->m_nFullImgHeight = m_stDeviceIndex[m_nCurrentPanelID].nFullImageHeight; m_pZSKKCalib->m_nSaturationValue = 50000; if (!m_pZSKKCalib->LoadZSKKGainMap(true, m_strPanelType)) { Warn("Load ZSKK Gain calibration failed"); } if (!m_pZSKKCalib->LoadZSKKPixelMap(true, m_strPanelType)) { Warn("Load ZSKK Defect calibration failed"); } } GetConfigParameters(nID); GetDetectorInformation(nID, true); SetDetectorStatusPolling(nID, true); StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_OK, "", nID); Info("Connect detector({$}) over", nID); } return true; } bool TrixellCtrl::ConnectDetectorInFWUpdating(int nDetectorID) { Info("Connect Detector({$}) in firmware updating", nDetectorID); return true; } /*** ** 说明:调用API,断开探测器连接 ** nDetectorID: 探测器ID ***/ bool TrixellCtrl::DisconnectDetector(int nDetectorID) { Info("Disconnect Detector:{$}", nDetectorID); if (m_nCalibrationMode)//Trixell校正 { //什么也不用做 } else { Info("Unload ZSKK Reference file"); m_pZSKKCalib->UnLoadZSKKGainMap(); m_pZSKKCalib->UnLoadZSKKPixMap(); } if (!SetSystemState(STATE_QUIET)) { Error("Set Quite State Failed"); } else { Info("Set Quite State OK"); } error_status eErrorStatus = TED_PixRad_Disconnect(nDetectorID); //EVT_DETECTOR_CLOSE if (TestError(eErrorStatus)) { Info("Disconnect Detector Success"); } else { Error("Disconnect Detector Failed"); } SetConnectConf(false, nDetectorID); ErrorFeedback(EVT_ERR_MAX_NUMBER, "false", nDetectorID); StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_DISCONNECT_SUCCESS, "", nDetectorID); return true; } /*** ** 说明:锁住流程,等待操作执行完毕 ** 参数:strPosition 执行lock的操作 ** 推荐用法:等待上一步操作完成(strposition有值);等待回调(strposition为空)。 ** 特殊流程下等待回调可写清strposition,便于分析日志 ** 完善用法(借鉴自v2):调用SDK接口前先lock,确保当前没有未执行完毕的接口, ** 接口调用完成后再次lock,等待回调(异步接口的执行结果), ** 最后unlock,确保本接口解锁,不影响其它流程 ***/ bool TrixellCtrl::LockPixrad(string strPosition, int nTimeout) { Info("--- LockPixrad {$} ---", strPosition.c_str()); DWORD nResult = WaitForSingleObject(m_hShareEvent, nTimeout); if (WAIT_TIMEOUT == nResult) { ResetEvent(m_hShareEvent); Warn("Wait response timeout"); return false; } ResetEvent(m_hShareEvent); return true; } /*** ** 说明:操作执行完毕,解锁流程 ** 参数:strPosition 执行unlock的操作 ** 推荐用法:操作完成(strposition有值);收到回调(strposition为空) ***/ void TrixellCtrl::UnlockPixrad(string strPosition) { Info("--- UnlockPixrad {$} ---", strPosition.c_str()); SetEvent(m_hShareEvent); } /*** ** 说明:调用API获取探测器配置 ** 调用时机:调用API连接探测器时;断线重连后第一次收到HW回调时 ***/ bool TrixellCtrl::GetConfigParameters(int nDetectorID) { memset(&m_configParams, 0, sizeof(m_configParams)); Info("Calling GetConfigParameters"); error_status ErrorStatus = TED_PixRad_GetConfigParameters(m_configParams); if (!TestError(ErrorStatus)) { Error("Get Config Para Failed"); return false; } string strPanelType = ""; Info("nbDetectorTypes = {$}", m_configParams.nbDetectorTypes); for (int i = 0; i < m_configParams.nbDetectorTypes; ++i) { Info("<<<<strPanelSN = m_configParams.detectorConfig[i].serialNumber; Info("Product configuration version = {$}", m_configParams.detectorConfig[i].version); Info("Product part number = {$}", m_configParams.detectorConfig[i].partNumber); m_pStPanelStatus[i]->strPartNumber = m_configParams.detectorConfig[i].partNumber; Info("Product interface board number = {$}", m_configParams.detectorConfig[i].interfaceBoard); Info("Product manufacturing date = {$}", m_configParams.detectorConfig[i].date); InfoFeedback(EVT_INFO_FIRMWARE, i, 0, 0, m_configParams.detectorConfig[i].version); ConfFeedback(EVT_CONF_PART_NUMBER, i, m_configParams.detectorConfig[i].partNumber); ConfFeedback(EVT_CONF_IFBOARD, i, m_configParams.detectorConfig[i].interfaceBoard); ConfFeedback(EVT_CONF_DATECODE, i, m_configParams.detectorConfig[i].date); if (m_configParams.detectorConfig[i].remoteDeviceConfig != 0) { Debug("<<<<serialNumber); Debug("Product manufacturing date = {$}", m_configParams.detectorConfig[i].remoteDeviceConfig->date); Debug("Product configuration version = {$}", m_configParams.detectorConfig[i].remoteDeviceConfig->version); } if (m_configParams.detectorConfig[i].batteryConfig != 0) { Debug("<<<<identification; Info("identification of the battery = {$}", m_configParams.detectorConfig[i].batteryConfig->identification); strBatterySN = strBatterySN.erase(0, strBatterySN.length() - 4); ConfFeedback(EVT_CONF_BATTERY_SN, i, strBatterySN.c_str()); Debug("year of exchange of the battery = {$}", m_configParams.detectorConfig[i].batteryConfig->exchangeYear); Debug("week of exchange of the battery = {$}", m_configParams.detectorConfig[i].batteryConfig->exchangeWeek); Debug("percentage from what battery is authorized to recharge = {$}", m_configParams.detectorConfig[i].batteryConfig->rechargeTrigger); Debug("minimum charge level (in percentage) to accept a wake up command = {$}", m_configParams.detectorConfig[i].batteryConfig->lowLevelWakeUpTrigger); Debug("minimum charge level (in percentage) to accept acquiring image = {$}", m_configParams.detectorConfig[i].batteryConfig->lowLevelStartImageTrigger); Debug("the temperature in used to divide the charging current to limit temperature of detector = {$}", m_configParams.detectorConfig[i].batteryConfig->securityTemperature); } if (m_configParams.detectorConfig[i].wifiConfig != 0) { Info("<<<<frontEndInfo.mode); Info("Front-End Country Code = {$}", m_configParams.detectorConfig[i].wifiConfig->frontEndInfo.countryCode); m_strDetectorSSID_Old = m_configParams.detectorConfig[i].wifiConfig->frontEndInfo.ssid; Info("Front-End SSID = {$}", m_strDetectorSSID_Old.c_str()); ConfFeedback(EVT_CONF_WIFI_SSID, i, m_configParams.detectorConfig[i].wifiConfig->frontEndInfo.ssid); } } Info("Host Nick Name= {$}", m_configParams.hostConfig.nickName); Info("library version number = {$}", m_configParams.libraryConfig.versionNumber); return true; } /* 激活、关闭探测器模式 strPanelType: 预留参数 nOmMode: 自定义的OpreationMode,根据上层传下来的检查模式赋值,包括rad,aed,tomo。用来设置SDK所需的OpreationMode nAppMode: CCOS配置文件中的LogicMode,与SDK配置文件中的application mode对应(目前只输出日志使用) bEnable: 激活或关闭,目前不受接口外部传值影响 */ bool TrixellCtrl::SetFpdExamMode(string strPanelType, int nOmMode, int nAppMode, bool bEnable) { Info("SetFpdExamMode nOmMode:{$}, nAppMode:{$}", nOmMode, nAppMode); Info("Current OmMode: {$}", m_nCurrentOmMode); /* tips 1: Autotrigger and digital tomo cannot be both enable at same time. Enabling one automatically disables the other. tips 2: DC_SYNCHRONIZATION: when the detector is shared between several host, its internal settings can be changer according to the need of each host. This command allows to synchronize the internal settings of the panel with the host. */ control_type type = DC_AUTOTRIGGER_NORMAL; string strOmMode = "unknown"; string strEnable = bEnable ? "enable" : "disable"; if (nOmMode == PIX_OM_RAD) { Info("Set FPD to RAD mode"); m_nCurrentMode = g_nRADmode; m_nCurrentOmMode = nOmMode; //记录当前的操作模式 //目前只可能用到rad、aed和tomo,所以如果不是aed、tomo则不需要disable.一旦之后用到了别的模式,此处需要扩充或修改. Info("Current operation mode {$} does not need to be disabled, return", m_nCurrentOmMode); return true; } else if(nOmMode == PIX_OM_AED) { Info("Set FPD to AED mode"); strOmMode = "AED"; type = DC_AUTOTRIGGER_NORMAL; m_nCurrentMode = g_nAEDmode; } else if (nOmMode == PIX_OM_TOMO) { Info("Set FPD to TOMO mode"); strOmMode = "TOMO"; type = DC_DIGITAL_TOMO; m_nCurrentMode = g_nTOMOmode; } else { Warn("Undefined OmMode {$}", nOmMode); return false; } if (!SetSystemState(STATE_QUIET)) //需要在QUIET状态下设置 { Info("Set quiet state failed"); return false; } Info("Calling DetectorControl, strEnable:{$} strOmMode:{$} nOmMode({$})", strEnable.c_str(), strOmMode, nOmMode); error_status ErrorCode = TED_PixRad_DetectorControl(type, bEnable); //EVT_DETECTOR_CONTROL_CHANGED if (!TestError(ErrorCode)) { return false; } if (!WaitRespond(g_nRespondTimeoutLong, "Control")) { Error("Detector control timeout"); return false; } m_nCurrentOmMode = nOmMode; if (!SetSystemState(STATE_QUIET)) //恢复到QUIET状态 { Error("Set quiet state failed"); } return true; } /* bEnablePreview: 是否开启了预览图,目前暂时用不到 nOmMode: 自定义的OpreationMode,根据上层传下来的检查模式赋值,包括rad,aed,tomo。用来设置SDK所需的OpreationMode nAppMode: CCOS配置文件中的LogicMode,与SDK配置文件中的application mode对应 */ bool TrixellCtrl::RefreshOffset(bool bEnablePreview, int nOmMode, int nAppMode, bool bWaitOver) { Info("Refresh offset begin bWaitOver:{$}", bWaitOver); if (!SetSystemState(STATE_QUIET)) //需要在quiet状态刷新offset { Error("Set quiet state failed"); return false; } application_mode applicationMode = (application_mode)(nAppMode - 1); operating_mode operatingMode; if (PIX_OM_AED == nOmMode) { operatingMode = OM_RAD_AUTOTRIGGER; } else if (PIX_OM_RAD == nOmMode) { operatingMode = OM_RAD; } else if (PIX_OM_TOMO == nOmMode) { operatingMode = OM_DIGITAL_TOMO; } else { Error("No support current operation mode: {$}, return false", nOmMode); return false; } unsigned short detectorMode = defaultDetectorMode; LockPixrad("Darkcalibration"); Info("Calling DarkCalibration(applicationMode: {$}, operatingMode: {$})", (int)applicationMode, (int)operatingMode); error_status Err = TED_PixRad_DarkCalibration(applicationMode, operatingMode, detectorMode); //EVT_ACTIVE_STATE(REFERENCE) -> EVT_START_DARK_CALIBRATION -> EVT_END_DARK_CALIBRATION -> EVT_ACTIVE_STATE(STAND_BY) if (!TestError(Err)) { Error("Refresh offset failed"); UnlockPixrad("Darkcalibration"); return false; } //以下内容先加回来,完善校正内容时再增加 //目的是校正时不卡住状态机,等执行完毕后直接通过Notify使状态机跳转 if (bWaitOver) { LockPixrad("Darkcalibration"); //等待回调(dark操作执行完毕) UnlockPixrad("Darkcalibration"); Info("Refresh offset over"); if (!SetSystemState(STATE_QUIET)) //恢复到quiet { Error("Set quiet state failed"); } } return true; } /* nAppMode: CCOS配置文件中的LogicMode,与SDK配置文件中的application mode对应 */ bool TrixellCtrl::LoadReference(int nAppMode, int nDetectorID, bool bLTEenable) { application_mode applicationMode = application_mode(nAppMode - 1); operating_mode operatingMode = OM_DEFAULT; unsigned short detectorMode = defaultDetectorMode; unsigned short gainReferenceId = defaultReferenceId; unsigned short dmReferenceId = defaultReferenceId; LockPixrad("LoadReferences"); Info("Calling LoadReference(appmode: {$})", (int)applicationMode); error_status Err = TED_PixRad_LoadReferences(applicationMode, operatingMode, detectorMode, gainReferenceId, dmReferenceId); //EVT_STATUS_POLLING_CHANGED -> EVT_START_LOAD_REFERENCES -> EVT_END_LOAD_REFERENCES -> EVT_ACTIVE_STATE(STANDBY) if (!TestError(Err)) { Error("Load reference command failed"); UnlockPixrad("LoadReferences"); return false; } Info("Load reference command ok"); LockPixrad("LoadReferences"); //等待回调(load操作执行完毕) UnlockPixrad("LoadReferences"); if (!SetSystemState(STATE_QUIET)) //恢复到quiet,上面流程会转换到standby状态 { return false; } if (CT_ALL == m_eCorrectionType) { Info("Load reference success"); } else { Warn("Load reference failed"); return false; } return true; } bool TrixellCtrl::LoadReferenceEx(application_mode aMode, operating_mode oMode, unsigned short usDetectorMode, unsigned short usGainID, unsigned short usDMID) { Info("LoadReferenceEx"); LockPixrad("LoadReferences"); Info("Calling LoadReference(application_mode: {$}, operating_mode: {$})", (int)aMode, (int)oMode); error_status ErrorStatus = TED_PixRad_LoadReferences(aMode, oMode, usDetectorMode, usGainID, usDMID); //EVT_STATUS_POLLING_CHANGED -> EVT_START_LOAD_REFERENCES -> EVT_END_LOAD_REFERENCES -> EVT_ACTIVE_STATE(STANDBY) if (!TestError(ErrorStatus)) { Error("Load reference command failed"); UnlockPixrad("LoadReferences"); return false; } Info("Load reference command ok"); LockPixrad("LoadReferences"); //等待回调(load操作执行完毕) UnlockPixrad("LoadReferences"); if (!SetSystemState(STATE_QUIET)) //恢复到quiet,上面流程会转换到standby状态 { return false; } return true; } bool TrixellCtrl::GetSystemState(system_state& stState) { Info("Calling GetSystemState"); error_status Err = TED_PixRad_GetSystemState(stState); if (!TestError(Err)) { return false; } else { switch (stState) { case STATE_QUIET: Info("Current System is in Quiet State"); break; case STATE_REFERENCE: Info("Current System is in Reference State"); break; case STATE_STAND_BY: Info("Current System is in Standby State"); break; case STATE_PATIENT: Info("Current System is in Patient State"); break; default: Info("Current System State is {$}", (int)stState); break; } } return true; } bool TrixellCtrl::SetSystemState(system_state stState) { Info("SetSystemState stState:{$}", (int)stState); LockPixrad("SetSystemState"); //等待上一步调用完成 system_state currentstate; if (!GetSystemState(currentstate)) { UnlockPixrad("SetSystemState"); return false; } if (currentstate != stState) { Info("Calling SetSystemState"); error_status Err = TED_PixRad_SetSystemState(stState); //EVT_ACTIVE_STATE if (!TestError(Err)) { UnlockPixrad("SetSystemState"); return false; } switch (stState) { case STATE_QUIET: //default state, no background task is running Info("Current System is in Quiet State"); break; case STATE_REFERENCE: //performs specific operation like calibration, references load and hardware information functions Info("Current System is in Reference State"); break; case STATE_STAND_BY: //have no use for other detectors than Pixium 4600 Info("Current System is in Standby State"); break; case STATE_PATIENT: //in this state, Pixrad is ready for clean image acquisition Info("Current System is in Patient State"); break; default: Info("Current System State is {$}", (int)stState); break; } LockPixrad(); //等待回调(set操作执行完毕) } UnlockPixrad("SetSystemState"); return true; } /*** ** 设置Pixrad的 acquisition type (x, offset, dm); ** output type (short, float); ** preview activation (true, false); ** correction type (); ** nAppMode: CCOS配置文件中的LogicMode,与SDK配置文件中的application mode对应 ***/ bool TrixellCtrl::SetApplicationParam(int nAppMode) { application_mode applicationMode = (application_mode)(nAppMode - 1); //appmode从0开始计数 Info("applicationMode:{$} nAppMode:{$}, currentID:{$}, type:{$}", (int)applicationMode, nAppMode, m_nCurrentPanelID, (int)m_eCorrectionType); ApplicationParameter pAppParam[5] = { 0 }; char szTemp[5] = { 0 }; //用于转换值 sprintf_s(szTemp, "%d", m_nTomoImgCount); pAppParam[0].name = "acquisition.type"; pAppParam[0].value = "x"; pAppParam[1].name = "output.type"; pAppParam[1].value = "short"; pAppParam[2].name = "output.preview"; pAppParam[2].value = "false"; if (m_bPreviewEnable) { pAppParam[2].name = "output.preview"; pAppParam[2].value = "true"; } if (m_eStatus == DetStatus_XrayCalibration) { pAppParam[2].name = "output.preview"; pAppParam[2].value = "false"; } // 如果设置单一校正模式,比如offset,需要调用两遍 TED_PixRad_SetApplicationParameters,第一遍all.enable = false,第二遍offset.enable = true if (m_eCorrectionType != m_eCurrentCT && m_eCurrentCT != CT_NONE) { switch (m_eCurrentCT) { case CT_OFFSET: Info("Offset correction disable"); pAppParam[3].name = "offset.enabled"; pAppParam[3].value = "false"; break; case CT_GAIN: Info("Gain correction disable"); pAppParam[3].name = "gain.enabled"; pAppParam[3].value = "false"; break; case CT_DEFECT: Info("Defect correction disable"); pAppParam[3].name = "defect.enabled"; pAppParam[3].value = "false"; break; case CT_ALL: Info("All correction disable"); pAppParam[3].name = "all.enabled"; pAppParam[3].value = "false"; break; default: break; } Info("Calling SetApplicationParameters"); error_status ErrorStatus = TED_PixRad_SetApplicationParameters(applicationMode, pAppParam, 4); //EVT_APPLICATION_PARAMETERS_STATUS if (TestError(ErrorStatus)) { Info("Set application parameters command OK"); } else { Error("Set application parameters command Failed"); return false; } } if (CT_ALL == m_eCorrectionType) { Info("All correction enable"); m_eCurrentCT = CT_ALL; pAppParam[3].name = "all.enabled"; pAppParam[3].value = "true"; } else if (CT_OFFSET == m_eCorrectionType) { Info("Offset correction enable"); m_eCurrentCT = CT_OFFSET; pAppParam[3].name = "offset.enabled"; pAppParam[3].value = "true"; } else if (CT_GAIN == m_eCorrectionType) { Info("Gain correction enable"); m_eCurrentCT = CT_GAIN; pAppParam[3].name = "gain.enabled"; pAppParam[3].value = "true"; } else if (CT_DEFECT == m_eCorrectionType) { Info("Defect correction enable"); m_eCurrentCT = CT_DEFECT; pAppParam[3].name = "defect.enabled"; pAppParam[3].value = "true"; } else { Info("Null correction"); m_eCurrentCT = CT_NONE; pAppParam[3].name = "all.enabled"; pAppParam[3].value = "false"; } pAppParam[4].name = "image.number"; pAppParam[4].value = szTemp; // pAppParam.name 还可以设置以下值: // offset.enable /gain.enabled /defectmap.enabled /echoline.enabled /echocolumn.ebable / // clipping.enabled /butting.enable /pixelcluster.enable /image.number Info("Calling SetApplicationParameters"); error_status ErrorStatus = TED_PixRad_SetApplicationParameters(applicationMode, pAppParam, 5); //EVT_APPLICATION_PARAMETERS_STATUS if (TestError(ErrorStatus)) { Info("Set application parameters command OK"); return true; } return false; } bool TrixellCtrl::ActiveGainCalibration() { if (!SetSystemState(STATE_QUIET)) //需要在quiet状态执行gain { Error("Set quiet state failed"); return false; } application_mode applicationMode = (application_mode)(m_nCurrentMode - 1); if (m_bLTEenable && m_nCurrentOmMode == PIX_OM_RAD) //软同步 长曝光 { applicationMode = application_mode(g_nRADLTEmode - 1); } unsigned short gainReferenceId = defaultReferenceId; unsigned short dmReferenceId = defaultReferenceId; m_eStatus = DetStatus_XrayCalibration; m_bConfirmCaliRst = false; //激活增益校正,恢复初值 m_bAutoContinueCal = false; //终止校正,恢复初值 LockPixrad("XrayCalibration"); Info("Calling XRayCalibration"); error_status Err = TED_PixRad_XRayCalibration(applicationMode, gainReferenceId, dmReferenceId); //EVT_ACTIVE_STATE(REFERENCE)->EVT_START_XRAY_CALIBRATION -> EVT_DOSE_PARAM_REQUEST(剂量有变化时才有) if (!TestError(Err)) { Error("Active XRay Calibration Failed"); m_eStatus = DetStatus_Standby; //增益失败,置回Standby //UnlockPixrad("XrayCalibration"); return false; } Info("Active XRay Calibration OK"); m_bGainPreparing = true; //进入增益校正状态,直到收到相应回调 LockPixrad("XrayCalibration"); //等待回调(XRayCalibration执行完毕) UnlockPixrad("XrayCalibration"); return true; } //增益校正触发SDK进行下一步操作 //bLock = true 比较耗时的情况,需要等回调 //rad,aed: 收到EVT_PREP_XRAY_SHOT为止,耗时约11s //tomo: 收到EVT_WAIT_START_XRAY为止,耗时至少20s bool TrixellCtrl::ResumeSequence(bool bLock) { Info("ResumeSequence bLock:{$}", bLock); try { if (bLock) { LockPixrad("ResumeSequence"); } Info("Calling ResumeSequence"); error_status ErrorStatus = TED_PixRad_ResumeSequence(); if (!TestError(ErrorStatus)) { Error("Resume Sequence command Failed"); if (bLock) { UnlockPixrad("ResumeSequence"); } } else { Info("Resume Sequence command OK"); if (bLock) { LockPixrad("ResumeSequence"); //等待回调(EVT_PREP_XRAY_SHOT / EVT_WAIT_START_XRAY) UnlockPixrad("ResumeSequence"); } return true; } } catch (...) { Error("Start acq crash!"); } return false; } void TrixellCtrl::OnProcessImg() { if (m_bPreviewImg) { if (!m_bPreviewEnable) { Warn("Preview image is disable"); return; } if (m_nSaveRaw >= CCOS_SAVE_ORIGINAL) { SaveRawImage("Original_Preview_Image.raw", m_pPreImgBuffer, m_nPreviewWidth, m_nPreviewHeight); } DataFeedback(EVT_DATA_PREVIEW_IMAGE, m_pPreImgBuffer); } else { if (m_nSaveRaw >= CCOS_SAVE_ORIGINAL) { SaveRawImage("Original_Image.raw", m_pRawImgBuffer, m_nRawImgWidth, m_nRawImgHeight); } if (m_nSaveRaw) { SaveRawFunc(PIX_IMG_RAW, m_pRawImgBuffer); } if (m_nWidthOffset != 0 || m_nHeightOffset != 0) { Debug("Begin get effect image"); if (!GetEffectiveImage(m_pImgBuffer, m_pRawImgBuffer, m_nRawImgWidth)) { return; } Debug("Get effect image over"); //通知裁剪后的大小 ConfFeedback(EVT_CONF_RAW_WIDTH, m_nCurrentPanelID, "", m_nImageWidth); ConfFeedback(EVT_CONF_RAW_HIGHT, m_nCurrentPanelID, "", m_nImageHeight); if (m_nSaveRaw >= CCOS_SAVE_AFTER_CROP) { SaveRawImage("After_Crop_Image.raw", m_pImgBuffer, m_nImageWidth, m_nImageHeight); } if (m_nCalibrationMode)//Trixell校正 { } else if (APP_STATUS_CAL_BEGIN != m_eAppStatus) { Info("Apply ZSKK Reference"); m_pZSKKCalib->m_nGridSuppressed = 6; m_pZSKKCalib->ApplyZSKKReference(m_nImageHeight, m_nImageWidth, m_pImgBuffer); } if (APP_STATUS_CAL_BEGIN == m_eAppStatus && m_bSaveCalibrationRaw) { string strImageName = "Calibration_Image_" + to_string(m_nCalibCurrentCalibrationRound) + "_" + to_string(m_nCalibCurrentExposureIndex) + ".raw"; SaveRawImage(strImageName.c_str(), m_pImgBuffer, m_nImageWidth, m_nImageHeight); } DataFeedback(EVT_DATA_RAW_IMAGE, m_pImgBuffer); } else { //通知裁剪后的大小 ConfFeedback(EVT_CONF_RAW_WIDTH, m_nCurrentPanelID, "", m_nRawImgWidth); ConfFeedback(EVT_CONF_RAW_HIGHT, m_nCurrentPanelID, "", m_nRawImgHeight); if (m_nCalibrationMode)//Trixell校正 { } else if (APP_STATUS_CAL_BEGIN != m_eAppStatus) { Info("Apply ZSKK Reference"); m_pZSKKCalib->m_nGridSuppressed = 6; m_pZSKKCalib->ApplyZSKKReference(m_nRawImgHeight, m_nRawImgWidth, m_pRawImgBuffer); } if (APP_STATUS_CAL_BEGIN == m_eAppStatus && m_bSaveCalibrationRaw) { string strImageName = "Calibration_Image_" + to_string(m_nCalibCurrentCalibrationRound) + "_" + to_string(m_nCalibCurrentExposureIndex) + ".raw"; SaveRawImage(strImageName.c_str(), m_pRawImgBuffer, m_nRawImgWidth, m_nRawImgHeight); } DataFeedback(EVT_DATA_RAW_IMAGE, m_pRawImgBuffer); } //目前程序逻辑这里的m_bAutonumousMode肯定是false if (m_bAutonumousMode) { Info("m_bAutonumousMode ImageWidth: {$}, ImageHeight: {$}", to_string(m_nImageWidth), to_string(m_nImageHeight)); string strImageName = "Image" + to_string(m_nAutonumousImageIndex) + "_" + to_string(m_nImageWidth) + "_" + to_string(m_nImageHeight) + "_16_1.raw"; SaveRawImage(strImageName.c_str(), m_pImgBuffer, m_nImageWidth, m_nImageHeight); return; } } } // pOutImg: 裁剪后图像; pInImg: 裁剪前图像; nInWidth: 裁剪前图像宽度 bool TrixellCtrl::GetEffectiveImage(WORD* pOutImg, WORD* pInImg, int nInWidth) { if (pOutImg == NULL || pInImg == NULL || nInWidth < 0) { Error("Illegal parameter, can not get effective image"); return false; } try { for (int i = 0; i < m_nImageHeight; i++) { memcpy(pOutImg + i * m_nImageWidth, pInImg + (i + m_nHeightOffset) * nInWidth + m_nWidthOffset, m_nImageWidth * sizeof(WORD)); } } catch (...) { Error("Get effective image crashed"); return false; } return true; } void TrixellCtrl::SaveRawFunc(eDetPixImgType eImgType, WORD* pInImg) { FILE* fp; string strFileName = m_strWorkPath + "\\Image"; char szTemp[30] = { 0 }; int nImgX, nImgY; switch (eImgType) { case PIX_IMG_PRE: nImgX = m_nPreviewWidth; nImgY = m_nPreviewHeight; Info("Save preview image"); strFileName += "\\Preview.raw"; break; case PIX_IMG_RAW: nImgX = m_nRawImgWidth; nImgY = m_nRawImgHeight; Info("Save raw image"); strFileName += "\\Raw.raw"; break; case PIX_IMG_FULL: if (PIX_OM_TOMO == m_nCurrentOmMode) { nImgX = m_nImageWidth; nImgY = m_nImageHeight; Info("Save tomo image"); sprintf_s(szTemp, "\\Tomo_%d.raw", m_nTomoImgIndex); strFileName += szTemp; } else { nImgX = m_nImageWidth; nImgY = m_nImageHeight; Info("Save full image"); strFileName += "\\Full.raw"; } break; default: Warn("Unknown type image"); return; } if ((fp = fopen(strFileName.c_str(), "wb+")) == NULL) { DWORD dw = GetLastError(); Error("fopen {$} failed, {$}", strFileName.c_str(), dw); return; } fwrite(pInImg, sizeof(WORD), nImgX * nImgY, fp); fclose(fp); Info("Save image over"); } /*** * 保存RAW图像 ***/ bool TrixellCtrl::SaveRawImage(const char* pImgName, const WORD* pRawImg, int nWidth, int nHeight) { Info("Begin to Save {$} Image, width: {$}, height: {$}", pImgName, nWidth, nHeight); if (pRawImg == NULL || pImgName == NULL) { return false; } string strImagePath = ""; if (m_bAutonumousMode) { string strImageDir = m_strWorkPath + "\\rawdata\\Autonumous\\" + m_strAutonumousMetaData; if (GetFileAttributesA(strImageDir.c_str()) != FILE_ATTRIBUTE_DIRECTORY) { bool flag = CreateDirectory(strImageDir.c_str(), NULL); Info("Create dir: {$}", strImageDir); } else { Info("{$} already exist", strImageDir); } strImagePath = m_strWorkPath + "\\rawdata\\Autonumous\\" + m_strAutonumousMetaData + "\\" + pImgName; } else { strImagePath = m_strWorkPath + "\\rawdata\\" + pImgName; } FILE* fp; if ((fp = fopen(strImagePath.c_str(), "wb+")) == NULL) { DWORD dw = GetLastError(); Error("fopen {$} failed, {$}", strImagePath.c_str(), dw); return false; } fwrite(pRawImg, sizeof(WORD), nWidth * nHeight, fp); fclose(fp); Info("End to Save Raw Image"); return true; } /*** ** 说明:处理dark校正完成流程 ***/ void TrixellCtrl::OnProcessDarkEnd() { Info("Refresh offset over"); if (!SetSystemState(STATE_QUIET)) //恢复到quiet { Error("Set quiet state failed"); } StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } /*** ** 说明:输出回调名以及参数 ** 返回值:true,没有错误;false,有错误 ***/ bool TrixellCtrl::ProcessEventError(string strEventName, error_status err, int nDetectorID) { if (ERR_SUCCESS == err) { Info("strEventName:{$} success!", strEventName.c_str()); } else { TestError(err, nDetectorID, strEventName); return false; } return true; } /*** ** 说明:启动红外配对线程 ***/ void TrixellCtrl::StartModuleThread() { DWORD dwThreadId; if (NULL == m_hModuleThread) { m_hModuleThread = CreateThread(NULL, 0, onModuleThread, this, 0, &dwThreadId); } else { Error("The module thread is running"); } if (NULL == m_hModuleThread) { Error("Start Module Thread failed"); } } /*** ** 说明:红外配对线程 ***/ DWORD __stdcall TrixellCtrl::onModuleThread(PVOID pvoid) { TrixellCtrl* pOpr = (TrixellCtrl*)pvoid; pOpr->OnModuleConnect(); CloseHandle(pOpr->m_hModuleThread); pOpr->m_hModuleThread = NULL; return 0; } /*** ** 说明:红外配对执行函数 ***/ bool TrixellCtrl::OnModuleConnect() { return true; } bool TrixellCtrl::IsConnected(string strIP) { Info("Check ping {$}", strIP); CMyPingip obPingIp; StatusFeedback(EVT_STATUS_PING, 0, "true"); if (!obPingIp.PingFunction(strIP.c_str()/*, g_pLog*/)) { Info("ping {$} Failed", strIP); StatusFeedback(EVT_STATUS_PING, 0, "false"); return false; } return true; } /*** ** 说明:修改SDK中探测器配置DetectorXXXX.ini ** 修改detector.path.0项 -> 改为修改detector.path#####项,由SDK判断探测器序列号 ***/ bool TrixellCtrl::ModifyModuleFPDConf(string strDetectorIP, string strHostIP) { string strIniFilePath = m_strWorkPath + "\\" + m_strCfgPath; string strDetectorIniPath = ""; string strDestPath = ""; bool bIsDRPanel = false; if (m_strModuleType.find("3543DR") != string::npos) { strDetectorIniPath = strIniFilePath + str3543DRCINI; strDestPath = strIniFilePath + str3543DRCINI_BK; bIsDRPanel = true; } else if (m_strModuleType.find("2430EZ") != string::npos) { strDetectorIniPath = strIniFilePath + str2430EZINI; strDestPath = strIniFilePath + str2430EZINI_BK; } else { strDetectorIniPath = strIniFilePath + str3543EZINI; strDestPath = strIniFilePath + str3543EZINI_BK; } Info("{$}", strDetectorIniPath.c_str()); string strKey; std::ostringstream ostrKey; ostrKey << "detector.path.sn" << m_strModuleSN; strKey = ostrKey.str(); Info("{$}", strKey.c_str()); bool bReplaceOldOne = true; bool bRet = CIniFileCreat(strDetectorIniPath.c_str()); if (bRet) { bool bFind = false; bFind = CIniFileGetValueByKey2(strKey.c_str(), strDetectorIP.c_str()); if (bFind) { Info("Same SN and IP setting"); CIniFileCloseWithoutWrite(); return true; } bRet = CIniFileSetTrixellSetting("hardware", "detector.path.sn", strKey.c_str(), strDetectorIP.c_str(), bReplaceOldOne); if (bRet) { ostrKey << "Set " << strKey << " = " << strDetectorIP << "Success"; Info("{$}", ostrKey.str().c_str()); } else { Error("Modify DetectorXXXX.ini file failed"); } CIniFileClose(); if (bRet) //备份文件 { CopyFile2Folder(strDetectorIniPath, strDestPath); } } else { Error("Read DetectorXXXX.ini file failed"); CIniFileCloseWithoutWrite(); } return bRet; } /*** ** 说明:修改探测器IP配置 ***/ bool TrixellCtrl::ModifyFPDsIPConf() { string strIniFilePath = m_strWorkPath + "\\" + m_strCfgPath; string strDetectorIniPath = ""; //SDK配置文件DetectorXXXX.ini路径 string strPanelType = ""; string strDetectorIP = ""; string strHostIP = ""; bool bRet = true; int nPanelID = 0; for (int nID = 0; nID < m_nPanelCount; nID++) { try { strPanelType = (string)m_pStPanelStatus[nID]->objPanelConfig["ProductID"]; strDetectorIP = (string)m_pStPanelStatus[nID]->objPanelConfig["connections"]["WiredIP"]; strHostIP = (string)m_pStPanelStatus[nID]->objPanelConfig["connections"]["LocalIP"]; //轮询已轮询过的探测器类型,看和当前的是否重复,重复则nPanelID自增 nPanelID = 0; //恢复初值 for (int i = 0; i < nID; i++) { if (strPanelType == (string)m_pStPanelStatus[nID]->objPanelConfig["ProductID"]) { nPanelID++; } } } catch (ResDataObjectExption &exp) { Error("Get configuration failed, {$}", exp.what()); return false; } if (strPanelType.find("3543EZh") != string::npos && strPanelType.find("3543EZhd") == string::npos) { //3543EZh探测器在SDK中的类型是3543EZe strPanelType = "3543EZe"; } strDetectorIniPath = strIniFilePath + "\\Detector" + strPanelType; if (nPanelID == 1) { strDetectorIniPath += "_A"; } else if (nPanelID == 2) { strDetectorIniPath += "_B"; } strDetectorIniPath += ".ini"; Info("{$}", strDetectorIniPath.c_str()); if (strPanelType.find("DR") != string::npos) { bRet = ModifyFPDIPConf(strDetectorIniPath, strDetectorIP); } else if (!IsPortablePanel(strPanelType)) { if(strPanelType.find("4143") != string::npos || strPanelType.find("4343rc") != string::npos || strPanelType.find("4343rg") != string::npos) { //这些探测器IP只能4选1,暂不支持配置 bRet = ModifyOLDFPDIPConfEx(strDetectorIP, strDetectorIniPath); } else { bRet = ModifyOLDFPDIPConf(strDetectorIP, strDetectorIniPath, strHostIP); } } else { bRet = ModifyFPDIPConf(strDetectorIniPath, strDetectorIP, strHostIP); } } return bRet; } /*** ** 说明:修改探测器IP配置 ** 需要修改local和detector ip配置项 ***/ bool TrixellCtrl::ModifyFPDIPConf(string strConfPath, string strDetectorIP, string strHostIP) { bool bRet = CIniFileCreat(strConfPath.c_str()); if (bRet) { bool bFind = false; bool bWrited = false; //true:修改了配置文件内容 bFind = CIniFileGetValueByKey2("detector.path.0", strDetectorIP.c_str()); if (bFind) { Info("Same IP setting"); } else { string strConfigPath = "detector.path.0 = " + strDetectorIP; bRet = CIniFileSetItemByKey("hardware", "detector.path.0", strConfigPath.c_str()); if (bRet) { Info("Set configuration ({$}) succeess", strConfigPath.c_str()); } else { Error("Set configuration ({$}) failed", strConfigPath.c_str()); } bWrited = true; } if (strHostIP != "") { bFind = CIniFileGetValueByKey2("local.path", strHostIP.c_str()); if (bFind) { Info("Same IP setting"); } else { string strConfigPath = "local.path = " + strHostIP; bRet = CIniFileSetItemByKey("hardware", "local.path", strConfigPath.c_str()); if (bRet) { Info("Set configuration ({$}) succeess", strConfigPath.c_str()); } else { Error("Set configuration ({$}) failed", strConfigPath.c_str()); } bWrited = true; } } if (bWrited) //修改了内容,重新写回去 { CIniFileClose(); } else { CIniFileCloseWithoutWrite(); } } else { Error("Read DetectorXXXX.ini file failed"); CIniFileCloseWithoutWrite(); } return bRet; } /*** ** 说明:修改探测器IP配置 ** 需要修改local和detector ip配置项; ** 一般是固定板,detector ip不带.0后缀 ***/ bool TrixellCtrl::ModifyOLDFPDIPConf(string strDetectorIP, string strConfPath, string strHostIP) { bool bRet = CIniFileCreat(strConfPath.c_str()); if (bRet) { bool bFind = false; bool bWrited = false; //true:修改了配置文件内容 bFind = CIniFileGetValueByKey2("detector.path", strDetectorIP.c_str()); if (bFind) { Info("Same IP setting"); } else { string strConfigPath = "detector.path = " + strDetectorIP; bRet = CIniFileSetItemByKey("hardware", "detector.path", strConfigPath.c_str()); if (bRet) { Info("Set configuration ({$}) succeess", strConfigPath.c_str()); } else { Error("Set configuration ({$}) failed", strConfigPath.c_str()); } bWrited = true; } bFind = CIniFileGetValueByKey2("local.path", strHostIP.c_str()); if (bFind) { Info("Same IP setting"); } else { string strConfigPath = "local.path = " + strHostIP; bRet = CIniFileSetItemByKey("hardware", "local.path", strConfigPath.c_str()); if (bRet) { Info("Set configuration ({$}) succeess", strConfigPath.c_str()); } else { Error("Set configuration ({$}) failed", strConfigPath.c_str()); } bWrited = true; } if (bWrited) { CIniFileClose(); } else { CIniFileCloseWithoutWrite(); } } else { Error("Read DetectorXXXX.ini file failed"); CIniFileCloseWithoutWrite(); } return bRet; } /*** ** 说明:修改探测器IP配置 ** 早先的固定板IP配置只能4选1,配置好使用的IP后需要将不用的IP加上分号注释掉 ***/ bool TrixellCtrl::ModifyOLDFPDIPConfEx(string strDetectorIP, string strConfPath) { bool bRet = CIniFileCreat(strConfPath.c_str()); if (bRet) { bool bFind = false; bool bWrited = false; //true:修改了配置文件内容 char szIP[50]; bFind = CIniFileGetValueByKey("detector.path", szIP); if (bFind) //有不带注释的detector.path 项 { string strIP = szIP; if (strIP.find(strDetectorIP) != string::npos) { Info("Same IP setting"); } else //先注释掉原来的,再改新的 { Info("Old IP setting: {$}", szIP); string strConfigPath = "detector.path = " + strIP; bRet = CIniFileSetItemByKey("hardware", strConfigPath.c_str(), (";" + strConfigPath).c_str()); if (bRet) { Info("Set configuration ({$}) succeess", (";" + strConfigPath).c_str()); strConfigPath = "detector.path = " + strDetectorIP + ":10001"; bRet = CIniFileSetItemByKey("hardware", strConfigPath.c_str(), strConfigPath.c_str()); if (bRet) { Info("Set configuration ({$}) succeess", strConfigPath.c_str()); } else { Error("Set configuration ({$}) failed", strConfigPath.c_str()); } } else { Error("Set configuration ({$}) failed", (";" + strConfigPath).c_str()); } bWrited = true; } } else //没有的话直接改 { string strConfigPath = "detector.path = " + strDetectorIP + ":10001"; bRet = CIniFileSetItemByKey("hardware", strConfigPath.c_str(), strConfigPath.c_str()); if (bRet) { Info("Set configuration ({$}) succeess", strConfigPath.c_str()); } else { Error("Set configuration ({$}) failed", strConfigPath.c_str()); } bWrited = true; } if (bWrited) { CIniFileClose(); } else { CIniFileCloseWithoutWrite(); } } else { Error("Read DetectorXXXX.ini file failed"); CIniFileCloseWithoutWrite(); } return bRet; } /*** ** 说明:修改SDK中探测器配置ModuleXX_IR_1.ini ** 修改module.serial.port项 ***/ bool TrixellCtrl::SetIRPort(string strDetectorType, int nPort) { if (nPort <= 0) { Error("The IR port({$}) is illegal", nPort); return false; } string strModuleIRFile = ""; string strModuleIRBKFile = ""; if (strDetectorType.find("3543DR") != string::npos) { strModuleIRFile = m_strWorkPath + "\\" + m_strCfgPath + "\\ModuleDR_IR_1.ini"; strModuleIRBKFile = m_strWorkPath + "\\" + m_strCfgPath + "\\ModuleDR_IR_1_bk.ini"; } else { strModuleIRFile = m_strWorkPath + "\\" + m_strCfgPath + "\\ModuleEZ_IR_1.ini"; strModuleIRBKFile = m_strWorkPath + "\\" + m_strCfgPath + "\\ModuleEZ_IR_1_bk.ini"; } char szConfigValue[10] = ""; //用于获取配置文件中的串口号,e.g. com3 //先确认有配置项 DWORD dwRet = GetPrivateProfileString("hardware", "module.serial.port", "", szConfigValue, sizeof(szConfigValue), strModuleIRFile.c_str()); if (dwRet == 0) { Error("Get IR port failed({$})", GetLastError()); return false; } Info("IR port of SDK config: {$}", szConfigValue); string strConfigValue = szConfigValue; strConfigValue = strConfigValue.substr(3); //截取"com"之后的字符 int nIRPort = atoi(strConfigValue.c_str()); if (nIRPort == nPort) { Info("Same port, return"); return true; } else { sprintf_s(szConfigValue, "com%d", nPort); Info("Set IR port to {$}", szConfigValue); dwRet = WritePrivateProfileString("hardware", "module.serial.port", szConfigValue, strModuleIRFile.c_str()); if (dwRet == 0) { Error("Set IR port failed({$})", GetLastError()); return false; } } Info("Set IR port OK"); return true; } /*** ** 说明:设置状态轮询使能 ***/ bool TrixellCtrl::SetStatusPolling(int nDetectorID, bool bEnable) { if (bEnable) { SetDetectorStatusPolling(nDetectorID, true); } else { SetDetectorStatusPolling(nDetectorID, false); } return true; } /*** ** 说明:调用API轮询探测器状态 ***/ bool TrixellCtrl::SetDetectorStatusPolling(int nDetectorID, bool bEnable) { Info("Calling DetectorStatusPolling(ID:{$} bEnable:{$})", nDetectorID, bEnable); error_status eErrorStatus = TED_PixRad_DetectorStatusPolling(nDetectorID, bEnable); if (!TestError(eErrorStatus)) { Error("Get detector status polling command Failed"); return false; } return true; } /*** ** 说明:获取探测器信息(HW/WIFI) ***/ bool TrixellCtrl::GetHardwareStatus(int nDetectorID) { if (m_pStPanelStatus[nDetectorID]->bConnectStatus) //只在连接状态下查询 { GetDetectorHardwareStatus(nDetectorID); //双板的HW都要查询 string strPanelType = m_pStPanelStatus[nDetectorID]->strPanelType; if (IsPortablePanel(strPanelType)) { GetDetectorWifiStatus(nDetectorID); } } return true; } /*** ** 说明:调用API获取HW信息 ***/ bool TrixellCtrl::GetDetectorHardwareStatus(int nDetectorID) { LockPixrad("GetDetectorHardwareStatus"); Info("Get Detector {$} Hardware Status", nDetectorID); error_status eErrorStatus = TED_PixRad_GetDetectorHardwareStatus(nDetectorID); //EVT_HARDWARE_STATUS->EVT_ACTIVE_STATE if (!TestError(eErrorStatus)) { Info("Get detector hardware status command Failed"); //UnlockPixrad("GetDetectorHardwareStatus"); return true; } LockPixrad("GetDetectorHardwareStatus"); UnlockPixrad("GetDetectorHardwareStatus"); return false; } /*** ** 说明:调用API获取Wifi ***/ bool TrixellCtrl::GetDetectorWifiStatus(int nDetectorID) { LockPixrad("GetDetectorWifiStatus"); //确保上一步执行完毕 m_bNeedFeedback = true; Info("Get Detector {$} Wifi Status", nDetectorID); error_status eErrorStatus = TED_PixRad_GetDetectorWifiStatus(nDetectorID); //EVT_WIFI_STATUS if (!TestError(eErrorStatus)) { Error("Get detector wifi status fail!"); m_bNeedFeedback = false; return false; } LockPixrad("GetDetectorWifiStatus"); //等待反馈 UnlockPixrad("GetDetectorWifiStatus"); return true; } /*** ** 说明:调用API获取shock sensor和Voltage ***/ bool TrixellCtrl::GetDetectorInformation(int nDetectorID, bool bRequireVoltage) { Info("Getting Detector Info"); if (m_pStPanelStatus[nDetectorID]->bConnectStatus) { if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); return false; } else { Info("Set Quiet State OK"); } LockPixrad("GetDetectorInformation"); //确保上一步执行完毕 Info("Get Detector {$} Shock Sensor", nDetectorID); error_status eErrorStatus = TED_PixRad_GetDetectorInformation(DI_SHOCK_SENSOR); //EVT_DETECTOR_INFORMATION if (!TestError(eErrorStatus)) { Info("Get detector Information command Failed"); //UnlockPixrad("GetDetectorInformation"); return false; } LockPixrad("GetDetectorInformation"); //等回调 UnlockPixrad("GetDetectorInformation"); if (bRequireVoltage) { LockPixrad("GetVoltage"); Info("Get Detector {$} Voltage", nDetectorID); eErrorStatus = TED_PixRad_GetVoltage(); //EVT_END_VOLTAGES if (!TestError(eErrorStatus)) { Info("Get detector Voltage Failed"); //UnlockPixrad("GetVoltage"); return false; } LockPixrad("GetVoltage"); //等回调 UnlockPixrad("GetVoltage"); } } else { Info("Not connect, return"); } return false; } /*** ** 说明:上传文件到探测器内部 ** 在RAD3中由上层流程触发,此处触发方式待定 ***/ bool TrixellCtrl::UploadSensitivity(int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } if (m_pStPanelStatus[nDetectorID]->bConnectStatus) { Warn("Communication error, not upload file"); return true; } string strFileName = m_pStPanelStatus[nDetectorID]->strPanelSN + "_Sensitivity.txt"; string strLocalPath = m_strWorkPath + "\\references\\" + strFileName; string strDestPath = m_pStPanelStatus[nDetectorID]->strPanelSN + "\\references\\CalibrationData\\"; strDestPath += m_pStPanelStatus[nDetectorID]->strPanelSN + "\\" + strFileName; CopyFile2Folder(strLocalPath, strDestPath); bool bResult = UploadtoDetector(strLocalPath, strFileName); return bResult; } /*** ** 说明:下载探测器内部的文件 ** 应用在attach流程 ***/ bool TrixellCtrl::DownloadSensitivity(int nDetectorID) { return true; } bool TrixellCtrl::UploadReferences(int nDetectorID) { return true; } bool TrixellCtrl::RestoreCalibrationData(bool bLTEenable, int nDetectorID) { return true; } /*** ** 说明:从探测器中下载校正文件和报告 ***/ bool TrixellCtrl::DownloadReferences(bool bLTEenable, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } string strGainFile = m_pStPanelStatus[nDetectorID]->strPanelSN + STR_GainFILE; string strDefectFile = m_pStPanelStatus[nDetectorID]->strPanelSN + STR_FXDFILE; //add20210402 长曝光 下载gain文件、defect文件 if (bLTEenable) { strGainFile = m_pStPanelStatus[nDetectorID]->strPanelSN + STR_GainFILEL; strDefectFile = m_pStPanelStatus[nDetectorID]->strPanelSN + STR_FXDFILEL; }//addend string strLocalPath = m_strWorkPath + "\\references\\" + strGainFile; DownloadfromDetector(strLocalPath, strGainFile); string strDestPath = m_strWorkPath + "\\references\\CalibrationData\\"; strDestPath += m_pStPanelStatus[nDetectorID]->strPanelSN + "\\" + strGainFile; CopyFile2Folder(strLocalPath, strDestPath); strLocalPath = m_strWorkPath + "\\references\\" + strDefectFile; DownloadfromDetector(strLocalPath, strDefectFile); strDestPath = m_strWorkPath + "\\references\\CalibrationData\\"; strDestPath += m_pStPanelStatus[nDetectorID]->strPanelSN + "\\" + strDefectFile; CopyFile2Folder(strLocalPath, strDestPath); string strManualDefectFile = m_pStPanelStatus[nDetectorID]->strPanelSN + STR_Manual_DefectFILE; //add20210402 长曝光 下载manual defect文件 if (bLTEenable) //0:STE; 1:LTE { strManualDefectFile = m_pStPanelStatus[nDetectorID]->strPanelSN + STR_Manual_DefectFILEL; }//addend strLocalPath = m_strWorkPath + "\\references\\" + strManualDefectFile; DownloadfromDetector(strLocalPath, strManualDefectFile); strDestPath = m_strWorkPath + "\\references\\CalibrationData\\"; strDestPath += m_pStPanelStatus[nDetectorID]->strPanelSN + "\\" + strManualDefectFile; CopyFile2Folder(strLocalPath, strManualDefectFile); string strPanelType = "3543dr"; string strTemp = m_pStPanelStatus[nDetectorID]->strPanelType; if (strTemp.find("3543EZ") != string::npos) { strPanelType = "3543ezh"; } else if (strTemp.find("2430EZ") != string::npos) { strPanelType = "2430ez"; } string strReferenceFile = ""; char szReferenceFile[50]; sprintf_s(szReferenceFile, "FDCalibReport_%s_fd%s_30.xml", m_pStPanelStatus[nDetectorID]->strPanelSN.c_str(), strPanelType.c_str()); //长曝光 下载校正报告 if (bLTEenable) //0:STE; 1:LTE { sprintf_s(szReferenceFile, "FDCalibReport_%s_fd%s_31.xml", m_pStPanelStatus[nDetectorID]->strPanelSN.c_str(), strPanelType.c_str()); } strReferenceFile = szReferenceFile; strLocalPath = m_strWorkPath + "\\references\\" + strReferenceFile; DownloadfromDetector(strLocalPath, strReferenceFile); strDestPath = m_strWorkPath + "\\references\\CalibrationData\\"; strDestPath += m_pStPanelStatus[nDetectorID]->strPanelSN + "\\" + strReferenceFile; CopyFile2Folder(strLocalPath, strDestPath); return true; } /*** ** 说明:上传manual defect map ** 在RAD3中由上层流程触发,此处触发方式待定 ***/ bool TrixellCtrl::UploadDefectCalibrationFiles(int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } Info("Upload Defect Calibration Files"); StatusFeedback(EVT_STATUS_SAVEDEFECT, PANEL_EVENT_START); bool bResult = false; if ((m_pStPanelStatus[nDetectorID]->strPanelSN == "") || !m_pStPanelStatus[nDetectorID]->bConnectStatus) { StatusFeedback(EVT_STATUS_SAVEDEFECT, PANEL_EVENT_END_ERROR); Info("Omit Upload Defect Files"); return false; } string strDefectFile = m_pStPanelStatus[nDetectorID]->strPanelSN + STR_Manual_DefectFILE; //长曝光 上传manual defect if (m_bLTEenable) //0:STE; 1:LTE { strDefectFile = m_pStPanelStatus[nDetectorID]->strPanelSN + STR_Manual_DefectFILEL; }//addend string strLocalPath = m_strWorkPath + "\\references\\" + strDefectFile; string strDestPath = m_strWorkPath + "\\references\\CalibrationData\\"; strDestPath += m_pStPanelStatus[nDetectorID]->strPanelSN + "\\" + strDefectFile; CopyFile2Folder(strLocalPath, strDestPath); bResult = UploadtoDetector(strLocalPath, strDefectFile); if (!bResult) { StatusFeedback(EVT_STATUS_SAVEDEFECT, PANEL_EVENT_END_ERROR); return false; } bResult = UploadDefectMap(); if (bResult) { StatusFeedback(EVT_STATUS_SAVEDEFECT, PANEL_EVENT_END); } else { StatusFeedback(EVT_STATUS_SAVEDEFECT, PANEL_EVENT_END_ERROR); } return true; } /*** ** 说明:上传defect map和校正报告 ***/ bool TrixellCtrl::UploadDefectMap(int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } //目前没有_Defect.map,先去掉这个流程 string strDefectMap = ""; string strLocalPath = ""; //string strDefectMap = m_pStPanelStatus[nDetectorID]->strPanelSN + "_Defect.map"; //string strLocalPath = m_strWorkPath + "\\references\\" + strDefectMap; if (!m_pStPanelStatus[nDetectorID]->bConnectStatus) { StatusFeedback(EVT_STATUS_SAVEDEFECT, PANEL_EVENT_END_ERROR); Error("Detector is disconnected, Save defect delta map failed"); return false; } string strDestPath = ""; //string strDestPath = m_strWorkPath + "\\references\\CalibrationData\\"; //strDestPath += m_pStPanelStatus[nDetectorID]->strPanelSN + "\\" + strDefectMap; //CopyFile2Folder(strLocalPath, strDestPath); bool bResult = false; //bool bResult = UploadtoDetector(strLocalPath, strDefectMap); string strPanelType = "3543dr"; string strTemp = m_pStPanelStatus[nDetectorID]->strPanelType; if (strTemp.find("3543EZ") != string::npos) { strPanelType = "3543ezh"; } else if (strTemp.find("2430EZ") != string::npos) { strPanelType = "2430ez"; } string strReferenceFile = ""; char szReferenceFile[50] = { 0 }; sprintf_s(szReferenceFile, "FDCalibReport_%s_fd%s_30.xml", m_pStPanelStatus[nDetectorID]->strPanelSN.c_str(), strPanelType.c_str()); //长曝光 上传校正报告 if (m_bLTEenable) //0:STE; 1:LTE { sprintf_s(szReferenceFile, "FDCalibReport_%s_fd%s_31.xml", m_pStPanelStatus[nDetectorID]->strPanelSN.c_str(), strPanelType.c_str()); } strReferenceFile = szReferenceFile; strLocalPath = m_strWorkPath + "\\references\\" + szReferenceFile; strDestPath = m_strWorkPath + "\\references\\CalibrationData\\"; strDestPath += m_pStPanelStatus[nDetectorID]->strPanelSN + "\\" + szReferenceFile; CopyFile2Folder(strLocalPath, strDestPath); bResult = UploadtoDetector(strLocalPath, strReferenceFile); if (!bResult) { return false; } return true; } /*** ** 说明:下载defect map ***/ bool TrixellCtrl::DownloadDefectMap(int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } string strDefectMap = m_pStPanelStatus[nDetectorID]->strPanelSN + "_Defect.map"; string strLocalPath = m_strWorkPath + "\\references\\" + strDefectMap; DownloadfromDetector(strLocalPath, strDefectMap, nDetectorID); string strDestPath = m_strWorkPath + "\\references\\CalibrationData\\"; strDestPath += m_pStPanelStatus[nDetectorID]->strPanelSN + "\\" + strDefectMap; CopyFile2Folder(strLocalPath, strDestPath); return true; } /*** ** 说明:调用API,上传文件到探测器内部 ***/ bool TrixellCtrl::UploadtoDetector(string strFilePath, string strFileName, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } bool bResult = false; LockPixrad("OpenRemoteStorageSession"); //确保上一步执行完毕 Info("Calling OpenRemoteStorageSession"); error_status eErrorStatus = TED_PixRad_OpenRemoteStorageSession(); //EVT_START_REMOTE_STORAGE_SESSION if (!TestError(eErrorStatus)) { Error("OpenRemoteStorageSession failed"); //UnlockPixrad("OpenRemoteStorageSession"); return false; } LockPixrad("OpenRemoteStorageSession"); //等待SessionID UnlockPixrad("OpenRemoteStorageSession"); Info("Calling RemoteStorageCreateDirectory"); rs_error_status rsErrorStatus = TED_PixRad_RemoteStorageCreateDirectory(m_nSessionID, "RAD3\\"); //双层目录,创建两次就可以了 if (!TestRSError(rsErrorStatus)) { Error("RemoteStorageCreateDirectory failed"); //return false; //这块应该一直是失败的(session error -31 'SFTP Protocol Error 4'),不影响 } string strRemotePath = "RAD3\\" + strFileName; Info("Calling Upload File:{$} To {$}", strFilePath.c_str(), strRemotePath.c_str()); rsErrorStatus = TED_PixRad_RemoteStorageUploadFile(m_nSessionID, strFilePath.c_str(), strRemotePath.c_str(), RsprogressCallback, 0); if (!TestRSError(rsErrorStatus)) { Error("RemoteStorageUploadFile failed"); bResult = false; } else { bResult = true; } LockPixrad("CloseRemoteStorageSession"); //确保上一步执行完毕 Info("Calling CloseRemoteStorageSession"); eErrorStatus = TED_PixRad_CloseRemoteStorageSession(); if (!TestError(eErrorStatus)) { Error("CloseRemoteStorageSession failed"); //UnlockPixrad("CloseRemoteStorageSession"); return false; } LockPixrad("CloseRemoteStorageSession"); UnlockPixrad("CloseRemoteStorageSession"); if (bResult) { Info("Upload files to detector success"); } else { Error("Upload files to detector failed"); } return bResult; } /*** ** 说明:调用API,下载探测器内部的文件 ***/ bool TrixellCtrl::DownloadfromDetector(string strFilePath, string strFileName, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } LockPixrad("OpenRemoteStorageSession"); //确保上一步执行完毕 Info("Calling OpenRemoteStorageSession"); error_status eErrorStatus = TED_PixRad_OpenRemoteStorageSession(); //EVT_START_REMOTE_STORAGE_SESSION if (!TestError(eErrorStatus)) { Error("OpenRemoteStorageSession failed"); //UnlockPixrad("OpenRemoteStorageSession"); return false; } LockPixrad("OpenRemoteStorageSession"); UnlockPixrad("OpenRemoteStorageSession"); string strRemotePath = "RAD3\\" + strFileName; Info("Calling Download File:{$} from {$}", strFilePath.c_str(), strRemotePath.c_str()); rs_error_status rsErrorStatus = TED_PixRad_RemoteStorageDownloadFile(m_nSessionID, strRemotePath.c_str(), strFilePath.c_str(), RsprogressCallback, 0); if (!TestRSError(rsErrorStatus)) { Error("RemoteStorageDownloadFile failed"); } LockPixrad("CloseRemoteStorageSession"); //确保上一步执行完毕 Info("Calling CloseRemoteStorageSession"); eErrorStatus = TED_PixRad_CloseRemoteStorageSession(); //EVT_END_REMOTE_STORAGE_SESSION->EVT_ACTIVE_STATE(xxx) 恢复到操作之前的state if (!TestError(eErrorStatus)) { Error("CloseRemoteStorageSession failed"); return false; } Info("Download files from detector over"); LockPixrad("CloseRemoteStorageSession"); //等待回调EVT_ACTIVE_STATE(STATE_PATIENT) UnlockPixrad("CloseRemoteStorageSession"); return true; } /*** ** 说明:加载校正文件 ***/ bool TrixellCtrl::FactoryCorrectionActive(bool bAttachProcess, int nDetectorID) { Info("FactoryCorrectionActive bAttachProcess:{$},nDetectorID:{$}", bAttachProcess, nDetectorID); if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } if (m_pStPanelStatus[nDetectorID]->bConnectStatus) { if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); return false; } else { Info("Set Quiet State OK"); } //1. 先同步本地和探测器端校正文件 if (bAttachProcess && nDetectorID == m_nAttachFPDID) { DownloadReferences(); DownloadReferences(true); //下载长曝光模式校正文件 DownloadDefectMap(); } //2. 再加载本地校正文件 int nMode = g_nRADmode; if (SYNC_AED == m_stDeviceIndex[m_nCurrentPanelID].nSyncMode) { nMode = g_nAEDmode; } bool bResult = LoadReference(nMode, nDetectorID); if (!bResult) //同步校正文件后,再次加载校正文件 { Error("Load All Reference File Failed"); } else { Info("Load All Reference File OK"); } //3. 重设状态 if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); } else { Info("Set Quiet State OK"); } return bResult; } return false; } /*** ** 说明:探测器自检 ***/ bool TrixellCtrl::SelfTestFPD(int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } if (m_pStPanelStatus[nDetectorID]->bConnectStatus) { LockPixrad("PerformDetectorSelfTest"); //确保上一步执行完毕 Info("Calling PerformDetectorSelfTest"); error_status eErrorStatus = TED_PixRad_PerformDetectorSelfTest(); // EVT_END_SELF_TEST if (!TestError(eErrorStatus)) { Error("Perform Detector SelfTest Error"); //UnlockPixrad("PerformDetectorSelfTest"); return false; } Info("Perform Detector SelfTest OK"); LockPixrad("PerformDetectorSelfTest"); UnlockPixrad("PerformDetectorSelfTest"); StatusFeedback(EVT_STATUS_SELFTEST, nDetectorID, m_SelfTest.encode()); } return true; } /*** ** 说明:获取校正时间 ** 连接成功后,校正完成后 获取 ***/ bool TrixellCtrl::GetCalibrationTime(int nDetectorID) { if (nDetectorID == -1) { nDetectorID = m_nCurrentPanelID; } SystemCalibrationTimeStatus stSystemCalibrationTimeStatus; error_status eErrorStatus = TED_PixRad_GetSystemCalibrationTimeStatus(stSystemCalibrationTimeStatus); if (TestError(eErrorStatus)) { Info("CalibrationTimeStatus Detector Number:{$}", stSystemCalibrationTimeStatus.nbDetectors); for (int i = 0; i < stSystemCalibrationTimeStatus.nbDetectors; ++i) { if (i != nDetectorID) { continue; } int nMode = 0; for (; nMode < stSystemCalibrationTimeStatus.detectorCalibrationTimeStatus[i].nbApplicationModes; ++nMode) { __platform_time_t nOffsetCalibrationTime = stSystemCalibrationTimeStatus.detectorCalibrationTimeStatus[i].applicationModeCalibrationTimeStatus[nMode].offsetCalibrationTime; __platform_time_t nPixelsClusterDefectCalibrationTime = stSystemCalibrationTimeStatus.detectorCalibrationTimeStatus[i].applicationModeCalibrationTimeStatus[nMode].pixelsClusterDefectCalibrationTime; __platform_time_t nGainCalibrationTime = stSystemCalibrationTimeStatus.detectorCalibrationTimeStatus[i].applicationModeCalibrationTimeStatus[nMode].gainCalibrationTime; __platform_time_t nGefectMapCalibrationTime = stSystemCalibrationTimeStatus.detectorCalibrationTimeStatus[i].applicationModeCalibrationTimeStatus[nMode].defectMapCalibrationTime; __platform_time_t* pnDefectTime = &nGefectMapCalibrationTime; __platform_time_t nPreviewOffsetCalibrationTime = stSystemCalibrationTimeStatus.detectorCalibrationTimeStatus[i].applicationModeCalibrationTimeStatus[nMode].previewOffsetCalibrationTime; __platform_time_t* pnPreviewOffsetTime = &nPreviewOffsetCalibrationTime; char szCalibTime[MAX_STRING] = { 0 }; errno_t nResult = _ctime64_s(szCalibTime, pnDefectTime); string strInitCalibTime = szCalibTime; Info("{$}", strInitCalibTime.c_str()); string strYear = ""; string strMonth = "01"; string strDay = ""; string strTime = "0"; int nIndex = 0, nTemp = 0; string str; for (int i = 0; i < strInitCalibTime.length(); i++) { //Thu Jan 01 08:00:00 1970 //c++11里,1号显示为01 //Sat Jan 2 14:00:01 2021 //c++高版本,1号显示为 1 if (szCalibTime[i] != ' ') { str += szCalibTime[i]; if (i == strInitCalibTime.length() - 1) { strYear = strInitCalibTime.substr(strInitCalibTime.length() - 5, 4); } } else { //printf("%s* \r\n", str.c_str()); if (str != "") { nTemp++; if (nTemp == 2) { strMonth = str; } if (nTemp == 3) { strDay = str; } str.clear(); } } } if (strMonth.find("Jan") != string::npos) { strMonth = "01"; } else if (strMonth.find("Feb") != string::npos) { strMonth = "02"; } else if (strMonth.find("Mar") != string::npos) { strMonth = "03"; } else if (strMonth.find("Apr") != string::npos) { strMonth = "04"; } else if (strMonth.find("May") != string::npos) { strMonth = "05"; } else if (strMonth.find("Jun") != string::npos) { strMonth = "06"; } else if (strMonth.find("Jul") != string::npos) { strMonth = "07"; } else if (strMonth.find("Aug") != string::npos) { strMonth = "08"; } else if (strMonth.find("Sep") != string::npos) { strMonth = "09"; } else if (strMonth.find("Oct") != string::npos) { strMonth = "10"; } else if (strMonth.find("Nov") != string::npos) { strMonth = "11"; } else if (strMonth.find("Dec") != string::npos) { strMonth = "12"; } strTime = strYear + strMonth + strDay; Info("Calibration Time:{$}", strTime.c_str()); if (g_nRADmode - 1 == nMode) { InfoFeedback(EVT_INFO_CALIBRATIOIN_TIME, nDetectorID, 0, 0, strTime.c_str()); } else if (g_nRADLTEmode - 1 == nMode) { InfoFeedback(EVT_INFO_CALIBRATIOIN_TIMEL, nDetectorID, 0, 0, strTime.c_str()); } } } } else { InfoFeedback(EVT_INFO_CALIBRATIOIN_TIME, nDetectorID, 0, 0, "0"); InfoFeedback(EVT_INFO_CALIBRATIOIN_TIMEL, nDetectorID, 0, 0, "0"); } return true; } /*** ** 说明:调用API,激活探测器 ***/ bool TrixellCtrl::SetActiveDetector(unsigned short usDetectorID) { Info("Activing Panel ID: {$}", usDetectorID); if (m_nPanelCount == 1) { Info("Set the only one Panel Active OK"); return true; } unsigned short nCurrentDetector = -1; if (!GetActiveDetector(nCurrentDetector)) { Error("Get Active Detector Failed"); return false; } if (nCurrentDetector == usDetectorID) { m_nCurrentPanelID = usDetectorID; Info("The Detector is already actived"); return true; } LockPixrad("SetActiveDetector"); error_status ErrorStatus = TED_PixRad_SetActiveDetector(usDetectorID); // EVT_ACTIVE_DETECTOR if (!TestError(ErrorStatus)) { Error("Set Active Detector command Failed"); //UnlockPixrad("SetActiveDetector"); return false; } Info("Set Active Detector command OK"); LockPixrad("SetActiveDetector"); UnlockPixrad("SetActiveDetector"); m_nCurrentPanelID = usDetectorID; return true; } /*** ** 说明:调用API,获取当前激活探测器的ID ***/ bool TrixellCtrl::GetActiveDetector(unsigned short& usDetectorID) { error_status ErrorStatus = TED_PixRad_GetActiveDetector(usDetectorID); if (!TestError(ErrorStatus)) { Error("Get Active Detector command Failed"); return false; } else { Info("Get Active Detector command OK"); Info("Current Active Detector is {$}", usDetectorID); return true; } } /*** * 说明:发送模拟的shock信息 * modify20220119 与客户端统一json格式,便于客户端解析 ***/ void TrixellCtrl::SimulateShockSensor(int nDetectorID, bool bSend) { } /*** ** 说明:解析字符串,读取应用模式和采集模式的对应关系 ** 应用模式,例如 101 201 501... 和rad、pf、cf、tomo等模式对应 ** 采集模式,1,2,3... 取自探测器配置文件 ***/ bool TrixellCtrl::GetModeMatchInfo() { string strModeMatch = ""; strModeMatch = (string)m_ModeConfig[FPDModeMatch]; strModeMatch = strModeMatch.substr(1, strModeMatch.length() - 2); //去掉前后括号 bool bFindComma = false; int nPos = (int)strModeMatch.find(":"); if (nPos == string::npos) { return false; } while (nPos > 0) { int n = (int)strModeMatch.find(","); if (n > 0) //说明还有下一组match关系 { bFindComma = true; } //拿到ExamMode string strExamMode = strModeMatch.substr(0, nPos); // \"101\" n = (int)strExamMode.find("\""); strExamMode = strExamMode.substr(n + 1); //去掉key前的引号 n = (int)strExamMode.find("\""); strExamMode = strExamMode.substr(0, n); //拿到LogicMode string strLogicMode = ""; if (bFindComma) { n = (int)strModeMatch.find(","); strLogicMode = strModeMatch.substr(nPos + 1, n - nPos - 1); //去掉逗号前的match关系 strModeMatch = strModeMatch.substr(n + 1); //例 \"501\":2,\"302\":2 } else { strLogicMode = strModeMatch.substr(nPos + 1); //去掉冒号前的match关系 strModeMatch = strModeMatch.substr(nPos + 1); } m_ModeMatch.add(strExamMode.c_str(), strLogicMode.c_str()); //printf("ExamMode: %s LogicMode: %s \n", strExamMode.c_str(), strLogicMode.c_str()); nPos = (int)strModeMatch.find(":"); bFindComma = false; //恢复初值 } return true; } bool TrixellCtrl::IsPortablePanel(string strPanelType) { if ((strPanelType.find("3543EZ") != string::npos) || (strPanelType.find("3543DR") != string::npos) || (strPanelType.find("2430EZ") != string::npos)) { return true; } return false; } bool TrixellCtrl::CopyFile2Folder(string strSrcPath, string strDstPath) { //MSDN: This string must be double-null terminated strSrcPath += '\0'; strDstPath += '\0'; Info("Copy {$} to {$}", strSrcPath.c_str(), strDstPath.c_str()); SHFILEOPSTRUCT sfo; sfo.hwnd = NULL; sfo.wFunc = FO_COPY;//FO_MOVE; sfo.pFrom = strSrcPath.c_str(); sfo.pTo = strDstPath.c_str(); sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO; //| FOF_NOCONFIRMMKDIR; // FOF_ALLOWUNDO:保存UNDO信息,以便在回收站中恢复文件; //FOF_NOCONFIRMATION:在出现目标文件已存在的时候,如果不设置此项,则它会出现确认是否覆盖的对话框,设置此项则自动确认,进行覆盖,不出现对话框。 int nRet = SHFileOperation(&sfo); Info("Copy File to Folder over, {$}", nRet); return true; } /*** ** 检查文件是否存在 ***/ bool TrixellCtrl::CheckFileExits(string strPath, string strFile) { vector filelist; if (!FindSubFiles(strPath, filelist)) { Info("{$} is a null path", strPath.c_str()); return false; } for (DWORD dw = 0; dw < filelist.size(); dw++) { string strTemp = filelist[dw]; if (strTemp == strFile) { return true; } } return false; } /*** ** 完成校正的处理 ** DPC生成校正报告后调用 ***/ void TrixellCtrl::OnEndCalibraion() { Info("OnEndCalibraion"); StatusFeedback(EVT_STATUS_SAVECALIB, PANEL_EVENT_START); bool bResult = true; //bool bResult = UploadReferences(); //no use for droc //bResult = bResult && UploadDefectMap(); GetCalibrationTime(); if (!SetSystemState(STATE_QUIET)) { Warn("Set Quiet State Failed"); } else { Info("Set Quiet State OK"); } if (bResult) { StatusFeedback(EVT_STATUS_SAVECALIB, PANEL_EVENT_END); //StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); //改为收到SDK回调时处理 } else { StatusFeedback(EVT_STATUS_SAVECALIB, PANEL_EVENT_END_ERROR); //StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_ERROR); //改为收到SDK回调时处理 } } void TrixellCtrl::ConfFeedback(int nEventID, int nDetectorID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceTrixell*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_CONFIGURATION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void TrixellCtrl::InfoFeedback(int nEventID, int nDetectorID, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceTrixell*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_INFORMATOION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void TrixellCtrl::StatusFeedback(int nEventID, int nParam1, const char* pszMsg, int nDetectorID, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceTrixell*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_STATUS, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void TrixellCtrl::DataFeedback(int nEventID, void* pParam, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceTrixell*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_DATA, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void TrixellCtrl::WarnFeedback(int nEventID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceTrixell*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_WARNING, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void TrixellCtrl::ErrorFeedback(int nEventID, const char* pszMsg, int nDetectorID, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceTrixell*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_ERROR, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } /*** ** 说明:红外功能设置 ** 参数:bModifyConfig,是否修改配置文件 ** bInvokeAPI,是否调用接口 ** 根据配置文件,设置COM口,使能红外监控扫描 ***/ bool TrixellCtrl::IRFuncSetting(bool bModifyConfig, bool bInvokeAPI) { int nModuleEnable = 0; bool bSetDRIRPort = true; //设置DR类型探测器的红外com口配置 bool bSetEZIRPort = true; //设置EZ类型探测器的红外com口配置 string strPanelType = ""; int nPort = -1; //通过循环,读取所有探测器配置的红外使能配置,有一个使能,则使能SDK红外扫描功能 try { bool bModuleEnable = false; for (int i = 0; i < m_nPanelCount; i++) { int nTemp = (int)m_pStPanelStatus[i]->objPanelConfig["ModuleEnable"]; if (nTemp > 0) { bModuleEnable = true; } } //修改com口配置 if (bModuleEnable && bModifyConfig) { Info("Detector enable module polling"); nPort = (int)m_pStPanelStatus[0]->objPanelConfig["connections"]["port"]; if (!SetIRPort("3543EZ", nPort)) //类型临时写死,等加入多板的时候再考虑完善方案 { SetIRPort("3543EZ", nPort); } } if (!bModuleEnable) { Info("Detector disable module polling"); } //使能红外扫描 if (bModuleEnable && bInvokeAPI) { LockPixrad("ModulePolling"); Info("Calling ModulePolling(enable)"); error_status Err = TED_PixRad_ModulePolling(true); //同步函数 //EVT_MODULE_POLLING_CHANGED if (!TestError(Err)) { Error("Enable module polling command Failed"); //UnlockPixrad("ModulePolling"); } else { Info("Enable module polling command OK"); LockPixrad("ModulePolling"); UnlockPixrad("ModulePolling"); } } } catch (ResDataObjectExption& exp) { Error("Get configuration failed, {$}", exp.what()); return false; } return true; } DWORD __stdcall TrixellCtrl::onFPDScanThread(PVOID pvoid) { TrixellCtrl* pOpr = (TrixellCtrl*)pvoid; Info("Enter Scan Thread"); bool bExit = false; int nTimecout = 0; //查询探测器状态的计时器 DWORD dwTimeout = INFINITE; while (!bExit) { DWORD dwRet = WaitForMultipleObjects(7, pOpr->m_hArrayEvent, FALSE, dwTimeout); if (WAIT_TIMEOUT == dwRet) { nTimecout += 5; if (nTimecout > pOpr->m_nStatusTimeout) { pOpr->RefreshHWStatus(); nTimecout = 0; } } else if (WAIT_OBJECT_0 == dwRet) //m_hStopScanEvent { bExit = true; } else if (WAIT_OBJECT_0 + 1 == dwRet) //m_hProcessImgEvent { pOpr->OnProcessImg(); } else if (WAIT_OBJECT_0 + 2 == dwRet) //m_hXWinOnEvent { pOpr->StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); } else if (WAIT_OBJECT_0 + 3 == dwRet) //m_hXWinOffEvent { pOpr->StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF); } else if (WAIT_OBJECT_0 + 4 == dwRet) //m_hEndCalibEvent { pOpr->OnEndCalibraion(); } else if (WAIT_OBJECT_0 + 5 == dwRet) //m_hDarkEndEvent { pOpr->OnProcessDarkEnd(); } else if (WAIT_OBJECT_0 + 6 == dwRet) //m_hClosePollingEvent { Info("Get m_hClosePollingEvent SetDetectorStatusPolling == false"); pOpr->SetDetectorStatusPolling(pOpr->m_nStopPollingIndex, false); } else { Error("Scan Thread Failed, {$}", dwRet); } } Info("Exit Scan Thread"); SetEvent(pOpr->m_hToggleEvent); return 0; } DWORD __stdcall TrixellCtrl::onCheckShockThread(PVOID pvoid) { TrixellCtrl* pOpr = (TrixellCtrl*)pvoid; Info("Enter CheckShock Thread"); while (!pOpr->m_bExitShockCheck) { Info("Waiting check shock information"); DWORD nResult = WaitForSingleObject(pOpr->m_hCheckShockEvent, INFINITE); if (WAIT_OBJECT_0 == nResult) //偶尔会出现EVT_HARDWARE太慢的情况 { if (!pOpr->m_bExitShockCheck) { if ((DetStatus_Acquire != pOpr->m_eStatus) && (DetStatus_Offset != pOpr->m_eStatus) && (DetStatus_XrayCalibration != pOpr->m_eStatus)) { pOpr->Thread_Lock(); int nDetectorID = pOpr->m_nShockFPDID; pOpr->Thread_UnLock(); Info("Call GetDetectorInformation(ID: {$})", nDetectorID); pOpr->GetDetectorInformation(nDetectorID, false); } else { Warn("Work status, Omit GetDetectorInformation"); //退出检查时会check } } else { Info("Quit GetDetectorInformation"); break; } } } Info("Exit CheckShock Thread"); return 0; } /*** ** 说明:停止线程 ** 退出时调用 ***/ void TrixellCtrl::StopThread() { m_bExitShockCheck = true; SetEvent(m_hCheckShockEvent); //关闭check线程 m_hCheckShockThread = NULL; if (m_hFPDScanThread != NULL) { ResetEvent(m_hToggleEvent); SetEvent(m_hStopScanEvent); DWORD result = WaitForSingleObject(m_hToggleEvent, 5000); if (result == WAIT_OBJECT_0) { Info("Leave Thread Over"); } else if (result == WAIT_TIMEOUT) { Warn("Till time out"); } m_hFPDScanThread = NULL; } SetEvent(m_hQuitAdaptEvent); Info("Quit apdat thread"); /*if (m_hRespondEvent) { CloseHandle(m_hRespondEvent); m_hRespondEvent = NULL; }*/ /*if (m_hStopScanEvent) { CloseHandle(m_hStopScanEvent); m_hStopScanEvent = NULL; }*/ /*if (m_hProcessImgEvent) { CloseHandle(m_hProcessImgEvent); m_hProcessImgEvent = NULL; }*/ /*if (m_hXWinOnEvent) { CloseHandle(m_hXWinOnEvent); m_hXWinOnEvent = NULL; } if (m_hXWinOffEvent) { CloseHandle(m_hXWinOffEvent); m_hXWinOffEvent = NULL; } if (m_hEndCalibEvent) { CloseHandle(m_hEndCalibEvent); m_hEndCalibEvent = NULL; } if (m_hDarkEndEvent) { CloseHandle(m_hDarkEndEvent); m_hDarkEndEvent = NULL; } if (m_hCheckShockEvent) { CloseHandle(m_hCheckShockEvent); m_hCheckShockEvent = NULL; } if (m_hToggleEvent) { CloseHandle(m_hToggleEvent); m_hToggleEvent = NULL; } if (m_hQuitAdaptEvent) { CloseHandle(m_hQuitAdaptEvent); m_hQuitAdaptEvent = NULL; }*/ } /*** ** 说明:升级固件接口 ***/ void TrixellCtrl::UpdateFirmware(int nDetectorID) { Info("Update firmware manually"); m_bUpdateFirmwareDirect = true; m_nUpdateFPDID = nDetectorID; HANDLE hUpdateThread; DWORD unThreadID; hUpdateThread = CreateThread(NULL, 0, onUpdateFWThread, this, 0, &unThreadID); if (hUpdateThread == NULL) { Error("Start Update Firmware Thread Error"); } } /*** ** 说明:升级固件线程 ***/ DWORD __stdcall TrixellCtrl::onUpdateFWThread(PVOID pvoid) { TrixellCtrl* pOpr = (TrixellCtrl*)pvoid; Info("Firmware update thread"); return pOpr->onUpdateFirmware(); } /*** ** 说明:升级固件执行函数 ***/ bool TrixellCtrl::onUpdateFirmware() { StatusFeedback(EVT_STATUS_UPDATE_FIRMWARE, PANEL_EVENT_START, "", m_nUpdateFPDID); if (!m_pStPanelStatus[m_nUpdateFPDID]->bConnectStatus || m_pStPanelStatus[m_nUpdateFPDID]->nBattery < 50) { Error("Detector isn't connect or Battery value<50"); StatusFeedback(EVT_STATUS_UPDATE_FIRMWARE, PANEL_EVENT_END_ERROR, "", m_nUpdateFPDID); return false; } string strFWVersion = ""; if (!GetFWVersion(m_pStPanelStatus[m_nUpdateFPDID]->strPartNumber, strFWVersion, m_nUpdateFPDID)) { Error("Cannot Get new FW Version"); if (m_bUpdateFirmwareDirect) { StatusFeedback(EVT_STATUS_UPDATE_FIRMWARE, PANEL_EVENT_END_ERROR, "", m_nUpdateFPDID); } m_bUpdateFirmwareDirect = false; return false; } CloseDetector(); ModifyFirmwareLogPath(m_nUpdateFPDID); Sleep(1000); //参照RAD3,休眠1s //printf("Executing EXE... \n"); int nProcID = CallAdapter(strFWVersion, m_pStPanelStatus[m_nUpdateFPDID]->strModuleIP, m_nUpdateFPDID); if (nProcID > 0) { bool bExitMonitorAdapt = true; while (bExitMonitorAdapt) { DWORD dwResult = WaitForSingleObject(m_hQuitAdaptEvent, 5000); if (dwResult == WAIT_OBJECT_0) { Info("Leave Thread Over"); if (m_bUpdateFirmwareDirect) { StatusFeedback(EVT_STATUS_UPDATE_FIRMWARE, PANEL_EVENT_END_ERROR, "", m_nUpdateFPDID); } m_bUpdateFirmwareDirect = false; return true; } else if (dwResult == WAIT_TIMEOUT) //failed to change state to quiet { Warn("Checking Adept.exe status"); nProcID = GetProcessidFromName("ADEPT.exe"); if (nProcID > 0) { Info("Find Adept.exe"); //printf("Updating... \n"); } else //升级结束 { Info("Adept.exe is not exist"); //printf("Over \n"); bExitMonitorAdapt = false; //退出循环 } } } int nPingTotalTime = 15;//ping不通,一次约6s,共15次,2分钟左右超时 int nPingTimes = 0; Info("onUpdateFirmware strModuleIP:{$}", m_pStPanelStatus[m_nUpdateFPDID]->strModuleIP); for (; nPingTimes < nPingTotalTime; nPingTimes++) { bool bConnect = IsConnected(m_pStPanelStatus[m_nUpdateFPDID]->strModuleIP); //有ping权限么? if (bConnect) { Info("Ping Detector successfully"); //printf("Ping Detector successfully\n"); break; } Sleep(2000); } //ping不通的话,加个输出 if (nPingTotalTime == nPingTimes) { Warn("Ping Detector IP Failed"); //printf("Ping Detector IP Failed\n"); } } else { Warn("Executing ADEPT.exe Failed"); //printf("Executing EXE Failed\n"); } m_pStPanelStatus[m_nUpdateFPDID]->bNeedUpdateFW = false; //不知道它的作用 m_bModuleConnecting = true; int nResult = InitDetector(!m_bUpdateFirmwareDirect, m_nUpdateFPDID); if (nResult != INIT_FIRMWARE) { if (m_pStPanelStatus[m_nUpdateFPDID]->bConnectStatus) //升级成功 { if (m_bUpdateFirmwareDirect) { Info("Update firmware success"); m_bModuleConnecting = false; StatusFeedback(EVT_STATUS_UPDATE_FIRMWARE, PANEL_EVENT_SUCCESS, "", m_nUpdateFPDID); } else { Info("Attach success"); UpdatePanelSerialFile(m_strModuleType, m_strModuleSN, m_pStPanelStatus[m_nUpdateFPDID]->strModuleIP, "", true); StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_CONNECT_OK, "", m_nUpdateFPDID); //StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_OK, "", m_nUpdateFPDID); //init反馈改为连接探测器使用 m_bModuleConnecting = false; } m_bUpdateFirmwareDirect = false; return true; } } else //INIT_FIRMWARE { // 只可能是固件升级失败; } m_bModuleConnecting = false; if (m_bUpdateFirmwareDirect) { Info("Update firmware failed"); m_bModuleConnecting = false; StatusFeedback(EVT_STATUS_UPDATE_FIRMWARE, PANEL_EVENT_END_ERROR, "", m_nUpdateFPDID); } else { Info("Attach failed"); DisconnectDetector(m_nUpdateFPDID); StatusFeedback(EVT_STATUS_DETECTORSHARE, PANEL_CONNECT_ERROR, "", m_nUpdateFPDID); } m_bUpdateFirmwareDirect = false; return true; } /*** ** 说明:读取配置文件,获取固件版本 ***/ bool TrixellCtrl::GetFWVersion(string strPNCode, string& strFirmwareVersion, int nDetectorID) { return true; } /*** ** 说明:修改固件升级的log路径 ***/ bool TrixellCtrl::ModifyFirmwareLogPath(int nDetectorID) { return true; } /*** ** 说明:编辑命令行参数,获取执行exe后的进程号 ***/ int TrixellCtrl::CallAdapter(string strFirmwareVersion, string strIPAddress, int nDetectorID) { return 0; } /*** ** 说明:执行ADEPT.exe程序 ***/ UINT TrixellCtrl::ExecuteEXE(string strExeName, string strParameters, DWORD& hProcID) { UINT iReturnVal = 0; hProcID = 0; TCHAR ptszParam[MAX_PATH]; memset(ptszParam, 0, MAX_PATH); sprintf(ptszParam, "%s %s", strExeName.c_str(), strParameters.c_str()); //sprintf(ptszParam, "%s", strExeName.c_str()); //test只启动exe,不执行操作 Debug("Execute {$}", ptszParam); PROCESS_INFORMATION pinfo; ZeroMemory(&pinfo, sizeof(pinfo)); STARTUPINFO si/* = {sizeof(si)}*/; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); //si.lpTitle = "ADEPT.exe"; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; if (!CreateProcess(NULL, // No module name (use command line) ptszParam, // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE NULL, //CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE, // No creation flags NULL, // Use parent's environment block NULL, //"C:\\Addon\\IC\\Detectortools\\SW_Update\\3543DR\\ADEPT", // lpCurrentDirectory &si, // Pointer to STARTUPINFO structure &pinfo) // Pointer to PROCESS_INFORMATION structure ) { //printf("CreateProcess failed (%d).\n", GetLastError()); iReturnVal = GetLastError(); } else { hProcID = pinfo.dwProcessId; } CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); return iReturnVal; } DWORD TrixellCtrl::GetProcessidFromName(string strProcName) { PROCESSENTRY32 ProcEntry; DWORD ProcID = 0; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); ProcEntry.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hSnapshot, &ProcEntry)) { return 0; } while (1) { ProcEntry.dwSize = sizeof(PROCESSENTRY32W); if (Process32Next(hSnapshot, &ProcEntry) == FALSE) { break; } if (strcmp(ProcEntry.szExeFile, strProcName.c_str()) == 0) { ProcID = ProcEntry.th32ProcessID; break; } } CloseHandle(hSnapshot); return ProcID; } /*** ** 说明:检查探测器状态线程 ***/ DWORD __stdcall TrixellCtrl::onFPDStatusThread(PVOID pvoid) { TrixellCtrl* pOpr = (TrixellCtrl*)pvoid; Info("Enter FPD status thread"); bool bExit = false; while (!bExit) { DWORD dwRet = WaitForSingleObject(pOpr->m_hQuitStatusEvent, 5000); if (WAIT_TIMEOUT == dwRet) { pOpr->onCheckFPDStatus(); } else if (WAIT_OBJECT_0 == dwRet) { bExit = true; } } SetEvent(pOpr->m_hToggleEvent); Info("Exit check FPD status thread"); return 0; } /*** ** 说明:检查探测器状态 ** 温度、电量、wifi、连接状态 ***/ bool TrixellCtrl::onCheckFPDStatus() { //*//一个平板的时候,重连的限制条件会少一些 if (m_nPanelCount == 1) { if (GetConnectConf(0) && !m_pStPanelStatus[0]->bInitOK //attach过了但没初始化成功 && m_bOpened //不是加载dll,初始化SDK等的错误导致的连接失败 && !m_bModuleConnecting //attach连接时,上述条件都会是true && !m_bAttaching ) { string strIP = (string)m_pStPanelStatus[0]->objPanelConfig["connections"]["WiredIP"]; Info("onCheckFPDStatus strIP:{$} m_nPanelCount == 1", strIP); bool bConnect = IsConnected(strIP); if (!bConnect) { Trace("Ping Detector failed"); return false; } //提前发送重连开始的消息,减少用户进行其它操作的可能性 m_bReInitialize = true; StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_START, "", 0); Info("Calling Connect(ID: 0)"); error_status ErrorStatus = TED_PixRad_Connect(0, ""); TestError(ErrorStatus); if (!WaitRespond(g_nConnectTimeout, "Connect")) //设置一个10秒的连接超时 { Error("Connect detector timeout"); } if (m_pStPanelStatus[0]->bConnectStatus) { Info("Connect Detector success"); } else { m_bReInitialize = false; StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END, "", 0); Warn("Connect Detector failed"); return false; } GetConfigParameters(0); Info("onCheckFPDStatus SetDetectorStatusPolling == true 111"); SetDetectorStatusPolling(0, true); //重连成功,置为true //以下流程部分为不区分探测器的接口,此处先切换探测器 if (!SetActiveDetector(0)) { m_bReInitialize = false; StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END, "", 0); return false; } GetDetectorInformation(0, true); FactoryCorrectionActive(false, 0); if (!m_pStPanelStatus[0]->bSelftested) { SelfTestFPD(0); } GetCalibrationTime(0); if (m_pStPanelStatus[0]->bConnectStatus) { if (!m_pStPanelStatus[0]->bDarkCalibDone) { m_nRefreshOftMode = g_nRADmode; RefreshOffset(true, PIX_OM_RAD, g_nRADmode); } if (!m_pStPanelStatus[0]->bLTEDarkCalibDone) { m_nRefreshOftMode = g_nRADLTEmode; RefreshOffset(true, PIX_OM_RAD, g_nRADLTEmode); } } m_bReInitialize = false; StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_OK, "", 0); ErrorFeedback(EVT_ERR_COMMUNICATE, "false", 0); } return true; } //*/ //modify20211220 双板时去掉当前平板的工作界面限制 bool bNotInWork = m_eAppStatus != APP_STATUS_WORK_BEGIN && m_eAppStatus != APP_STATUS_CAL_BEGIN && //检查、校正界面不执行 DetStatus_Acquire != m_eStatus && DetStatus_Offset != m_eStatus && DetStatus_XrayCalibration != m_eStatus; //检查、校正状态不执行 //和DPC模块确认的新逻辑,不依靠connect做先启动软件后启动硬件的重连 for (int nID = 0; nID < m_nPanelCount; nID++) { if ((bNotInWork || (!bNotInWork && nID == m_nCurrentPanelID)) //不在工作界面 或 在工作界面的当前探测器 && GetConnectConf(nID) && !m_pStPanelStatus[nID]->bInitOK //attach过了但没初始化成功 && m_bOpened //不是加载dll,初始化SDK等的错误导致的连接失败 && !m_bModuleConnecting && !m_bAttaching) { string strIP = (string)m_pStPanelStatus[nID]->objPanelConfig["connections"]["WiredIP"]; Info("onCheckFPDStatus strIP:{$} 222", strIP); bool bConnect = IsConnected(strIP); if (!bConnect) { Trace("Ping Detector failed"); continue; //一块连接失败,继续连接其它的,不要互相影响 } //提前发送重连开始的消息,减少用户进行其它操作的可能性 m_bReInitialize = true; StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_START, "", nID); Info("Calling Connect(ID: {$})", nID); error_status ErrorStatus = TED_PixRad_Connect(nID, ""); TestError(ErrorStatus); if (!WaitRespond(g_nConnectTimeout, "Connect")) //设置一个10秒的连接超时 { Error("Connect detector timeout"); continue; } if (m_pStPanelStatus[nID]->bConnectStatus) { Info("Connect Detector success"); } else { m_bReInitialize = false; StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END, "", nID); Warn("Connect Detector failed"); continue; //一块连接失败,继续连接其它的,不要互相影响 } GetConfigParameters(nID); Info("onCheckFPDStatus SetDetectorStatusPolling == true 222"); SetDetectorStatusPolling(nID, true); //重连成功,置为true //以下流程部分为不区分探测器的接口,此处先切换探测器 if (!SetActiveDetector(nID)) { m_bReInitialize = false; StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END, "", nID); continue; } GetDetectorInformation(nID, true); FactoryCorrectionActive(false, nID); if (!m_pStPanelStatus[nID]->bSelftested) { SelfTestFPD(nID); } GetCalibrationTime(nID); if (m_pStPanelStatus[nID]->bConnectStatus) { if (!m_pStPanelStatus[nID]->bDarkCalibDone) { m_nRefreshOftMode = g_nRADmode; RefreshOffset(true, PIX_OM_RAD, g_nRADmode); } if (!m_pStPanelStatus[nID]->bLTEDarkCalibDone) { m_nRefreshOftMode = g_nRADLTEmode; RefreshOffset(true, PIX_OM_RAD, g_nRADLTEmode); } } m_bReInitialize = false; StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_OK, "", nID); ErrorFeedback(EVT_ERR_COMMUNICATE, "false", nID); } } return true; } bool TrixellCtrl::InDetectorShare() { if (APP_STATUS_DETSHARE_BEGIN == m_eAppStatus) { return true; } else { Error("Not In Detector Share Window"); return false; } } /*** ** 说明:设置连接配置 ** 修改subDPC中的Reconnect配置项,该配置项为true时调用API,连接探测器 ***/ bool TrixellCtrl::SetConnectConf(bool bConnect, int nDetectorID) { return true; } /*** ** 说明:获取连接配置 ** 获取subDPC中的Reconnect配置项,该配置项为true时调用API,连接探测器 ** 返回值:true,表示连接;false,表示不连接 ***/ bool TrixellCtrl::GetConnectConf(int nDetectorID) { bool bConnect = false; try { int nTemp = m_ModeConfig[CcosDetectorAttachedFlag]; if (nTemp > 0) { bConnect = true; } } catch (ResDataObjectExption& exp) { Error("Get configuration failed, {$}", exp.what()); } return bConnect; } string TrixellCtrl::GetPanelResource(string strKey) { string strPanelResPath; strPanelResPath = m_strWorkPath + "\\OEMDrivers\\Detector\\Trixell\\TrixellDRDetector\\CCOSLogInfor.xml"; Info("{$}", strPanelResPath.c_str()); string strMsgText = ""; GetValueByKeyA(strPanelResPath.c_str(), strKey.c_str(), strMsgText); return strMsgText; } /*** ** 说明:更新PanelSerial.xml列表 ***/ bool TrixellCtrl::UpdatePanelSerialFile(string strPanelType, string strSN, string strSetIP, string strDate, bool bActive) { PanelSerialList stPanelInfo; string strCalibDate = "0"; string strIP = ""; int nID = 0; bool bResult = GetPanelSNList(strSN, stPanelInfo); if (!bResult) { if (!bActive) { Info("Omit Update SN List"); return true; } //如果没有找到SN,赋新值,加入列表 stPanelInfo.strPanelType = "3543"; stPanelInfo.strPanelSize = "L"; if (strPanelType.find("3543") == string::npos) { stPanelInfo.strPanelType = "2430"; stPanelInfo.strPanelSize = "S"; } stPanelInfo.strPanelSN = strSN; stPanelInfo.strIPAddress = strSetIP; } else //更新校正日期 { // } if (strDate != "") { stPanelInfo.strCalibDate = strDate; } else { stPanelInfo.strCalibDate = "null"; //填空字符串会导致日志记录乱码+无用内容,所以改为null } //else 保留读取的值 if (bActive) { stPanelInfo.strActive = "true"; } else { stPanelInfo.strActive = "false"; } Debug("{$}", stPanelInfo.strPanelType.c_str()); Debug("{$}", stPanelInfo.strPanelSN.c_str()); Info("{$}", stPanelInfo.strActive.c_str()); Debug("{$}", stPanelInfo.strIPAddress.c_str()); Debug("{$}", stPanelInfo.strCalibDate.c_str()); Debug("{$}", stPanelInfo.strPanelSize.c_str()); bResult = m_objSNlist.AddNewPanelSerial(stPanelInfo); if (bResult) { Info("Update PanelSerial.xml Success"); return true; } else { Info("Update PanelSerial.xml Failed"); return false; } } /*** ** 说明:更新PanelSerial.xml列表 ***/ bool TrixellCtrl::GetPanelSNList(string strPanelSerial, PanelSerialList& stpanelInfo) { list obListPanel; list::iterator iter; bool bResult = m_objSNlist.GetPanelSerialList(obListPanel); if (!bResult) { Error("PanelSerial.xml is NULL"); return false; } Info("{$}", strPanelSerial.c_str()); for (iter = obListPanel.begin(); iter != obListPanel.end(); iter++) { if (strPanelSerial.find(iter->strPanelSN) != string::npos) { Info("{$}", iter->strPanelType.c_str()); Info("{$}", iter->strPanelSN.c_str()); Info("{$}", iter->strActive.c_str()); Info("{$}", iter->strIPAddress.c_str()); Info("{$}", iter->strCalibDate.c_str()); Info("{$}", iter->strPanelSize.c_str()); stpanelInfo = *iter; Info("Find Detector SN Success"); return true; } else { Info("{$}", iter->strPanelSN.c_str()); } } return false; } /*** ** 定时查询每个探测器的状态 ** 如果使用polling功能,会影响SDK休眠 ***/ void TrixellCtrl::RefreshHWStatus() { if ((m_eAppStatus != APP_STATUS_WORK_BEGIN && m_eAppStatus != APP_STATUS_CAL_BEGIN) //检查、校正界面不执行 && (DetStatus_Acquire != m_eStatus) && (DetStatus_Offset != m_eStatus) && (DetStatus_XrayCalibration != m_eStatus)) { //非检查、校正界面,定期获取全部平板的状态 for (int index = 0; index < m_nPanelCount; index++) { GetHardwareStatus(index); } } else { for (int index = 0; index < m_nPanelCount; index++) { if (index != m_nCurrentPanelID) //检查界面只刷新非当前平板的状态 { Info("RefreshHWStatus SetDetectorStatusPolling == true"); SetDetectorStatusPolling(index, true); Sleep(50); //确保开启polling } } } } void TrixellCtrl::ProcessEvent(const event_id eventID, const Event *eventData) { int nDetectorID = eventData->detector; //并一定是针对探测器的消息,所以此值不一定是0或者1,2 Info("{$}[CB {$}]", nDetectorID, (int)eventID); switch (eventID) { case EVT_START_DARK_CALIBRATION: ProcessEventError("EVT_START_DARK_CALIBRATION", eventData->error, nDetectorID); break; case EVT_END_DARK_CALIBRATION: //先参照增益流程增加calibrationstatus的callback if (!ProcessEventError("EVT_END_DARK_CALIBRATION", eventData->error, nDetectorID)) { if (ERR_SEQUENCE_CANCELED == eventData->error) { Info("ERR_SEQUENCE_CANCELED"); // 校正取消 } else if (ERR_RESUME_TIMEOUT == eventData->error) { Info("ERR_RESUME_TIMEOUT"); // 校正超时 StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_TIMEOUT); } else if (ERR_CALIBRATION_ACQUISITION == eventData->error) { Info("ERR_CALIBRATION_ACQUISITION"); // 校正超时 StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_ERROR); } } else { if (g_nRADmode == m_nRefreshOftMode) { m_pStPanelStatus[nDetectorID]->bDarkCalibDone = true; } else if (g_nRADLTEmode == m_nRefreshOftMode) { m_pStPanelStatus[nDetectorID]->bLTEDarkCalibDone = true; } } m_eStatus = DetStatus_Standby; //Dark校正结束,置为Standby break; case EVT_START_XRAY_CALIBRATION: ProcessEventError("EVT_START_XRAY_CALIBRATION", eventData->error, nDetectorID); m_bPrepShot = false; //校正开始,置回初值 break; case EVT_END_XRAY_CALIBRATION: if (!ProcessEventError("EVT_END_XRAY_CALIBRATION", eventData->error, nDetectorID)) { if (ERR_SEQUENCE_CANCELED == eventData->error) { Info("ERR_SEQUENCE_CANCELED"); // 校正取消 StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } else if (ERR_RESUME_TIMEOUT == eventData->error) { Info("ERR_RESUME_TIMEOUT"); // 校正超时 string strLastError = GetPanelResource("CalibrationTimeOut"); Info("{$}", strLastError.c_str()); StatusFeedback(EVT_STATUS_SINGLEEXP, EVT_STATUS_LASTERROR, strLastError.c_str()); StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_TIMEOUT); } else if (ERR_CALIBRATION_ACQUISITION == eventData->error) { Info("ERR_CALIBRATION_ACQUISITION"); // 校正超时 string strLastError = GetPanelResource("CalibrationAcqFailed"); Info("{$}", strLastError.c_str()); StatusFeedback(EVT_STATUS_SINGLEEXP, EVT_STATUS_LASTERROR, strLastError.c_str()); StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_ERROR); } } else { StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } m_bPrepShot = false; //校正结束,置回初值 m_eStatus = DetStatus_Standby; //增益校正结束,置为Standby break; case EVT_START_GAIN_CALIBRATION: //! Sent when the gain only calibration begins ProcessEventError("EVT_START_GAIN_CALIBRATION", eventData->error, nDetectorID); break; case EVT_END_GAIN_CALIBRATION: ProcessEventError("EVT_END_GAIN_CALIBRATION", eventData->error, nDetectorID); break; case EVT_START_REFRESH_CALIBRATION: //! Sent when the refresh calibration begins ProcessEventError("EVT_START_REFRESH_CALIBRATION", eventData->error, nDetectorID); break; case EVT_END_REFRESH_CALIBRATION: ProcessEventError("EVT_END_REFRESH_CALIBRATION", eventData->error, nDetectorID); break; case EVT_START_LOAD_REFERENCES: ProcessEventError("EVT_START_LOAD_REFERENCES", eventData->error, nDetectorID); break; case EVT_END_LOAD_REFERENCES: if (!ProcessEventError("EVT_END_LOAD_REFERENCES", eventData->error, nDetectorID)) { m_eCorrectionType = CT_OFFSET; } else { m_eCorrectionType = CT_ALL; } break; case EVT_START_LOAD_GAIN_REFERENCE: ProcessEventError("EVT_START_LOAD_GAIN_REFERENCE", eventData->error, nDetectorID); break; case EVT_END_LOAD_GAIN_REFERENCE: ProcessEventError("EVT_END_LOAD_GAIN_REFERENCE", eventData->error, nDetectorID); break; case EVT_START_UNLOAD_REFERENCES: ProcessEventError("EVT_START_UNLOAD_REFERENCES", eventData->error, nDetectorID); break; case EVT_END_UNLOAD_REFERENCES: ProcessEventError("EVT_END_UNLOAD_REFERENCES", eventData->error, nDetectorID); break; case EVT_START_DARK_ACCEPTANCE_TEST: //! Sent when the dark acceptance test begins ProcessEventError("EVT_START_DARK_ACCEPTANCE_TEST", eventData->error, nDetectorID); break; case EVT_END_DARK_ACCEPTANCE_TEST: ProcessEventError("EVT_END_DARK_ACCEPTANCE_TEST", eventData->error, nDetectorID); break; case EVT_START_XRAY_ACCEPTANCE_TEST: ProcessEventError("EVT_START_XRAY_ACCEPTANCE_TEST", eventData->error, nDetectorID); break; case EVT_END_XRAY_ACCEPTANCE_TEST: ProcessEventError("EVT_END_XRAY_ACCEPTANCE_TEST", eventData->error, nDetectorID); break; case EVT_START_VOLTAGES: //! Sent when the current voltages request of detector begins ProcessEventError("EVT_START_VOLTAGES", eventData->error, nDetectorID); break; case EVT_END_VOLTAGES: if (ProcessEventError("EVT_END_VOLTAGES", eventData->error, nDetectorID)) { HardwareVoltage* pData = static_cast(eventData->data); //ResDataObject jsParamList; string strVoltageList = "["; string strVoltageItem = ""; for (int i = 0; i < pData->nbPods; ++i) { for (int j = 0; j < pData->pod[i].nbChannel; ++j) { int nFlag = pData->pod[i].channel[j].flag; string strName = pData->pod[i].channel[j].name; float fValue = pData->pod[i].channel[j].value; Info("Voltage channel:{$} Flag:{$},Name:{$},Value:{$}", j, nFlag, strName.c_str(), fValue); std::ostringstream strVoltageKey; strVoltageKey << "FDVoltage_Pod" << i << "_Channel" << strName; std::ostringstream strVoltageValue; strVoltageValue << fValue; //jsParamList.add(strVoltageKey.str().c_str(), strVoltageValue.str().c_str()); strVoltageItem += strVoltageKey.str(); strVoltageItem += ":"; strVoltageItem += strVoltageValue.str(); strVoltageList = strVoltageList + strVoltageItem + "\r\n"; strVoltageItem = ""; //恢复初值 } } strVoltageList = strVoltageList.substr(0, strVoltageList.length() - 2); strVoltageList += "]"; //Info( jsParamList.encode()); Debug("{$}", strVoltageList.c_str()); InfoFeedback(EVT_INFO_FPVOLTAGE, nDetectorID, 0, 0, strVoltageList.c_str()/*jsParamList.encode()*/); } UnlockPixrad("EVT_END_VOLTAGES"); break; case EVT_START_LAST_ACQUISITION_DATA: //! Sent when the storage of last acquisition data begins ProcessEventError("EVT_START_LAST_ACQUISITION_DATA", eventData->error, nDetectorID); break; case EVT_END_LAST_ACQUISITION_DATA: ProcessEventError("EVT_END_LAST_ACQUISITION_DATA", eventData->error, nDetectorID); break; case EVT_START_RESET_DETECTOR: ProcessEventError("EVT_START_RESET_DETECTOR", eventData->error, nDetectorID); break; case EVT_END_RESET_DETECTOR: ProcessEventError("EVT_END_RESET_DETECTOR", eventData->error, nDetectorID); break; case EVT_START_SELF_TEST: //! Sent when the self test of detector begins ProcessEventError("EVT_START_SELF_TEST", eventData->error, nDetectorID); break; case EVT_END_SELF_TEST: if (ProcessEventError("EVT_END_SELF_TEST", eventData->error, nDetectorID)) { SelfTestResult* pSelfTest = static_cast(eventData->data); ResDataObject jsParamList; for (int i = 0; i < pSelfTest->nbTests; ++i) { SelfTestResult::TestResult result = pSelfTest->testResult[i]; Info("test[{$}] - {$} - : {$}", result.id, result.name, result.value ? "passed" : "failed"); string strResultName = result.name; for (size_t i = 0; i < strResultName.length() - 1; i++) { if (strResultName[i] == ' ') { strResultName[i] = '_'; } } if (strResultName[strResultName.length() - 1] == ' ') { strResultName = strResultName.substr(0, strResultName.length() - 1); } jsParamList.add(strResultName.c_str(), result.value ? "pass" : "failed"); } //DPC处理Selftest有耗时,改到接口调用处反馈selftest //StatusFeedback(EVT_STATUS_SELFTEST, nDetectorID, jsParamList.encode()); m_SelfTest.clear(); m_SelfTest = jsParamList; m_pStPanelStatus[nDetectorID]->bSelftested = true; } UnlockPixrad("EVT_END_SELF_TEST"); break; case EVT_START_LAST_IMAGE_RECOVERY: ProcessEventError("EVT_START_LAST_IMAGE_RECOVERY", eventData->error, nDetectorID); m_bIsImageRecovering = false; break; case EVT_END_LAST_IMAGE_RECOVERY: if (ProcessEventError("EVT_END_LAST_IMAGE_RECOVERY", eventData->error, nDetectorID)) { ErrorFeedback(EVT_ERR_GET_IMAGE, "false"); //图像recover成功 StatusFeedback(EVT_STATUS_PANEL, PANEL_STANDBY); } else { if (!m_bTransImageSuccess) { ErrorFeedback(EVT_ERR_GET_IMAGE, "true"); //图像recover失败 StatusFeedback(EVT_STATUS_PANEL, PANEL_STANDBY); } } UnlockPixrad("EVT_END_LAST_IMAGE_RECOVERY"); break; case EVT_WIFI_PARAMETERS_CHANGED: ProcessEventError("EVT_WIFI_PARAMETERS_CHANGED", eventData->error, nDetectorID); break; case EVT_IMAGE_PATTERN_CHANGED: //! Sent when the change of pattern of the detector finishes ProcessEventError("EVT_IMAGE_PATTERN_CHANGED", eventData->error, nDetectorID); break; case EVT_HARDWARE_STATUS: //! Sent when hardware status has been performed if (ProcessEventError("EVT_HARDWARE_STATUS", eventData->error, nDetectorID)) { //如果断线了,获取一次configparameters m_pStPanelStatus[nDetectorID]->bConnectStatus = true; //收到hw回调 HardwareStatus* pData = reinterpret_cast(eventData->data); if (NULL == pData) { return; } /*** ** GetHardwareStatus时是获取某一块平板的状态,此时callback只有一个平板的信息, ** 所以以下向上层反馈信息时,ID不能用for循环下标,得用回调中的DetectorID ***/ float fTemperature; for (int i = 0; i < pData->nbDetectors; i++) { fTemperature = pData->detectorStatus[i].temperature; Info("detector {$} temperature: {$}", nDetectorID, fTemperature); StatusFeedback(EVT_STATUS_TEMPERATURE, 0, "", nDetectorID, fTemperature); #pragma region DetectorState int nDetectorState = pData->detectorStatus[i].state; switch (nDetectorState) { case DS_OPERATION: Info("Detector state: DS_OPERATION"); break; case DS_SERVICE: Info("Detector state: DS_SERVICE"); break; case DS_DOWNLOAD: Info("Detector state: DS_DOWNLOAD"); break; case DS_STANDBY: Info("Detector state: DS_STANDBY"); break; case DS_BOOT: Info("Detector state: DS_BOOT"); break; case DS_SLEEP: Info("Detector state: DS_SLEEP"); break; case DS_ERROR: Info("Detector state: DS_ERROR"); break; case DS_AUTOTRIGGER: Info("Detector state: DS_AUTOTRIGGER"); break; case DS_IMAGE_PENDING: Info("Detector state: DS_IMAGE_PENDING"); break; case DS_LICENSE_LOCKED: Info("Detector state: DS_LICENSE_LOCKED"); break; case DS_NOTDEFINED: Info("Detector state: DS_NOTDEFINED"); break; default: break; } if (DS_IMAGE_PENDING == nDetectorState) { StatusFeedback(EVT_STATUS_IMAGEPENDING, 0, "true", nDetectorID); } else { StatusFeedback(EVT_STATUS_IMAGEPENDING, 0, "false", nDetectorID); } #pragma endregion #pragma region battery //获取电量信息 if (pData->detectorStatus[i].energyStatus != 0) { int nPowerSource = pData->detectorStatus[i].energyStatus->powerSource; if (PS_BACKUP_CABLE == nPowerSource) { Info("front-end power source: BACKUPCABLE"); StatusFeedback(EVT_STATUS_BATTERY_CHARGING, 0, "true", nDetectorID); } else if (PS_BATTERY == nPowerSource) { Info("front-end power source: BATTERY"); StatusFeedback(EVT_STATUS_BATTERY_CHARGING, 0, "false", nDetectorID); } int nFullChargeCapacity = pData->detectorStatus[i].energyStatus->batteryStatus.fullChargeCapacity; Info("Detector({$}) full charge capacity of the battery: {$}", nDetectorID, nFullChargeCapacity); InfoFeedback(EVT_INFO_BATTERY_CAPACITY, nDetectorID, nFullChargeCapacity); m_pStPanelStatus[nDetectorID]->nBattery = pData->detectorStatus[i].energyStatus->batteryStatus.charge; StatusFeedback(EVT_STATUS_BATTERY_VALUE, pData->detectorStatus[i].energyStatus->batteryStatus.charge, "", nDetectorID); float fBatteryTemperature = pData->detectorStatus[i].energyStatus->batteryStatus.temperature; Info("temperature of the battery: {$}", fBatteryTemperature); InfoFeedback(EVT_INFO_BATTERY_TEMPERATURE, nDetectorID, 0, fBatteryTemperature); int nBatteryCycles = pData->detectorStatus[i].energyStatus->batteryStatus.chargeCycles; Info("number of charge/discharge cycles: {$}", nBatteryCycles); InfoFeedback(EVT_INFO_BATTERY_CHARGES, nDetectorID, nBatteryCycles); } #pragma endregion #if 0 //获取gridstatus if (pData->detectorStatus[i].gridStatus != 0) { int nGrid = pData->detectorStatus[i].gridStatus->grid; Info("Pixrad Grid Status: {$}", nGrid); } int nLifeTime = pData->detectorStatus[i].counterStatus.lifeTime; Info("Life Time: {$}", nLifeTime); ConfFeedback(EVT_CONF_LIFETIME, nDetectorID, "", nLifeTime); int nPowerOn = pData->detectorStatus[i].counterStatus.powerOn; InfoFeedback(EVT_INFO_POWER_ON, nDetectorID, nPowerOn); if (pData->detectorStatus[i].shockStatus != 0) { int nbCounter = pData->detectorStatus[i].shockStatus->nbCounters; int nShockNumbers = 0; for (int j = 0; j < nbCounter; ++j) { nShockNumbers += pData->detectorStatus[i].shockStatus->counters[j]; } Info("Shock Number: {$}", nShockNumbers); if (nShockNumbers == 0) { if (m_pStPanelStatus[i]->nTotalShockNumber <= 0) { SimulateShockSensor(i, false); } else { Fatal("Detector is dropping down"); } } else { if ((m_pStPanelStatus[i]->nTotalShockNumber != -1) && (nShockNumbers > m_pStPanelStatus[i]->nTotalShockNumber)) { Info("Need Get ShockSensor Information"); Thread_Lock(); m_nShockFPDID = i; Thread_UnLock(); SetEvent(m_hCheckShockEvent); } m_pStPanelStatus[i]->nTotalShockNumber = nShockNumbers; } } #pragma region motionStatus if (pData->detectorStatus[i].motionStatus != 0) { int nOrientation = pData->detectorStatus[i].motionStatus->orientation; string strOrientation = ""; if (DET_MOVING == nOrientation) { strOrientation = "DET_MOVING"; Info("Orientation:DET_MOVING"); } else if (DET_HORIZONTAL_RIGHT_SIDE == nOrientation) { strOrientation = "DET_HORIZONTAL_RIGHT_SIDE"; Info("Orientation:DET_HORIZONTAL_RIGHT_SIDE"); } else if (DET_HORIZONTAL_UPSIDE_DOWN == nOrientation) { strOrientation = "DET_HORIZONTAL_UPSIDE_DOWN"; Info("Orientation:DET_HORIZONTAL_UPSIDE_DOWN"); } else if (DET_IN_BETWEEN_PORTRAIT_RIGHT_SIDE == nOrientation) { strOrientation = "DET_IN_BETWEEN_PORTRAIT_RIGHT_SIDE"; Info("Orientation:DET_IN_BETWEEN_PORTRAIT_RIGHT_SIDE"); } else if (DET_IN_BETWEEN_PORTRAIT_UPSIDE_DOWN == nOrientation) { strOrientation = "DET_IN_BETWEEN_PORTRAIT_UPSIDE_DOWN"; Info("Orientation:DET_IN_BETWEEN_PORTRAIT_UPSIDE_DOWN"); } else if (DET_IN_BETWEEN_LANDSCAPE_RIGHT == nOrientation) { strOrientation = "DET_IN_BETWEEN_LANDSCAPE_RIGHT"; Info("Orientation:DET_IN_BETWEEN_LANDSCAPE_RIGHT"); } else if (DET_IN_BETWEEN_LANDSCAPE_LEFT == nOrientation) { strOrientation = "DET_IN_BETWEEN_LANDSCAPE_LEFT"; Info("Orientation:DET_IN_BETWEEN_LANDSCAPE_LEFT"); } else if (DET_IN_BETWEEN_UNDEFINED == nOrientation) { strOrientation = "DET_IN_BETWEEN_UNDEFINED"; Info("Orientation:DET_IN_BETWEEN_UNDEFINED"); } else if (DET_VERTICAL_PORTRAIT_RIGHT_SIDE == nOrientation) { strOrientation = "DET_VERTICAL_PORTRAIT_RIGHT_SIDE"; Info("Orientation:DET_VERTICAL_PORTRAIT_RIGHT_SIDE"); } else if (DET_VERTICAL_PORTRAIT_UPSIDE_DOWN == nOrientation) { strOrientation = "DET_VERTICAL_PORTRAIT_UPSIDE_DOWN"; Info("Orientation:DET_VERTICAL_PORTRAIT_UPSIDE_DOWN"); } else if (DET_VERTICAL_LANDSCAPE_RIGHT == nOrientation) { strOrientation = "DET_VERTICAL_LANDSCAPE_RIGHT"; Info("Orientation:DET_VERTICAL_LANDSCAPE_RIGHT"); } else if (DET_VERTICAL_LANDSCAPE_LEFT == nOrientation) { strOrientation = "DET_VERTICAL_LANDSCAPE_LEFT"; Info("Orientation:DET_VERTICAL_LANDSCAPE_LEFT"); } else if (DET_VERTICAL_UNDEFINED == nOrientation) { strOrientation = "DET_VERTICAL_UNDEFINED"; Info("Orientation:DET_VERTICAL_UNDEFINED"); } else { strOrientation = "UNKNOWN"; Info("Orientation:UNKNOWN"); } float fpitch = pData->detectorStatus[i].motionStatus->pitch; float froll = pData->detectorStatus[i].motionStatus->roll; float fyaw = pData->detectorStatus[i].motionStatus->yaw; char szPitch[8] = { 0 }; sprintf_s(szPitch, "%.2f", fpitch); char szRoll[8] = { 0 }; sprintf_s(szRoll, "%.2f", froll); char szYaw[8] = { 0 }; sprintf_s(szYaw, "%.2f", fyaw); ResDataObject jsParamList; jsParamList.add("DetectorOrientation", strOrientation.c_str()); jsParamList.add("DetectorPitch", szPitch); jsParamList.add("DetectorRoll", szRoll); jsParamList.add("DetectorYaw", szYaw); StatusFeedback(EVT_STATUS_MOTION, nDetectorID, jsParamList.encode()); } #pragma endregion #endif } ErrorFeedback(EVT_ERR_COMMUNICATE, "false", nDetectorID); //hw callback清错 } if (!m_pStPanelStatus[nDetectorID]->bIsPortable) //非移动板没有wifi回调,在此处停止查询状态 { if (nDetectorID != m_nCurrentPanelID) { //非当前平板是靠开启polling功能实现查询状态的,查询一次后,停止查询 m_nStopPollingIndex = nDetectorID; SetEvent(m_hClosePollingEvent); } } break; case EVT_START_ACQUISITION: ProcessEventError("EVT_START_ACQUISITION", eventData->error, nDetectorID); m_bPreviewImg = false; //采集开始,恢复初值 m_bIsExpInAuto = false; //采集开始,恢复初值 ErrorFeedback(EVT_ERR_EXP_REQUEST, "false"); //开始采集,清除 break; case EVT_END_ACQUISITION: //! Sent when an acquisition is finished with the acquired image m_bPreviewImg = false; //采集结束,恢复初值 if (m_bWaitAcqEnd) { m_bWaitAcqEnd = false; UnlockPixrad("EVT_END_ACQUISITION"); m_eStatus = DetStatus_Standby; //停止采集,置回Standby } if (m_eStatus == DetStatus_Acquire) //如果回调早于stopacquisition接口调用,则置为DETECTOR_STATUS_STANDBY { m_eStatus = DetStatus_Standby; //停止采集,置回Standby } else if(m_eStatus == DetStatus_XrayCalibration) { UnlockPixrad("EVT_END_ACQUISITION"); } StatusFeedback(EVT_STATUS_PANEL, PANEL_STANDBY); if (!ProcessEventError("EVT_END_ACQUISITION", eventData->error, nDetectorID)) { if (!m_bTransImageSuccess) //曝光了但没拿到图像 { ErrorFeedback(EVT_ERR_GET_IMAGE, "true"); //曝光没拿到图像 } else if (ERR_DETECTOR_IMAGE_PENDING == eventData->error) { ErrorFeedback(EVT_ERR_GET_IMAGE, "true"); //探测器反馈有图 } else { ErrorFeedback(EVT_ERR_EXP_REQUEST, "true"); } } break; case EVT_PREVIEW: Info("Pre Image Arrived!"); m_bPreviewImg = true; if (ProcessEventError("EVT_PREVIEW", eventData->error, nDetectorID) && m_bPreviewEnable) { if (m_bAutonumousMode) { Info("Current in Autonumous Mode, omit preview image"); break; } AcquisitionImage* pAcquisitionImage = static_cast(eventData->data); memcpy(m_pPreImgBuffer, pAcquisitionImage->imgPtr, m_nPreviewWidth * m_nPreviewHeight * sizeof(WORD)); Info("copy buffer over"); SetEvent(m_hProcessImgEvent); Info("set ProcessImgEvent over"); } break; case EVT_IMAGE_AVAILABLE: { Info("Image Arrived!"); //tomo时 EVT_IMAGE_AVAILABLE到下一次EVT_START_TRANSMIT,约18ms m_bPreviewImg = false; //收到大图,恢复初值 if (m_nIgnoreImgNum < m_nIgnoreImgCount) { Info("EVT_IMAGE_AVAILABLE Ignore ({$}/{$}) Image", m_nIgnoreImgNum + 1, m_nIgnoreImgCount); m_nIgnoreImgNum++; break; } if (ProcessEventError("EVT_IMAGE_AVAILABLE", eventData->error, nDetectorID)) { m_bTransImageSuccess = true; //表明图像已获取成功 ErrorFeedback(EVT_ERR_GET_IMAGE, "false"); //拿到图像 AcquisitionImage* pAcquisitionImage = static_cast(eventData->data); Info("Get Acquisition Image"); if (pAcquisitionImage->imgPtr == NULL) { Error("Get Image is NULL"); } else { struct tm stLocalTime; char szTemp[100] = { 0 }; stLocalTime = *localtime(&pAcquisitionImage->imgParam.acquisitionTime); strftime(szTemp, sizeof(szTemp), "%Y-%m-%d %H:%M:%S", &stLocalTime); m_nTomoImgIndex = pAcquisitionImage->imgParam.number; Info("Acquire Image SizeX: {$}, SizeY: {$}, Index: {$}, AcquireT: {$}", pAcquisitionImage->imgParam.sizeX, pAcquisitionImage->imgParam.sizeY, pAcquisitionImage->imgParam.number, szTemp); correction_type correctType = pAcquisitionImage->imgParam.correctionType; switch (correctType) { case CT_NONE: Info("CorrectionType:NONE"); break; case CT_OFFSET: Info("CorrectionType:OFFSET"); break; case CT_GAIN: Info("CorrectionType:GAIN"); break; case CT_DEFECT: Info("CorrectionType:DEFECT"); break; case CT_ALL: Info("CorrectionType:ALL"); break; default: Info("CorrectionType:{$}", (int)correctType); break; } if (m_nWidthOffset != 0 || m_nHeightOffset != 0) { Info("m_nWidthOffset != 0 || m_nHeightOffset != 0"); memcpy(m_pRawImgBuffer, pAcquisitionImage->imgPtr, m_nRawImgHeight * m_nRawImgWidth * sizeof(WORD)); } else { if (m_bAutonumousMode) { Info("m_bAutonumousMode == true"); m_nImageWidth = pAcquisitionImage->imgParam.sizeX; m_nImageHeight = pAcquisitionImage->imgParam.sizeY; if (m_pImgBuffer) { delete m_pImgBuffer; m_pImgBuffer = NULL; } Info("m_bAutonumousMode image width:{$} height:{$}", m_nImageWidth, m_nImageHeight); m_pImgBuffer = new WORD[m_nImageWidth * m_nImageHeight]; memcpy(m_pImgBuffer, pAcquisitionImage->imgPtr, m_nImageHeight * m_nImageWidth * sizeof(WORD)); } } //memcpy(m_pImgBuffer, pAcquisitionImage->imgPtr, m_nImageHeight * m_nImageWidth * sizeof(WORD)); Info("copy buffer over"); StatusFeedback(EVT_STATUS_PANEL, PANEL_GET_IMAGE); SetEvent(m_hProcessImgEvent); Info("set ProcessImgEvent over"); } } SetEvent(m_hXWinOffEvent); } break; case EVT_FRAME_DONE: //! Sent when an image has been taken with the TED_PixRad_StartFrame function ProcessEventError("EVT_FRAME_DONE", eventData->error, nDetectorID); break; case EVT_READY: if (ProcessEventError("EVT_READY", eventData->error, nDetectorID)) { //aed模式刷新暗场也会有ready回调,但此时不能解锁,要等end dark回调解锁 if (PIX_OM_AED == m_nCurrentOmMode && !m_bRefreshing) { UnlockPixrad("EVT_READY"); //aed模式进入ready状态,解锁 } } break; case EVT_XRAY_ON: Info("EVT_XRAY_ON index: {$}", m_nXwinOnIndex); //printf("EVT_XRAY_ON \n"); /*** ** modify20210202 ** SMS项目TOMO采集时,由于机架需要固定的时间来达到匀速, ** 所以第m_nXwinOnIndex个EVT_XRAY_ON向子系统发送ACQ消息 ** (开始采集到第一个XRAY_ON耗时不固定,但两个EVT_XRAY_ON的间隔时间是固定的) ***/ //if (DetStatus_Acquire == m_eStatus) //{ // if (m_nXwinOnIndex + 1 > m_nIgnoreImgCount) // { // SetEvent(m_hXWinOnEvent); // m_bIsExpInAuto = true; //开窗,置为true // } // else //忽略WindowOn分支 // { // if (m_nXwinOnIndex == 0) // { // UnlockPixrad("EVT_XRAY_ON"); //收到WindowOn,解锁,使FrameStart执行完毕 // } // Info("Ignore ({$}/{$}) XrayOn", m_nXwinOnIndex + 1, m_nIgnoreImgCount); // } //} //else //{ // SetEvent(m_hXWinOnEvent); // //if (DetStatus_XrayCalibration == m_eStatus) // { // m_bGainProcess = true; //开窗,进入增益曝光的一个小循环 // //m_nGainExpIndex++; // m_bPrepShot = false; //开窗,恢复初值 // } //} //m_nXwinOnIndex++; if (PIX_OM_AED == m_nCurrentOmMode) //AED+Demo发送XWindowOnNotify通知 { StatusFeedback(EVT_STATUS_PANEL, PANEL_AED_XRAY_ON); } SetEvent(m_hXWinOnEvent); m_bIsExpInAuto = true; break; case EVT_XRAY_OFF: ProcessEventError("EVT_XRAY_OFF", eventData->error, nDetectorID); //if (DetStatus_Acquire == m_eStatus) //{ // if (m_nXwinOnIndex + 1 > m_nIgnoreImgCount) // { // SetEvent(m_hXWinOffEvent); // } //} //else if (DetStatus_XrayCalibration == m_eStatus) //{ // if (m_nXwinOnIndex + 1 > m_nIgnoreImgCount) // { // SetEvent(m_hXWinOffEvent); // } // m_bConfirmCaliRst = true; //增益校正曝光,默认接受结果 //} if (PIX_OM_AED == m_nCurrentOmMode) { StatusFeedback(EVT_STATUS_PANEL, PANEL_AED_XRAY_OFF); } m_bTransImageSuccess = false; //关窗,置为false,等待图像 break; case EVT_START_TRANSMIT: ProcessEventError("EVT_START_TRANSMIT", eventData->error, nDetectorID); break; case EVT_END_TRANSMIT: ProcessEventError("EVT_END_TRANSMIT", eventData->error, nDetectorID); break; case EVT_DOSE_PARAM_REQUEST: //! Indicates the PixRad is requesting a dose setting before the next image/sequence to acquire { DoseParameters* pDoseParameters = static_cast(eventData->data); m_fDose = pDoseParameters->dose; Info("EVT_DOSE_PARAM_REQUEST {$}", m_fDose); DataFeedback(EVT_DATA_DOSEPARAM, NULL, 0, m_fDose); m_bConfirmCaliRst = false; //收到增益dose要求,恢复初值 m_bAutoContinueCal = false; //收到增益dose要求,恢复初值 if (m_bGainPreparing) { m_bGainPreparing = false; UnlockPixrad("EVT_DOSE_PARAM_REQUEST"); //进入增益校正状态,解锁 } if (!m_bGainPreparing && m_fCurrentDose != m_fDose) //需要切换给上层的Dose { UnlockPixrad("EVT_DOSE_PARAM_REQUEST"); } } break; case EVT_PREP_XRAY_SHOT: //! Indicates a xray shot will happened in a few seconds (delay fixed in .ini file) ProcessEventError("EVT_PREP_XRAY_SHOT", eventData->error, nDetectorID); if (!m_bPrepShot) { m_bPrepShot = true; //收到回调 } if (m_nCurrentOmMode != PIX_OM_TOMO) { UnlockPixrad("EVT_PREP_XRAY_SHOT"); //校正FramePrep时的Resuming执行完毕 } break; case EVT_OFFSET_INVALID: //! Indicates that the offset acquisition is not valid ProcessEventError("EVT_OFFSET_INVALID", eventData->error, nDetectorID); break; case EVT_X_DOSE_LEVEL: //! Indicates that the measured level { m_bTransImageSuccess = true; //表明图像已获取成功 m_bConfirmCaliRst = false; //剂量不合适,不接受增益结果 m_bAutoContinueCal = false; //剂量不合适,需要手动触发下一次增益 if (ProcessEventError("EVT_X_DOSE_LEVEL", eventData->error, nDetectorID)) { DoseLevelError doseLevel = *(static_cast(eventData->data)); dose_level nDoseLevel = *(static_cast(eventData->data)); string strCurDose = GetPanelResource("CurrentDose"); if (DL_HIGH == nDoseLevel) { string strDoseNote = GetPanelResource("DoseTooHigh"); char szValue[MAX_PATH] = { 0 }; sprintf_s(szValue, "%s %.1f %s [%.1f - %.1f]", strCurDose.c_str(), doseLevel.measured_level, strDoseNote.c_str(), doseLevel.min_threshold, doseLevel.max_threshold); string strLastError = szValue; Info("{$}", strLastError.c_str()); StatusFeedback(EVT_STATUS_SINGLEEXP, EVT_STATUS_LASTERROR, strLastError.c_str()); StatusFeedback(EVT_STATUS_SINGLEEXP, DOSE_TOO_HIGH); } else { string strDoseNote = GetPanelResource("DoseTooLow"); char szValue[MAX_PATH] = { 0 }; sprintf_s(szValue, "%s %.1f %s [%.1f - %.1f]", strCurDose.c_str(), doseLevel.measured_level, strDoseNote.c_str(), doseLevel.min_threshold, doseLevel.max_threshold); string strLastError = szValue; Info("{$}", strLastError.c_str()); StatusFeedback(EVT_STATUS_SINGLEEXP, EVT_STATUS_LASTERROR, strLastError.c_str()); StatusFeedback(EVT_STATUS_SINGLEEXP, DOSE_TOO_LOW); } if (m_bGainProcess) { //m_nGainExpIndex--; //曝光不合格,次数减一 m_bGainProcess = false; //SDK返回当前增益曝光结果(剂量不合适),结束增益曝光小循环 UnlockPixrad("EVT_X_DOSE_LEVEL"); //得到当前增益曝光结果 } m_nCaliFailedCount++; if (m_nCaliFailedCount > 10) { //失败次数过多,停止校正,避免无法终止 ys Warn("The gain failed too many times, stop it"); m_nCaliFailedCount = 0; //(*m_pPanelID2DPC)[m_nCurrentPanelID]->StopCalibration(); } } } break; case EVT_X_OBJECT_DETECTED: //! Indicates that an object has been detected on the image { m_bConfirmCaliRst = false; //检测到物体,不接受增益结果 m_bAutoContinueCal = false; //检测到物体,需要手动触发下一次增益 m_bTransImageSuccess = true; //表明图像已获取成功 ProcessEventError("EVT_X_OBJECT_DETECTED", eventData->error, nDetectorID); //printf("EVT_X_OBJECT_DETECTED \n"); //test string strLastError = GetPanelResource("ObjectInDetector"); Info("{$}", strLastError.c_str()); StatusFeedback(EVT_STATUS_SINGLEEXP, EVT_STATUS_LASTERROR, strLastError.c_str()); StatusFeedback(EVT_STATUS_SINGLEEXP, DOSE_OBJECT); if (m_bGainProcess) { //m_nGainExpIndex--; //曝光不合格,次数减一 m_bGainProcess = false; //SDK返回当前增益曝光结果(有物体),结束增益曝光小循环 UnlockPixrad("EVT_X_OBJECT_DETECTED"); //得到当前增益曝光结果 } m_nCaliFailedCount++; } break; case EVT_REMAINING_TIME: //! Event for display elapsed time in seconds for calibration { DataCalibration* pData = static_cast(eventData->data); Info("EVT_REMAINING_TIME : total = {$}, remaining = {$} [{$}%%]", pData->totalTime, pData->remainingTime, pData->percentageDone); if (m_bConfirmCaliRst) { //printf("EVT_REMAINING_TIME : total = %d, remaining = %d [%d%%] \n", pData->totalTime, pData->remainingTime, pData->percentageDone); //test m_bConfirmCaliRst = false; //接受图像,恢复初值 m_bAutoContinueCal = true; //当前增益OK,自动触发下一次增益 StatusFeedback(EVT_STATUS_SINGLEEXP, DOSE_ACCEPT); Info("ConfirmCaliRst true"); } if (m_bGainProcess) { Info("Gain process true"); m_bTransImageSuccess = true; //表明图像已获取成功 m_bGainProcess = false; //SDK返回当前增益曝光结果(接受),结束增益曝光小循环 UnlockPixrad("EVT_REMAINING_TIME"); //得到当前增益曝光结果 } } break; case EVT_STANDBY_REFRESH: //! Event sent during the standby state calibration ProcessEventError("EVT_STANDBY_REFRESH", eventData->error, nDetectorID); break; case EVT_ACTIVE_STATE: //! Indicates the system state has changed { if (!ProcessEventError("EVT_ACTIVE_STATE", eventData->error, nDetectorID)) { Error("Failed to set active state"); UnlockPixrad("EVT_ACTIVE_STATE"); } else { system_state* pState = static_cast(eventData->data); m_currentState = *pState; if (m_currentState == STATE_PATIENT) { Info("Current state: STATE_PATIENT"); UnlockPixrad("EVT_ACTIVE_STATE"); } else if (m_currentState == STATE_QUIET) { Info("Current state: STATE_QUIET"); UnlockPixrad("EVT_ACTIVE_STATE"); } else if (m_currentState == STATE_REFERENCE) { Info("Current state: STATE_REFERENCE"); } else if (m_currentState == STATE_STAND_BY) { Info("Current state: STATE_STAND_BY"); //dark calibration不锁线程,完成后在子线程处理结束流程 if (CCOS_CALIBRATION_TYPE_DARK == m_eCaliType) { SetEvent(m_hDarkEndEvent); } else //一般刷新时锁线程,在此处解锁EVT_END_XRAY_CALIBRATION { UnlockPixrad("EVT_ACTIVE_STATE"); //offset刷新完成 } } else { Info("Current state: {$}", (int)m_currentState); } } } break; case EVT_ACTIVE_DETECTOR: //! Indicates that the active detector has changed ProcessEventError("EVT_ACTIVE_DETECTOR", eventData->error, nDetectorID); UnlockPixrad("EVT_ACTIVE_DETECTOR"); break; case EVT_OFFSET_REQUEST: //! Indicates delay without offset is exceeded. //Require the main software to acquire an offset image ProcessEventError("EVT_OFFSET_REQUEST", eventData->error, nDetectorID); break; case EVT_TIMEOUT_PATIENT: //! Indicates delay timeout without offset image ProcessEventError("EVT_TIMEOUT_PATIENT", eventData->error, nDetectorID); break; case EVT_TEMPERATURE_LIMIT: //! Indicates a temperature of detector is too high ProcessEventError("EVT_TEMPERATURE_LIMIT", eventData->error, nDetectorID); break; case EVT_OFFSET_VALID_LIMIT: //! Indicates that the number of successive non valid offsets has exceed the allowed value ProcessEventError("EVT_OFFSET_VALID_LIMIT", eventData->error, nDetectorID); break; case EVT_WIFI_STATUS: if (ProcessEventError("EVT_WIFI_STATUS", eventData->error, nDetectorID)) { WifiStatus* pData = static_cast(eventData->data); for (int i = 0; i < pData->nbDetectors; ++i) { if (pData->detectorStatus[i].wifiInfo != 0) { int nWifiChannel = pData->detectorStatus[i].wifiInfo->frontEndStatus.channel; Info("channel of frontEndStatus is {$}", nWifiChannel); Debug("power of frontEndStatus is {$}", pData->detectorStatus[i].wifiInfo->frontEndStatus.power); InfoFeedback(EVT_INFO_WIFI_CHANNEL, nDetectorID, nWifiChannel); if (pData->detectorStatus[i].wifiInfo->frontEndStatus.extendedStatus != 0) { int nWifiSignalPower = pData->detectorStatus[i].wifiInfo->frontEndStatus.extendedStatus->signalPower; Info("Detector({$} )signalPower of frontEndStatus extendedStatus is {$}", nDetectorID, nWifiSignalPower); InfoFeedback(EVT_INFO_WIFI_SIGNALPOWER, nDetectorID, nWifiSignalPower); int nWifiNoisePower = pData->detectorStatus[i].wifiInfo->frontEndStatus.extendedStatus->noisePower; Info("noisePower of frontEndStatus extendedStatus is {$}", nWifiNoisePower); InfoFeedback(EVT_INFO_WIFI_NOISEPOWER, nDetectorID, nWifiNoisePower); int nWifiDataRate = pData->detectorStatus[i].wifiInfo->frontEndStatus.extendedStatus->dataRate; Info("dataRate of frontEndStatus extendedStatus is {$}", nWifiDataRate); InfoFeedback(EVT_INFO_WIFI_DATARATE, nDetectorID, nWifiDataRate); int nRawLinkQuality = pData->detectorStatus[i].wifiInfo->frontEndStatus.extendedStatus->rawLinkQuality; StatusFeedback(EVT_STATUS_WIFI, nRawLinkQuality, "", nDetectorID); } } } } if (m_bNeedFeedback) { UnlockPixrad("EVT_WIFI_STATUS"); } if (m_pStPanelStatus[nDetectorID]->bIsPortable) { if (nDetectorID != m_nCurrentPanelID) { //非当前平板是靠开启polling功能实现查询状态的,查询一次后,停止查询 m_nStopPollingIndex = nDetectorID; SetEvent(m_hClosePollingEvent); } } break; case EVT_START_BATTERY_CALIBRATION: //! Sent when the detector battery calibration begins ProcessEventError("EVT_START_BATTERY_CALIBRATION", eventData->error, nDetectorID); break; case EVT_END_BATTERY_CALIBRATION: ProcessEventError("EVT_END_BATTERY_CALIBRATION", eventData->error, nDetectorID); break; case EVT_DETECTOR_CONTROL_CHANGED: //! Sent when the detector control has been enabled/disabled { if (ProcessEventError("EVT_DETECTOR_CONTROL_CHANGED", eventData->error, nDetectorID)) { DetectorControlValue* pCtrlType = static_cast(eventData->data); string strEnable = "DISABLE"; if (pCtrlType->enable) { strEnable = "ENABLE"; } switch (pCtrlType->type) { case DC_DOCKING_STATION_SAPM_CONTACTS: Info("DC_DOCKING_STATION_SAPM_CONTACTS {$}", strEnable.c_str()); break; case DC_FRONTEND_LEDS_SCROLLING: Info("DC_FRONTEND_LEDS_SCROLLING {$}", strEnable.c_str()); break; case DC_FRONTEND_POWEROFF: Info("DC_FRONTEND_POWEROFF {$}", strEnable.c_str()); ErrorFeedback(EVT_ERR_POWER_OFF, "true"); m_pStPanelStatus[nDetectorID]->bConnectStatus = false; break; case DC_FRONTEND_LOWPOWER: Info("DC_FRONTEND_LOWPOWER {$}", strEnable.c_str()); if (pCtrlType->enable) { if ((m_eAppStatus != APP_STATUS_WORK_BEGIN && m_eAppStatus != APP_STATUS_CAL_BEGIN) //检查、校正界面不执行 && (DetStatus_Acquire != m_eStatus) && (DetStatus_Offset != m_eStatus) && (DetStatus_XrayCalibration != m_eStatus)) { Warn("Do not sent sleep msg to upper in status({$} {$})", (int)m_eAppStatus, (int)m_eStatus); } else { StatusFeedback(EVT_STATUS_SLEEP, 0, "true", nDetectorID); } } break; case DC_IMAGE_STORAGE: Info("DC_IMAGE_STORAGE {$}", strEnable.c_str()); break; case DC_AUTOTRIGGER_LOWEST: Info("DC_AUTOTRIGGER_LOWEST {$}", strEnable.c_str()); UnlockPixrad("DC_AUTOTRIGGER_LOWEST"); //启动、关闭aed成功 break; case DC_AUTOTRIGGER_LOW: Info("DC_AUTOTRIGGER_LOW {$}", strEnable.c_str()); UnlockPixrad("DC_AUTOTRIGGER_LOW"); //启动、关闭aed成功 break; case DC_AUTOTRIGGER_NORMAL: Info("DC_AUTOTRIGGER_NORMAL {$}", strEnable.c_str()); m_pStPanelStatus[nDetectorID]->bDC_AED = true; SendRespond("Control"); UnlockPixrad("DC_AUTOTRIGGER_NORMAL"); //启动、关闭aed成功 break; case DC_AUTOTRIGGER_INTERMEDIATE: Info("DC_AUTOTRIGGER_INTERMEDIATE {$}", strEnable.c_str()); UnlockPixrad("DC_AUTOTRIGGER_INTERMEDIATE"); //启动、关闭aed成功 break; case DC_AUTOTRIGGER_HIGH: Info("DC_AUTOTRIGGER_HIGH {$}", strEnable.c_str()); UnlockPixrad("DC_AUTOTRIGGER_HIGH"); //启动、关闭aed成功 break; case DC_WIFI: Info("DC_WIFI {$}", strEnable.c_str()); break; case DC_HOST_LOCK: Info("DC_HOST_LOCK {$}", strEnable.c_str()); break; case DC_QUATERNION_CALCULATION: Info("DC_QUATERNION_CALCULATION {$}", strEnable.c_str()); break; case DC_DETECTOR_READY: Info("DC_DETECTOR_READY {$}", strEnable.c_str()); break; case DC_DIGITAL_TOMO: Info("DC_DIGITAL_TOMO {$}", strEnable.c_str()); UnlockPixrad("DC_DIGITAL_TOMO"); //启动、关闭tomo成功 break; case DC_SYNCHRONIZATION: Info("DC_SYNCHRONIZATION {$}", strEnable.c_str()); UnlockPixrad("DC_SYNCHRONIZATION"); //启动、关闭sync成功 break; default: Info("Control changed: {$} {$}", (int)pCtrlType->type, strEnable.c_str()); break; } } else { UnlockPixrad("EVT_DETECTOR_CONTROL_CHANGED"); } } break; case EVT_ACCEPTANCE_TEST_RESULT: //! Sent when the acceptance test has been computed ProcessEventError("EVT_ACCEPTANCE_TEST_RESULT", eventData->error, nDetectorID); break; case EVT_WAIT_START_XRAY: //! Sent to request the start of the x-ray generator ProcessEventError("EVT_WAIT_START_XRAY", eventData->error, nDetectorID); if (m_nCurrentOmMode == PIX_OM_TOMO) { UnlockPixrad("EVT_WAIT_START_XRAY"); //校正FramePrep时的Resuming执行完毕 } break; case EVT_WAIT_STOP_XRAY: //! Sent to request the stop of the x-ray generator { ProcessEventError("EVT_WAIT_STOP_XRAY", eventData->error, nDetectorID); try { Info("Calling ResumeSequence"); error_status ErrorStatus = TED_PixRad_ResumeSequence(); if (!TestError(ErrorStatus)) { Error("Resume Sequence command Failed"); } else { Info("Resume Sequence command OK"); } } catch (...) { Error("Start acq crash!"); m_eStatus = DetStatus_Standby; } } break; case EVT_DETECTOR_INIT: //! Sent when detector init has been performed if (ProcessEventError("EVT_DETECTOR_INIT", eventData->error, nDetectorID)) { char** path = static_cast(eventData->data); Info("SUCCESSFULLY CONNECTED TO {$}", *path); m_pStPanelStatus[nDetectorID]->strModuleIP = *path; //收到init回调,记录下IP,用于固件升级 m_pStPanelStatus[nDetectorID]->bInitOK = true; //m_nInitFPDCount++; m_pStPanelStatus[nDetectorID]->bConnectStatus = true; //收到init回调且没有错误,置为true ErrorFeedback(EVT_ERR_COMMUNICATE, "false", nDetectorID); } else { m_pStPanelStatus[nDetectorID]->bConnectStatus = false; } SendRespond("Connect"); break; case EVT_DETECTOR_CLOSE: ProcessEventError("EVT_DETECTOR_CLOSE", eventData->error, nDetectorID); break; case EVT_DETECTOR_RECONNECTED: ProcessEventError("EVT_DETECTOR_RECONNECTED", eventData->error, nDetectorID); ErrorFeedback(EVT_ERR_POWER_OFF, "false"); m_pStPanelStatus[nDetectorID]->bConnectStatus = true; break; case EVT_TRANSMIT_PROGRESS: //! Indicates the image transmission progress { unsigned short progress = *(static_cast(eventData->data)); Info("EVT_TRANSMIT_PROGRESS -{$}", progress); } break; case EVT_START_SCAN_DETECTORS: ProcessEventError("EVT_START_SCAN_DETECTORS", eventData->error, nDetectorID); break; case EVT_END_SCAN_DETECTORS: ProcessEventError("EVT_END_SCAN_DETECTORS", eventData->error, nDetectorID); break; case EVT_SEQUENCE_FAILURE: ProcessEventError("EVT_SEQUENCE_FAILURE", eventData->error, nDetectorID); break; case EVT_DETECTOR_SSID_SWITCHED: //! Sent when detector connection SSID has been switched ProcessEventError("EVT_DETECTOR_SSID_SWITCHED", eventData->error, nDetectorID); break; case EVT_DETECTOR_LOW_BATTERY: ProcessEventError("EVT_DETECTOR_LOW_BATTERY", eventData->error, nDetectorID); break; case EVT_DETECTOR_BUTTON: //! Sent when detector button is pushed or released ProcessEventError("EVT_DETECTOR_BUTTON", eventData->error, nDetectorID); break; case EVT_DETECTOR_IR_ID: //! Sent when detector infrared id is changed ProcessEventError("EVT_DETECTOR_IR_ID", eventData->error, nDetectorID); break; case EVT_MODULE_POLLING_CHANGED: //! Sent when module polling activation status has changed if (ProcessEventError("EVT_MODULE_POLLING_CHANGED", eventData->error, nDetectorID)) { bool* enable = static_cast(eventData->data); if (*enable) { Info("Module polling is enabled"); } else { Info("Module polling is disabled"); } } UnlockPixrad("EVT_MODULE_POLLING_CHANGED"); break; case EVT_MODULE_PRESENCE_CHANGED: //! Sent when module presence status has changed if (ProcessEventError("EVT_MODULE_PRESENCE_CHANGED", eventData->error, nDetectorID)) { bool* present = static_cast(eventData->data); if (*present) { m_bModulePresent = true; Info("Moudle({$}) is present", eventData->module); if (m_bAttaching) { Warn("FPD is Attaching, return"); return; } ErrorFeedback(EVT_ERR_MAX_NUMBER, "false"); if (APP_STATUS_DETSHARE_BEGIN == m_eAppStatus) //需要考虑增加界面 { if (!m_bModuleConnecting) //探测器没有在连接过程中,可以执行attach { Info("Start IR infrared Module"); } else { Info("In Detector Sharing Process"); } } else //如果不在检查中,不响应 { Warn("Not in Detector Share Window"); } } else { m_bModulePresent = false; Info("Module({$}) is now missing", eventData->module); } } break; case EVT_MODULE_INFORMATION: //! Sent when module info is available if (ProcessEventError("EVT_MODULE_INFORMATION", eventData->error, nDetectorID)) { ModuleInformation* moduleInfo = static_cast(eventData->data); switch (moduleInfo->infoType) { case DETECTOR_SERIAL_NUMBER: m_strModuleSN = moduleInfo->info; Info("detector serial number:{$}", m_strModuleSN.c_str()); //ConfFeedback(EVT_CONF_MODULE_SN, m_nCurrentPanelID/*nDetectorID*/, m_strModuleSN.c_str()); break; case DETECTOR_IP: m_strModuleIP = moduleInfo->info; Info("Detector IP Address:{$}", m_strModuleIP.c_str()); //ConfFeedback(EVT_CONF_MODULE_IP, m_nCurrentPanelID, m_strModuleIP.c_str()); //把配置文件中的反馈上去 break; case DETECTOR_TYPE: { string strModuleType = moduleInfo->info; if (strModuleType.find("3543DR") != string::npos) //3543DRcs { m_strModuleType = "PIXIUM3543DR"; } else if (strModuleType.find("3543EZ") != string::npos) { m_strModuleType = "PIXIUM3543EZh"; } else if (strModuleType.find("2430EZ") != string::npos) { m_strModuleType = "PIXIUM2430EZ"; } Info("Detector {$} Type:{$}", nDetectorID, strModuleType.c_str()); /*ConfFeedback(EVT_CONF_MODULE_TYPE, m_nCurrentPanelID, m_strModuleType.c_str());*/ } break; case DETECTOR_SSID: m_strModuleSSID = moduleInfo->info; Info("Detector SSID Name:{$}", m_strModuleSSID.c_str()); break; case DETECTOR_HOST_IP: { string strModuleHostIP = moduleInfo->info; Info("Detector Host IP Address:{$}", strModuleHostIP.c_str()); } break; default: break; } } UnlockPixrad("EVT_MODULE_INFORMATION"); break; case EVT_MODULE_IR_ID: //! Sent to inform of current infrared id (after set/get) ProcessEventError("EVT_MODULE_IR_ID", eventData->error, nDetectorID); break; case EVT_MODULE_IP_CONFIG_CHANGED: //! Sent when module has changed ip configuration if (ProcessEventError("EVT_MODULE_IP_CONFIG_CHANGED", eventData->error, nDetectorID)) { ModuleIpConfig* moduleIpConfig = static_cast(eventData->data); Info("Module {$} IP configuration changed to : detector={$} host={$}", eventData->module, moduleIpConfig->detectorIp, moduleIpConfig->hostIp); } UnlockPixrad("EVT_MODULE_IP_CONFIG_CHANGED"); break; case EVT_MODULE_SSID_SWITCHED: //! Sent when module has switched ssid if (ProcessEventError("EVT_MODULE_SSID_SWITCHED", eventData->error, nDetectorID)) { char** ssid = static_cast(eventData->data); Info("Module {$} switched SSID to: {$}", eventData->module, *ssid); } UnlockPixrad("EVT_MODULE_SSID_SWITCHED"); break; case EVT_IMAGE_METADATA_CHANGED: //! Indicates image metadata has been changed ProcessEventError("EVT_IMAGE_METADATA_CHANGED", eventData->error, nDetectorID); break; case EVT_START_REMOTE_STORAGE_SESSION: //! Indicates the remote storage session begins if (ProcessEventError("EVT_START_REMOTE_STORAGE_SESSION", eventData->error, nDetectorID)) { m_nSessionID = *static_cast(eventData->data); Info("Remote storage session open with id {$}", m_nSessionID); } UnlockPixrad("EVT_START_REMOTE_STORAGE_SESSION"); break; case EVT_END_REMOTE_STORAGE_SESSION: if (!ProcessEventError("EVT_END_REMOTE_STORAGE_SESSION", eventData->error, nDetectorID)) { UnlockPixrad("EVT_END_REMOTE_STORAGE_SESSION"); //出错的情况下,等不到后面的EVT_ACTIVE_STATE解锁了,所以这里自己解锁一下 } break; case EVT_START_STOREDIMAGE_LIST: //! Sent when get stored image list begins ProcessEventError("EVT_START_STOREDIMAGE_LIST", eventData->error, nDetectorID); break; case EVT_END_STOREDIMAGE_LIST: ProcessEventError("EVT_END_STOREDIMAGE_LIST", eventData->error, nDetectorID); if (TestError(eventData->error)) { ImageInfosList* pData = static_cast(eventData->data); for (int i = 0; i < pData->nbImages; ++i) { ImageInfos imageInfos = pData->imageInfos[i]; //m_StoredImageList.push_back( imageInfos ); if (imageInfos.imgParam.metadata != NULL) { string strData = imageInfos.imgParam.metadata->data; int nSize = imageInfos.imgParam.metadata->dataSize; Info("{$} | {$}", strData, nSize); if (strData == "") //图像头为空的不处理 { Error("Illegal Image Header!"); continue; } string strBarcode = RecognizeBarcode(strData, nSize); m_StoredImageMetaDataList.push_back(strBarcode); Info("Index: {$}; Barcode: {$}", i, strBarcode); if (m_vecStorageList.size() == 0) { Info("New first Patient ID"); m_vecStorageList.push_back(strBarcode); } else { bool bSamePatientID = false; for (int j = 0; j < m_vecStorageList.size(); j++) { /*if (m_vecStorageList[i].Find(strBarcode) >= 0)*/ if (m_vecStorageList[j] == strBarcode)//修改比对cstring的方式,原方式记录形如“abcd”的条形码后会漏掉“abc”条形码 { bSamePatientID = true; break; } } if (!bSamePatientID) { Info("New Patient ID"); m_vecStorageList.push_back(strBarcode); } } } //end if } } else { Error("Get StoredImageList Error"); } UnlockPixrad("EVT_END_STOREDIMAGE_LIST"); break; case EVT_START_STOREDIMAGE: //! Sent when get stored image begins ProcessEventError("EVT_START_STOREDIMAGE", eventData->error, nDetectorID); break; case EVT_END_STOREDIMAGE: ProcessEventError("EVT_END_STOREDIMAGE", eventData->error, nDetectorID); SendRespond("GetStoredImage"); break; case EVT_STOREDIMAGE_REMOVED: //! Indicates the stored image has been removed ProcessEventError("EVT_STOREDIMAGE_REMOVED", eventData->error, nDetectorID); SendRespond("RemoveStoredImage"); break; case EVT_START_SYNCHRO_REFERENCES: //! Sent when the references synchronization begins ProcessEventError("EVT_START_SYNCHRO_REFERENCES", eventData->error, nDetectorID); break; case EVT_END_SYNCHRO_REFERENCES: ProcessEventError("EVT_END_SYNCHRO_REFERENCES", eventData->error, nDetectorID); break; case EVT_SYNCHRO_REFERENCES_PROGRESS: //! Indicates the references sycnhronization progress ProcessEventError("EVT_SYNCHRO_REFERENCES_PROGRESS", eventData->error, nDetectorID); break; case EVT_START_CLEAR_SYNCHRO_REFERENCES: //! Sent when the references removal begins ProcessEventError("EVT_START_CLEAR_SYNCHRO_REFERENCES", eventData->error, nDetectorID); break; case EVT_END_CLEAR_SYNCHRO_REFERENCES: ProcessEventError("EVT_END_CLEAR_SYNCHRO_REFERENCES", eventData->error, nDetectorID); break; case EVT_CLEAR_SYNCHRO_REFERENCES_PROGRESS: //! Indicates the references removal progress ProcessEventError("EVT_CLEAR_SYNCHRO_REFERENCES_PROGRESS", eventData->error, nDetectorID); break; case EVT_DETECTOR_PARAMETER_VALUE: //! Sent when a detector parameter value has been set/get ProcessEventError("EVT_DETECTOR_PARAMETER_VALUE", eventData->error, nDetectorID); break; case EVT_STATUS_POLLING_CHANGED: //! Sent when detector status polling activation status has changed { if (TestError(eventData->error)) { bool enable = *static_cast(eventData->data); string strEnable = "DISABLE"; if (enable) { strEnable = "ENABLE"; } Info("EVT_STATUS_POLLING_CHANGED {$}", strEnable); } else { Info("EVT_STATUS_POLLING_CHANGED ERROR"); } } break; case EVT_DETECTOR_INFORMATION: //! Sent when a detector information has been set/get if (ProcessEventError("EVT_DETECTOR_INFORMATION", eventData->error, nDetectorID)) { DetectorInformationValue* pstInformationValue = static_cast(eventData->data); switch (pstInformationValue->type) { case DI_SHOCK_SENSOR: { Info("SHOCK SENSOR INFORMATION : "); if (pstInformationValue->data != 0) { ShockEvents* stShock = static_cast(pstInformationValue->data); time_t lDate = (time_t)stShock->resetDate; struct tm stLocalTime; char szTemp[100] = { 0 }; stLocalTime = *localtime(&lDate); strftime(szTemp, sizeof(szTemp), "%Y-%m-%d %H:%M:%S", &stLocalTime); Info("Reset Date:{$}", szTemp); int nShockNumbers = stShock->nbEvents; Info("Shock Event Numbers:{$}", nShockNumbers); if (stShock->nbEvents == 0) { SimulateShockSensor(nDetectorID); break; } string strShockList = "{"; for (int nEvent = 0; nEvent < stShock->nbEvents; ++nEvent) { string strLevels = ""; int nLastLevel = 0; for (int nLevel = 0; nLevel < stShock->events[nEvent].nbLevels; ++nLevel) { for (int k = 0; k < stShock->events[nEvent].levels[nLevel].nbGroups; ++k) { if (stShock->events[nEvent].levels[nLevel].groups[k].triggered) { nLastLevel = nLevel + 1; Info("Event Level:{$},Groups:{$} is Trigged", nLastLevel, k); //Event:0,Date:1481060292,Levels:1=xx } } } time_t lDate = (time_t)stShock->events[nEvent].date; struct tm stLocalTime; char szTemp[100] = { 0 }; stLocalTime = *localtime(&lDate); strftime(szTemp, sizeof(szTemp), "%Y-%m-%d %H:%M:%S", &stLocalTime); Info("Event:{$},Date:{$},Levels:{$}", nEvent, szTemp, nLastLevel); //Event:0,Date:1481060292,Levels:1=xx auto strInfo = to_string(nEvent); auto strLevel = to_string(nLastLevel); std::ostringstream ostrShockData; ostrShockData << R"("Shock)" << strInfo << R"(":{"SN":")" << m_pStPanelStatus[nDetectorID]->strPanelSN << R"(","Time":")" << szTemp << R"(","Level":")" << strLevel << R"("},)"; //e.g. "Shock1":{"SN":"%s","Time":"%s","Level":"%s"}," Info("{$}", ostrShockData.str().c_str()); strShockList += ostrShockData.str(); } strShockList = strShockList.substr(0, strShockList.length() - 1); //最后一个不加逗号 strShockList += "}"; InfoFeedback(EVT_INFO_SHOCKSENSOR_INFO, nDetectorID, 0, 0, strShockList.c_str()); Info("{$}", strShockList.c_str()); StatusFeedback(EVT_STATUS_SHOCK_SENSOR, nShockNumbers, "", nDetectorID); } } break; default: break; } } UnlockPixrad("EVT_DETECTOR_INFORMATION"); break; case EVT_DETECTOR_LOW_BATTERY_FOR_IMAGE: //! Sent when detector battery level is too low for acquiring an image ProcessEventError("EVT_DETECTOR_LOW_BATTERY_FOR_IMAGE", eventData->error, nDetectorID); m_bPreviewImg = false; //电量低,采集结束,恢复初值 //(*m_pPanelID2DPC)[m_nCurrentPanelID]->AddErrMsg(4); if (m_eStatus == DetStatus_Acquire) //如果回调早于stopacquisition接口调用,则置为DETECTOR_STATUS_STANDBY { //(*m_pPanelID2DPC)[m_nCurrentPanelID]->SetDetectorStatus(DETECTOR_STATUS_STANDBY); //电量低,SDK采集流程结束,设置状态 m_eStatus = DetStatus_Standby; //电量低,停止采集,置回Standby } break; case EVT_APPLICATION_PARAMETERS_STATUS: //! Sent when the application mode parameters have been set ProcessEventError("EVT_APPLICATION_PARAMETERS_STATUS", eventData->error, nDetectorID); break; case EVT_START_TRANSFER_STOREDIMAGES: //! Sent when the transfer of all stored images begins ProcessEventError("EVT_START_TRANSFER_STOREDIMAGES", eventData->error, nDetectorID); break; case EVT_END_TRANSFER_STOREDIMAGES: ProcessEventError("EVT_END_TRANSFER_STOREDIMAGES", eventData->error, nDetectorID); UnlockPixrad("EVT_END_TRANSFER_STOREDIMAGES"); break; case EVT_START_REMOVE_ALL_STOREDIMAGES: ProcessEventError("EVT_START_REMOVE_ALL_STOREDIMAGES", eventData->error, nDetectorID); SendRespond("RemoveAutonumousAll"); break; case EVT_END_REMOVE_ALL_STOREDIMAGES: ProcessEventError("EVT_END_REMOVE_ALL_STOREDIMAGES", eventData->error, nDetectorID); break; case EVT_APPLICATION_CONTROL_CHANGED: //! Sent when the mode has been activated ProcessEventError("EVT_APPLICATION_CONTROL_CHANGED", eventData->error, nDetectorID); SendRespond("AutononousOffline"); break; case EVT_DETECTOR_CONNECTION_REFUSED: //! Sent when the detector has refused an incoming connection request from another host ProcessEventError("EVT_DETECTOR_CONNECTION_REFUSED", eventData->error, nDetectorID); break; case EVT_DETECTOR_CONNECTION_ABORTED: //! Sent when another host connects to the detector ProcessEventError("EVT_DETECTOR_CONNECTION_ABORTED", eventData->error, nDetectorID); break; case EVT_DETECTOR_SCAN_STATUS: //! Sent during a status scan when a detector status is available ProcessEventError("EVT_DETECTOR_SCAN_STATUS", eventData->error, nDetectorID); break; case EVT_MODULE_NETWORK_CONFIG_CHANGED: //! Sent when module has changed network configuration (SSID + IPs) if (ProcessEventError("EVT_MODULE_NETWORK_CONFIG_CHANGED", eventData->error, nDetectorID)) { ModuleNetworkConfig* moduleNetConfig = static_cast(eventData->data); Info("Module {$} network configuration changed to : ssid={$} detector={$} host={$}", eventData->module, moduleNetConfig->ssid, moduleNetConfig->ipConfig.detectorIp, moduleNetConfig->ipConfig.hostIp); } UnlockPixrad("EVT_MODULE_NETWORK_CONFIG_CHANGED"); break; case EVT_START_DETECTOR_CONFIG: //! Sent when a new detector config begins ProcessEventError("EVT_START_DETECTOR_CONFIG", eventData->error, nDetectorID); break; case EVT_END_DETECTOR_CONFIG: ProcessEventError("EVT_END_DETECTOR_CONFIG", eventData->error, nDetectorID); break; case EVT_DETECTOR_LICENSE_SESSION_ID: //! Sent when detector license id has been requested ProcessEventError("EVT_DETECTOR_LICENSE_SESSION_ID", eventData->error, nDetectorID); break; case EVT_END_DETECTOR_LICENSE_SESSION_REQUEST: //! Sent when an attempt to modify locking counter has been done ProcessEventError("EVT_END_DETECTOR_LICENSE_SESSION_REQUEST", eventData->error, nDetectorID); break; case EVT_LICENSE_LOCKING_COUNTER_ABOUT_TO_EXPIRE: //! sent when detector locking counter is about to expire //(according to the parameterized threshold) ProcessEventError("EVT_LICENSE_LOCKING_COUNTER_ABOUT_TO_EXPIRE", eventData->error, nDetectorID); break; case EVT_LICENSE_LOCKING_COUNTER_EXPIRED: //! sent when detector locking counter has expired, //detector is then locked and image acquisition features are disabled, unless unlock again ProcessEventError("EVT_LICENSE_LOCKING_COUNTER_EXPIRED", eventData->error, nDetectorID); break; case EVT_ACQUISITION_SYNCHRO: //! sent when digital tomography acquisition has been launched, //to notify user of the synchronization status { AcquisitionSynchronization* acqSync = static_cast(eventData->data); float fDelta = acqSync->delta_us; //computed delta duration in microseconds to use for pixrad timing synchronization with detector acquisition sequence float fStdDev = acqSync->stdDev_us; //standard deviation of delta value, used to check the steadiness of the synchronization float fDelta_med = acqSync->delta_med_us; //median of delta values Info("EVT_ACQUISITION_SYNCHRO delta: %fms, standard: %fus, median: %fms", fDelta / 1000, fStdDev, fDelta_med / 1000); } break; case EVT_ACQUISITION_TIME: //! sent when digital tomography acquisition has been launched, //to notify user of the core acquisition start time at host and detector level { AcquisitionTime* stAcqTime = static_cast(eventData->data); long long startDate = stAcqTime->detectorStartDate_us; //system date at which the detector started the acquisition long long preambleTime = stAcqTime->detectorPreambleTime_us; //preamble time given by the detector Info("EVT_ACQUISITION_TIME %lldus, %lldus", startDate, preambleTime); } break; default: break; } } //设置保存过程图接口 bool TrixellCtrl::SetSaveRawDataMode(int nSaveRawDataMode) { Info(__FUNCTION__); m_nSaveRaw = nSaveRawDataMode; Info("Save Raw Mode: ({$})", m_nSaveRaw); return true; } //离线采集断连设置离线模式接口 bool TrixellCtrl::OfflineFPD(int nDetectorID) { Info(__FUNCTION__); m_nAutonumousID = nDetectorID; int nIndex = nDetectorID; if (m_pStPanelStatus[nIndex]->bHaveAutonumousMode == false) { Info("Current detector can not support antonumous mode"); return true; } Info("Current detector support antonumous mode"); if (m_pStPanelStatus[nIndex]->bAutonumousMode == true) { Info("Current detector already in offline mode"); StatusFeedback(EVT_AUTONUMOUS_STATUS, PANEL_DISCONNECT_SUCCESS, "", nDetectorID); return true; } Info("Current detector set to offline mode"); StartOfflineAutonumousThread(); return true; } //离线采集:设置到offline线程 bool TrixellCtrl::StartOfflineAutonumousThread() { HANDLE hAutonumousThread; unsigned int unThreadID; Info("Start Offline Autonumous Thread "); hAutonumousThread = (HANDLE)_beginthreadex(NULL, 0, onOfflineAutonumousMode, (LPVOID)this, 0, &unThreadID); if (hAutonumousThread == NULL) { Error("Start Autonumous Thread Error"); return false; } return true; } unsigned TrixellCtrl::onOfflineAutonumousMode(void* pParam) { TrixellCtrl* pInstance = (TrixellCtrl*)pParam; Info("Offline Autonumous Mode"); if (!pInstance->OfflineAutonumousMode()) { pInstance->StatusFeedback(EVT_AUTONUMOUS_STATUS, PANEL_DISCONNECT_ERROR, "", pInstance->m_nAutonumousID); } else { pInstance->StatusFeedback(EVT_AUTONUMOUS_STATUS, PANEL_DISCONNECT_SUCCESS, "", pInstance->m_nAutonumousID); pInstance->m_pStPanelStatus[pInstance->m_nAutonumousID]->bAutonumousMode = true; } return 0; } bool TrixellCtrl::OfflineAutonumousMode() { // 1. 先切换到选中的探测器上 if (m_nDetectorID != m_nAutonumousID) { if (!SetActiveDetector(m_nAutonumousID)) { Error("Change Detector Failed"); return false; } } // 2. AED必须在QUIET状态 if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); return false; } // 3 将此探测器设置到AED模式 SetSyncMode(m_nDetectorID, SYNC_AED); if (!m_pStPanelStatus[m_nAutonumousID]->bDC_AED == true) //如果没有切换到AED模式,也报错 { Error("Set AED sync mode failed"); return false; } //4. 设置采集参数,主要是设置采集时图像自动OFFSET //SetApplicationParam(2); application_mode applicationMode = APPLICATION_MODE2; Info("applicationMode: {$}, current detector ID: {$}", (int)applicationMode, m_nAutonumousID); ApplicationParameter pAppParam[5] = { 0 }; char szTemp[5] = { 0 }; sprintf_s(szTemp, "%d", m_nTomoImgCount); pAppParam[0].name = "acquisition.type"; pAppParam[0].value = "x"; pAppParam[1].name = "output.type"; pAppParam[1].value = "short"; pAppParam[2].name = "output.preview"; pAppParam[2].value = "false"; if (m_bPreviewEnable) { pAppParam[2].name = "output.preview"; pAppParam[2].value = "true"; } if (CT_ALL == m_pStPanelStatus[m_nCurrentPanelID]->eCorrectType[0]) { Info("All correction enable"); pAppParam[3].name = "all.enabled"; pAppParam[3].value = "true"; } else if (CT_OFFSET == m_pStPanelStatus[m_nCurrentPanelID]->eCorrectType[0]) { Info("Offset correction enable"); pAppParam[3].name = "offset.enabled"; pAppParam[3].value = "true"; } else if (CT_GAIN == m_pStPanelStatus[m_nCurrentPanelID]->eCorrectType[0]) { Info("Gain correction enable"); pAppParam[3].name = "gain.enabled"; pAppParam[3].value = "true"; } else if (CT_DEFECT == m_pStPanelStatus[m_nCurrentPanelID]->eCorrectType[0]) { Info("Defect correction enable"); pAppParam[3].name = "defect.enabled"; pAppParam[3].value = "true"; } pAppParam[4].name = "image.number"; pAppParam[4].value = szTemp; Info("Calling SetApplicationParameters"); error_status ErrorStatus = TED_PixRad_SetApplicationParameters(applicationMode, pAppParam, 5); //EVT_APPLICATION_PARAMETERS_STATUS if (!TestError(ErrorStatus)) { Error("Set application parameters command Failed"); return false; } Info("Set application parameters command OK"); //SetImageMetaData("0000"); //5. 设置到AC_AUTONOMOUS_NORMAL 离线模式 if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); return false; } Info("Call TED_PixRad_ApplicationControl in Autononous"); ErrorStatus = TED_PixRad_ApplicationControl(applicationMode, AC_AUTONOMOUS_NORMAL, true); // EVT_APPLICATION_CONTROL_CHANGED if (!TestError(ErrorStatus)) { Error("Set Application Control Failed"); return false; } if (!WaitRespond(g_nRespondTimeout, "AutonumousOffline")) { Error("Autonumous Offline failed"); return false; } Info("Set Application Control OK"); // 6 探测器会断开与SDK的连接 //SendDetectorInfo(m_nAutonumousID - 1, false); // 7. 切换回到当前的探测器 if (m_nDetectorID != m_nAutonumousID) { if (!SetActiveDetector(m_nDetectorID)) { Error("Change to Current Detector Failed"); return false; } if (!SetSystemState(STATE_PATIENT)) { Error("Set Quiet State Failed"); //SendPanelStatus(PNL_DISCONNECT, RESULT_ERROR); return false; } } return true; } bool TrixellCtrl::SetSyncMode(int nDetectorID, SYNC_MODE nSyncMode) { Info(__FUNCTION__); int nIndex = nDetectorID; if (m_pStPanelStatus[nIndex]->bDC_AED == true) { Info("Already in AutoTrigger Mode, Return"); return true; } if (!SetSystemState(STATE_QUIET)) //设置到QUIET状态 { Error("Set Quiet State Failed"); return false; } LockPixrad("DetectorControl"); Info("Call DetectorControl at DC_AUTOTRIGGER"); error_status ErrorStatus = TED_PixRad_DetectorControl(DC_AUTOTRIGGER_NORMAL, true); //EVT_DETECTOR_CONTROL_CHANGED if (!TestError(ErrorStatus)) { Info("Detector control command failed"); return false; } Info("Detector control command OK"); LockPixrad("DetectorControl"); UnlockPixrad("DetectorControl"); if (!SetSystemState(STATE_QUIET)) //恢复到QUIET状态 { Error("Set Quiet State Failed"); } Info("Set AutoTrigger Mode End"); return true; } bool TrixellCtrl::SetSyncMode(int nDetectorID, int nSyncMode) { Info("Set detector({$}) sync mode: {$}", nDetectorID, nSyncMode); if (m_nCurrentOmMode != nSyncMode) { if (!SetSystemState(STATE_QUIET)) //需要在QUIET状态下设置 { Info("Set quiet state failed"); return false; } Info("Calling DetectorControl, reset"); error_status ErrorCode = TED_PixRad_DetectorControl(DC_AUTOTRIGGER_NORMAL, false); //EVT_DETECTOR_CONTROL_CHANGED if (!TestError(ErrorCode)) { return false; } if (!WaitRespond(g_nRespondTimeoutLong, "Control")) { Error("Detector control timeout"); return false; } if (!SetSystemState(STATE_QUIET)) //恢复到QUIET状态 { Error("Set quiet state failed"); } m_nCurrentAppMode = 0; } m_nCurrentOmMode = nSyncMode; return true; } //离线采集断连设置在线模式接口 bool TrixellCtrl::OnlineFPD(int nDetectorID) { Info(__FUNCTION__); m_nAutonumousID = nDetectorID; int nIndex = nDetectorID; if (m_pStPanelStatus[nIndex]->bHaveAutonumousMode == false) { Info("Current detector can not support antonumous mode"); return true; } Info("Current detector support antonumous mode"); if (m_pStPanelStatus[nIndex]->bAutonumousMode == false) { Info("Current detector already in online mode"); StatusFeedback(EVT_AUTONUMOUS_STATUS, PANEL_CONNECT_OK, "", nDetectorID); return true; } Info("Current detector set to online mode"); StartOnlineAutonumousThread(); return true; } //离线采集:设置到online线程 bool TrixellCtrl::StartOnlineAutonumousThread() { HANDLE hAutonumousThread; unsigned int unThreadID; Info("Start Offline Autonumous Thread "); hAutonumousThread = (HANDLE)_beginthreadex(NULL, 0, onOnlineAutonumousMode, (LPVOID)this, 0, &unThreadID); if (hAutonumousThread == NULL) { Error("Start Autonumous Thread Error"); return false; } return true; } unsigned TrixellCtrl::onOnlineAutonumousMode(void* pParam) { TrixellCtrl* pInstance = (TrixellCtrl*)pParam; Info("Online Autonumous Mode"); if (!pInstance->OnlineAutonumousMode()) { pInstance->StatusFeedback(EVT_AUTONUMOUS_STATUS, PANEL_CONNECT_ERROR, "", pInstance->m_nAutonumousID); } else { pInstance->StatusFeedback(EVT_AUTONUMOUS_STATUS, PANEL_CONNECT_OK, "", pInstance->m_nAutonumousID); pInstance->m_pStPanelStatus[pInstance->m_nAutonumousID]->bAutonumousMode = false; } return 0; } /*** * 离线采集重连接口。 ***/ bool TrixellCtrl::OnlineAutonumousMode() { Info(__FUNCTION__); int nIndex = m_nAutonumousID; //1. 先设置到QUIET模式 if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); return false; } Info("Call TED_PixRad_Connect %d", m_nAutonumousID); //2. 重新连接探测器 error_status ErrorStatus = TED_PixRad_Connect(m_nAutonumousID, ""); //EVT_DETECTOR_INIT if (!TestError(ErrorStatus)) { Error("Connect Detector Failed"); return false; } if (!WaitRespond(g_nConnectTimeout, "Connect")) //设置一个10秒的连接超时 { Error("Autonumous connect detector timeout"); return false; } if (m_pStPanelStatus[nIndex]->bConnectStatus == false) { Error("Connect Detector Failed"); ErrorFeedback(EVT_ERR_COMMUNICATE, "false", 0); return false; } //3. 连接成功后,初始化探测器设置 Info("Connect Detector Success"); //4. 获取wifi battery GetHardwareStatus(m_nAutonumousID); //把探测器信息先发上去 //6.切换到正常拍片的同步模式 if (SYNC_AED == m_stDeviceIndex[m_nCurrentPanelID].nSyncMode) { SetSyncMode(m_nDetectorID, SYNC_AED); } else { SetFpdExamMode("", PIX_OM_AED, g_nAEDmode, false); } //7.刷新AED模式下的Offset if (!m_pStPanelStatus[nIndex]->bAEDDarkCalibDone) //如果没有采集到dark calbration { Warn("Get dark calibration files failed"); } else { Info("Refresh dark calibration files success"); } //8. 加载矫正文件 /*application_mode applicationMode = APPLICATION_MODE2; operating_mode operatingMode = OM_RAD_AUTOTRIGGER; unsigned short detectorMode = defaultDetectorMode; unsigned short gainReferenceId = defaultReferenceId; unsigned short dmReferenceId = defaultReferenceId; bool bResult = LoadReferenceEx(applicationMode, operatingMode, detectorMode, gainReferenceId, dmReferenceId); if (!bResult) { Error("Load All Autonumous Reference File Failed"); } else { Info("Load All Autonumous Reference File OK"); }*/ //9. 设置到PATIENT模式 if (!SetSystemState(STATE_PATIENT)) { Error("Set Quiet State Failed"); } return true; } /*** * 离线采集接口:获取采集的病人列表 ***/ bool TrixellCtrl::GetAutonumousImageList(int nDetectorID, vector& AutonumousList) { Info("Get FPD({$}) Patient List", nDetectorID); // 探测器不支持离线采集则直接返回 int nIndex = nDetectorID; if (m_pStPanelStatus[nIndex]->bHaveAutonumousMode == false) { Info("Current detector can not support antonumous mode"); return true; } //1. 先切换到当前探测器 m_nAutonumousID = nDetectorID; //2. 获取当前探测器中的列表 LockPixrad("GetStoredImageList"); m_vecStorageList.clear(); m_StoredImageMetaDataList.clear(); Info("Call TED_PixRad_GetStoredImageList"); error_status ErrorStatus = TED_PixRad_GetStoredImageList(); //EVT_END_STOREDIMAGE_LIST if (!TestError(ErrorStatus)) { Error("Get StoredImage List failed"); } Info("Get StoredImage List command OK"); LockPixrad("GetStoredImageList"); //等待返回结果 UnlockPixrad("GetStoredImageList"); Info("Get Image List Over"); AutonumousList = m_vecStorageList; return true; } string TrixellCtrl::RecognizeBarcode(string strData, int nLen) { if (strData == "") //图像头为空的不处理 { Error("Illegal Image Header!"); return ""; } size_t nDataMinPos = 0; for (size_t i = 0; i < strData.length(); i++) //去掉条形码字符串两边的乱码 { if ((strData[i] >= '!') && (strData[i] <= '~')) { nDataMinPos = i; break; } } string strBarcode = strData.substr(nDataMinPos, nLen); Info("{$}", strBarcode); return strBarcode; } /*** * 离线采集接口:删除采集的病人列表 ***/ bool TrixellCtrl::RemoveAutonumousImageList(string strMeta) { Info(__FUNCTION__); size_t nImageNumber = m_vecStorageList.size(); int i = 0; bool bFindImage = false; while (i < nImageNumber) { if (m_vecStorageList[i] == "") { } else { //CString strImageData = m_StoredImageList[i].imgParam.metadata->data; // , strMetaData, strMetaData.GetLength()) == 0) string strImageData = m_vecStorageList[i]; if (strImageData == strMeta) //注意字串和主串,查找形如“abc”的条形码后会删掉“abcd”条形码的图像 { bFindImage = true; Info("Find Image with MetaData: {$}", strImageData); Info("Call TED_PixRad_RemoveStoredImage"); error_status ErrorStatus = TED_PixRad_RemoveStoredImage(i); if (TestError(ErrorStatus)) { Info("Remove StoredImage command OK"); } if (!WaitRespond(g_nRespondTimeout, "RemoveStoredImage")) { Error("Remove StoredImage timeout"); return false; } } } i++; } Info("Remove Denoted Images Over"); return true; } /*** * 离线采集接口:删除采集的所有病人列表 ***/ bool TrixellCtrl::RemoveAutonumousAll() { Info(__FUNCTION__); error_status ErrorStatus; Info("Call TED_PixRad_RemoveAllStoredImages"); ErrorStatus = TED_PixRad_RemoveAllStoredImages(); //EVT_START_REMOVE_ALL_STOREDIMAGES if (!TestError(ErrorStatus)) { Error("Remove All StoredImage failed"); return false; } Info("Remove All StoredImage command OK"); if (!WaitRespond(g_nRespondTimeout, "RemoveAutonumousAll")) { Error("Remove All StoredImage timeout"); return false; } Info("Remove All StoredImage success"); return true; } /*** * 离线采集接口:采集的病人Image ***/ bool TrixellCtrl::GetImageMetaData(string strMetaData) { m_bWorkMode = true; m_strGetMetaData = strMetaData; Info("Get Meta Images: {$}", strMetaData); HANDLE hGetStoredImageThread = nullptr; DWORD dwThreadID = 0; Info("Start Get Stored Image Thread "); hGetStoredImageThread = CreateThread(NULL, 0, onGetStoredImageThread, this, 0, &dwThreadID); if (hGetStoredImageThread == NULL) { Error("Get Stored Image Thread Error"); } return true; } DWORD __stdcall TrixellCtrl::onGetStoredImageThread(PVOID pvoid) { TrixellCtrl* pInstance = (TrixellCtrl*)pvoid; Info("Begin Get Stored Image Thread"); pInstance->GetStoredImage(pInstance->m_strGetMetaData); Info("End Get Stored Image Thread"); return 0; } /*** * 图像获取:一个strMetaData可以对应多个图 ***/ bool TrixellCtrl::GetStoredImage(string strMetaData) { //设置为工作模式 StatusFeedback(EVT_AUTONUMOUS_STATUS, PANEL_START_STOREDIMAGE, "", 0); if (!SetSystemState(STATE_PATIENT)) { Error("Set Patient State Failed"); } size_t nImageNumber = m_StoredImageMetaDataList.size(); Info("Total Stored Images is {$}", nImageNumber); int i = 0; bool bFindImage = false; m_strAutonumousMetaData = ""; m_nAutonumousImageIndex = 0; m_bAutonumousMode = true; while (i < nImageNumber) { if (m_StoredImageMetaDataList[i] == "") { Warn("Image Meta is NULL"); } else { string strImageData = m_StoredImageMetaDataList[i]; if (strImageData == strMetaData) { bFindImage = true; Info("Find Image with MetaData: {$}", strImageData); m_strAutonumousMetaData = strImageData; m_nAutonumousImageIndex = i; Info("Call TED_PixRad_GetStoredImage"); error_status ErrorStatus = TED_PixRad_GetStoredImage(i, false, true, DT_USHORT_TYPE); if (TestError(ErrorStatus)) { Info("Get Stored Image command OK"); //break; } else { Error("Get Stored Image command failed"); //UnlockPixrad(); break; } if (!WaitRespond(g_nRespondTimeout, "GetStoredImage")) //5秒超时 { Error("GetStoredImage detector timeout"); } //调用一次该接口,下面Event会收到一遍 //- EVT_START_STOREDIMAGE //- EVT_START_TRANSMIT //- EVT_END_TRANSMIT //- EVT_PREVIEW //- EVT_START_TRANSMIT //- EVT_END_TRANSMIT //- EVT_IMAGE_AVAILABLE //- EVT_END_STOREDIMAGE } } i++; } if (!bFindImage) //没有找到该图像 { Warn("Image with MetaData:%s Missed", strMetaData); return false; } m_bAutonumousMode = false; StatusFeedback(EVT_AUTONUMOUS_STATUS, PANEL_END_STOREDIMAGE, "", 0); Info("Get mapping image over."); return true; } bool TrixellCtrl::ExportAutonumousAll() { HANDLE hExportAutonumousThread = nullptr; DWORD dwThreadID = 0; Info("Start Export Image to Local Thread "); hExportAutonumousThread = CreateThread(NULL, 0, onExportAutonumousToLocal, this, 0, &dwThreadID); if (hExportAutonumousThread == NULL) { Error("Get Stored Image Thread Error"); } return true; } DWORD __stdcall TrixellCtrl::onExportAutonumousToLocal(PVOID pvoid) { TrixellCtrl* pInstance = (TrixellCtrl*)pvoid; Info("Begin Export Stored Image Thread"); pInstance->ExportAutonumousToLocal(); Info("End Export Stored Image Thread"); return 0; } bool TrixellCtrl::ExportAutonumousToLocal() { Info(__FUNCTION__); //1.设置探测器到QUIET if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); return false; } //2.导出所有到本地.fxd文件 string strExportPath = m_strWorkPath + "\\rawdata\\Autonumous\\"; Info("Export all Image into local path: {$}", strExportPath); LockPixrad("TransferStoredImages"); Info("Call TED_PixRad_TransferStoredImages"); error_status ErrorStatus = TED_PixRad_TransferStoredImages(strExportPath.c_str(),true, true, DT_USHORT_TYPE); if (!TestError(ErrorStatus)) { Error("Export Stored Image command failed"); } else { Info("Export Stored Image command OK"); //UnlockPixrad("TransferStoredImages"); } LockPixrad("TransferStoredImages"); UnlockPixrad("TransferStoredImages"); //3.恢复QUIET状态 if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); return false; } //4.将所有图保存为RAW图 for (int i = 0; i < m_vecStorageList.size(); ++i) { GetStoredImage(m_vecStorageList[i]); } //5.恢复QUIET状态 if (!SetSystemState(STATE_QUIET)) { Error("Set Quiet State Failed"); return false; } StatusFeedback(EVT_AUTONUMOUS_STATUS, PANEL_EXPORT_AUTONUMOUS_FINISH, "", 0); Info("Export Autonumous over"); return true; } /*** * 等待函数, 等待Event成功返回true,失败返回false ***/ bool TrixellCtrl::WaitRespond(int nTimeOut, string strAction) { Info("---WaitRespond({$})--- {$}", nTimeOut, strAction); DWORD dwResult = WaitForSingleObject(m_hRespondEvent, nTimeOut); if (dwResult == WAIT_TIMEOUT) //等待超时 { Error("Waited TimeOut"); ResetEvent(m_hRespondEvent); return false; } else if (dwResult == WAIT_OBJECT_0) { Info("Waited got Signal"); ResetEvent(m_hRespondEvent); } else { DWORD dwErrorCode = GetLastError(); Error("Waited Failed: {$}", dwErrorCode); ResetEvent(m_hRespondEvent); return false; } return true; } /*** * 解锁等待函数 ***/ bool TrixellCtrl::SendRespond(string strAction) { SetEvent(m_hRespondEvent); Info("---WaitRespond End--- {$}", strAction); return true; } /*** * 触发采集序列 ***/ bool TrixellCtrl::ApplicationAcquireSequence() { Info("ApplicationAcquireSequence start"); application_mode applicationMode = application_mode(m_nCurrentMode - 1); string strTemp = "unknown"; if (PIX_OM_AED == m_nCurrentOmMode) { strTemp = "aed"; } else if (PIX_OM_RAD == m_nCurrentOmMode) { strTemp = "rad"; } else if (PIX_OM_TOMO == m_nCurrentOmMode) { strTemp = "tomo"; } //LockPixrad("ApplicationAcquisition"); Info("Call ApplicationAcquisition(appmode:{$}, {$})", (int)applicationMode, strTemp.c_str()); error_status ErrorStatus = TED_PixRad_ApplicationAcquisition(applicationMode); //EVT_START_ACQUISITION if (!TestError(ErrorStatus)) { StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_END_ERROR); } //LockPixrad("ApplicationAcquisition"); //UnlockPixrad("ApplicationAcquisition"); Info("Application acquisition over"); m_nXwinOnIndex = 0; //开始采集,置为初值 m_nTomoImgIndex = 0; //开始采集,置为初值 m_nIgnoreImgNum = 0; //开始采集,置为初值 Info("ApplicationAcquireSequence over"); return true; }