#include "stdafx.h" #include #include #include //文件流库函数 #include #include "SensviewCtrl.h" #include "common_api.h" #include "MyPingip.h" extern Log4CPP::Logger* gLogger; #include #pragma comment(lib,"Shlwapi.lib") #pragma comment(lib, "Version.lib") const int nINIT_TIME = 50000; const int nCMD_TIME = 5000; SensviewCtrl* g_pSensviewCtrl = nullptr; SensviewCtrl::SensviewCtrl() : g_strAppPath("") , m_nPanelCount(0) , m_nDetectorID(1) , m_nDetectorIndex(0) , m_nCorrectionType(0) , m_hSDKModule(nullptr) , m_hInitThread(nullptr) , m_hExitEvent(nullptr) , m_hRecoverImage(nullptr) , m_hCofirmCalib(nullptr) , m_hEndCalibEvent(nullptr) , m_hScanEnd(nullptr) , m_hSharedEvent(nullptr) , m_hWindowOffEvent(nullptr) , m_pXWindowoffThread(nullptr) , m_hScanEventThread(nullptr) , m_nCurrentMode(-1) , m_strCurrentExamType("") , m_bSaveRaw(false) , m_pwPreviewImg(nullptr) , m_pwRawImageData(nullptr) , m_nFrameID(0) , m_nExiThreshold(0) , m_bOffsetAll(false) , m_bGrabStatus(false) , m_fFrameRate(0.0f) { m_pDPC2PanelID = new map(); m_pPanelID2DPC = new map(); //m_pImageBuffer = NULL; m_strWorkPath = ""; m_eAppStatus = APP_STATUS_IDLE; m_nImageWidth = 0; m_nImageHeight = 0; m_nRawImgWidth = 0; m_nRawImgHeight = 0; m_nWidthOffset = 0; m_nHeightOffset = 0; m_nImgBits = 16; m_nPixelPitch = 150; m_bPreviewEnable = false; m_nPreviewWidth = 0; m_nPreviewHeight = 0; m_eCaliType = CCOS_CALIBRATION_TYPE_NONE; m_nDoseParam = 0; m_fCurrentDose = 0; m_nCaliFailedCount = 0; m_bGainPreparing = false; m_bGainProcess = false; m_bConfirmCaliRst = false; m_bPreviewImg = false; //m_nGainNodeCount = 0; //m_nGainNodeIndex = 0; //m_nGainExpCount = 0; //m_nGainExpIndex = 0; m_bIsImageRecovering = false; m_bInCalibrating = false; m_pHardwareStatusThread = NULL; m_bInExposure = false; m_nRecoverImageTimes = 0; for (int i = 0; i < SENSVIEW_SCAN_NUM; i++) { m_hArrayEvent[i] = nullptr; } m_bSetCorrectFile = false; m_mapLogicModeOperationMode.clear(); } SensviewCtrl::~SensviewCtrl() { OnEXIT(); delete m_pDPC2PanelID; m_pDPC2PanelID = NULL; delete m_pPanelID2DPC; m_pPanelID2DPC = NULL; m_mapLogicModeOperationMode.clear(); } bool SensviewCtrl::OnEXIT() { /*SetEvent(m_hEndHWStatusThreadEvent); Info("Waiting HWStatus Thread End"); int nResult = WaitForSingleObject(m_hHWStatusThreadEndEvent, 10000); if (WAIT_TIMEOUT == nResult) { Error("HWStatus Thread Quit Failed"); } else { Info("HWStatus Thread Quit Success"); }*/ for (int nDetectorID = 0; nDetectorID < m_nPanelCount; nDetectorID++) { DisconnectFD(nDetectorID); } SetEvent(m_hExitEvent); Info("Waiting detector ScanEvent Thread End"); if (WAIT_TIMEOUT == WaitForSingleObject(m_hScanEnd, 2000)) { Error("Detector ScanEvent Thread Quit Failed"); } else { Info("Detector ScanEvent Thread Quit Success"); } DeleteHandle(); Info("Free SDK DLL"); FreeSDKDLL(); return true; } void SensviewCtrl::DeleteHandle() { if (m_hSharedEvent) { CloseHandle(m_hSharedEvent); m_hSharedEvent = nullptr; } if (m_hExitEvent) { CloseHandle(m_hExitEvent); m_hExitEvent = nullptr; } if (m_hRecoverImage) { CloseHandle(m_hRecoverImage); m_hRecoverImage = nullptr; } if (m_hCofirmCalib) { CloseHandle(m_hCofirmCalib); m_hCofirmCalib = nullptr; } if (m_hEndCalibEvent) { CloseHandle(m_hEndCalibEvent); m_hEndCalibEvent = nullptr; } if (m_hScanEnd) { CloseHandle(m_hScanEnd); m_hScanEnd = nullptr; } if (m_hHWStatusThreadEndEvent) { CloseHandle(m_hHWStatusThreadEndEvent); m_hHWStatusThreadEndEvent = NULL; } if (m_pwPreviewImg) { delete[] m_pwPreviewImg; m_pwPreviewImg = NULL; } if (m_pwRawImageData) { delete[] m_pwRawImageData; m_pwRawImageData = NULL; } } //SDK回调函数 void SensviewCtrl::ProcessEventCallback(void* lpCallbackData, NV_EVENTTYPE eventID, void* lpEventData) { if (nullptr == lpCallbackData) { return; } SensviewCtrl * pCurrentCtrl = (SensviewCtrl *)lpCallbackData; Info("EventID: {$}", (int)eventID); switch (eventID) { case NV_EVENTTYPE_ACQ: { if (!pCurrentCtrl->m_bGrabStatus) { Warn("Invalid image, omit"); return; } if (nullptr == lpEventData) { Warn("Invalid buffer, omit"); return; } NV_ImageInfo* pImageInfo = (NV_ImageInfo*)lpEventData; int nRawImgHeight = pImageInfo->iSizeX; int nRawImgWidth = pImageInfo->iSizeY; Info("Image Height: {$}, Width: {$}", nRawImgHeight, nRawImgWidth); memcpy(pCurrentCtrl->m_pwRawImageData, pImageInfo->pImageBuffer, nRawImgHeight * nRawImgWidth * sizeof(WORD)); pCurrentCtrl->OnProcessImg(); } break; case NV_EVENTTYPE_MAXFRAME: break; case NV_EVENTTYPE_OFFSETCALFINISH: { Info("NV_EVENTTYPE_OFFSETCALFINISH"); pCurrentCtrl->SendNotify(); } break; case NV_EVENTTYPE_GAINCALFINISH: break; case NV_EVENTTYPE_DEFECTCALFINISH: break; case NV_EVENTTYPE_OPENXRAY: break; case NV_EVENTTYPE_CLOSEXRAY: break; case NV_EVENTTYPE_TEMPERATURE: { NV_EVENTDATA_TEMPERATURE* pTemperatureInfo = (NV_EVENTDATA_TEMPERATURE*)lpEventData; pCurrentCtrl->StatusFeedback(EVT_STATUS_TEMPERATURE, 0, "", 1, pTemperatureInfo->temperature1); } break; case NV_EVENTTYPE_SYSTEMSTATUS: break; case NV_EVENTTYPE_CONNBREAK: break; case NV_EVENTTYPE_AUTOOFFSETCAL: { Info("NV_EVENTTYPE_AUTOOFFSETCAL"); pCurrentCtrl->SendNotify(); } break; case NV_EVENTTYPE_CALACQ: break; default: break; } } //等到SDK回调返回true, 超时返回false bool SensviewCtrl::WaitRespond(int nTimeOut) { Info("---WaitRespond---:{$}", nTimeOut); DWORD nResult = WaitForSingleObject(m_hSharedEvent, nTimeOut); if (WAIT_TIMEOUT == nResult) //偶尔会出现EVT_HARDWARE太慢的情况 { Warn("Lock TimeOut");//出现超时,肯定是有问题了 ResetEvent(m_hSharedEvent); return false; } ResetEvent(m_hSharedEvent); return true; } void SensviewCtrl::SendNotify() { Info("---SendNotify---"); SetEvent(m_hSharedEvent); } void SensviewCtrl::ResetLock() { ResetEvent(m_hSharedEvent); } void SensviewCtrl::Pausetime(DWORD dwSpan) { DWORD dtstart = ::GetTickCount(); while ((::GetTickCount() - dtstart) < dwSpan) { MSG msg; while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } } } bool SensviewCtrl::Init(string strAppPath) { g_strAppPath = strAppPath; /*m_strWorkPath = strAppPath + (string)m_ModeConfig["SDKPath"]; Info("SensviewCtrl::Init {$}\n", m_strWorkPath.c_str()); if (!LoadSDKDLL(m_strWorkPath)) { Error("SensviewCtrl::Init LoadSDKDLL failed\n"); return false; }*/ m_hSharedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hWindowOffEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hHWStatusThreadEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL); Info("SensviewCtrl::Init over\n"); return true; } //启动初始化线程 void SensviewCtrl::StartInitFPDThread() { if (m_hInitThread) { Warn("Init thread already exsit, omit"); return; } Info("Start Init Thread"); DWORD unThreadID = 0; m_hInitThread = CreateThread(0, 0, onInitPanel, this, 0, &unThreadID); if (m_hInitThread == nullptr) { Fatal("Start Init Thread Error"); } return; } //初始化 DWORD SensviewCtrl::onInitPanel(void* pParam) { SensviewCtrl* pInstance = (SensviewCtrl*)pParam; pInstance->Action_Init(); pInstance->m_hInitThread = nullptr; return true; } void SensviewCtrl::Action_Init() { Info("SensviewCtrl::Action_Init"); m_bInitialing = true; int nDetectorID = 1; Info("Start Register Detector: {$}", nDetectorID); NV_StatusType nRet = NV_SetEventCallback(SensviewCtrl::ProcessEventCallback, this); if (TestError(nDetectorID, nRet)) { Error("Register Detector {$} Callback Failed", nDetectorID); } Info("Register Detector {$} Callback Success", nDetectorID); if (!DetectorInitProcess(nDetectorID)) { Error("Init process failed"); } ScanEventThread(); //StartHardwareStatusThread(); //走探测器回调不用主动查询啦 m_bInitialing = false; Info("Action init over\n"); } //初始化连接探测器 bool SensviewCtrl::DetectorInitProcess(int nDetectorID, bool bFetchCalibration) { OnInitStatus(nDetectorID, PANEL_EVENT_START); int nDetectorIndex = nDetectorID - 1; //枚举网络链路上的设备 NV_DET arrDet[8]; int nDetectorCount = 0; NV_StatusType nRet = NV_EnumDets(arrDet, 8, &nDetectorCount); if (TestError(nDetectorID, nRet)) { Error("Discover detector failed"); return false; } if (nDetectorCount <= 0) { Warn("No any detector in descovery"); return false; } m_stDeviceIndex[nDetectorIndex].bExisted = true; Info("Discover detector number: {$}", nDetectorCount); for (int i = 0; i < nDetectorCount; i++) { Info("DetectorID: {$}, ManufactureName: {$}, ModelName: {$}, DeviceVersion: {$}, SerialNumber: {$}", arrDet[i]._uDetID, arrDet[i].ManufactureName, arrDet[i].ModelName, arrDet[i].DeviceVersion, arrDet[i].SerialNumber); } Info("Call Connect detector1"); nRet = NV_OpenDet(arrDet[0]._uDetID); if (TestError(nDetectorID, nRet)) { Error("Connect Detector {$} Failed", nDetectorID); m_stDeviceIndex[nDetectorIndex].bConnectStatus = false; return false; } m_stDeviceIndex[nDetectorIndex].bConnectStatus = true; Info("Connect Detector {$} Success", nDetectorID); ListDetectorInfo(nDetectorID); //设置帧类型 nRet = NV_SetFrameType(MTU_4KB); if (TestError(nDetectorID, nRet)) { Error("Set detector frametype MTU_4KB failed"); return false; } Info("Set detector frametype MTU_4KB"); //获取探测器像素尺寸 int nWidth = 0; int nHeight = 0; int nBit = 0; nRet = NV_GetSensorSize(&nWidth, &nHeight, &nBit); if (TestError(nDetectorID, nRet)) { Error("Get detector size failed"); return false; } Info("Get detector size: width({$}), height({$}), bit({$})", nWidth, nHeight, nBit); if (bFetchCalibration) //特殊需求,同步校正文件//正常初始化,不同步校正文件 { DownloadfromDetector(nDetectorID); } //暗场的模式组成map SetOffsetModeScope(); //加载校正 //SetDetectorCorrection(nDetectorID, m_nCorrectionType); //获取探测器支持的触发模式 ListDetectorTriggerMode(nDetectorID); //列出探测器支持的Binning模式 ListDetectorBinningMode(nDetectorID); //列出探测器支持的增益档位 ListDetectorGainMode(nDetectorID); m_stDeviceIndex[nDetectorIndex].bInitOK = true; OnInitStatus(nDetectorID, PANEL_EVENT_END_OK); return true; } //重连接 bool SensviewCtrl::RetryConnect(int nDetectorID) { Info("RetryConnect start"); return false; } bool SensviewCtrl::OnInitStatus(int nPanelIndex, ENUM_PANEL_EVENT_STATE ePanelState) { int nDetectorID = 0; if (PANEL_EVENT_START == ePanelState) { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_START, ""); } else if (PANEL_EVENT_END_OK == ePanelState) { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_OK, ""); } else if (PANEL_EVENT_END_ERROR == ePanelState) { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_ERROR, ""); } else if (PANEL_EVENT_END == ePanelState) //未连接探测器 { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END, ""); }//end if return true; } //辅助线程句柄 void SensviewCtrl::ScanAddHandle() { m_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hRecoverImage = CreateEvent(NULL, FALSE, FALSE, NULL); m_hCofirmCalib = CreateEvent(NULL, FALSE, FALSE, NULL); m_hEndCalibEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hOffsetEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hArrayEvent[0] = m_hExitEvent; m_hArrayEvent[1] = m_hRecoverImage; m_hArrayEvent[2] = m_hCofirmCalib; m_hArrayEvent[3] = m_hEndCalibEvent; m_hArrayEvent[4] = m_hOffsetEvent; m_hScanEnd = CreateEvent(NULL, FALSE, FALSE, NULL); return; } /************************************************************************************ 功能:启动线程,处理一些异步消息 ************************************************************************************/ void SensviewCtrl::ScanEventThread() { if (m_hScanEventThread) { Info("ScanEvent Thread already run\n"); return; } Info("Start ScanEvent Thread"); ScanAddHandle(); DWORD unThreadID; m_hScanEventThread = (HANDLE)CreateThread(NULL, 0, onScanEvent, (LPVOID)this, 0, &unThreadID); if (m_hScanEventThread == NULL) { Fatal("Start Scan Event Error"); } else { Info("Start ScanEvent Thread ok"); } //endif } /************************************************************************************ 功能:启动线程,处理一些异步消息 m_hRecoverImage 异步,恢复图像 m_hCofirmCalib 异步,确认每一次校正的结果,如剂量大了/小了/ m_hReconnectFD 异步,初始化探测器 ************************************************************************************/ DWORD SensviewCtrl::onScanEvent(void* pParam) { SensviewCtrl* pInstance = (SensviewCtrl*)pParam; if (pInstance == NULL) { return false; } bool bExitFlag = true; while (bExitFlag) { Info("( Waiting for Signal...)"); DWORD dwResult = WaitForMultipleObjects(SENSVIEW_SCAN_NUM, pInstance->m_hArrayEvent, FALSE, INFINITE); if (WAIT_OBJECT_0 == dwResult) //m_hExitEvent { Info("Get Exit Event"); bExitFlag = false; } else if (WAIT_OBJECT_0 + 1 == dwResult) //m_hRecoverImage { if (pInstance->m_nRecoverImageTimes < 2) { Info("Get RecoverImage Event"); pInstance->RecoverLastImageAuto(); } else { Info("Get RecoverImage Event already, omit it"); pInstance->ErrorFeedback(EVT_ERR_GET_IMAGE, "true"); } } else if (WAIT_OBJECT_0 + 2 == dwResult) //m_hCofirmCalib { Info("Get Cofirm Calibration Event"); pInstance->ConfirmCalibration(); } else if (WAIT_OBJECT_0 + 3 == dwResult) //m_hEndCalibEvent { Info("Get EndCalibraion Event"); pInstance->OnEndCalibraion(); } else if (WAIT_OBJECT_0 + 4 == dwResult) //m_hOffsetEvent { Info("Get Offset Event"); pInstance->OffsetCalibration(); } } SetEvent(pInstance->m_hScanEnd); Info("Sensview ScanEvent Thread End"); return true; } bool SensviewCtrl::SetAppMode(int nDetectorID, int nMode) { Info("Set detector({$}) work mode: {$}", nDetectorID, nMode); return true; } //接口成功返回false,接口失败或有错返回true bool SensviewCtrl::TestError(int nDetectorID, int nErrorStatus) { string strLog = ""; switch (nErrorStatus) { case NV_SC_SUCCESS: return false; case NV_SC_ERROR: Fatal("Generic error"); break; case NV_SC_ERR_NOT_INITIALIZED: Fatal("Detector not Initialized"); break; case NV_SC_ERR_NOT_IMPLEMENTED: Error("Function not implemented"); break; case NV_SC_ERR_RESOURCE_IN_USE: Error("Resource in use"); break; case NV_SC_ACCESS_DENIED: Error("Access denied"); break; case NV_SC_INVALID_HANDLE: Error("invalid handle"); break; case NV_SC_INVALID_ID: Error("invalid ID"); break; case NV_SC_NO_DATA: Error("no data"); break; case NV_SC_INVALID_PARAMETER: Error("invalid parameter"); break; case NV_SC_FILE_IO: Error("file IO error"); break; case NV_SC_TIMEOUT: Error("timeout error"); break; case NV_SC_ERR_ABORT: Error("abort error"); break; case NV_SC_INVALID_BUFFER_SIZE: Error("invalid buffer size error"); break; default: Error("Undefined error"); break; } return true; } bool SensviewCtrl::LoadSDKDLL(string strWorkPath) { string strDllDir = strWorkPath; if (SetDllDirectory(strDllDir.c_str()) == 0) { DWORD dw = GetLastError(); Info("SetDllDirectory error,error code [{$}]", dw); return false; } string strDllPath = strWorkPath + "\\nvDentalDet.dll"; Info("Load nvDentalDet.dll"); m_hSDKModule = LoadLibrary(strDllPath.c_str()); if (NULL == m_hSDKModule) { Fatal("Load nvDentalDet.dll failed!"); return false; } /*m_fpCreate = (FnCreate)GetProcAddress(m_hSDKModule, IRAY_FPD_PROC_NAME_CREATE); if (NULL == m_fpCreate) { Fatal("GetProcAddress:Create failed!"); return false; }*/ return true; } void SensviewCtrl::FreeSDKDLL() { if (m_hSDKModule) { FreeLibrary(m_hSDKModule); m_hSDKModule = NULL; Info("Free SDK DLL"); } } bool SensviewCtrl::AddDPCs(nsDPC::FPDDeviceSensview* pDrvDPC, ResDataObject& Configuration, DeviceIndexStruct& DeviceStruct) { map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { Warn("SensviewCtrl::AddDPCs This DPC already exist\n"); return false; } Info("--Func-- AddDPCs {$}", pDrvDPC); m_pCurrentDPC = pDrvDPC; //拿到当前探测器的配置 m_stDeviceIndex[m_nPanelCount] = DeviceStruct; m_ObjFPDsInfo[m_nPanelCount] = Configuration; Info("AddDPCs, {$} {$} ", m_stDeviceIndex[m_nPanelCount].strDetectorModel, m_stDeviceIndex[m_nPanelCount].strDeviceName); m_pDPC2PanelID->insert(pair(pDrvDPC, m_nPanelCount)); m_pPanelID2DPC->insert(pair(m_nPanelCount, pDrvDPC)); m_ModeConfig = Configuration; m_bPreviewImg = m_stDeviceIndex[m_nDetectorIndex].bPreviewEnable; m_nCorrectionType = m_stDeviceIndex[m_nDetectorIndex].AcqModeInfo.nCorrectionType; m_nPanelCount++; Info("SensviewCtrl::AddDPCs ok {$}\n", m_nPanelCount); return true; } bool SensviewCtrl::DelDPCs(nsDPC::FPDDeviceSensview* 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); } m_stDeviceIndex[DPCsIter->second] = {}; m_ObjFPDsInfo[DPCsIter->second].clear(); m_pDPC2PanelID->erase(DPCsIter); m_nPanelCount--; Info("SensviewCtrl::DelDPCs ok {$}\n", m_nPanelCount); } return true; } void SensviewCtrl::ConfFeedback(int nEventID, int nDetectorID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nDetectorIndex; } ((*m_pPanelID2DPC)[m_nDetectorIndex])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_CONFIGURATION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void SensviewCtrl::InfoFeedback(int nEventID, int nDetectorID, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nDetectorIndex; } ((*m_pPanelID2DPC)[m_nDetectorIndex])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_INFORMATOION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void SensviewCtrl::StatusFeedback(int nEventID, int nParam1, const char* pszMsg, int nDetectorID, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nDetectorIndex; } ((*m_pPanelID2DPC)[m_nDetectorIndex])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_STATUS, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void SensviewCtrl::DataFeedback(int nEventID, void* pParam, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nDetectorIndex; } ((*m_pPanelID2DPC)[m_nDetectorIndex])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_DATA, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void SensviewCtrl::WarnFeedback(int nEventID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nDetectorIndex; } ((*m_pPanelID2DPC)[m_nDetectorIndex])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_WARNING, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void SensviewCtrl::ErrorFeedback(int nEventID, const char* pszMsg, int nDetectorID, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nDetectorIndex; } ((*m_pPanelID2DPC)[m_nDetectorIndex])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_ERROR, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } /********************************************************************/ /* 将文件删除 /********************************************************************/ bool SensviewCtrl::DeleteOneFolder(string strSourceFolder) { Info("Delete {$}", strSourceFolder.c_str()); if (!PathFileExists(strSourceFolder.c_str())) { Info("SourceFolder don't exist"); return false; } char pFolderSource[MAX_PATH] = { 0 }; memset(pFolderSource, 0x00, MAX_PATH); strcpy(pFolderSource, strSourceFolder.c_str()); //第一个文件 SHFILEOPSTRUCT sfo; memset(&sfo, 0, sizeof(SHFILEOPSTRUCT)); sfo.hwnd = NULL; sfo.wFunc = FO_DELETE;//FO_MOVE; sfo.pFrom = pFolderSource; sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION;// | FOF_ALLOWUNDO; //| FOF_NOCONFIRMMKDIR; // FOF_ALLOWUNDO:保存UNDO信息,以便在回收站中恢复文件; //FOF_NOCONFIRMATION:在出现目标文件已存在的时候,如果不设置此项,则它会出现确认是否覆盖的对话框,设置此项则自动确认,进行覆盖,不出现对话框。 SHFileOperation(&sfo); Info("Delete File over"); return true; } //将strSrcPath文件拷贝到strDstPath目录 bool SensviewCtrl::CopyFile2Folder(string strSrcPath, string strDstPath) { //MSDN: This string must be double-null terminated strSrcPath += '\0'; strDstPath += '\0'; //上面两行代码非常重要,直接影响下面SHFileOperation的稳定性 Info("Copy {$} to {$}", strSrcPath.c_str(), strDstPath.c_str()); if (!PathFileExists(strSrcPath.c_str())) { Info("SourceFolder don't exist"); return false; } if (!PathFileExists(strDstPath.c_str())) { Info("DestFolder don't exist"); return false; } 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 SensviewCtrl::SwithPanel(int nPanelId) { return true; } bool SensviewCtrl::ActivePanel(nsDPC::FPDDeviceSensview* pDrvDPC, bool bActive) { Info("ActivePanel start: {$}, DetectorIndex {$}", pDrvDPC, m_nDetectorIndex); map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { if (m_nDetectorIndex != DPCsIter->second) { Info("DetectorIndex {$} != DPCsIter->second {$}", m_nDetectorIndex, DPCsIter->second); if (!SwithPanel(DPCsIter->second)) { return false; } m_nDetectorIndex = DPCsIter->second; m_pCurrentDPC = pDrvDPC; m_nCurrentMode = -1; m_ModeConfig.clear(); m_ModeConfig = m_ObjFPDsInfo[m_nDetectorIndex]; m_bPreviewImg = m_stDeviceIndex[m_nDetectorIndex].bPreviewEnable; Info("ActivePanel over: {$}, m_nDetectorIndex {$}", pDrvDPC, m_nDetectorIndex); for (int i = 0; i < m_nPanelCount; i++) { ((nsDPC::FPDDeviceSensview*)(*m_pPanelID2DPC)[i])->UnactiveBySDK(pDrvDPC); } } else { Info("DetectorIndex {$} == DPCsIter->second {$}", m_nDetectorIndex, DPCsIter->second); } } else { Warn("Not find DPC in group"); return false; } return true; } bool SensviewCtrl::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: m_bInCalibrating = true; strLog = "APP_STATUS_CAL_BEGIN"; break; case APP_STATUS_CAL_END: m_bInCalibrating = false; strLog = "APP_STATUS_CAL_END"; break; default: break; } Info("Enter exam: {$}", strLog.c_str()); m_eAppStatus = eStatus; return true; } /*** ** 说明:连接 ** 加载SDK,初始化SDK,连接探测器等初始化操作 ** 参数:strWorkPath,初始化SDK必须的conf路径 ***/ bool SensviewCtrl::Connect(string strAppPath, nsDPC::FPDDeviceSensview* pDrvDPC) { Info("--Func-- Connect"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC, return true"); return true; } StartInitFPDThread(); Info("=== Connect detector OK ==="); return true; } void SensviewCtrl::DisconnectFD(int nDetectorID) { Info("DisconnectFD({$})", nDetectorID); if (m_bGrabStatus) { StopAcquisition(nullptr); } NV_StatusType nRet = NV_CloseDet(); if (TestError(nDetectorID, nRet)) { Fatal("NV_CloseDet Failed"); } Info("disconnect over"); } /*** ** 说明:退出 ** 释放SDK ***/ bool SensviewCtrl::DisConnect(nsDPC::FPDDeviceSensview* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC, return"); return true; } Info("--Func-- DisConnect"); DisconnectFD(m_nDetectorID); Info("DisConnect Over"); return true; } /********************************************************************/ /* 功能:没有曝光窗口关闭的消息,启动线程,等待500ms曝光窗口过后,模拟发送曝光窗口关闭的消息给HW层 /********************************************************************/ bool SensviewCtrl::StartXWindowOffThread() { if (m_pXWindowoffThread == NULL) { DWORD m_NotifyThreadID = 0; m_pXWindowoffThread = CreateThread(0, 0, XWindowOffThread, this, 0, &m_NotifyThreadID); if (m_pXWindowoffThread == NULL) { Fatal("Start Exp Thread Failed"); return false; } } return true; } /********************************************************************/ /* 功能:若探测器没有曝光窗口关闭的消息,启动线程,等待500ms曝光窗口过后,模拟发送曝光窗口关闭的消息给HW层 /********************************************************************/ DWORD SensviewCtrl::XWindowOffThread(LPVOID pParam) { SensviewCtrl* pCurPanel = (SensviewCtrl*)pParam; if (pCurPanel == NULL) { return false; } //DWORD dwTimer = pCurPanel->m_stDeviceIndex[pCurPanel->m_nDetectorIndex].AcqModeInfo.nXwindow; DWORD dwTimer = 10; DWORD dwResult = WaitForSingleObject(pCurPanel->m_hWindowOffEvent, dwTimer); Info("Simulate XWINDOW_OFF"); pCurPanel->StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF); pCurPanel->m_pXWindowoffThread = nullptr; return true; } RET_STATUS SensviewCtrl::SetSyncMode(SYNC_MODE nSyncMode, HARDWARE_TRIGGER_MODE TriggerMode) { return RET_STATUS::RET_SUCCEED; } bool SensviewCtrl::SetAcqMode(nsDPC::FPDDeviceSensview* pDrvDPC, int nLogicMode, DetModeInfo& AcqModeInfo) { Info("## SetAcqMode ##({$})", nLogicMode); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC {$}, {$} != {$} ,return", pDrvDPC, (*m_pDPC2PanelID)[pDrvDPC], m_nDetectorIndex); return false; } if (m_bGrabStatus) { StopAcquisition(nullptr); } m_nCurrentMode = nLogicMode; m_strCurrentExamType = AcqModeInfo.strExamType; m_nRawImgWidth = AcqModeInfo.nRawImgWidth; m_nRawImgHeight = AcqModeInfo.nRawImgHeight; m_nImageWidth = AcqModeInfo.nImageWidth; m_nImageHeight = AcqModeInfo.nImageHeight; m_nImgBits = AcqModeInfo.nPhySizeInfoBit; m_nPixelPitch = AcqModeInfo.nPixelPitch; m_bSaveRaw = AcqModeInfo.bSaveRawEnable; m_nCorrectionType = AcqModeInfo.nCorrectionType; m_nExiThreshold = AcqModeInfo.nExiThreshold; Info("RawImage({$}*{$}), Bits({$}), CorrectionType: {$}; SaveRaw({$})", m_nRawImgWidth, m_nRawImgHeight, m_nImgBits, m_nCorrectionType, m_bSaveRaw); if (m_pwRawImageData) { delete[] m_pwRawImageData; m_pwRawImageData = nullptr; } m_pwRawImageData = new WORD[m_nRawImgWidth * m_nRawImgHeight]; if (m_pwRawImageData == nullptr) { Fatal("Allocate Raw Image Failed"); return false; } //设置触发方式 if (!SetDetectorFluSync(m_nDetectorID, AcqModeInfo.nTriggerType)) { return false; } //设置Binning模式 if (!SetDetectorBinningMode(m_nDetectorID, AcqModeInfo.nBinningMode)) { return false; } //设置Gain档位 if (!SetDetectorGainMode(m_nDetectorID, AcqModeInfo.nGainValue)) { return false; } //设置帧率(点片单独设置帧率,透视上层下发帧率) if (AcqModeInfo.strExamType.find("RAD") != std::string::npos) { if (!SetFluPPS(AcqModeInfo.nFrequency * 1.0f)) { return false; } } //加载校正 SetDetectorCorrection(m_nDetectorID, AcqModeInfo.nCorrectionType); Info("Set mode over"); return true; } /*** ** 说明:曝光前的准备流程 ***/ RET_STATUS SensviewCtrl::PrepareAcquisition(nsDPC::FPDDeviceSensview* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC, return"); return RET_STATUS::RET_FAILED; } if (m_stDeviceIndex[m_nDetectorIndex].bConnectStatus == false) { Info("Current detector is not connect, return"); return RET_STATUS::RET_FAILED; } return RET_STATUS::RET_FAILED; } RET_STATUS SensviewCtrl::StartAcquisition(nsDPC::FPDDeviceSensview* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC, return"); return RET_STATUS::RET_FAILED; } RET_STATUS Ret = RET_STATUS::RET_FAILED; StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_START); NV_StatusType nRet = NV_StartAcq(); if (TestError(m_nDetectorID, nRet)) { Fatal("NV_StartAcq Failed"); return Ret; } m_bInExposure = true; m_bGrabStatus = true; m_nFrameID = 0; StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_END_OK); return RET_STATUS::RET_SUCCEED; } RET_STATUS SensviewCtrl::StopAcquisition(nsDPC::FPDDeviceSensview* pDrvDPC) { Info("**StopAcquisition**"); RET_STATUS Ret = RET_STATUS::RET_FAILED; NV_StatusType nRet = NV_StopAcq(); if (TestError(m_nDetectorID, nRet)) { Fatal("NV_StopAcq Failed"); return Ret; } Info("Stop Acq Success"); m_bInExposure = false; m_bGrabStatus = false; Ret = RET_STATUS::RET_SUCCEED; return Ret; } bool SensviewCtrl::InitCalibration() { DataFeedback(EVT_DATA_DOSEPARAM, NULL, m_nDoseParam); return true; } /*** ** 说明:激活校正 ** 增益校正(探测器采用post-offset,暗场校正基本没用了)时拿到dose回调,算作执行完毕 ***/ RET_STATUS SensviewCtrl::ActiveCalibration(CCOS_CALIBRATION_TYPE Type, nsDPC::FPDDeviceSensview* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC, return"); return RET_STATUS::RET_FAILED; } RET_STATUS Ret = RET_STATUS::RET_SUCCEED; if (CCOS_CALIBRATION_TYPE_DARK == Type) { Info("ActiveDarkCalibration"); } else if (CCOS_CALIBRATION_TYPE_XRAY == Type) { Info("ActiveXrayCalibration"); StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_START); if (!InitCalibration()) { StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_ERROR); return RET_STATUS::RET_FAILED; } } else { Error("Active not supported calibration({$}), return! \n", (int)Type); Ret = RET_STATUS::RET_NOSUPPORT; return Ret; } m_eCaliType = Type; return Ret; } /*** ** 说明:开始校正(状态机FrameStart) ** Salmon项目只有普通rad模式,所以本接口基本没用 ***/ RET_STATUS SensviewCtrl::StartCalibration(nsDPC::FPDDeviceSensview* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC, return"); return RET_STATUS::RET_FAILED; } RET_STATUS Ret = RET_STATUS::RET_FAILED; if (CCOS_CALIBRATION_TYPE_DARK == m_eCaliType) { Info("StartDarkCalibration \n"); //SetEvent(m_hOffsetEvent); Ret = RET_STATUS::RET_SUCCEED; } else { Info("StartXrayCalibration \n"); Ret = RET_STATUS::RET_SUCCEED; } return Ret; } bool SensviewCtrl::ConfirmCalibration() { return true; } bool SensviewCtrl::AcceptCalibration() { Info("Accept Calibration"); return true; } bool SensviewCtrl::RejectCalibration() { Info("Reject Calibration"); return true; } /*** ** 说明:终止校正 ***/ RET_STATUS SensviewCtrl::AbortCalibration(nsDPC::FPDDeviceSensview* pDrvDPC) { return RET_STATUS::RET_SUCCEED; } /*** ** 说明:准备校正(状态机FramePrep) ** 曝光使能过程,使探测器开窗 ***/ RET_STATUS SensviewCtrl::PrepareCalibration(nsDPC::FPDDeviceSensview* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC, return"); return RET_STATUS::RET_FAILED; } Debug("PrepareCalibration Over"); return RET_STATUS::RET_SUCCEED; } /*** ** 说明:结束校正 ** DPC处理完校正报告后调用,此处上传map、报告等文件 ***/ RET_STATUS SensviewCtrl::CompleteCalibration(nsDPC::FPDDeviceSensview* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC, return"); return RET_STATUS::RET_FAILED; } SetEvent(m_hEndCalibEvent); Info("CompleteCalibration"); return RET_STATUS::RET_SUCCEED; } void SensviewCtrl::OnEndCalibraion() { Info("OnEndCalibraion start"); Info("Calibration completed!"); return; } bool SensviewCtrl::RecoverLastImage() { Info("Recover Last Image"); return RecoverImage(); } bool SensviewCtrl::RecoverLastImageAuto() { Info("Recover Last Image Auto"); return true; } bool SensviewCtrl::FlipX(WORD* pData, int nWidth, int nHeight) { int j = 0; int i = 0; Info("Flip Image Width:{$},Height:{$}", nWidth, nHeight); WORD temp; //修改翻转的判断,之前的代码会导致中央区域多翻转一个像素 for (i = 0; i < nHeight; i++) { for (j = 0; j < nWidth / 2; j++) { temp = pData[i * nWidth + j]; pData[i * nWidth + j] = pData[(i + 1) * nWidth - j - 1]; pData[(i + 1) * nWidth - j - 1] = temp; } } Info("Flip Image Over"); return true; } bool SensviewCtrl::FlipXRotate90(WORD* pData, int nWidth, int nHeight) { Info("Rotate 270 angle"); WORD* ptempData = new WORD[nWidth * nHeight]; memcpy(ptempData, pData, nWidth * nHeight * sizeof(WORD)); for (int i = 0; i < nWidth; i++) for (int j = 0; j < nHeight; j++) pData[i * nWidth + j] = ptempData[j * nWidth + (nWidth - 1 - i)]; delete[]ptempData; ptempData = NULL; FlipX(pData, nWidth, nHeight); return true; } //读取电池 bool SensviewCtrl::ReadBatteryStatus(int nDetectorID) { if (!m_stDeviceIndex[m_nDetectorIndex].bBatteryEnable) { return false; } Debug("Read Battery Success"); return true; } bool SensviewCtrl::CheckBattery(int nDetectorID) { return true; } bool SensviewCtrl::ReadWifiStatus(int nDetectorID) { if (!m_stDeviceIndex[m_nDetectorIndex].bWifiEnable) { return false; } Debug("Read Wifi"); Warn("Read Wifi Timeout"); return false; } bool SensviewCtrl::CheckWiFi(int nDetectorID) { return true; } //读取探测器温度 bool SensviewCtrl::ReadTempStatus(int nDetectorID) { Debug("Read Temperture"); Debug("Read Temperture Success"); return true; } bool SensviewCtrl::CheckTemperature(int nDetectorID) { return true; } //清空板内校正的校正选项,否则写入参数可能会失败 bool SensviewCtrl::ClearCorrection(int nDetectorID) { Info("Clear Correction Option"); return true; } //设置探测器校正 bool SensviewCtrl::SetDetectorCorrection(int nDetectorID, int nCorrectionType) { Info("Set Detector({$}) correction: {$}", nDetectorID, nCorrectionType); NV_StatusType nRet = NV_SC_SUCCESS; std::string strOffsetType = ""; if (nCorrectionType & CORRECT_OFFSET) { /*string strOffsetFile = m_stDeviceIndex[m_nDetectorIndex].strFPDConfFilePath + "\\1.offset"; Debug("Offset file path: {$}", strOffsetFile); std::ifstream inputFile(strOffsetFile.c_str(), std::ios::binary); if (!inputFile) { Error("Load file failed!"); return false; } inputFile.seekg(0, std::ios::end); int fileSize = inputFile.tellg(); inputFile.seekg(0, std::ios::beg); char* pTemplateData = new char[fileSize]; inputFile.read(pTemplateData, fileSize); Info("Load over, file size: {$}", fileSize); nRet = NV_LoadOffsetTemplateData(pTemplateData, fileSize); if (TestError(nDetectorID, nRet)) { Warn("NV_LoadOffsetTemplateData Failed"); return false; } inputFile.close();*/ /*nRet = NV_LoadLocalOffsetTemplate(); if (TestError(nDetectorID, nRet)) { Warn("NV_LoadLocalOffsetTemplate Failed"); return false; }*/ //校正使能 strOffsetType = "Offset"; nRet = NV_SetOffsetCal(NV_CORR_ON); if (TestError(nDetectorID, nRet)) { Warn("NV_SetOffsetCal Failed"); return false; } } else { strOffsetType = "No-Offset"; nRet = NV_SetOffsetCal(NV_CORR_OFF); if (TestError(nDetectorID, nRet)) { Warn("NV_SetOffsetCal Failed"); return false; } } std::string strGainType = ""; if (nCorrectionType & CORRECT_GAIN) { /*string strGainFile = m_stDeviceIndex[m_nDetectorIndex].strFPDConfFilePath + "\\2.gain"; Debug("Offset file path: {$}", strGainFile); std::ifstream inputFile(strGainFile.c_str(), std::ios::binary); if (!inputFile) { Error("Load file failed!"); return false; } inputFile.seekg(0, std::ios::end); int fileSize = inputFile.tellg(); inputFile.seekg(0, std::ios::beg); char* pTemplateData = new char[fileSize]; inputFile.read(pTemplateData, fileSize); Info("Load over, file size: {$}", fileSize); nRet = NV_LoadGainTemplateData(pTemplateData, fileSize); if (TestError(nDetectorID, nRet)) { Warn("NV_LoadGainTemplateData Failed"); return false; } inputFile.close();*/ /*nRet = NV_LoadLocalGainTemplate(); if (TestError(nDetectorID, nRet)) { Warn("NV_LoadLocalGainTemplate Failed"); return false; }*/ strGainType = " + Gain"; nRet = NV_SetGainCal(NV_CORR_ON); if (TestError(nDetectorID, nRet)) { Warn("NV_SetGainCal Failed"); return false; } } else { strGainType = " No-Gain"; nRet = NV_SetGainCal(NV_CORR_OFF); if (TestError(nDetectorID, nRet)) { Warn("NV_SetGainCal Failed"); return false; } } std::string strDefectType = ""; if (nCorrectionType & CORRECT_DEFECT) { strDefectType = " + Defect"; nRet = NV_SetDefectCal(NV_CORR_ON); if (TestError(nDetectorID, nRet)) { Warn("NV_SetDefectCal Failed"); return false; } } else { strGainType = " No-Defect"; nRet = NV_SetDefectCal(NV_CORR_OFF); if (TestError(nDetectorID, nRet)) { Warn("NV_SetDefectCal Failed"); return false; } } Info("Detector correction type: {$}", strOffsetType + strGainType + strDefectType); Info("SetDetectorCorrection Success"); return true; } //设置动态探测器内外触发方式 bool SensviewCtrl::SetDetectorFluSync(int nDetectorID, int nFluSync) { Info("Set detector({$}) trigger mode: {$}({$})", nDetectorID, DetTriggerMode[nFluSync], nFluSync); NV_StatusType nRet = NV_SetAcquisitionMode(NV_AcquisitionMode(nFluSync)); if (TestError(nDetectorID, nRet)) { Fatal("NV_SetAcquisitionMode Failed"); return false; } /*NV_AcquisitionMode aMode; NV_StatusType nRet = NV_GetAcquisitionMode(&aMode); if (TestError(nDetectorID, nRet)) { Fatal("NV_GetAcquisitionMode Failed"); return false; } if ((int)aMode != nFluSync) { nRet = NV_SetAcquisitionMode(NV_AcquisitionMode(nFluSync)); if (TestError(nDetectorID, nRet)) { Fatal("NV_SetAcquisitionMode Failed"); return false; } } else { Info("Same fluro sync mode, Omit"); }*/ return true; } //设置Binning模式 bool SensviewCtrl::SetDetectorBinningMode(int nDetectorID, int nBinningMode) { Info("Set detector({$}) binning mode: {$}({$})", nDetectorID, DetBinningMode[nBinningMode], nBinningMode); NV_StatusType nRet = NV_SetBinningMode(NV_BinningMode(nBinningMode)); if (TestError(nDetectorID, nRet)) { Fatal("NV_SetBinningMode Failed"); return false; } return true; /*NV_BinningMode bMode; NV_StatusType nRet = NV_GetBinningMode(&bMode); if (TestError(nDetectorID, nRet)) { Fatal("NV_GetBinningMode Failed"); return false; } if ((int)bMode != nBinningMode) { nRet = NV_SetBinningMode(NV_BinningMode(nBinningMode)); if (TestError(nDetectorID, nRet)) { Fatal("NV_SetBinningMode Failed"); return false; } } else { Info("Same binning mode, Omit"); } return true;*/ } //设置Gain模式 bool SensviewCtrl::SetDetectorGainMode(int nDetectorID, int nGainValue) { Info("Set detector({$}) gain level: {$}", nDetectorID, nGainValue); NV_StatusType nRet = NV_SetGainEx(nGainValue); if (TestError(nDetectorID, nRet)) { Fatal("NV_SetGainEx Failed"); return false; } return true; /*int nGainTemp = 0; NV_StatusType nRet = NV_GetGainEx(&nGainTemp); if (TestError(nDetectorID, nRet)) { Fatal("NV_GetGainEx Failed"); return false; } if (nGainValue != nGainTemp) { nRet = NV_SetGainEx(nGainValue); if (TestError(nDetectorID, nRet)) { Fatal("NV_SetGainEx Failed"); return false; } } else { Info("Same gain mode, Omit"); } return true;*/ } //从校正文件中读取校正日期 bool SensviewCtrl::GetCalibrationTime(int nDetectorID, bool bExpMode) { return true; } //从探测器上下载文件:Gain文件,defect文件 bool SensviewCtrl::DownloadfromDetector(int nDetectorID) { string strLog; string strWorkDir = m_stDeviceIndex[m_nDetectorIndex].strWorkDir; string strLocalPath = strWorkDir; string strCreatePath = strWorkDir + "\\Correct\\STE"; if (!PathFileExists(strCreatePath.c_str())) { bool bRtn = CreateDirectory(strCreatePath.c_str(), NULL); if (bRtn) { strLog = "create " + strCreatePath + " ok"; Info("{$}", strLog.c_str()); } else { strLog = "create " + strCreatePath + " failed"; Error("{$}", strLog.c_str()); return false; } } else { strLog = strCreatePath + " already exist"; Info("{$}", strLog.c_str()); } return true; } // 从SDK指定目录拷贝失败的校正文件到CalibrationFailedData中 bool SensviewCtrl::SaveFailedCalibFiles(int nDetectorID, bool bExpMode) { Info("SaveCalibrationFailedData"); Info("SaveCalibrationFailedData over"); return true; } bool SensviewCtrl::CleanCalibFiles(int nDetectorID, bool bExpMode) { return true; } bool SensviewCtrl::CancelImageRecover() { Info("Cancel Image Recover"); return true; } //----------------------------------------------------------------------------- // 函数描述 : 恢复图像:将曝光未获取成功的图像,重新获取出来 //----------------------------------------------------------------------------- bool SensviewCtrl::RecoverImage() { return true; } bool SensviewCtrl::IsConnected(string strIP) { Info("Check ping {$}", strIP); CMyPingip obPingIp; StatusFeedback(EVT_STATUS_PING, 0, "true"); if (!obPingIp.PingFunction(strIP.c_str())) { Info("ping {$} Failed", strIP); StatusFeedback(EVT_STATUS_PING, 0, "false"); return false; } return true; } //----------------------------------------------------------------------------- // Reconnect探测器(上层button) // //----------------------------------------------------------------------------- bool SensviewCtrl::ResetFPD(nsDPC::FPDDeviceSensview* pDrvDPC) { Info("Reset FPD"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nDetectorIndex) { Warn("Not current DPC, return"); return false; } return true; } void SensviewCtrl::OnProcessPreImg() { if (m_bPreviewEnable) { DataFeedback(EVT_DATA_PREVIEW_IMAGE, m_pwPreviewImg); } } void SensviewCtrl::OnProcessImg() { if (m_bSaveRaw) { string strImageName = "Flu_" + to_string(m_nFrameID) + ".raw"; SaveRawImage(strImageName.c_str(), m_pwRawImageData, m_nRawImgWidth, m_nRawImgHeight); } //暗场图挡图处理 if (!CheckImageEXI(m_pwRawImageData, m_nRawImgWidth, m_nRawImgHeight, m_nImgBits, m_nExiThreshold, 0.05f)) { Warning("Current frame EXI too low, omit"); return; } m_nFrameID++; if (m_nFrameID <= 1) //挡住第一张 { Info("Skip first frame"); return; } DataFeedback(EVT_DATA_RAW_IMAGE, m_pwRawImageData); if (m_strCurrentExamType.find("RAD") != std::string::npos) //只有点片才发关窗终止Workflow { StartXWindowOffThread(); } } bool SensviewCtrl::StartHardwareStatusThread() { if (m_pHardwareStatusThread == NULL) { m_hEndHWStatusThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); DWORD m_HardwareStatusID; m_pHardwareStatusThread = CreateThread(0, 0, HardwareStatusThread, this, 0, &m_HardwareStatusID); if (m_pHardwareStatusThread == NULL) { Fatal("Start HardwareStatus Thread Failed"); return false; } } return true; } DWORD SensviewCtrl::HardwareStatusThread(LPVOID pParam) { SensviewCtrl* pCurPanel = (SensviewCtrl*)pParam; if (pCurPanel == NULL) { return false; } Info("HardwareStatusThread start"); DWORD dwTimer = 5000; DWORD dwCounter = 0; while (true) { DWORD dwResult = WaitForSingleObject(pCurPanel->m_hEndHWStatusThreadEvent, dwTimer); if (dwResult == WAIT_OBJECT_0) { break; } else { if (dwCounter % 60 == 0) //五分钟查一次 { pCurPanel->GetHardwareStatus(); dwCounter = 0; } dwCounter++; } } CloseHandle(pCurPanel->m_hEndHWStatusThreadEvent); SetEvent(pCurPanel->m_hHWStatusThreadEndEvent); Info("HardwareStatusThread stop"); return true; } bool SensviewCtrl::GetHardwareStatus() { if (m_bInExposure) { Info("In Exposuring,omit check hw status"); return true; } for (int i = 0; i < m_nPanelCount; i++) { int nDetectorID = i + 1; if (!GetConnectionStatus(nDetectorID)) // 如果检测到平板探测器失去连接,那么要通知DROC { Info("FD {$} is communication error", nDetectorID); m_stDeviceIndex[i].bConnectStatus = false; ErrorFeedback(EVT_ERR_COMMUNICATE, "true", nDetectorID); } else if (m_stDeviceIndex[i].bConnectStatus) { Info("Check FPD {$} Status", nDetectorID); if (m_stDeviceIndex[i].bConnectChanged) { m_stDeviceIndex[i].bConnectChanged = false; } /*if (ReadTempStatus(nDetectorID)) { CheckTemperature(nDetectorID); } if (ReadBatteryStatus(nDetectorID)) { CheckBattery(nDetectorID); } if (ReadWifiStatus(nDetectorID)) { CheckWiFi(nDetectorID); } if (ReadLivingTime(nDetectorID)) { CheckLivingTime(nDetectorID); }*/ } } return true; } bool SensviewCtrl::GetConnectionStatus(int nDetectorID) { return false; } /*** * 保存RAW图像 ***/ bool SensviewCtrl::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 = g_strAppPath + "\\Image\\" + 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; } //刷新Offset bool SensviewCtrl::StartOffset(bool isAll) { if (!m_stDeviceIndex[m_nDetectorIndex].bConnectStatus) { Warn("Detector communication loss"); return false; } m_bOffsetAll = isAll; Info("Offset mode: {$}", isAll ? "All" : "NoAll"); SetEvent(m_hOffsetEvent); //OffsetCalibration() return true; } //如果是isAll=true, 则刷新全部模式,如果isAll=false, 则刷新当前模式和点片模式 bool SensviewCtrl::OffsetCalibration() { Info("OffsetCalibration start"); bool bOffsetFailed = false; StatusFeedback(PANEL_OFFSET_CAL, OFFSET_RUNNING); StatusFeedback(PANEL_OFFSET_COUNT, 1); StatusFeedback(PANEL_OFFSET_PROGRESS, 0); if (!OffsetProcess(m_nDetectorID, 1)) { Error("Offset process failed"); bOffsetFailed = true; } StatusFeedback(PANEL_OFFSET_PROGRESS, 1); /*if (m_bOffsetAll) { int nTotalMode = m_mapLogicModeOperationMode.size(); StatusFeedback(PANEL_OFFSET_COUNT, nTotalMode); int nOffsetProgress = 0; for (map::iterator it = m_mapLogicModeOperationMode.begin(); it != m_mapLogicModeOperationMode.end(); it++) { StatusFeedback(PANEL_OFFSET_PROGRESS, nOffsetProgress); if (!OffsetProcess(m_nDetectorID, it->second)) { Error("Offset mode {$} failed"); bOffsetFailed = true; break; } nOffsetProgress++; } } else { StatusFeedback(PANEL_OFFSET_COUNT, 2); Info("Refresh RAD"); if (!OffsetProcess(m_nDetectorID, 1)) { Error("Offset mode rad failed"); bOffsetFailed = true; } StatusFeedback(PANEL_OFFSET_PROGRESS, 1); Info("Refresh Mode({$})", 2); if (!OffsetProcess(m_nDetectorID, 2)) { Error("Offset mode flu failed"); bOffsetFailed = true; } StatusFeedback(PANEL_OFFSET_PROGRESS, 2); }*/ if (bOffsetFailed) { StatusFeedback(PANEL_OFFSET_CAL, OFFSET_ERROR); } else { StatusFeedback(PANEL_OFFSET_CAL, OFFSET_IDLE); } Info("Offset FINISH"); return true; } //刷新暗场 bool SensviewCtrl::OffsetProcess(int nDetectorID, int nMode) { Info("OffsetProcess start"); NV_StatusType nRet = NV_RunOffsetCalThread(); if (TestError(nDetectorID, nRet)) { Warn("NV_PerformOffsetCal Failed"); return false; } ResetLock(); if (WaitRespond(50000)) { Info("Offset success"); return true; } else { Info("Offset timeout"); return true; } //Info("OffsetProcess over"); return true; } bool SensviewCtrl::AbortOffset() { Info("Abort refresh offset"); NV_StatusType nRet = NV_CancelOffsetCal(); if (TestError(1, nRet)) { Warn("NV_CancelOffsetCal Failed"); return false; } SendNotify(); StatusFeedback(PANEL_OFFSET_CAL, OFFSET_IDLE); return true; } //检查图像EXI, 返回true: 有射线,返回false: 无射线 bool SensviewCtrl::CheckImageEXI(WORD* pImage, int nWidth, int nHeight, int nImageBit, int nThreshold, float fArea) { if (nThreshold == 0) { Info("Omit check EXI"); return true; } Info("Check EXI"); if (!pImage) { Error("Buffer is null"); return false; //图像读入失败。 } int N = 65536; int* Histogram = NULL; Histogram = new int[N]; if (Histogram == NULL) { Error("Alloc buffer failed"); return false; //内存分配失败。 } memset(Histogram, 0, sizeof(int) * N); unsigned long int nCount = 0; unsigned long int temp = 0; int nIdxI = 0; int nIdxJ = 0; for (nIdxJ = 30; nIdxJ < nHeight - 30; nIdxJ = nIdxJ + 4) { for (nIdxI = 30; nIdxI < nWidth - 30; nIdxI = nIdxI + 4) { temp = int(pImage[nIdxJ * nWidth + nIdxI]); Histogram[temp]++; nCount++; } } float fCoe = 0.01f; int nCoeCount = int(fCoe * nCount); int nAreaCount = int((1 - fCoe) * nCount * fArea); long int nIdx = 0; long int nSum = 0; for (nIdx = N - 1; nIdx >= 0; nIdx--) { nSum += Histogram[nIdx]; if (nSum >= nCoeCount) break; } unsigned long int fMean = 0; unsigned long int nflag = 0; for (int i = nIdx; i >= 0; i--) { if (Histogram[nIdx] == 0) { continue; } fMean += nIdx * Histogram[nIdx]; nflag += Histogram[nIdx]; if (nflag >= nAreaCount) { break; } } if (Histogram) { delete[] Histogram; Histogram = NULL; } if (nflag == 0) { Warning("Not have Xray image"); return false; //无x射线 } fMean = unsigned long int(fMean / nflag); Info("Mean count({$})", fMean); if (fMean >= nThreshold) { //LogInfo("Xray image"); return true; } else { //LogInfo("Not have Xray image"); return false; } } bool SensviewCtrl::SetOffsetModeScope() { Info("SetModeScope"); int nModeNum = m_pCurrentDPC->GetTotalAcqModeNum(); Info("Mode number: {$}", nModeNum); int nLogicMode = 0; int nOperationMode = 0; for (int i = 0; i < nModeNum; i++) { if ((int)m_ModeConfig["ModeTable"][i]["OffsetEnable"] == 1) { nLogicMode = (int)m_ModeConfig["ModeTable"][i]["LogicMode"]; nOperationMode = (int)m_ModeConfig["ModeTable"][i]["OperationMode"]; m_mapLogicModeOperationMode.insert(pair(nLogicMode, nOperationMode)); } } return true; } //列出探测器的触发模式 bool SensviewCtrl::ListDetectorTriggerMode(int nDetectorID) { Info("ListDetectorTriggerMode"); int nTempBuffer = 0x0F; int nTempCount = 0; NV_AcquisitionMode* pMode = new NV_AcquisitionMode[nTempBuffer]; NV_StatusType nRet = NV_EnumAcquisitionMode(pMode, nTempBuffer, &nTempCount); if (TestError(nDetectorID, nRet)) { Warn("NV_EnumAcquisitionMode Failed"); return false; } if (nTempCount <= 0) { Warn("No support any trigger mode"); return false; } for (int i = 0; i < nTempCount; i++) { Info("Index: {$}, TriggerMode: {$}({$})", i, DetTriggerMode[int(pMode[i])], int(pMode[i])); } delete[] pMode; return true; } //列出探测器的Binning模式 bool SensviewCtrl::ListDetectorBinningMode(int nDetectorID) { Info("ListDetectorBinningMode"); int nTempBuffer = 0x0F; int nTempCount = 0; NV_BinningMode* pMode = new NV_BinningMode[nTempBuffer]; NV_StatusType nRet = NV_EnumBinningMode(pMode, nTempBuffer, &nTempCount); if (TestError(nDetectorID, nRet)) { Warn("NV_EnumBinningMode Failed"); return false; } if (nTempCount <= 0) { Warn("No support any binning mode"); return false; } for (int i = 0; i < nTempCount; i++) { Info("Index: {$}, BinningMode: {$}({$})", i, DetBinningMode[int(pMode[i])], int(pMode[i])); } delete[] pMode; return true; } //列出探测器的Gain档位 bool SensviewCtrl::ListDetectorGainMode(int nDetectorID) { Info("ListDetectorGainMode"); int nTempCount = 0; NV_StatusType nRet = NV_EnumGains(&nTempCount); if (TestError(nDetectorID, nRet)) { Warn("NV_EnumGains Failed"); return false; } Info("GainMode: 0~{$}", nTempCount - 1); return true; } //探测器基本信息 bool SensviewCtrl::ListDetectorInfo(int nDetectorID) { Info("ListDetectorInfo"); NV_Version detVer; NV_StatusType nRet = NV_GetVersion(&detVer); if (TestError(nDetectorID, nRet)) { Warn("NV_GetVersion Failed"); return false; } string strFWVersion = std::to_string(detVer.FirmwareVersion >> 24 & 0xFF) + "." + std::to_string(detVer.FirmwareVersion >> 16 & 0xFF) + "." + std::to_string(detVer.FirmwareVersion >> 8 & 0xFF) + "." + std::to_string(detVer.FirmwareVersion >> 0 & 0xFF); Info("Firmware version: {$}", strFWVersion); string strHWVersion = std::to_string(detVer.HardwareVersion >> 24 & 0xFF) + "." + std::to_string(detVer.HardwareVersion >> 16 & 0xFF) + "." + std::to_string(detVer.HardwareVersion >> 8 & 0xFF) + "." + std::to_string(detVer.HardwareVersion >> 0 & 0xFF); Info("Hardware version: {$}", strHWVersion); string strKerVersion = std::to_string(detVer.KernelVersion >> 24 & 0xFF) + "." + std::to_string(detVer.KernelVersion >> 16 & 0xFF) + "." + std::to_string(detVer.KernelVersion >> 8 & 0xFF) + "." + std::to_string(detVer.KernelVersion >> 0 & 0xFF); Info("Kernel version: {$}", strKerVersion); char szSN[32] = ""; unsigned long iSize = 32; nRet = NV_GetSerialNum(szSN, &iSize); if (TestError(nDetectorID, nRet)) { Warn("NV_GetSerialNum Failed"); return false; } Info("Detector serial number: {$}", szSN); return true; } bool SensviewCtrl::SetFluPPS(float fFluPPS) { if (fFluPPS <= 0.0f) { Warn("Current frame rate is Illegal"); return false; } Info("Set Detector flu frame rate: {$}", fFluPPS); ////方式一:设置扩展曝光时间 ////计算扩展曝光时间,单位0.1ms //int nExpTime = 10000 / int(fFluPPS); //int nRet = NV_SetExpTime(nExpTime); //if (TestError(m_nDetectorID, nRet)) //{ // Fatal("NV_SetExpTime Failed"); // return false; //} //方式二:设帧率 int nRet = NV_SetFramePerSecond(int(fFluPPS)); if (TestError(m_nDetectorID, nRet)) { Fatal("NV_SetFramePerSecond Failed"); return false; } m_fFrameRate = fFluPPS; return true; } bool SensviewCtrl::GetFluPPS(float& fFluPPS) { fFluPPS = m_fFrameRate; return true; }