Detector_TiRayDR.cpp 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798
  1. #include "Detector_TiRayDR.h"
  2. #include "CCOS.Dev.FPD.TiRayDR.h"
  3. #include "MyPingip.h"
  4. #include <dlfcn.h>
  5. #include <pthread.h>
  6. #include "Log4CPP.h"
  7. using EventListenerType = void(*)(TiRayEvent, void*);
  8. Detector_TiRayDR* g_pDetector = nullptr;
  9. //extern Log4CPP::Logger* mLog::gLogger;
  10. /****************************************/
  11. int (*GetSdkVersion_Ptr)(void);
  12. TiRayError(*Scan_Ptr)(ResultCallback fn, const char* interfaceIp, int scanDuration);
  13. TiRayError(*SetIp_Ptr)(const char* detectorSN, const char* upperIp, const char* lowerIp, const char* interfaceIp);
  14. TiRayError(*Startup_Ptr)(TiRayModel model, EventCallback fn, const StartupOption * option);
  15. void (*Stop_Ptr)();
  16. TiRayError(*Execute_Ptr)(int detectorId, int commandId, TiRayVariant argv[], int argc);
  17. TiRayError(*ApplyPreset_Ptr)(int detectorId, TiRayVariant argv[], int argc, ResultCallback fn);
  18. TiRayError(*GenerateTemplate_Ptr)(TemplateType type, TiRayVariant images[], int count, void* templateBuffer, int bufferSize);
  19. static int g_load_error = 0;
  20. static void LoadOneFunc(void* hInstLib, void** pFunction, const char* funcName)
  21. {
  22. *pFunction = dlsym(hInstLib, funcName);
  23. const char* dlsym_error = dlerror();
  24. if (dlsym_error != NULL) {
  25. printf("Failed to load %s. Error = %s", funcName, dlsym_error);
  26. g_load_error = 1;
  27. }
  28. }
  29. void OnEvent(TiRayEvent eventType, TiRayVariant argv[], int argc) {
  30. if (argc > 0) {
  31. auto arg = new std::vector<TiRayVariant>(argc);
  32. for (int i = 0; i < argc; i++) {
  33. if (argv[i].Type == TiRayVariant::TiRayBuffer) {
  34. arg->at(i).Type = TiRayVariant::TiRayBuffer;
  35. arg->at(i).DataLen = argv[i].DataLen;
  36. arg->at(i).DataValue = new char[argv[i].DataLen];
  37. memcpy(arg->at(i).DataValue, argv[i].DataValue, argv[i].DataLen);
  38. }
  39. else {
  40. memcpy(&arg->at(i), &argv[i], sizeof(TiRayVariant));
  41. }
  42. }
  43. }
  44. }
  45. #define LOAD_ONE_FUNC(handle, funcName) LoadOneFunc(handle, (void**)&(funcName##_Ptr), #funcName)
  46. /****************************************/
  47. Detector_TiRayDR::Detector_TiRayDR()
  48. :m_nPanelCount{},
  49. m_nCurrentPanelID{0},
  50. m_nImageWidth{},
  51. m_nImageHeight{},
  52. m_nWidthOffset{},
  53. m_nHeightOffset{},
  54. m_nRawImgWidth{},
  55. m_nRawImgHeight{},
  56. m_nCalibrationRounds{},
  57. m_nCalibCurrentCalibrationRound{},
  58. m_nCalibCurrentExposureIndex{},
  59. m_nExposureNumCurrentRound{},
  60. m_hTiRayDRModule{},
  61. m_hReconnectThread{},
  62. m_hFPDScanThread{},
  63. m_hRadAcquisitionThread{},
  64. m_hStatusMonitorThread{},
  65. m_pRawImgBuffer{},
  66. m_pImgBuffer{},
  67. m_pZSKKCalib{},
  68. m_strDetectorType{},
  69. m_strSerialNum{},
  70. m_nImageNum{},
  71. m_nDetectorID{},
  72. m_nNotifyStatusTimePeriod{},
  73. m_pStPanelStatus{},
  74. m_nReconnectTimePeriod(5000),
  75. m_nAppStatus(APP_STATUS::APP_STATUS_IDLE),
  76. m_eCaliType(CCOS_CALIBRATION_TYPE_NONE),
  77. m_nSyncMode(SYNC_SOFTWARE),
  78. m_nCalibrationMode(CCOS_CALIBRATION_MODE_ZSKK),
  79. m_bSaveRaw(true),
  80. m_bConnected(false),
  81. m_bAEDReady(false),
  82. m_bAEDWorkFlag(false),
  83. m_bExitRadAcqStatus(false),
  84. m_bMonitorFlag(false)
  85. {
  86. m_pDPC2PanelID = new map<FPDDeviceTiRay*, int>();
  87. m_pPanelID2DPC = new map<int, FPDDeviceTiRay*>();
  88. m_hExitRadAcqStatus = LinuxEvent::CreateEvent(LinuxEvent::AUTO_RESET, FALSE);
  89. m_hInitEvent = LinuxEvent::CreateEvent(LinuxEvent::AUTO_RESET, FALSE);
  90. m_hExitEvent = LinuxEvent::CreateEvent(LinuxEvent::AUTO_RESET, FALSE);
  91. m_hReConnectEvent = LinuxEvent::CreateEvent(LinuxEvent::AUTO_RESET, FALSE);
  92. m_hRadEvent = LinuxEvent::CreateEvent(LinuxEvent::AUTO_RESET, FALSE);
  93. m_hArrayEvent.push_back(m_hInitEvent);
  94. m_hArrayEvent.push_back(m_hExitEvent);
  95. m_hArrayEvent.push_back(m_hReConnectEvent);
  96. m_hArrayEvent.push_back(m_hRadEvent);
  97. m_hToggleEvent = LinuxEvent::CreateEvent(LinuxEvent::AUTO_RESET, FALSE);
  98. }
  99. Detector_TiRayDR::~Detector_TiRayDR()
  100. {
  101. CloseStatusMonitor();
  102. CloseDetectorScan();
  103. if (m_hReconnectThread != 0) {
  104. if (m_bReconnectThreadRunning) {
  105. struct timespec ts;
  106. clock_gettime(CLOCK_REALTIME, &ts);
  107. ts.tv_sec += 2; // 设置2秒超时
  108. // 等待线程结束
  109. pthread_timedjoin_np(m_hReconnectThread, nullptr, &ts);
  110. }
  111. // 如果线程仍在运行,强制取消
  112. if (m_bReconnectThreadRunning) {
  113. pthread_cancel(m_hReconnectThread);
  114. }
  115. m_hReconnectThread = 0;
  116. }
  117. if (m_pRawImgBuffer)
  118. {
  119. delete[] m_pRawImgBuffer;
  120. m_pRawImgBuffer = nullptr;
  121. }
  122. if (m_pImgBuffer)
  123. {
  124. delete[] m_pImgBuffer;
  125. m_pImgBuffer = nullptr;
  126. }
  127. if (m_pZSKKCalib)
  128. {
  129. delete m_pZSKKCalib;
  130. m_pZSKKCalib = nullptr;
  131. }
  132. }
  133. bool Detector_TiRayDR::ScanDetector(string& strDetectorInfo)
  134. {
  135. ResDataObject result;
  136. std::vector<scan_result> scan_results;
  137. // 扫描探测器并收集所有结果
  138. scan([&scan_results](scan_result&& res) {
  139. scan_results.emplace_back(std::move(res));
  140. });
  141. if (scan_results.empty()) {
  142. std::cerr << "[Detector_TiRayDR::ScanDetector] No detectors were found!" << std::endl;
  143. return false;
  144. }
  145. std::cout << "[Detector_TiRayDR::ScanDetector] Scanned " << scan_results.size() << " detector(s):" << std::endl;
  146. for (size_t i = 0; i < scan_results.size(); ++i) {
  147. const auto& res = scan_results[i];
  148. ResDataObject detectorData;
  149. detectorData.add("SerialNumber", res.sn.c_str());
  150. detectorData.add("Model", res.model.c_str());
  151. detectorData.add("TupperIP", res.upper_ip.c_str());
  152. detectorData.add("DetectorIP", res.detector_ip.c_str());
  153. std::string key = "DetectorData_" + std::to_string(i);
  154. result.add(key.c_str(), detectorData);
  155. // 输出当前探测器信息
  156. std::cout << "[Detector_TiRayDR::ScanDetector] Detector " << (i + 1) << ":"
  157. << " Serial number:" << res.sn
  158. << ", Model:" << res.model
  159. << ", tupper IP:" << res.upper_ip
  160. << ", detector IP:" << res.detector_ip << std::endl;
  161. }
  162. try {
  163. strDetectorInfo = result.encode();
  164. }
  165. catch (const std::exception& e) {
  166. std::cerr << "[Detector_TiRayDR::ScanDetector] Encode failed: " << e.what() << std::endl;
  167. return false;
  168. }
  169. return true;
  170. }
  171. bool Detector_TiRayDR::DriverEntry(FPDDeviceTiRay* pDrvDPC, ResDataObject& Configuration)
  172. {
  173. //FINFO("--TiRayDR Func-- DriverEntry Start");
  174. map<FPDDeviceTiRay*, int>::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC);
  175. if (DPCsIter != m_pDPC2PanelID->end())
  176. {
  177. //FERROR("This DPC already exist");
  178. return false;
  179. }
  180. CPanelStatus* p = new CPanelStatus();
  181. m_pStPanelStatus[m_nPanelCount] = p;
  182. m_pDPC2PanelID->insert(pair<FPDDeviceTiRay*, int>(pDrvDPC, m_nPanelCount));
  183. m_pPanelID2DPC->insert(pair<int, FPDDeviceTiRay*>(m_nPanelCount, pDrvDPC));
  184. m_nPanelCount++;
  185. m_ModeConfig = Configuration; //记录配置 --目前只有一个平板,多板时应该分别存储
  186. //FINFO("Config: {$}", m_ModeConfig.encode());
  187. try
  188. {
  189. m_nCalibrationMode = (CCOS_CALIBRATION_MODE)(int)m_ModeConfig["CalibMode"];
  190. }
  191. catch (ResDataObjectExption& e)
  192. {
  193. //FERROR("Read configuration failed, Error code: {$}", e.what());
  194. }
  195. //FINFO("TiRayDR DriverEntry Over");
  196. return true;
  197. }
  198. bool Detector_TiRayDR::Connect(FPDDeviceTiRay* pDrvDPC, const char* szWorkPath)
  199. {
  200. FINFO("--TiRayDR Func-- Connect Start");
  201. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  202. {
  203. FINFO("Not current DPC, return true");
  204. return true;
  205. }
  206. if (!m_pZSKKCalib)
  207. {
  208. m_pZSKKCalib = new CZSKKCalibrationCtrl();
  209. }
  210. m_strWorkPath = szWorkPath;
  211. if (m_hFPDScanThread == 0)
  212. {
  213. pthread_t threadId;
  214. int result = pthread_create(&threadId, NULL, onFPDScanThread, this);
  215. if (result == 0) {
  216. m_hFPDScanThread = threadId; // 存储线程ID
  217. }
  218. else {
  219. FERROR("Thread creation failed: %d", result);
  220. return false;
  221. }
  222. }
  223. if (m_hInitEvent) {
  224. m_hInitEvent->SetEvent();
  225. }
  226. FINFO("TiRayDR Connect Over");
  227. return true;
  228. }
  229. bool Detector_TiRayDR::Disconnect()
  230. {
  231. FINFO("--TiRayDR Func-- Disconnect Begin");
  232. m_hExitEvent->SetEvent(); //关闭Scan线程
  233. bool result = m_hToggleEvent->Wait(65000);
  234. if (result)
  235. {
  236. FINFO("Leave scan thread over");
  237. }
  238. else
  239. {
  240. FERROR("Till time detectorData");
  241. }
  242. FINFO("Call API Stop");
  243. Stop();
  244. FINFO("TiRayDR Disconnect Over");
  245. return true;
  246. }
  247. void Detector_TiRayDR::EnterExamMode(int nExamMode)
  248. {
  249. switch (nExamMode)
  250. {
  251. case APP_STATUS_WORK_BEGIN:
  252. FINFO("Enter into Exam Windows");
  253. m_nAppStatus = APP_STATUS_WORK_BEGIN;
  254. break;
  255. case APP_STATUS_WORK_END:
  256. FINFO("Quit Exam Windows");
  257. m_nAppStatus = APP_STATUS_WORK_END;
  258. break;
  259. case APP_STATUS_DETSHARE_BEGIN:
  260. FINFO("Enter into Detector Share Windows");
  261. m_nAppStatus = APP_STATUS_DETSHARE_BEGIN;
  262. break;
  263. case APP_STATUS_DETSHAR_END:
  264. FINFO("Quit Detector Share Windows");
  265. m_nAppStatus = APP_STATUS_DETSHAR_END;
  266. break;
  267. case APP_STATUS_CAL_BEGIN:
  268. FINFO("Enter into Calibration Windows");
  269. m_nAppStatus = APP_STATUS_CAL_BEGIN;
  270. break;
  271. case APP_STATUS_CAL_END:
  272. FINFO("Quit Calibration Windows");
  273. m_nAppStatus = APP_STATUS_CAL_END;
  274. break;
  275. case APP_STATUS_WORK_IN_SENSITIVITY:
  276. FINFO("Enter into sensitivity test interface");
  277. m_nAppStatus = APP_STATUS_WORK_IN_SENSITIVITY;
  278. break;
  279. default:
  280. break;
  281. }
  282. }
  283. /***
  284. ** 根据采集模式申请图像buffer
  285. ***/
  286. bool Detector_TiRayDR::SetAcqMode(int nMode)
  287. {
  288. FINFO("--TiRayDR Func-- SetAcqMode Start");
  289. FINFO("Detector_TiRayDR::SetAcqMode mode:{$}", nMode);
  290. if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectState)
  291. {
  292. FERROR("Detector not connected, return");
  293. return false;
  294. }
  295. int nRes;
  296. m_bExitRadAcqStatus = false;
  297. try
  298. {
  299. //设置采集模式,根据不同的场景设置不同的采集模式
  300. m_nImageWidth = (int)m_ModeConfig["ModeTable"][0]["ImageWidth"];
  301. m_nImageHeight = (int)m_ModeConfig["ModeTable"][0]["ImageHeight"];
  302. m_nWidthOffset = (int)m_ModeConfig["ModeTable"][0]["WidthOffset"];
  303. m_nHeightOffset = (int)m_ModeConfig["ModeTable"][0]["HeightOffset"];
  304. FINFO("After crop image width: {$}, height: {$}, WidthOffset: {$}, HeightOffset: {$}", m_nImageWidth, m_nImageHeight, m_nWidthOffset, m_nHeightOffset);
  305. m_bSaveRaw = (int)m_ModeConfig["ModeTable"][0]["IsSaveRaw"];
  306. FINFO("m_nSaveRaw:{$}", m_bSaveRaw);
  307. if (nullptr != m_pImgBuffer)
  308. {
  309. delete[] m_pImgBuffer;
  310. m_pImgBuffer = nullptr;
  311. }
  312. m_pImgBuffer = new WORD[(size_t)m_nImageWidth * (size_t)m_nImageHeight];
  313. }
  314. catch (ResDataObjectExption& e)
  315. {
  316. FERROR("Get config FERROR: {$}", e.what());
  317. return false;
  318. }
  319. TiRayVariant Param[2]{};
  320. Param[0].Type = TiRayVariant::TiRayInt;
  321. Param[0].IntValue = TiRayAttribute::Attr_BinningMode;
  322. Param[1].Type = TiRayVariant::TiRayInt;
  323. Param[1].IntValue = BinningMode::Binning_None;
  324. nRes = Execute_Ptr(m_nDetectorID, Cmd_WriteAttribute, Param, 2);
  325. if ((TiRayError)nRes != TiRayError::Err_Success)
  326. {
  327. FERROR("Set BinningMode Failed, Reason:{$}", nRes);
  328. return false;
  329. }
  330. else
  331. {
  332. FINFO("Set BinningMode Success");
  333. }
  334. TiRayVariant ParamAED[2]{};
  335. ParamAED[0].Type = TiRayVariant::TiRayInt;
  336. ParamAED[0].IntValue = TiRayAttribute::Attr_AEDSensitivity;
  337. ParamAED[1].Type = TiRayVariant::TiRayInt;
  338. ParamAED[1].IntValue = 200;
  339. nRes = Execute_Ptr(m_nDetectorID, Cmd_WriteAttribute, ParamAED, 2);
  340. if ((TiRayError)nRes != TiRayError::Err_Success)
  341. {
  342. FERROR("Set BinningMode Failed, Reason:{$}", nRes);
  343. return false;
  344. }
  345. else
  346. {
  347. FINFO("Set BinningMode Success");
  348. }
  349. StatusFeedback(EVT_STATUS_PANEL, PANEL_SLEEP);
  350. FINFO("TiRayDR SetAcqMode Over");
  351. return true;
  352. }
  353. bool Detector_TiRayDR::SetSyncMode(int nSyncMode)
  354. {
  355. FINFO("--TiRayDR Func-- SetSyncMode Start");
  356. FINFO("SetSyncMode: {$}", nSyncMode);
  357. std::cout << "--TiRayDR Func-- SetSyncMode Start" << std::endl;
  358. std::cout << "SetSyncMode: " << nSyncMode << std::endl;
  359. int nRes;
  360. TiRayVariant Param[2]{};
  361. Param[0].Type = TiRayVariant::TiRayInt;
  362. Param[0].IntValue = TiRayAttribute::Attr_WorkMode;
  363. Param[1].Type = TiRayVariant::TiRayInt;
  364. if (nSyncMode == 1)
  365. {
  366. Param[1].IntValue = WorkMode::WorkMode_Idle;
  367. m_nSyncMode = SYNC_MODE::SYNC_SOFTWARE;
  368. std::cout << "Setting SyncMode to Software Sync" << std::endl;
  369. nRes = Execute_Ptr(m_nDetectorID, Cmd_WriteAttribute, Param, 2);
  370. if ((TiRayError)nRes != TiRayError::Err_Success)
  371. {
  372. std::cout << "Error: Failed to set SyncMode to Software Sync. Reason: " << nRes << std::endl;
  373. FERROR("Set SyncMode SoftSync, Reason:{$}", nRes);
  374. return false;
  375. }
  376. else
  377. {
  378. std::cout << "Success: Software Sync mode set successfully" << std::endl;
  379. FINFO("Set SoftSync Success");
  380. }
  381. }
  382. else if (nSyncMode == 2)
  383. {
  384. m_nSyncMode = SYNC_MODE::SYNC_HARDWARE;
  385. Param[1].IntValue = WorkMode::WorkMode_SyncIn;
  386. std::cout << "Setting SyncMode to Hardware Sync" << std::endl;
  387. nRes = Execute_Ptr(m_nDetectorID, Cmd_WriteAttribute, Param, 2);
  388. if ((TiRayError)nRes != TiRayError::Err_Success)
  389. {
  390. std::cout << "Error: Failed to set SyncMode to Hardware Sync. Reason: " << nRes << std::endl;
  391. FERROR("Set SyncMode HardSync, Reason:{$}", nRes);
  392. return false;
  393. }
  394. else
  395. {
  396. std::cout << "Success: Hardware Sync mode set successfully" << std::endl;
  397. FINFO("Set HardSync Success");
  398. }
  399. }
  400. else if (nSyncMode == 3)
  401. {
  402. Param[1].IntValue = WorkMode_FreeSync;
  403. m_nSyncMode = SYNC_MODE::SYNC_AED;
  404. std::cout << "Setting SyncMode to AED Sync" << std::endl;
  405. nRes = Execute_Ptr(m_nDetectorID, Cmd_WriteAttribute, Param, 2);
  406. if ((TiRayError)nRes != TiRayError::Err_Success)
  407. {
  408. std::cout << "Error: Failed to set SyncMode to AED Sync. Reason: " << nRes << std::endl;
  409. FERROR("Set SyncMode AED, Reason:{$}", nRes);
  410. return false;
  411. }
  412. else
  413. {
  414. std::cout << "Success: AED Sync mode set successfully" << std::endl;
  415. FINFO("Set AED Success");
  416. }
  417. }
  418. m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode = (SYNC_MODE)m_nSyncMode;
  419. FINFO("TiRayDR SetSyncMode Over");
  420. std::cout << "TiRayDR SetSyncMode Over" << std::endl;
  421. return true;
  422. }
  423. bool Detector_TiRayDR::PrepareAcquisition(FPDDeviceTiRay* pDrvDPC)
  424. {
  425. FINFO("--TiRayDR Func-- PrepareAcquisition Start");
  426. FINFO("PrepareAcquisition start");
  427. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  428. {
  429. FERROR("Not current DPC, return");
  430. return false;
  431. }
  432. //未初始化、未连接 不执行
  433. if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectState)
  434. {
  435. FERROR("Detector not connected, return");
  436. return false;
  437. }
  438. g_pDetector->StatusFeedback(EVT_STATUS_PANEL, PANEL_STANDBY);
  439. //m_hRadEvent->SetEvent();
  440. FINFO("TiRayDR PrepareAcquisition Over");
  441. return true;
  442. }
  443. bool Detector_TiRayDR::StartAcquisition(FPDDeviceTiRay* pDrvDPC)
  444. {
  445. std::cout << "--TiRayDR Func-- StartAcquisition Start" << std::endl;
  446. FINFO("--TiRayDR Func-- StartAcquisition Start");
  447. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  448. {
  449. std::cout << "Not current DPC, return" << std::endl;
  450. FERROR("Not current DPC, return");
  451. return false;
  452. }
  453. //未初始化、未连接 不执行
  454. if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectState)
  455. {
  456. std::cout << "Detector not connected, return" << std::endl;
  457. FERROR("Detector not connected, return");
  458. return false;
  459. }
  460. if (m_nSyncMode == SYNC_MODE::SYNC_SOFTWARE)
  461. {
  462. //SetSyncMode(1);
  463. auto err = Execute_Ptr(m_nDetectorID, Cmd_Photo, nullptr, 0);
  464. if (err != Err_Success) {
  465. cout << "[Detector_TiRayDR::StartAcquisition] Failed to Execute_Ptr Cmd_Photo. Error code: " << err << endl;
  466. return false;
  467. }
  468. }
  469. StatusFeedback(EVT_STATUS_PANEL, PANEL_START_ACQ);
  470. m_bAEDWorkFlag = true;
  471. StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON);
  472. std::cout << "TiRayDR StartAcquisition Over" << std::endl;
  473. FINFO("TiRayDR StartAcquisition Over");
  474. return true;
  475. }
  476. bool Detector_TiRayDR::StopAcquisition(FPDDeviceTiRay* pDrvDPC)
  477. {
  478. FINFO("--TiRayDR Func-- StopAcquisition Start");
  479. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  480. {
  481. FERROR("Not current DPC, return");
  482. return false;
  483. }
  484. if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectState)
  485. {
  486. FERROR("Detector not connected, return");
  487. return false;
  488. }
  489. FINFO("## Stop Acquisition ##");
  490. StatusFeedback(EVT_STATUS_PANEL, PANEL_STANDBY);
  491. SetTiRayDPCStatus(eDetStatus::DetStatus_Standby); //停止采集
  492. FINFO("TiRayDR StopAcquisition Over");
  493. return true;
  494. }
  495. bool Detector_TiRayDR::ActiveCalibration(FPDDeviceTiRay* pDrvDPC, CCOS_CALIBRATION_TYPE eType)
  496. {
  497. FINFO("--TiRayDR Func-- ActiveCalibration Start");
  498. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  499. {
  500. FERROR("Not current DPC, return");
  501. return false;
  502. }
  503. if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectState)
  504. {
  505. FERROR("bConnectState is false, Detector not connected, return");
  506. return false;
  507. }
  508. StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_START);
  509. m_nAppStatus = APP_STATUS_CAL_BEGIN; //激活校正,置为校正界面
  510. m_eCaliType = eType;
  511. if (CCOS_CALIBRATION_TYPE_DARK == m_eCaliType)
  512. {
  513. FINFO("Active Dark Calibration");
  514. }
  515. if (CCOS_CALIBRATION_TYPE_XRAY == m_eCaliType)
  516. {
  517. FINFO("Active Xray Calibration");
  518. if (m_nCalibrationMode) //厂商校正ActiveCalibration
  519. {
  520. }
  521. //else //ZSKK校正
  522. //{
  523. // if (!m_pZSKKCalib)
  524. // {
  525. // FERROR("ZSKK Calibration object is undefined");
  526. // }
  527. // else
  528. // {
  529. // //加载ZSKK的校正文件
  530. // m_pZSKKCalib->m_strRawImgPath = m_strWorkPath + "/rawdata/";
  531. // m_pZSKKCalib->m_strRefFilePath = m_strWorkPath + "/references/";
  532. // m_pZSKKCalib->m_nFullImgWidth = m_nImageWidth;
  533. // m_pZSKKCalib->m_nFullImgHeight = m_nImageHeight;
  534. // m_pZSKKCalib->m_nReferenceNum = m_nCalibrationRounds;
  535. // m_pZSKKCalib->m_nSaturationValue = 50000;
  536. // //LoadZSKKGainMap 参数为false,意思是开始增益校正
  537. // m_pZSKKCalib->LoadZSKKGainMap(false, m_strDetectorType);
  538. // m_pZSKKCalib->LoadZSKKPixelMap(false, m_strDetectorType);
  539. // FINFO("Load ecom gain and pixel map, references file path: {$}", m_pZSKKCalib->m_strRefFilePath);
  540. // }
  541. //}
  542. }
  543. FINFO("TiRayDR ActiveCalibration Over");
  544. return true;
  545. }
  546. /***
  547. * 接受曝光图像
  548. ***/
  549. bool Detector_TiRayDR::AcceptCalibration()
  550. {
  551. FINFO("--TiRayDR Func-- AcceptCalibration Start");
  552. if (m_nCalibrationMode)//厂商校正AcceptCalibration
  553. {
  554. //不做处理
  555. }
  556. else //ZSKK校正
  557. {
  558. //WORD* pImageBuffer = nullptr;
  559. ////这里要注意使用的image buffer是哪个,裁剪和不裁剪是不一样的
  560. //if (m_nWidthOffset != 0 || m_nHeightOffset != 0)
  561. //{
  562. // pImageBuffer = m_pImgBuffer;
  563. //}
  564. //else
  565. //{
  566. // pImageBuffer = m_pImgBuffer;//之后再做区分,先测试用
  567. //}
  568. //if (m_nCalibCurrentExposureIndex == 1)
  569. //{
  570. // m_pZSKKCalib->AddImageToPixMap(pImageBuffer);
  571. // m_pZSKKCalib->AverageZSKKGainMap(pImageBuffer, m_nCalibCurrentCalibrationRound - 1, true);
  572. //}
  573. //else
  574. //{
  575. // m_pZSKKCalib->AverageZSKKGainMap(pImageBuffer, m_nCalibCurrentCalibrationRound - 1, false); //曝光第几轮
  576. //}
  577. }
  578. FINFO("TiRayDR AcceptCalibration Over");
  579. return true;
  580. }
  581. /***
  582. * 拒绝曝光图像
  583. ***/
  584. bool Detector_TiRayDR::RejectCalibration()
  585. {
  586. const std::string funcTag = "[Detector_TiRayDR::RejectCalibration] ";
  587. // 检查当前是否在进行增益校正
  588. if (m_eCaliType != CCOS_CALIBRATION_TYPE_XRAY)
  589. {
  590. cout << funcTag << "No active gain calibration in progress" << endl;
  591. return false;
  592. }
  593. bool rejected = false;
  594. if (m_bUseGainV2)
  595. {
  596. if (!m_currentDoseImages.empty())
  597. {
  598. m_currentDoseImages.pop_back();
  599. cout << funcTag << "Rejected last image in dose group " << m_currentDoseIndex
  600. << ". Remaining in group: " << m_currentDoseImages.size() << endl;
  601. rejected = true;
  602. }
  603. else
  604. {
  605. cout << funcTag << "No images in current dose group to reject" << endl;
  606. }
  607. }
  608. else
  609. {
  610. if (!m_gainCalibImages.empty())
  611. {
  612. m_gainCalibImages.pop_back(); // 移除最后添加的图像
  613. cout << funcTag << "Rejected last gain image. Remaining: " << m_gainCalibImages.size() << endl;
  614. rejected = true;
  615. }
  616. else
  617. {
  618. cout << funcTag << "No gain images to reject" << endl;
  619. }
  620. }
  621. return rejected;
  622. }
  623. /***
  624. * 设置校正轮数
  625. ***/
  626. bool Detector_TiRayDR::SetCalibRounds(int nCalibRounds)
  627. {
  628. FINFO("--TiRayDR Func-- SetCalibRounds Start");
  629. m_nCalibrationRounds = nCalibRounds;
  630. FINFO("Set reference number: {$}", m_nCalibrationRounds);
  631. FINFO("TiRayDR SetCalibRounds Over");
  632. return true;
  633. }
  634. bool Detector_TiRayDR::GetCalibrationStep(int nCalibCurrentCalibrationRound, int nCalibrationRounds, int nCalibCurrentExposureIndex, int nExposureNumCurrentRound)
  635. {
  636. FINFO("--TiRayDR Func-- GetCalibrationStep Start");
  637. m_nCalibCurrentCalibrationRound = nCalibCurrentCalibrationRound;
  638. m_nCalibrationRounds = nCalibrationRounds;
  639. m_nCalibCurrentExposureIndex = nCalibCurrentExposureIndex;
  640. m_nExposureNumCurrentRound = nExposureNumCurrentRound;
  641. FINFO("Calibration Step===Round: {$}/{$}, ExposureNum: {$}/{$}", nCalibCurrentCalibrationRound, nCalibrationRounds,
  642. nCalibCurrentExposureIndex, nExposureNumCurrentRound);
  643. FINFO("TiRayDR GetCalibrationStep Over");
  644. return true;
  645. }
  646. bool Detector_TiRayDR::PrepareCalibration(FPDDeviceTiRay* pDrvDPC)
  647. {
  648. const std::string funcTag = "[Detector_TiRayDR::PrepareCalibration] ";
  649. std::cout << funcTag << "--TiRayDR Function-- PrepareCalibration started" << std::endl;
  650. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  651. {
  652. std::cout << funcTag << "Error: Not current DPC device, returning false" << std::endl;
  653. return false;
  654. }
  655. if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectState)
  656. {
  657. std::cout << funcTag << "Error: Detector not connected (bConnectState is false), returning false" << std::endl;
  658. return false;
  659. }
  660. auto writeAttrWithLog = [this](const std::string& attrName, int value, int err) {
  661. if (err == Err_Success)
  662. {
  663. std::cout << "[Detector_TiRayDR::PrepareCalibration] Success: Wrote attribute " << attrName << " with value " << value << std::endl;
  664. }
  665. else
  666. {
  667. std::cout << "[Detector_TiRayDR::PrepareCalibration] Error: Failed to write attribute " << attrName << ", error code: " << err << std::endl;
  668. }
  669. return err;
  670. };
  671. if (CCOS_CALIBRATION_TYPE_DARK == m_eCaliType)
  672. {
  673. int ret = DarkAcquisition();
  674. std::cout << funcTag << "Info: DarkAcquisition returned " << ret << std::endl;
  675. if (!ret)
  676. {
  677. std::cout << funcTag << "Info: Sending calibration start status (EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_BEGIN)" << std::endl;
  678. StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_BEGIN);
  679. }
  680. }
  681. else if (CCOS_CALIBRATION_TYPE_XRAY == m_eCaliType)
  682. {
  683. std::cout << funcTag << "Info: Preparing X-ray calibration (CCOS_CALIBRATION_TYPE_XRAY)" << std::endl;
  684. int err = write_attribute(Attr_WorkMode, WorkMode_FreeSync);
  685. writeAttrWithLog("Attr_WorkMode", WorkMode_FreeSync, err);
  686. err = write_attribute(Attr_PhotoInterval, 3000);
  687. writeAttrWithLog("Attr_PhotoInterval", 3000, err);
  688. err = write_attribute(Attr_CalibrationMode, CalibrationMode_None);
  689. writeAttrWithLog("Attr_CalibrationMode", CalibrationMode_None, err);
  690. }
  691. std::cout << funcTag << "Info: TiRayDR PrepareCalibration completed" << std::endl;
  692. return true;
  693. }
  694. //软同步调用接口,其它同步模式没有动作
  695. bool Detector_TiRayDR::StartCalibration(FPDDeviceTiRay* pDrvDPC)
  696. {
  697. FINFO("--TiRayDR Func-- StartCalibration Start");
  698. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  699. {
  700. FERROR("Not current DPC, return");
  701. return false;
  702. }
  703. //未初始化、未连接 不执行
  704. if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectState)
  705. {
  706. FERROR("bConnectState is false, Detector not connected, return");
  707. return false;
  708. }
  709. if (CCOS_CALIBRATION_TYPE_DARK == m_eCaliType)
  710. {
  711. FINFO("StartCalibration DARK");
  712. StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK);
  713. m_pStPanelStatus[m_nCurrentPanelID]->eFPDStatus = eDetStatus::DetStatus_Offset;
  714. }
  715. else if (CCOS_CALIBRATION_TYPE_XRAY == m_eCaliType)
  716. {
  717. FINFO("StartCalibration XRAY");
  718. bool ret = StartAcquisition(pDrvDPC);
  719. if (!ret)
  720. {
  721. FERROR("StartCalibration Over");
  722. return false;
  723. }
  724. m_pStPanelStatus[m_nCurrentPanelID]->eFPDStatus = eDetStatus::DetStatus_XrayCalibration;
  725. }
  726. FINFO("TiRayDR StartCalibration Over");
  727. return true;
  728. }
  729. /***
  730. ** 说明:终止校正
  731. ***/
  732. RET_STATUS Detector_TiRayDR::AbortCalibration(FPDDeviceTiRay* pDrvDPC)
  733. {
  734. const std::string funcTag = "[Detector_TiRayDR::AbortCalibration] ";
  735. FINFO("--TiRayDR Func-- AbortCalibration Start");
  736. if (m_eCaliType == CCOS_CALIBRATION_TYPE_XRAY)
  737. {
  738. // 清除增益校正相关数据
  739. m_gainCalibImages.clear();
  740. m_currentDoseImages.clear();
  741. m_gainV2MeanImages.clear();
  742. m_currentDoseIndex = 0;
  743. cout << funcTag << "Aborted " << (!m_bUseGainV2 ? "Gain" : "GainV2")
  744. << " calibration. All related data cleared" << endl;
  745. }
  746. auto err = write_attribute(Attr_CalibrationMode, CalibrationMode_Defect);
  747. if (err == Err_Success)
  748. {
  749. std::cout << funcTag << "Success: Wrote attribute Attr_CalibrationMode with value CalibrationMode_Defect" << std::endl;
  750. }
  751. else
  752. {
  753. std::cout << funcTag << "Error: Failed to write attribute Attr_CalibrationMode, error code: " << err << std::endl;
  754. }
  755. // 恢复初始状态
  756. m_eCaliType = CCOS_CALIBRATION_TYPE_NONE;
  757. m_nAppStatus = APP_STATUS_CAL_END;
  758. FINFO("TiRayDR AbortCalibration Over");
  759. return RET_STATUS::RET_SUCCEED;
  760. }
  761. bool Detector_TiRayDR::StopCalibration(FPDDeviceTiRay* pDrvDPC)
  762. {
  763. FINFO("--TiRayDR Func-- StopCalibration Start");
  764. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  765. {
  766. FERROR("Not current DPC, return");
  767. return false;
  768. }
  769. if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectState)
  770. {
  771. FERROR("bConnectState is false, Detector not connected, return");
  772. return false;
  773. }
  774. m_nAppStatus = APP_STATUS_CAL_END;
  775. FINFO("TiRayDR StopCalibration Over");
  776. return true;
  777. }
  778. /***
  779. ** 说明:结束校正
  780. ** DPC处理完校正报告后调用,此处上传map、报告等文件
  781. ***/
  782. bool Detector_TiRayDR::CompleteCalibration(FPDDeviceTiRay* pDrvDPC)
  783. {
  784. FINFO("--TiRayDR Func-- CompleteCalibration Start");
  785. FINFO("Calib Type {$}", (int)m_eCaliType);
  786. const std::string funcTag = "[Detector_TiRayDR::CompleteCalibration] ";
  787. if (m_eCaliType == CCOS_CALIBRATION_TYPE_DARK)
  788. {
  789. FINFO("DARK Calib over");
  790. }
  791. else if (m_eCaliType == CCOS_CALIBRATION_TYPE_XRAY)
  792. {
  793. FINFO("XRAY Calib over");
  794. m_nAppStatus = APP_STATUS_CAL_END;
  795. }
  796. m_eCaliType = CCOS_CALIBRATION_TYPE_NONE;
  797. auto err = write_attribute(Attr_CalibrationMode, CalibrationMode_Defect);
  798. if (err == Err_Success)
  799. {
  800. std::cout << funcTag << "Success: Wrote attribute Attr_CalibrationMode with value CalibrationMode_Defect" << std::endl;
  801. }
  802. else
  803. {
  804. std::cout << funcTag << "Error: Failed to write attribute Attr_CalibrationMode, error code: " << err << std::endl;
  805. }
  806. FINFO("TiRayDR CompleteCalibration Over");
  807. return true;
  808. }
  809. bool Detector_TiRayDR::SaveCalibrationFile()
  810. {
  811. FINFO("--TiRayDR Func-- SaveCalibrationFile Start");
  812. if (m_nCalibrationMode)//厂商校正
  813. {
  814. //不做处理
  815. }
  816. else
  817. {
  818. FINFO("Save ZSKK Calibration File");
  819. m_pZSKKCalib->StoreZSKKGainMap(m_strDetectorType);
  820. m_pZSKKCalib->StoreZSKKPixMap(m_strDetectorType);
  821. }
  822. //更新配置文件中校正日期和时间
  823. GlobalTime stCurrentTime = { 0 };
  824. GetLocalTime(&stCurrentTime);
  825. FINFO("Current time: {$04d}/{$02d}/{$02d} {$02d}:{$02d}:{$02d}:{$03d}",
  826. stCurrentTime.wYear, stCurrentTime.wMonth, stCurrentTime.wDay,
  827. stCurrentTime.wHour, stCurrentTime.wMinute, stCurrentTime.wSecond, stCurrentTime.wMilliseconds);
  828. FINFO("TiRayDR SaveCalibrationFile Over");
  829. return true;
  830. }
  831. CCOS_CALIBRATION_TYPE Detector_TiRayDR::GetCalibType()
  832. {
  833. FINFO("--TiRayDR Func-- GetCalibType Start");
  834. FINFO("Get Calib Type {$}", (int)m_eCaliType);
  835. FINFO("TiRayDR GetCalibType Over");
  836. return m_eCaliType;
  837. }
  838. ModelResolveResult Detector_TiRayDR::ResolveModelType(const std::string& detectorType)
  839. {
  840. ModelResolveResult result;
  841. result.isValid = true;
  842. if (detectorType == "GQ1613") {
  843. result.model = Model_GQ1613;
  844. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_GQ1613)..." << endl;
  845. }
  846. else if (detectorType == "DY1613") {
  847. result.model = Model_DY1613;
  848. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_DY1613)..." << endl;
  849. }
  850. else if (detectorType == "LT1719") {
  851. result.model = Model_LT1719;
  852. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_LT1719)..." << endl;
  853. }
  854. else if (detectorType == "DY4343") {
  855. result.model = Model_DY4343;
  856. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_DY4343)..." << endl;
  857. }
  858. else if (detectorType == "DY2530W") {
  859. result.model = Model_DY2530W;
  860. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_DY2530W)..." << endl;
  861. }
  862. else if (detectorType == "DY2121") {
  863. result.model = Model_DY2121;
  864. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_DY2121)..." << endl;
  865. }
  866. else if (detectorType == "DY4343D") {
  867. result.model = Model_DY4343D;
  868. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_DY4343D)..." << endl;
  869. }
  870. else if (detectorType == "GZ0404") {
  871. result.model = Model_GZ0404;
  872. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_GZ0404)..." << endl;
  873. }
  874. else if (detectorType == "DY3543W") {
  875. result.model = Model_DY3543W;
  876. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_DY3543W)..." << endl;
  877. }
  878. else if (detectorType == "DY4343W") {
  879. result.model = Model_DY4343W;
  880. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_DY4343W)..." << endl;
  881. }
  882. else if (detectorType == "DY3543") {
  883. result.model = Model_DY3543;
  884. cout << "[Detector_TiRayDR::OpenDetector] Try to start the detector(Model_DY3543)..." << endl;
  885. }
  886. else {
  887. cout << "[Detector_TiRayDR::OpenDetector] Unsupported detector type: " << detectorType << endl;
  888. // 使用第一个枚举值作为默认,通过isValid标志判断有效性
  889. result.model = Model_GQ1613;
  890. result.isValid = false;
  891. }
  892. return result;
  893. }
  894. bool Detector_TiRayDR::LoadDll(string strWorkPath)
  895. {
  896. FINFO("--TiRayDR Func-- LoadDll Start");
  897. string strSDKPath = "";
  898. try
  899. {
  900. strSDKPath = (string)m_ModeConfig["SDKPath"];
  901. }
  902. catch (ResDataObjectExption& e)
  903. {
  904. FERROR("Read configuration failed! reason: {$}", e.what());
  905. return false;
  906. }
  907. string workpath = strWorkPath + strSDKPath;
  908. string drvpath = workpath + "/TiRayLib.so";
  909. FINFO("SDK path:{$}", drvpath);
  910. m_hTiRayDRModule = dlopen(drvpath.c_str(), RTLD_LAZY);
  911. if (m_hTiRayDRModule == nullptr)
  912. {
  913. FERROR("Load {$} failed! FERROR: {$}", drvpath.c_str(), dlerror());
  914. return false;
  915. }
  916. LOAD_ONE_FUNC(m_hTiRayDRModule, GetSdkVersion);
  917. LOAD_ONE_FUNC(m_hTiRayDRModule, Scan);
  918. LOAD_ONE_FUNC(m_hTiRayDRModule, SetIp);
  919. LOAD_ONE_FUNC(m_hTiRayDRModule, Startup);
  920. LOAD_ONE_FUNC(m_hTiRayDRModule, Stop);
  921. LOAD_ONE_FUNC(m_hTiRayDRModule, Execute);
  922. LOAD_ONE_FUNC(m_hTiRayDRModule, ApplyPreset);
  923. LOAD_ONE_FUNC(m_hTiRayDRModule, GenerateTemplate);
  924. FINFO("TiRayDR LoadDll Over");
  925. return true;
  926. }
  927. bool Detector_TiRayDR::ReleaseDll()
  928. {
  929. FINFO("--TiRayDR Func-- ReleaseDll Start");
  930. if (m_hTiRayDRModule != nullptr)
  931. {
  932. int result = dlclose(m_hTiRayDRModule);
  933. if (result != 0) {
  934. const char* error = dlerror();
  935. if (error) {
  936. FERROR("Failed to unload library: %s", error);
  937. }
  938. else {
  939. FERROR("Failed to unload library (unknown error)");
  940. }
  941. return false;
  942. }
  943. m_hTiRayDRModule = nullptr;
  944. }
  945. FINFO("TiRayDR ReleaseDll Over");
  946. return true;
  947. }
  948. /***
  949. ** 连接探测器
  950. ***/
  951. bool Detector_TiRayDR::OpenDetector()
  952. {
  953. FINFO("--TiRayDR Func-- OpenDetector Start");
  954. m_strWiredIP = (std::string)m_ModeConfig["DetectorWiredIP"];
  955. m_strWirelessIP = (std::string)m_ModeConfig["DetectorWirelessIP"];
  956. m_strLocalIP = (std::string)m_ModeConfig["LocalIP"];
  957. m_strSerialNum = (std::string)m_ModeConfig["SerialNumber"];
  958. FINFO("Configuration parameters loaded - Wired IP:{$}, Wireless IP:{$}, Local IP:{$}",
  959. m_strWiredIP, m_strWirelessIP, m_strLocalIP);
  960. FINFO("WiredIP: {$}, LocalIP: {$}, WirelessIP: {$}, SerialNumber:{$}", m_strWiredIP, m_strLocalIP, m_strWirelessIP, m_strSerialNum);
  961. // 检查连接状态
  962. bool wired = CheckConnect(m_strWiredIP);
  963. bool wireless = CheckConnect(m_strWirelessIP);
  964. FINFO("[Detector_TiRayDR::OpenDetector] Connection status - Wired:{$}, wireless:{$}",
  965. wired ? "Connected" : "Not connected",
  966. wireless ? "Connected" : "Not Connected");
  967. FINFO("[Detector_TiRayDR::OpenDetector] Start scanning the detector...");
  968. std::vector<scan_result> scan_results;
  969. scan([&scan_results](scan_result&& result) {
  970. scan_results.emplace_back(std::move(result));
  971. });
  972. if (scan_results.empty()) {
  973. FINFO("[Detector_TiRayDR::OpenDetector] No detectors were found!");
  974. return false;
  975. }
  976. FINFO("[Detector_TiRayDR::OpenDetector] Scanned to {$} detector:", scan_results.size());
  977. for (auto& res : scan_results) {
  978. FINFO("[Detector_TiRayDR::OpenDetector] Serial number:{$}, Model:{$}, tupper IP:{$}, detector IP:{$}",
  979. res.sn, res.model, res.upper_ip, res.detector_ip);
  980. }
  981. m_strDetectorType = (string)m_ModeConfig["DetectorType"];
  982. FINFO("[Detector_TiRayDR::OpenDetector] Target detector type from config: {$}", m_strDetectorType);
  983. // 选择目标探测器:优先匹配型号,否则使用第一个
  984. scan_result target_res = scan_results[0];
  985. bool found_matching = false;
  986. for (auto& res : scan_results) {
  987. if (res.model == m_strDetectorType) {
  988. target_res = res;
  989. found_matching = true;
  990. break; // 找到第一个匹配的即可
  991. }
  992. }
  993. if (found_matching) {
  994. FINFO("[Detector_TiRayDR::OpenDetector] Found matching detector. Model: {$}, Serial: {$}",
  995. target_res.model, target_res.sn);
  996. }
  997. else {
  998. FINFO("[Detector_TiRayDR::OpenDetector] No matching detector model, using first detected. Model: {$}, Serial: {$}",
  999. target_res.model, target_res.sn);
  1000. }
  1001. // 初始化启动参数
  1002. string ip = "0.0.0.0";
  1003. StartupOption option{};
  1004. memcpy(option.Ip, ip.c_str(), std::min(ip.size(), sizeof(option.Ip) - 1));
  1005. option.EnableLog = true;
  1006. // 调用解析函数处理设备类型
  1007. ModelResolveResult resolveResult = ResolveModelType(target_res.model);
  1008. if (!resolveResult.isValid) {
  1009. return false;
  1010. }
  1011. // 启动探测器
  1012. auto err = Startup_Ptr(resolveResult.model, on_event_callback, &option);
  1013. if (err != Err_Success) {
  1014. FINFO("[Detector_TiRayDR::OpenDetector] Failed to start the detector");
  1015. return false;
  1016. }
  1017. auto LoadCalibrationFile = [this](int calibrationParam)
  1018. {
  1019. TiRayError err;
  1020. switch (calibrationParam) {
  1021. case 1:
  1022. err = write_attribute(Attr_CalibrationMode, CalibrationMode_None);
  1023. break;
  1024. case 2:
  1025. err = write_attribute(Attr_CalibrationMode, CalibrationMode_Gain);
  1026. break;
  1027. case 3:
  1028. err = write_attribute(Attr_CalibrationMode, CalibrationMode_Offset);
  1029. break;
  1030. case 4:
  1031. err = write_attribute(Attr_CalibrationMode, CalibrationMode_Defect);
  1032. break;
  1033. default:
  1034. FINFO("[Detector_TiRayDR::OpenDetector] Invalid calibration parameter: {$}", calibrationParam);
  1035. return false;
  1036. }
  1037. if (err != Err_Success) {
  1038. FINFO("[Detector_TiRayDR::OpenDetector] Failed to write Attr_CalibrationMode, error code: {$}", err);
  1039. }
  1040. else {
  1041. FINFO("[Detector_TiRayDR::OpenDetector] Succeeded in writing Attr_CalibrationMode");
  1042. }
  1043. return true;
  1044. };
  1045. FINFO("Start setting the IP address...");
  1046. err = SetIp_Ptr(target_res.sn.c_str(), m_strLocalIP.c_str(), m_strWiredIP.c_str(), nullptr);
  1047. if (err != TiRayError::Err_Success)
  1048. {
  1049. FINFO("The IP setting failed, error code:{$} (will continue to execute)", err);
  1050. return false;
  1051. }
  1052. else {
  1053. FINFO("IP setting was successful");
  1054. }
  1055. while (!m_bConnected)
  1056. {
  1057. usleep(10000);
  1058. }
  1059. m_pStPanelStatus[m_nCurrentPanelID]->bConnectState = true;
  1060. //FINFO("m_pStPanelStatus[m_nCurrentPanelID]->bConnectState = true");
  1061. //StatusFeedback(EVT_STATUS_PANEL, PANEL_CONNECT);
  1062. //FINFO("Connect detector({$}) success", m_nDetectorID);
  1063. if (m_strDetectorType == "DY4343" || m_strDetectorType == "DY4343D")
  1064. {
  1065. m_bUseGainV2 = true;
  1066. }
  1067. m_nImageWidth = (int)m_ModeConfig["ModeTable"][0]["ImageWidth"];
  1068. m_nImageHeight = (int)m_ModeConfig["ModeTable"][0]["ImageHeight"];
  1069. m_nRawImgWidth = (int)m_ModeConfig["ModeTable"][0]["RawImgWidth"];
  1070. m_nRawImgHeight = (int)m_ModeConfig["ModeTable"][0]["RawImgHeight"];
  1071. FINFO("After crop image width: {$}, height: {$}, WidthOffset: {$}, HeightOffset: {$}", m_nImageWidth, m_nImageHeight, m_nWidthOffset, m_nHeightOffset);
  1072. m_bSaveRaw = (int)m_ModeConfig["ModeTable"][0]["IsSaveRaw"];
  1073. if (m_pRawImgBuffer == nullptr)
  1074. {
  1075. m_pRawImgBuffer = new WORD[(size_t)m_nRawImgHeight * (size_t)m_nRawImgWidth];
  1076. }
  1077. if (true)
  1078. {
  1079. m_pImgBuffer = new WORD[(size_t)m_nImageWidth * (size_t)m_nImageWidth];
  1080. }
  1081. // 加载校准文件
  1082. cout << "[Detector_TiRayDR::OpenDetector] Start loading the calibration file..." << endl;
  1083. //if (m_nCalibrationMode) //TiRayCalibration
  1084. SetSyncMode(3);
  1085. err = write_attribute(Attr_PhotoInterval, 3000);
  1086. if (err != Err_Success)
  1087. FINFO("[Detector_TiRayDR::OpenDetector] Failed to write Attr_PhotoInterval. Error code: {$}", err);
  1088. err = write_attribute(Attr_PhotoNumber, 1);
  1089. if (err != Err_Success)
  1090. FINFO("[Detector_TiRayDR::OpenDetector] Failed to write Attr_PhotoNumber. Error code: {$}", err);
  1091. LoadCalibrationFile(4);
  1092. err = write_attribute(Attr_AEDSensitivity, 1000);
  1093. if (err != Err_Success)
  1094. FINFO("[Detector_TiRayDR::OpenDetector] Failed to write Attr_AEDSensitivity. Error code: {$}", err);
  1095. SetTiRayDPCStatus(eDetStatus::DetStatus_Standby);
  1096. FINFO("OpenDetector Over");
  1097. return true;
  1098. }
  1099. bool Detector_TiRayDR::CheckConnect(string strIP)
  1100. {
  1101. CMyPingip obPingIp;
  1102. if (!obPingIp.PingFunction(strIP.c_str()))
  1103. {
  1104. FINFO("ping {$} Failed", strIP);
  1105. return false;
  1106. }
  1107. return true;
  1108. }
  1109. bool Detector_TiRayDR::OpenStatusMonitor()
  1110. {
  1111. FINFO("---Open Status Monitor Thread---");
  1112. if (m_hStatusMonitorThread == 0) // 检查线程是否已创建
  1113. {
  1114. int result = pthread_create(&m_hStatusMonitorThread, NULL, TiRayStatusMonitorThread, this);
  1115. if (result != 0) {
  1116. FERROR("Failed to create status monitor thread: %d", result);
  1117. return false;
  1118. }
  1119. }
  1120. return true;
  1121. }
  1122. void* Detector_TiRayDR::TiRayStatusMonitorThread(PVOID pvoid)
  1123. {
  1124. Detector_TiRayDR* pCurrentPanelOpr = static_cast<Detector_TiRayDR*>(pvoid);
  1125. if (pCurrentPanelOpr == nullptr)
  1126. {
  1127. FERROR("TiRay Status Monitor parameter FERROR");
  1128. return nullptr;
  1129. }
  1130. FINFO("Begin StatusMonitor");
  1131. DWORD dwStatusCheckTime = 5000;
  1132. while (!pCurrentPanelOpr->m_bMonitorFlag)
  1133. {
  1134. pCurrentPanelOpr->StatusMonitor();
  1135. usleep(pCurrentPanelOpr->m_nNotifyStatusTimePeriod*1000);
  1136. }
  1137. return 0;
  1138. }
  1139. bool Detector_TiRayDR::StatusMonitor()
  1140. {
  1141. if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectState)
  1142. {
  1143. FERROR("Detector not connected, return");
  1144. ErrorFeedback(EVT_ERR_COMMUNICATE, "true");
  1145. return false;
  1146. }
  1147. //StatusType: 1:Temperature 2:Wifi 3:Battery
  1148. //auto ReadStatus = [this](int StatusType)
  1149. //{
  1150. // TiRayVariant TempParam[1]{};
  1151. // TempParam[0].Type = TiRayVariant::TiRayInt;
  1152. //};
  1153. int nTemperature = 0;
  1154. int nWifiQuality = 0;
  1155. int nBatteryLevel = 0;
  1156. TiRayVariant TemperatureParam[1]{};
  1157. TemperatureParam[0].Type = TiRayVariant::TiRayInt;
  1158. TemperatureParam[0].IntValue = 0;
  1159. Execute_Ptr(m_nDetectorID, Cmd_ReadAttribute, TemperatureParam, 1);
  1160. nTemperature = TemperatureParam[0].IntValue;
  1161. TiRayVariant WifiParam[1]{};
  1162. WifiParam[0].Type = TiRayVariant::TiRayInt;
  1163. WifiParam[0].IntValue = nWifiQuality;
  1164. Execute_Ptr(m_nDetectorID, Cmd_ReadAttribute, WifiParam, 1);
  1165. TiRayVariant BatteryParam[1]{};
  1166. BatteryParam[0].Type = TiRayVariant::TiRayInt;
  1167. BatteryParam[0].IntValue = nBatteryLevel;
  1168. Execute_Ptr(m_nDetectorID, Cmd_ReadAttribute, BatteryParam, 1);
  1169. StatusFeedback(EVT_STATUS_TEMPERATURE, 0, "", m_nCurrentPanelID, nTemperature);
  1170. StatusFeedback(EVT_STATUS_BATTERY_VALUE, nBatteryLevel, "", m_nCurrentPanelID);
  1171. StatusFeedback(EVT_STATUS_WIFI, nWifiQuality, "", m_nCurrentPanelID);
  1172. return true;
  1173. }
  1174. bool Detector_TiRayDR::CloseStatusMonitor()
  1175. {
  1176. m_bMonitorFlag = true;
  1177. m_hStatusMonitorThread = 0;
  1178. FINFO("---Close Status Monitor Thread---");
  1179. return true;
  1180. }
  1181. bool Detector_TiRayDR::CloseDetectorScan()
  1182. {
  1183. m_hExitEvent->SetEvent();
  1184. return false;
  1185. }
  1186. bool Detector_TiRayDR::LoadCalibrationFiles(int nCalibrationMode)
  1187. {
  1188. FINFO("--TiRayDR Func-- LoadCalibrationFiles");
  1189. int nRes;
  1190. TiRayVariant Param[2]{};
  1191. Param[0].Type = TiRayVariant::TiRayInt;
  1192. Param[0].IntValue = TiRayAttribute::Attr_CalibrationMode;
  1193. Param[1].Type = TiRayVariant::TiRayInt;
  1194. if (nCalibrationMode == 1)
  1195. {
  1196. Param[1].IntValue = CalibrationMode::CalibrationMode_None;
  1197. }
  1198. else if (nCalibrationMode == 2)
  1199. {
  1200. Param[1].IntValue = CalibrationMode::CalibrationMode_Gain;
  1201. }
  1202. else if (nCalibrationMode == 3)
  1203. {
  1204. Param[1].IntValue = CalibrationMode::CalibrationMode_Offset;
  1205. }
  1206. else if (nCalibrationMode == 4)
  1207. {
  1208. Param[1].IntValue = CalibrationMode::CalibrationMode_Defect;
  1209. FINFO("All Calibration Mode");
  1210. }
  1211. nRes = Execute_Ptr(m_nDetectorID, Cmd_WriteAttribute, Param, 2);
  1212. if ((TiRayError)nRes != TiRayError::Err_Success)
  1213. {
  1214. FERROR("Use CalibrationMode Failed, Reason:{$}", nRes);
  1215. return false;
  1216. }
  1217. else
  1218. {
  1219. FINFO("Use CalibrationMode Success");
  1220. }
  1221. FINFO("LoadCalibrationFiles Over");
  1222. return true;
  1223. }
  1224. void* Detector_TiRayDR::onFPDScanThread(PVOID pvoid)
  1225. {
  1226. Detector_TiRayDR* pOpr = (Detector_TiRayDR*)pvoid;
  1227. FINFO("Enter scan thread");
  1228. bool bExit = false;
  1229. DWORD dwTimeOut = INFINITE;
  1230. while (!bExit)
  1231. {
  1232. DWORD dwRet = LinuxEvent::WaitForMultipleEvents(pOpr->m_hArrayEvent,dwTimeOut);
  1233. if (WAIT_OBJECT_0 == dwRet) //m_hInitEvent
  1234. {
  1235. pOpr->OnProcessInitFPD();
  1236. }
  1237. else if (WAIT_OBJECT_0 + 1 == dwRet) //m_hExitEvent
  1238. {
  1239. bExit = true;
  1240. }
  1241. else if (WAIT_OBJECT_0 + 2 == dwRet) //m_hReConnectEvent
  1242. {
  1243. pOpr->OnReconnectFPD();
  1244. }
  1245. else if (WAIT_OBJECT_0 + 3 == dwRet) //m_hRadEvent
  1246. {
  1247. FINFO("[Get Rad Event]");
  1248. pOpr->OpenRadAcquisition();
  1249. }
  1250. else if (WAIT_TIMEOUT == dwRet)
  1251. {
  1252. }
  1253. }
  1254. pOpr->m_hToggleEvent->SetEvent();
  1255. FINFO("Leave scan thread");
  1256. return 0;
  1257. }
  1258. void Detector_TiRayDR::OnProcessInitFPD()
  1259. {
  1260. FINFO("--TiRayDR Func-- OnProcessInitFPD");
  1261. StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_START);
  1262. if (!LoadDll(m_strWorkPath))
  1263. {
  1264. ErrorFeedback(EVT_ERR_INIT_FAILED, "true");
  1265. StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_ERROR); //初始化失败
  1266. return;
  1267. }
  1268. register_event_listener(OnEvent);
  1269. FINFO("Register Event Listener");
  1270. if (!OpenDetector())
  1271. {
  1272. FINFO("Open detector failed, Connect failed");
  1273. ErrorFeedback(EVT_ERR_COMMUNICATE, "true");
  1274. StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END); //初始化时连接失败
  1275. }
  1276. else
  1277. {
  1278. m_pStPanelStatus[m_nCurrentPanelID]->bInitOver = true;
  1279. StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_OK);
  1280. }
  1281. FINFO("OnProcessInitFPD Over");
  1282. }
  1283. void Detector_TiRayDR::OnReconnectFPD()
  1284. {
  1285. FINFO("OnReconnectFPD start");
  1286. if (m_hReconnectThread == 0)
  1287. {
  1288. m_bReconnectThreadRunning = true;
  1289. int result = pthread_create(&m_hReconnectThread, NULL, onReconnectThread, this);
  1290. if (result != 0) {
  1291. FERROR("Failed to create reconnect thread: %d", result);
  1292. m_hReconnectThread = 0;
  1293. m_bReconnectThreadRunning = false;
  1294. }
  1295. }
  1296. FINFO("OnReconnectFPD end");
  1297. }
  1298. /***
  1299. ** 获取一帧暗场图
  1300. ***/
  1301. int Detector_TiRayDR::DarkAcquisition()
  1302. {
  1303. const std::string funcTag = "[Detector_TiRayDR::DarkAcquisition] ";
  1304. TiRayError err;
  1305. // 设置校准模式为None
  1306. err = write_attribute(Attr_CalibrationMode, CalibrationMode_None);
  1307. if (err != Err_Success) {
  1308. cout << funcTag << "Failed to write Attr_CalibrationMode. Error code: " << err << endl;
  1309. return -1;
  1310. }
  1311. // 设置拍摄间隔
  1312. err = write_attribute(Attr_PhotoInterval, 1000);
  1313. if (err != Err_Success) {
  1314. cout << funcTag << "Failed to write Attr_PhotoInterval. Error code: " << err << endl;
  1315. return -1;
  1316. }
  1317. // 设置工作模式为空闲
  1318. err = write_attribute(Attr_WorkMode, WorkMode_Idle);
  1319. if (err != Err_Success) {
  1320. cout << funcTag << "Failed to write Attr_WorkMode. Error code: " << err << endl;
  1321. return -1;
  1322. }
  1323. // 执行拍摄命令
  1324. err = Execute_Ptr(m_nDetectorID, Cmd_Photo, nullptr, 0);
  1325. if (err != Err_Success) {
  1326. cout << funcTag << "Failed to Execute_Ptr Cmd_Photo. Error code: " << err << endl;
  1327. return -1;
  1328. }
  1329. return 0; // 成功执行返回0
  1330. }
  1331. /***
  1332. ** 裁剪图像
  1333. ** pOutImg: 裁剪后图像; pInImg: 裁剪前图像; nInWidth: 裁剪前图像宽度
  1334. ***/
  1335. bool Detector_TiRayDR::GetEffectiveImage(WORD* pOutImg, WORD* pInImg, int nInWidth)
  1336. {
  1337. if (pOutImg == NULL || pInImg == NULL || nInWidth < 0)
  1338. {
  1339. FERROR("Illegal parameter, can not get effective image");
  1340. return false;
  1341. }
  1342. try
  1343. {
  1344. for (int i = 0; i < m_nImageHeight; i++)
  1345. {
  1346. memcpy(pOutImg + i * m_nImageWidth, pInImg + (i + m_nHeightOffset) * nInWidth + m_nWidthOffset, m_nImageWidth * sizeof(WORD));
  1347. }
  1348. }
  1349. catch (...)
  1350. {
  1351. FERROR("Get effective image crashed");
  1352. return false;
  1353. }
  1354. return true;
  1355. }
  1356. Detector_TiRayDR::eDetStatus Detector_TiRayDR::GetTiRayDPCStatus(int nDetectorIndex)
  1357. {
  1358. if (-1 == nDetectorIndex)
  1359. {
  1360. nDetectorIndex = m_nCurrentPanelID;
  1361. }
  1362. string strStatus = "Unknown";
  1363. switch (m_pStPanelStatus[nDetectorIndex]->eFPDStatus)
  1364. {
  1365. case eDetStatus::DetStatus_NotIni:
  1366. strStatus = "NotIni";
  1367. break;
  1368. case eDetStatus::DetStatus_NotConn:
  1369. strStatus = "NotConn";
  1370. break;
  1371. case eDetStatus::DetStatus_Sleep:
  1372. strStatus = "Sleep";
  1373. break;
  1374. case eDetStatus::DetStatus_Standby:
  1375. strStatus = "Standby";
  1376. break;
  1377. case eDetStatus::DetStatus_Work:
  1378. strStatus = "Work";
  1379. break;
  1380. case eDetStatus::DetStatus_Acquire:
  1381. strStatus = "Acquire";
  1382. break;
  1383. case eDetStatus::DetStatus_Offset:
  1384. strStatus = "Offset";
  1385. break;
  1386. case eDetStatus::DetStatus_XrayCalibration:
  1387. strStatus = "XrayCalibration";
  1388. break;
  1389. default:
  1390. break;
  1391. }
  1392. FINFO("Driver status: {$}", strStatus.c_str());
  1393. return m_pStPanelStatus[nDetectorIndex]->eFPDStatus;
  1394. }
  1395. bool Detector_TiRayDR::SetTiRayDPCStatus(eDetStatus status, int nDetectorIndex)
  1396. {
  1397. if (-1 == nDetectorIndex)
  1398. {
  1399. nDetectorIndex = m_nCurrentPanelID;
  1400. }
  1401. string strStatus = "Unknown";
  1402. bool bSetStatus = true;
  1403. switch (status)
  1404. {
  1405. case eDetStatus::DetStatus_NotIni:
  1406. strStatus = "NotIni";
  1407. break;
  1408. case eDetStatus::DetStatus_NotConn:
  1409. strStatus = "NotConn";
  1410. break;
  1411. case eDetStatus::DetStatus_Sleep:
  1412. strStatus = "Sleep";
  1413. break;
  1414. case eDetStatus::DetStatus_Standby:
  1415. strStatus = "Standby";
  1416. break;
  1417. case eDetStatus::DetStatus_Work:
  1418. strStatus = "Work";
  1419. break;
  1420. case eDetStatus::DetStatus_Acquire:
  1421. strStatus = "Acquire";
  1422. break;
  1423. case eDetStatus::DetStatus_Offset:
  1424. strStatus = "Offset";
  1425. break;
  1426. case eDetStatus::DetStatus_XrayCalibration:
  1427. strStatus = "XrayCalibration";
  1428. break;
  1429. default:
  1430. bSetStatus = false;
  1431. break;
  1432. }
  1433. if (bSetStatus)
  1434. {
  1435. m_pStPanelStatus[nDetectorIndex]->eFPDStatus = status;
  1436. FINFO("Set driver status: {$}", strStatus.c_str());
  1437. }
  1438. else
  1439. {
  1440. FERROR("{$} {$} is a illegal status", strStatus, (int)status);
  1441. }
  1442. return bSetStatus;
  1443. }
  1444. bool Detector_TiRayDR::IsConnected(string strIP)
  1445. {
  1446. FINFO("Check ping {$}", strIP);
  1447. CMyPingip obPingIp;
  1448. if (!obPingIp.PingFunction(strIP.c_str()))
  1449. {
  1450. FINFO("ping {$} Failed", strIP);
  1451. return false;
  1452. }
  1453. return true;
  1454. }
  1455. bool Detector_TiRayDR::CheckConnection()
  1456. {
  1457. return false;
  1458. }
  1459. bool Detector_TiRayDR::ReConnectFPD()
  1460. {
  1461. CloseStatusMonitor();
  1462. return true;
  1463. }
  1464. bool Detector_TiRayDR::OpenRadAcquisition()
  1465. {
  1466. FINFO("---Begin Rad Acquisition Thread---");
  1467. m_bExitRadAcqStatus = true;
  1468. if (m_hRadAcquisitionThread == 0)
  1469. {
  1470. int result = pthread_create(&m_hRadAcquisitionThread, NULL, RadAcquisitionThread, this);
  1471. if (result != 0) {
  1472. FERROR("Failed to create status monitor thread: %d", result);
  1473. return false;
  1474. }
  1475. }
  1476. return true;
  1477. }
  1478. void* Detector_TiRayDR::RadAcquisitionThread(void* pParam)
  1479. {
  1480. Detector_TiRayDR* pCurrentPanelOpr = reinterpret_cast<Detector_TiRayDR*>(pParam);
  1481. if (pCurrentPanelOpr == nullptr)
  1482. {
  1483. FERROR("Query Acq Status Thread parameter FERROR");
  1484. }
  1485. pCurrentPanelOpr->PerformRadAcquisition();
  1486. pCurrentPanelOpr->CloseRadAcquisition();
  1487. return nullptr;
  1488. }
  1489. bool Detector_TiRayDR::PerformRadAcquisition()
  1490. {
  1491. FINFO("## PerformRadAcquisition ##");
  1492. FINFO("Start Acquisition");
  1493. FINFO("DetectorID: {$}", m_nDetectorID);
  1494. //int nRes = Execute_Ptr(m_nDetectorID, Cmd_Photo, nullptr, 0);
  1495. //if ((TiRayError)nRes != TiRayError::Err_Success)
  1496. //{
  1497. // FERROR("Start Acquisition Failed");
  1498. //}
  1499. while (true)
  1500. {
  1501. usleep(100000);
  1502. if (!m_bExitRadAcqStatus)
  1503. {
  1504. break;
  1505. }
  1506. }
  1507. m_hExitRadAcqStatus->SetEvent();
  1508. FINFO("PerformRadAcquisition Over");
  1509. return true;
  1510. }
  1511. bool Detector_TiRayDR::CloseRadAcquisition()
  1512. {
  1513. m_bExitRadAcqStatus = false;
  1514. bool dwResult = false;
  1515. if (m_hExitRadAcqStatus) {
  1516. dwResult = m_hExitRadAcqStatus->Wait(1000);
  1517. }
  1518. if (dwResult)
  1519. {
  1520. FINFO("[Get ExitRadAcqStatus Event]");
  1521. }
  1522. else
  1523. {
  1524. if (m_hRadAcquisitionThread != 0) {
  1525. pthread_cancel(m_hRadAcquisitionThread);
  1526. // 等待线程实际退出
  1527. struct timespec ts;
  1528. clock_gettime(CLOCK_REALTIME, &ts);
  1529. ts.tv_sec += 1; // 等待1秒
  1530. pthread_timedjoin_np(m_hRadAcquisitionThread, nullptr, &ts);
  1531. FWARN("Kill QueryAcqStatus Thread");
  1532. }
  1533. FWARN("Kill QueryAcqStatus Thread");
  1534. }
  1535. m_hRadAcquisitionThread = 0;
  1536. FINFO("---Exit Rad Acq Status Thread---");
  1537. return true;
  1538. }
  1539. /***
  1540. ** 检测接口是否有错误,true:有错;false:没错
  1541. ***/
  1542. bool Detector_TiRayDR::TestError(TiRayError nErrorCode)
  1543. {
  1544. if (nErrorCode == TiRayError::Err_Success)
  1545. {
  1546. return true;
  1547. }
  1548. else
  1549. {
  1550. switch (nErrorCode)
  1551. {
  1552. case TiRayError::Err_SystemFailure:
  1553. {
  1554. FERROR("System Internal Error");
  1555. break;
  1556. }
  1557. case TiRayError::Err_WrongModel:
  1558. {
  1559. FERROR("The specified model is incorrect");
  1560. break;
  1561. }
  1562. case TiRayError::Err_DetectorNonExists:
  1563. {
  1564. FERROR("The specified detector with the given ID dose not exist");
  1565. break;
  1566. }
  1567. case TiRayError::Err_NetworkFailure:
  1568. {
  1569. FERROR("The network communication has failed");
  1570. break;
  1571. }
  1572. case TiRayError::Err_InvalidParam:
  1573. {
  1574. FERROR("The provided parameters are incorrect");
  1575. break;
  1576. }
  1577. case TiRayError::Err_UploadInProgress:
  1578. {
  1579. FERROR("The upload is in progress");
  1580. break;
  1581. }
  1582. default:
  1583. FERROR("Unkonwn Error");
  1584. break;
  1585. }
  1586. return false;
  1587. }
  1588. }
  1589. void Detector_TiRayDR::register_event_listener(const EventListener& fn)
  1590. {
  1591. const auto iter = std::find_if(m_listeners.begin(), m_listeners.end(), [&fn](auto& listener) {
  1592. return listener.template target<EventListenerType>() == fn.template target<EventListenerType>();
  1593. });
  1594. if (iter == m_listeners.end())
  1595. m_listeners.push_back(fn);
  1596. }
  1597. void Detector_TiRayDR::unregister_event_listener(const EventListener& fn)
  1598. {
  1599. const auto iter = std::find_if(m_listeners.begin(), m_listeners.end(), [&fn](auto& listener) {
  1600. return listener.template target<EventListenerType>() == fn.template target<EventListenerType>();
  1601. });
  1602. if (iter == m_listeners.end())
  1603. m_listeners.erase(iter);
  1604. }
  1605. bool Detector_TiRayDR::cropImage(unsigned short* srcData, int srcWidth, int srcHeight,
  1606. unsigned short* destData, int destWidth, int destHeight)
  1607. {
  1608. // 验证指针有效性
  1609. if (srcData == nullptr || destData == nullptr) {
  1610. cout << "[Detector_TiRayDR::cropImage] Error: Source or destination pointer is null" << endl;
  1611. return false;
  1612. }
  1613. // 验证尺寸合法性
  1614. if (destWidth <= 0 || destHeight <= 0 ||
  1615. srcWidth <= 0 || srcHeight <= 0 ||
  1616. destWidth > srcWidth || destHeight > srcHeight)
  1617. {
  1618. cout << "[Detector_TiRayDR::cropImage] Invalid crop size: src("
  1619. << srcWidth << "x" << srcHeight << ") dest("
  1620. << destWidth << "x" << destHeight << ")" << endl;
  1621. return false;
  1622. }
  1623. // 计算裁剪起始位置
  1624. int startX = (srcWidth - destWidth) / 2;
  1625. int startY = (srcHeight - destHeight) / 2;
  1626. // 边界检查
  1627. if (startX < 0) startX = 0;
  1628. if (startY < 0) startY = 0;
  1629. // 确保裁剪区域不会超出源图像边界
  1630. if (startX + destWidth > srcWidth) {
  1631. destWidth = srcWidth - startX;
  1632. cout << "[Detector_TiRayDR::cropImage] Adjusted destWidth to " << destWidth
  1633. << " to avoid out-of-bounds access" << endl;
  1634. }
  1635. if (startY + destHeight > srcHeight) {
  1636. destHeight = srcHeight - startY;
  1637. cout << "[Detector_TiRayDR::cropImage] Adjusted destHeight to " << destHeight
  1638. << " to avoid out-of-bounds access" << endl;
  1639. }
  1640. // 逐行复制裁剪区域
  1641. for (int y = 0; y < destHeight; ++y)
  1642. {
  1643. // 计算源图像行起始地址
  1644. const unsigned short* srcRow = srcData + (startY + y) * srcWidth + startX;
  1645. // 计算目标图像行起始地址
  1646. unsigned short* destRow = destData + y * destWidth;
  1647. // 复制一行像素
  1648. memcpy(destRow, srcRow, destWidth * sizeof(unsigned short));
  1649. }
  1650. cout << "[Detector_TiRayDR::cropImage] Successfully cropped image from "
  1651. << srcWidth << "x" << srcHeight << " to " << destWidth << "x" << destHeight << endl;
  1652. return true;
  1653. }
  1654. std::string Detector_TiRayDR::saveProcessedImage(Detector_TiRayDR& detector, unsigned short* data, size_t size, const std::string& baseTimestamp)
  1655. {
  1656. const size_t MAX_PROC_FILE_COUNT = 10;
  1657. const std::string TMPFS_DIR = "/mnt/tmpfs/";
  1658. const std::string ORIGINAL_DIR = detector.m_strWorkPath + "/RawData/";
  1659. std::string procDir;
  1660. bool useTmpfs = false;
  1661. // 确定存储目录
  1662. if (std::filesystem::exists(TMPFS_DIR) && std::filesystem::is_directory(TMPFS_DIR))
  1663. {
  1664. procDir = TMPFS_DIR;
  1665. useTmpfs = true;
  1666. std::cout << "[Detector_TiRayDR::saveProcessedImage] Using tmpfs directory: " << procDir << std::endl;
  1667. }
  1668. else
  1669. {
  1670. procDir = ORIGINAL_DIR;
  1671. std::cout << "[Detector_TiRayDR::saveProcessedImage] /mnt/tmpfs not found, using original directory: " << procDir << std::endl;
  1672. }
  1673. const std::string FILE_PREFIX = "Proc_";
  1674. std::string filePath;
  1675. try
  1676. {
  1677. std::filesystem::create_directories(procDir);
  1678. filePath = procDir + FILE_PREFIX + baseTimestamp + ".raw";
  1679. std::ofstream file(filePath, std::ios::binary);
  1680. if (file.is_open())
  1681. {
  1682. file.write(reinterpret_cast<const char*>(detector.m_pImgBuffer), size);
  1683. std::cout << "[Detector_TiRayDR::saveProcessedImage] Saved image: " << filePath << std::endl;
  1684. }
  1685. else
  1686. {
  1687. std::cout << "[Detector_TiRayDR::saveProcessedImage] Failed to open file: " << filePath << std::endl;
  1688. return "";
  1689. }
  1690. cleanOldFiles(procDir, FILE_PREFIX, MAX_PROC_FILE_COUNT, useTmpfs);
  1691. }
  1692. catch (const std::filesystem::filesystem_error& e)
  1693. {
  1694. std::cout << "[Detector_TiRayDR::saveProcessedImage] File system error: " << e.what() << std::endl;
  1695. return "";
  1696. }
  1697. catch (const std::exception& e)
  1698. {
  1699. std::cout << "[Detector_TiRayDR::saveProcessedImage] Unexpected error: " << e.what() << std::endl;
  1700. return "";
  1701. }
  1702. return filePath;
  1703. }
  1704. void Detector_TiRayDR::saveRawImage(Detector_TiRayDR& detector, unsigned short* data, size_t size, const std::string& baseTimestamp)
  1705. {
  1706. const std::string RAW_DIR = detector.m_strWorkPath + "/OriginalData/";
  1707. const std::string FILE_PREFIX = "orig_";
  1708. const size_t MAX_RAW_FILE_COUNT = 20;
  1709. std::string filePath;
  1710. try
  1711. {
  1712. std::filesystem::create_directories(RAW_DIR);
  1713. filePath = RAW_DIR + FILE_PREFIX + baseTimestamp + ".raw";
  1714. std::ofstream file(filePath, std::ios::binary);
  1715. if (file.is_open())
  1716. {
  1717. // 直接写入unsigned short缓冲区数据
  1718. file.write(reinterpret_cast<const char*>(data), size);
  1719. cout << "[Detector_TiRayDR::saveRawImage] Saved raw image: " << filePath << endl;
  1720. }
  1721. else
  1722. {
  1723. cout << "[Detector_TiRayDR::saveRawImage] Failed to open file: " << filePath << endl;
  1724. return;
  1725. }
  1726. // 清理旧的原始图
  1727. cleanOldFiles(RAW_DIR, FILE_PREFIX, MAX_RAW_FILE_COUNT, false);
  1728. }
  1729. catch (const std::filesystem::filesystem_error& e)
  1730. {
  1731. cout << "[Detector_TiRayDR::saveRawImage] File system error: " << e.what() << endl;
  1732. }
  1733. }
  1734. std::filesystem::space_info getFileSystemInfo(const std::string& dirPath) {
  1735. try {
  1736. return std::filesystem::space(dirPath);
  1737. }
  1738. catch (const std::filesystem::filesystem_error& e) {
  1739. std::cout << "[getFileSystemInfo] Failed to get filesystem info for "
  1740. << dirPath << ": " << e.what() << std::endl;
  1741. return {};
  1742. }
  1743. }
  1744. void Detector_TiRayDR::cleanOldFiles(const std::string& dirPath, const std::string& filePrefix,
  1745. size_t maxCount, bool checkSize)
  1746. {
  1747. const std::string funcTag = "[Detector_TiRayDR::cleanOldFiles] ";
  1748. try
  1749. {
  1750. // 检查目录是否存在
  1751. if (!std::filesystem::exists(dirPath) || !std::filesystem::is_directory(dirPath))
  1752. {
  1753. std::cout << funcTag << "Directory not found: " << dirPath << std::endl;
  1754. return;
  1755. }
  1756. std::vector<std::filesystem::directory_entry> targetFiles;
  1757. for (const auto& entry : std::filesystem::directory_iterator(dirPath))
  1758. {
  1759. // 只处理常规文件
  1760. if (!entry.is_regular_file())
  1761. continue;
  1762. // 检查文件扩展名是否为.raw
  1763. const std::string extension = entry.path().extension().string();
  1764. if (extension != ".raw")
  1765. continue;
  1766. // 检查文件名是否以指定前缀开头
  1767. const std::string filename = entry.path().filename().string();
  1768. if (filename.length() < filePrefix.length())
  1769. continue;
  1770. if (filename.substr(0, filePrefix.length()) == filePrefix)
  1771. {
  1772. targetFiles.push_back(entry);
  1773. }
  1774. }
  1775. // 按文件最后修改时间排序(最旧的在前)
  1776. std::sort(targetFiles.begin(), targetFiles.end(),
  1777. [](const std::filesystem::directory_entry& a, const std::filesystem::directory_entry& b)
  1778. {
  1779. return std::filesystem::last_write_time(a) < std::filesystem::last_write_time(b);
  1780. });
  1781. // 1. 先按数量限制清理
  1782. size_t filesToDelete = 0;
  1783. if (targetFiles.size() > maxCount)
  1784. {
  1785. filesToDelete = targetFiles.size() - maxCount;
  1786. // 删除超出数量限制的最旧文件
  1787. for (size_t i = 0; i < filesToDelete; ++i)
  1788. {
  1789. const auto& fileToDelete = targetFiles[i];
  1790. if (std::filesystem::remove(fileToDelete.path()))
  1791. {
  1792. std::cout << funcTag << "Deleted old file (count limit): " << fileToDelete.path() << std::endl;
  1793. }
  1794. else
  1795. {
  1796. std::cout << funcTag << "Failed to delete file: " << fileToDelete.path() << std::endl;
  1797. }
  1798. }
  1799. // 更新目标文件列表(移除已删除的文件)
  1800. targetFiles.erase(targetFiles.begin(), targetFiles.begin() + filesToDelete);
  1801. filesToDelete = 0; // 重置计数器用于大小检查
  1802. }
  1803. // 2. 如果需要,按大小限制清理(仅对tmpfs目录)
  1804. if (checkSize && !targetFiles.empty())
  1805. {
  1806. // 获取文件系统信息
  1807. auto fsInfo = getFileSystemInfo(dirPath);
  1808. if (fsInfo.capacity == 0) // 获取信息失败
  1809. {
  1810. std::cout << funcTag << "Cannot check filesystem size, skipping size check" << std::endl;
  1811. return;
  1812. }
  1813. // 计算最大允许使用空间(预留10%作为缓冲)
  1814. const uintmax_t reservedSpace = fsInfo.capacity / 10; // 10%预留空间
  1815. const uintmax_t maxAllowedSize = fsInfo.capacity - reservedSpace;
  1816. // 计算当前文件总大小
  1817. auto calculateTotalSize = [](const std::vector<std::filesystem::directory_entry>& files) {
  1818. uintmax_t total = 0;
  1819. for (const auto& file : files) {
  1820. total += file.file_size();
  1821. }
  1822. return total;
  1823. };
  1824. uintmax_t currentTotalSize = calculateTotalSize(targetFiles);
  1825. std::cout << funcTag << "Current files total size: " << currentTotalSize
  1826. << ", Max allowed size: " << maxAllowedSize << std::endl;
  1827. // 如果当前总大小超过限制,继续删除最旧的文件
  1828. while (currentTotalSize > maxAllowedSize && !targetFiles.empty())
  1829. {
  1830. const auto& fileToDelete = targetFiles[0];
  1831. uintmax_t fileSize = fileToDelete.file_size();
  1832. if (std::filesystem::remove(fileToDelete.path()))
  1833. {
  1834. std::cout << funcTag << "Deleted old file (size limit): " << fileToDelete.path()
  1835. << " (" << fileSize << " bytes)" << std::endl;
  1836. // 更新总量和文件列表
  1837. currentTotalSize -= fileSize;
  1838. targetFiles.erase(targetFiles.begin());
  1839. filesToDelete++;
  1840. }
  1841. else
  1842. {
  1843. std::cout << funcTag << "Failed to delete file: " << fileToDelete.path() << std::endl;
  1844. break; // 删除失败时停止处理
  1845. }
  1846. }
  1847. }
  1848. std::cout << funcTag << "Cleanup completed. Deleted " << filesToDelete
  1849. << " files. Remaining: " << targetFiles.size() << std::endl;
  1850. }
  1851. catch (const std::filesystem::filesystem_error& e)
  1852. {
  1853. std::cout << funcTag << "File system error: " << e.what() << std::endl;
  1854. }
  1855. catch (const std::exception& e)
  1856. {
  1857. std::cout << funcTag << "Unexpected error: " << e.what() << std::endl;
  1858. }
  1859. }
  1860. void Detector_TiRayDR::handleHardwareSyncImage(Detector_TiRayDR& detector, TiRayVariant argv[])
  1861. {
  1862. detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON);
  1863. const size_t rawPixelCount = argv[3].DataLen / sizeof(unsigned short);
  1864. detector.m_pRawImgBuffer = reinterpret_cast<unsigned short*>(argv[3].DataValue);
  1865. const size_t rawSize = rawPixelCount * sizeof(unsigned short);
  1866. bool cropSuccess = cropImage(
  1867. detector.m_pRawImgBuffer,
  1868. detector.m_nRawImgWidth, detector.m_nRawImgHeight, // 原始图像宽高
  1869. detector.m_pImgBuffer,
  1870. detector.m_nImageWidth, detector.m_nImageHeight // 目标宽高
  1871. );
  1872. if (!cropSuccess)
  1873. {
  1874. cout << "[Detector_TiRayDR::handleAedSyncImage] Failed to crop image" << endl;
  1875. return;
  1876. }
  1877. const size_t processedSize = detector.m_nImageWidth * detector.m_nImageHeight * sizeof(unsigned short);
  1878. // 生成关联的基础文件名
  1879. const std::string baseTimestamp = std::to_string(
  1880. std::chrono::duration_cast<std::chrono::milliseconds>(
  1881. std::chrono::system_clock::now().time_since_epoch()
  1882. ).count()
  1883. );
  1884. std::string processedImagePath = saveProcessedImage(
  1885. detector,
  1886. detector.m_pImgBuffer,
  1887. processedSize,
  1888. baseTimestamp
  1889. );
  1890. if (detector.m_bSaveRaw)
  1891. {
  1892. saveRawImage(
  1893. detector,
  1894. detector.m_pRawImgBuffer,
  1895. rawSize,
  1896. baseTimestamp
  1897. );
  1898. }
  1899. // 应用校准
  1900. // applyCalibration(detector);
  1901. detector.InfoFeedback(EVT_DATA_RAW_IMAGE, -1, 0, 0, processedImagePath.c_str());
  1902. //detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF);
  1903. detector.m_bExitRadAcqStatus = false;
  1904. }
  1905. void Detector_TiRayDR::handleSoftwareSyncImage(Detector_TiRayDR& detector, TiRayVariant argv[])
  1906. {
  1907. detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON);
  1908. const size_t rawPixelCount = argv[3].DataLen / sizeof(unsigned short);
  1909. detector.m_pRawImgBuffer = reinterpret_cast<unsigned short*>(argv[3].DataValue);
  1910. const size_t rawSize = rawPixelCount * sizeof(unsigned short);
  1911. bool cropSuccess = cropImage(
  1912. detector.m_pRawImgBuffer,
  1913. detector.m_nRawImgWidth, detector.m_nRawImgHeight, // 原始图像宽高
  1914. detector.m_pImgBuffer,
  1915. detector.m_nImageWidth, detector.m_nImageHeight // 目标宽高
  1916. );
  1917. if (!cropSuccess)
  1918. {
  1919. cout << "[Detector_TiRayDR::handleSoftwareSyncImage] Failed to crop image" << endl;
  1920. return;
  1921. }
  1922. const size_t processedSize = detector.m_nImageWidth * detector.m_nImageHeight * sizeof(unsigned short);
  1923. // 生成关联的基础文件名
  1924. const std::string baseTimestamp = std::to_string(
  1925. std::chrono::duration_cast<std::chrono::milliseconds>(
  1926. std::chrono::system_clock::now().time_since_epoch()
  1927. ).count()
  1928. );
  1929. std::string processedImagePath = saveProcessedImage(
  1930. detector,
  1931. detector.m_pImgBuffer,
  1932. processedSize,
  1933. baseTimestamp
  1934. );
  1935. if (detector.m_bSaveRaw)
  1936. {
  1937. saveRawImage(
  1938. detector,
  1939. detector.m_pRawImgBuffer,
  1940. rawSize,
  1941. baseTimestamp
  1942. );
  1943. }
  1944. detector.InfoFeedback(EVT_DATA_RAW_IMAGE, -1, 0, 0, processedImagePath.c_str());
  1945. // 应用校准
  1946. // applyCalibration(detector);
  1947. //detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF);
  1948. detector.m_bExitRadAcqStatus = false;
  1949. }
  1950. void Detector_TiRayDR::handleAedSyncImage(Detector_TiRayDR& detector, TiRayVariant argv[])
  1951. {
  1952. detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_START_ACQ);
  1953. detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_XRAY_ON);
  1954. detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON);
  1955. const size_t rawPixelCount = argv[3].DataLen / sizeof(unsigned short);
  1956. detector.m_pRawImgBuffer = reinterpret_cast<unsigned short*>(argv[3].DataValue);
  1957. const size_t rawSize = rawPixelCount * sizeof(unsigned short);
  1958. bool cropSuccess = cropImage(
  1959. detector.m_pRawImgBuffer,
  1960. detector.m_nRawImgWidth, detector.m_nRawImgHeight, // 原始图像宽高
  1961. detector.m_pImgBuffer,
  1962. detector.m_nImageWidth, detector.m_nImageHeight // 目标宽高
  1963. );
  1964. if (!cropSuccess)
  1965. {
  1966. cout << "[Detector_TiRayDR::handleAedSyncImage] Failed to crop image" << endl;
  1967. return;
  1968. }
  1969. const size_t processedSize = detector.m_nImageWidth * detector.m_nImageHeight * sizeof(unsigned short);
  1970. // 生成关联的基础文件名
  1971. const std::string baseTimestamp = std::to_string(
  1972. std::chrono::duration_cast<std::chrono::milliseconds>(
  1973. std::chrono::system_clock::now().time_since_epoch()
  1974. ).count()
  1975. );
  1976. std::string processedImagePath = saveProcessedImage(
  1977. detector,
  1978. detector.m_pImgBuffer,
  1979. processedSize,
  1980. baseTimestamp
  1981. );
  1982. if (detector.m_bSaveRaw)
  1983. {
  1984. saveRawImage(
  1985. detector,
  1986. detector.m_pRawImgBuffer,
  1987. rawSize,
  1988. baseTimestamp
  1989. );
  1990. }
  1991. // applyCalibration(detector);
  1992. detector.InfoFeedback(EVT_DATA_RAW_IMAGE, -1, 0, 0, processedImagePath.c_str());
  1993. detector.m_bAEDWorkFlag = false;
  1994. //usleep(500000);
  1995. //detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF);
  1996. detector.m_bExitRadAcqStatus = false;
  1997. }
  1998. void Detector_TiRayDR::handleDarkCalibration(Detector_TiRayDR& detector, TiRayVariant argv[])
  1999. {
  2000. const std::string funcTag = "[Detector_TiRayDR::handleDarkCalibration] ";
  2001. static int callCount = 0;
  2002. static std::vector<TiRayVariant> datas;
  2003. // 处理当前传入的图像数据
  2004. auto size = argv[3].DataLen;
  2005. auto data = argv[3].DataValue;
  2006. image_info image;
  2007. image.width = argv[0].IntValue;
  2008. image.height = argv[1].IntValue;
  2009. image.data.resize(size);
  2010. memcpy(image.data.data(), data, size);
  2011. // 将当前图像数据存入集合
  2012. TiRayVariant variant;
  2013. variant.Type = TiRayVariant::TiRayBuffer;
  2014. variant.DataLen = static_cast<int>(image.data.size());
  2015. variant.DataValue = image.data.data();
  2016. datas.push_back(variant);
  2017. // 调用次数递增(当前已处理的图像数量)
  2018. callCount++;
  2019. // 若未收集到6张图,调用拍摄命令准备下一张
  2020. if (callCount < 6) {
  2021. auto err = Execute_Ptr(detector.m_nDetectorID, Cmd_Photo, nullptr, 0);
  2022. if (err != Err_Success) {
  2023. cout << funcTag << "Failed to execute Cmd_Photo for next image. Error code: " << err << endl;
  2024. // 重置状态,避免异常累积
  2025. callCount = 0;
  2026. datas.clear();
  2027. return;
  2028. }
  2029. cout << funcTag << "Prepared for " << callCount + 1 << "th image" << endl;
  2030. }
  2031. // 收集到6张图,执行模板生成和上传
  2032. else {
  2033. image_info template_image;
  2034. template_image.data.resize(datas[0].DataLen);
  2035. template_image.width = image.width;
  2036. template_image.height = image.height;
  2037. // 生成模板并检查结果
  2038. auto err = GenerateTemplate_Ptr(Offset, datas.data(), static_cast<int>(datas.size()),
  2039. template_image.data.data(), static_cast<int>(template_image.data.size()));
  2040. if (err != Err_Success) {
  2041. cout << funcTag << "Failed to generate offset template. Error code: " << err << endl;
  2042. }
  2043. else {
  2044. cout << funcTag << "Offset template generated successfully with 6 images" << endl;
  2045. // 上传模板并检查结果
  2046. err = detector.upload(detector.offset, template_image.data.data(), static_cast<int>(template_image.data.size()));
  2047. if (err != Err_Success) {
  2048. cout << funcTag << "Failed to upload offset template. Error code: " << err << endl;
  2049. }
  2050. else {
  2051. cout << funcTag << "Offset template uploaded successfully" << endl;
  2052. }
  2053. }
  2054. // 重置静态变量,为下一次校准做准备
  2055. callCount = 0;
  2056. datas.clear();
  2057. }
  2058. }
  2059. void Detector_TiRayDR::handleGainCalibration(Detector_TiRayDR& detector, TiRayVariant argv[])
  2060. {
  2061. const std::string funcTag = "[Detector_TiRayDR::handleGainCalibration] ";
  2062. int doseCount = 5; // 剂量数量
  2063. int imagesPerDose = 6; // 每个剂量的图像数量
  2064. auto size = argv[3].DataLen;
  2065. auto data = argv[3].DataValue;
  2066. // 创建图像信息并存储
  2067. image_info image;
  2068. image.width = argv[0].IntValue;
  2069. image.height = argv[1].IntValue;
  2070. image.data.resize(size);
  2071. memcpy(image.data.data(), data, size);
  2072. // 根据模式存储图像
  2073. if (!detector.m_bUseGainV2)
  2074. {
  2075. // Gain模式:直接存储所有30张图像
  2076. detector.m_gainCalibImages.push_back(image);
  2077. cout << funcTag << "Gain mode - Collected " << detector.m_gainCalibImages.size()
  2078. << "/" << doseCount * imagesPerDose << " images" << endl;
  2079. // 收集完30张图像后生成并上传模板
  2080. if (detector.m_gainCalibImages.size() == doseCount * imagesPerDose)
  2081. {
  2082. cout << funcTag << "All 30 gain calibration images collected, generating template..." << endl;
  2083. // 准备数据并生成Gain模板
  2084. std::vector<TiRayVariant> datas;
  2085. for (auto& img : detector.m_gainCalibImages)
  2086. {
  2087. TiRayVariant variant;
  2088. variant.Type = TiRayVariant::TiRayBuffer;
  2089. variant.DataLen = static_cast<int>(img.data.size());
  2090. variant.DataValue = img.data.data();
  2091. datas.push_back(variant);
  2092. }
  2093. image_info template_image;
  2094. template_image.width = detector.m_gainCalibImages[0].width;
  2095. template_image.height = detector.m_gainCalibImages[0].height;
  2096. template_image.data.resize(datas[0].DataLen);
  2097. auto err = GenerateTemplate_Ptr(Gain, datas.data(), static_cast<int>(datas.size()),
  2098. template_image.data.data(), static_cast<int>(template_image.data.size()));
  2099. if (err != Err_Success)
  2100. {
  2101. cout << funcTag << "Failed to generate Gain template. Error code: " << err << endl;
  2102. }
  2103. else
  2104. {
  2105. cout << funcTag << "Gain template generated successfully" << endl;
  2106. // 上传模板
  2107. err = detector.upload(detector.gain, template_image.data.data(),
  2108. static_cast<int>(template_image.data.size()));
  2109. if (err != Err_Success)
  2110. {
  2111. cout << funcTag << "Failed to upload Gain template. Error code: " << err << endl;
  2112. }
  2113. else
  2114. {
  2115. cout << funcTag << "Gain template uploaded successfully" << endl;
  2116. }
  2117. }
  2118. // 清空存储的图像,准备下次校正
  2119. detector.m_gainCalibImages.clear();
  2120. }
  2121. }
  2122. else if (detector.m_bUseGainV2)
  2123. {
  2124. // Gainv2模式:按剂量组存储图像
  2125. detector.m_currentDoseImages.push_back(image);
  2126. cout << funcTag << "Gainv2 mode - Collected " << detector.m_currentDoseImages.size()
  2127. << "/" << imagesPerDose << " images for dose " << detector.m_currentDoseIndex + 1 << endl;
  2128. // 收集完当前剂量的6张图像后生成均值图
  2129. if (detector.m_currentDoseImages.size() == imagesPerDose)
  2130. {
  2131. cout << funcTag << "All " << imagesPerDose << " images for dose " << detector.m_currentDoseIndex + 1
  2132. << " collected, generating mean image..." << endl;
  2133. // 生成当前剂量的均值图
  2134. std::vector<TiRayVariant> datas;
  2135. for (auto& img : detector.m_currentDoseImages)
  2136. {
  2137. TiRayVariant variant;
  2138. variant.Type = TiRayVariant::TiRayBuffer;
  2139. variant.DataLen = static_cast<int>(img.data.size());
  2140. variant.DataValue = img.data.data();
  2141. datas.push_back(variant);
  2142. }
  2143. image_info mean_image;
  2144. mean_image.width = detector.m_currentDoseImages[0].width;
  2145. mean_image.height = detector.m_currentDoseImages[0].height;
  2146. mean_image.data.resize(datas[0].DataLen);
  2147. auto err = GenerateTemplate_Ptr(Mean, datas.data(), static_cast<int>(datas.size()),
  2148. mean_image.data.data(), static_cast<int>(mean_image.data.size()));
  2149. if (err != Err_Success)
  2150. {
  2151. cout << funcTag << "Failed to generate mean image for dose " << detector.m_currentDoseIndex + 1
  2152. << ". Error code: " << err << endl;
  2153. // 清空当前剂量数据,重新收集
  2154. detector.m_currentDoseImages.clear();
  2155. return;
  2156. }
  2157. // 保存均值图并重置当前剂量图像集合
  2158. detector.m_gainV2MeanImages.push_back(mean_image);
  2159. detector.m_currentDoseImages.clear();
  2160. detector.m_currentDoseIndex++;
  2161. cout << funcTag << "Mean image for dose " << detector.m_currentDoseIndex
  2162. << " generated successfully. Total mean images: " << detector.m_gainV2MeanImages.size() << endl;
  2163. // 收集完5个剂量的均值图后生成最终模板
  2164. if (detector.m_gainV2MeanImages.size() == doseCount)
  2165. {
  2166. cout << funcTag << "All " << doseCount << " mean images collected, generating final GainV2 template..." << endl;
  2167. // 生成最终的GainV2模板
  2168. std::vector<TiRayVariant> meanDatas;
  2169. for (auto& meanImg : detector.m_gainV2MeanImages)
  2170. {
  2171. TiRayVariant variant;
  2172. variant.Type = TiRayVariant::TiRayBuffer;
  2173. variant.DataLen = static_cast<int>(meanImg.data.size());
  2174. variant.DataValue = meanImg.data.data();
  2175. meanDatas.push_back(variant);
  2176. }
  2177. image_info final_template;
  2178. final_template.width = detector.m_gainV2MeanImages[0].width;
  2179. final_template.height = detector.m_gainV2MeanImages[0].height;
  2180. final_template.data.resize(meanDatas[0].DataLen);
  2181. auto err = GenerateTemplate_Ptr(GainV2, meanDatas.data(), static_cast<int>(meanDatas.size()),
  2182. final_template.data.data(), static_cast<int>(final_template.data.size()));
  2183. if (err != Err_Success)
  2184. {
  2185. cout << funcTag << "Failed to generate GainV2 template. Error code: " << err << endl;
  2186. }
  2187. else
  2188. {
  2189. cout << funcTag << "GainV2 template generated successfully" << endl;
  2190. // 上传模板
  2191. err = detector.upload(detector.gain, final_template.data.data(),
  2192. static_cast<int>(final_template.data.size()));
  2193. if (err != Err_Success)
  2194. {
  2195. cout << funcTag << "Failed to upload GainV2 template. Error code: " << err << endl;
  2196. }
  2197. else
  2198. {
  2199. cout << funcTag << "GainV2 template uploaded successfully" << endl;
  2200. }
  2201. }
  2202. // 重置所有存储和计数器,准备下次校正
  2203. detector.m_gainV2MeanImages.clear();
  2204. detector.m_currentDoseIndex = 0;
  2205. }
  2206. }
  2207. }
  2208. }
  2209. void Detector_TiRayDR::handleImageReceived(Detector_TiRayDR& detector, TiRayVariant argv[])
  2210. {
  2211. // 处理暗校准模式
  2212. if (CCOS_CALIBRATION_TYPE_DARK == detector.m_eCaliType)
  2213. {
  2214. handleDarkCalibration(detector, argv);
  2215. return;
  2216. }
  2217. else if (CCOS_CALIBRATION_TYPE_XRAY == detector.m_eCaliType)
  2218. {
  2219. handleGainCalibration(detector, argv);
  2220. return;
  2221. }
  2222. // 根据同步模式处理图像
  2223. switch (detector.m_nSyncMode)
  2224. {
  2225. case SYNC_MODE::SYNC_AED:
  2226. handleAedSyncImage(detector, argv);
  2227. break;
  2228. case SYNC_MODE::SYNC_SOFTWARE:
  2229. handleSoftwareSyncImage(detector, argv);
  2230. break;
  2231. case SYNC_MODE::SYNC_HARDWARE:
  2232. handleHardwareSyncImage(detector, argv);
  2233. break;
  2234. }
  2235. }
  2236. void Detector_TiRayDR::on_event_callback(int detectorId, TiRayEvent eventType, TiRayVariant argv[], int argc, void* reservedArg, int reservedArgLen)
  2237. {
  2238. auto& detector = *g_pDetector;
  2239. const std::string funcTag = "[Detector_TiRayDR::on_event_callback] ";
  2240. switch (eventType)
  2241. {
  2242. case TiRayEvent::Evt_DetectorConnect:
  2243. {
  2244. detector.m_nDetectorID = detectorId;
  2245. detector.m_bConnected = true;
  2246. detector.m_pStPanelStatus[detector.m_nCurrentPanelID]->bConnectState = true;
  2247. detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_CONNECT);
  2248. cout << funcTag << "Evt_DetectorConnect!!!" << endl;
  2249. FINFO("Evt_DetectorConnect!!");
  2250. break;
  2251. }
  2252. case TiRayEvent::Evt_DetectorDisconnect:
  2253. {
  2254. detector.m_nDetectorID = INT_MAX;
  2255. detector.m_bConnected = false;
  2256. detector.m_pStPanelStatus[detector.m_nCurrentPanelID]->bConnectState = false;
  2257. detector.StatusFeedback(EVT_STATUS_PANEL, PANEL_CLOSE);
  2258. detector.m_hReConnectEvent->SetEvent();
  2259. cout << funcTag << "Evt_DetectorDisconnect!!!" << endl;
  2260. FINFO("Evt_DetectorDisconnect!!");
  2261. break;
  2262. }
  2263. case TiRayEvent::Evt_WriteAttribute:
  2264. {
  2265. FINFO("WriteAttribute Success");
  2266. break;
  2267. }
  2268. case TiRayEvent::Evt_ReadAttribute:
  2269. {
  2270. FINFO("ReadAttribute Success");
  2271. //const TiRayAttribute attrib = (TiRayAttribute)argv[0].IntValue;
  2272. //if (attrib == Attr_BatteryStatus) {
  2273. // auto battery_level = argv[1].IntValue;
  2274. // auto is_recharging = argv[2].IntValue;
  2275. //}
  2276. break;
  2277. }
  2278. case TiRayEvent::Evt_ImageReceived:
  2279. {
  2280. cout << funcTag << "Evt_ImageReceived!!!" << endl;
  2281. FINFO("Evt_ImageReceived!!");
  2282. handleImageReceived(detector, argv);
  2283. break;
  2284. }
  2285. case TiRayEvent::Evt_ExposureStatus:
  2286. {
  2287. FINFO("argv {$}, argc {$}", argv[0].IntValue, argc);
  2288. if (argv[0].IntValue == 0)
  2289. {
  2290. detector.m_bAEDReady = true;
  2291. }
  2292. if (argv[0].IntValue == 1)
  2293. {
  2294. detector.m_bAEDReady = false;
  2295. }
  2296. break;
  2297. }
  2298. case TiRayEvent::Evt_UploadProgress:
  2299. cout << funcTag << "Upload progress: " << argv[0].IntValue << "%" << endl;
  2300. break;
  2301. case TiRayEvent::Evt_UpdateFinish:
  2302. cout << funcTag << "Update completed successfully" << endl;
  2303. detector.StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK);
  2304. break;
  2305. case TiRayEvent::Evt_UploadTimeout:
  2306. // 输出上传超时警告
  2307. cout << funcTag << "Warning: Upload timed detectorData" << endl;
  2308. break;
  2309. default:
  2310. FERROR("not support current event ID:{$}", (int)eventType);
  2311. break;
  2312. }
  2313. }
  2314. void Detector_TiRayDR::ConfFeedback(int nEventID, int nDetectorID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam)
  2315. {
  2316. if (-1 == nDetectorID)
  2317. {
  2318. nDetectorID = m_nCurrentPanelID;
  2319. }
  2320. ((FPDDeviceTiRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  2321. nEventID, EVT_LEVEL_CONFIGURATION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  2322. }
  2323. void Detector_TiRayDR::InfoFeedback(int nEventID, int nDetectorID, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, void* pParam)
  2324. {
  2325. if (-1 == nDetectorID)
  2326. {
  2327. nDetectorID = m_nCurrentPanelID;
  2328. }
  2329. ((FPDDeviceTiRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  2330. nEventID, EVT_LEVEL_INFORMATOION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  2331. }
  2332. void Detector_TiRayDR::StatusFeedback(int nEventID, int nParam1, const char* pszMsg, int nDetectorID, float fParam2, int nPtrParamLen, void* pParam)
  2333. {
  2334. if (-1 == nDetectorID)
  2335. {
  2336. nDetectorID = m_nCurrentPanelID;
  2337. }
  2338. ((FPDDeviceTiRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  2339. nEventID, EVT_LEVEL_STATUS, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  2340. }
  2341. void Detector_TiRayDR::DataFeedback(int nEventID, void* pParam, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, int nDetectorID)
  2342. {
  2343. if (-1 == nDetectorID)
  2344. {
  2345. nDetectorID = m_nCurrentPanelID;
  2346. }
  2347. ((FPDDeviceTiRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  2348. nEventID, EVT_LEVEL_DATA, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  2349. }
  2350. void Detector_TiRayDR::WarnFeedback(int nEventID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam, int nDetectorID)
  2351. {
  2352. if (-1 == nDetectorID)
  2353. {
  2354. nDetectorID = m_nCurrentPanelID;
  2355. }
  2356. ((FPDDeviceTiRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  2357. nEventID, EVT_LEVEL_WARNING, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  2358. }
  2359. void Detector_TiRayDR::ErrorFeedback(int nEventID, const char* pszMsg, int nDetectorID, int nParam1, float fParam2, int nPtrParamLen, void* pParam)
  2360. {
  2361. if (-1 == nDetectorID)
  2362. {
  2363. nDetectorID = m_nCurrentPanelID;
  2364. }
  2365. ((FPDDeviceTiRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  2366. nEventID, EVT_LEVEL_ERROR, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  2367. }
  2368. bool Detector_TiRayDR::UpdateCalibMode(CCOS_CALIBRATION_MODE eCalibMode)
  2369. {
  2370. FINFO("--TiRayDR Func-- UpdateCalibMode");
  2371. FINFO("CalibMode:{$}", (int)eCalibMode);
  2372. m_nCalibrationMode = eCalibMode;
  2373. FINFO("UpdateCalibMode Over");
  2374. return true;
  2375. }
  2376. void Detector_TiRayDR::SetNotifyStatusTimePeriod(int nTime)
  2377. {
  2378. FINFO("--Func TiRay-- SetNotifyStatusTimePeriod Start");
  2379. FINFO("NotifyStatusTimePeriod:{$}", nTime);
  2380. m_nNotifyStatusTimePeriod = nTime;
  2381. FINFO("SetNotifyStatusTimePeriod Over");
  2382. }
  2383. void Detector_TiRayDR::SetReconnectTimePeriod(int nTime)
  2384. {
  2385. FINFO("--Func TiRay-- SetReconnectTimePeriod Start");
  2386. FINFO("ReconnectTimePeriod:{$}", nTime);
  2387. m_nReconnectTimePeriod = nTime;
  2388. FINFO("SetReconnectTimePeriod Over");
  2389. }
  2390. int Detector_TiRayDR::TiRay_GetSdkVersion()
  2391. {
  2392. return GetSdkVersion_Ptr();
  2393. }
  2394. TiRayError Detector_TiRayDR::TiRay_Execute(int detectorId, int commandId, TiRayVariant argv[], int argc)
  2395. {
  2396. return Execute_Ptr(detectorId, commandId, argv, argc);
  2397. }
  2398. TiRayError Detector_TiRayDR::TiRay_ApplyPreset(int detectorId, TiRayVariant argv[], int argc, ResultCallback fn)
  2399. {
  2400. return ApplyPreset_Ptr(detectorId, argv, argc, fn);
  2401. }
  2402. TiRayError Detector_TiRayDR::TiRay_GenerateTemplate(TemplateType type, TiRayVariant images[], int count, void* templateBuffer, int bufferSize)
  2403. {
  2404. return GenerateTemplate_Ptr(type, images, count, templateBuffer, bufferSize);
  2405. }
  2406. TiRayError Detector_TiRayDR::TiRay_Scan(ResultCallback fn, const char* interfaceIp, int scanDuration)
  2407. {
  2408. return Scan_Ptr(fn, interfaceIp, scanDuration);
  2409. }
  2410. TiRayError Detector_TiRayDR::TiRay_SetIp(const char* detectorSN, const char* upperIp, const char* lowerIp, const char* interfaceIp)
  2411. {
  2412. return SetIp_Ptr(detectorSN, upperIp, lowerIp, interfaceIp);
  2413. }
  2414. TiRayError Detector_TiRayDR::TiRay_Startup(TiRayModel model, EventCallback fn, const StartupOption* option)
  2415. {
  2416. return Startup_Ptr(model, fn, option);
  2417. }
  2418. void Detector_TiRayDR::TiRay_Stop()
  2419. {
  2420. Stop_Ptr();
  2421. }
  2422. /***
  2423. ** 说明:重连探测器线程
  2424. ***/
  2425. void* Detector_TiRayDR::onReconnectThread(PVOID pvoid)
  2426. {
  2427. FINFO("Reconnect detector thread start");
  2428. Detector_TiRayDR* pThis = static_cast<Detector_TiRayDR*>(pvoid);
  2429. while (!pThis->m_bConnected)
  2430. {
  2431. pThis->OpenDetector();
  2432. usleep(pThis->m_nReconnectTimePeriod*1000);
  2433. }
  2434. pThis->m_bReconnectThreadRunning = false;
  2435. FINFO("Leave reconnect detector thread");
  2436. return 0;
  2437. }
  2438. TiRayError Detector_TiRayDR::upload(upload_type type, char* data, int size)
  2439. {
  2440. TiRayVariant param[1]{};
  2441. param[0].Type = TiRayVariant::TiRayBuffer;
  2442. param[0].DataValue = data;
  2443. param[0].DataLen = size;
  2444. if (type == offset) {
  2445. return Execute_Ptr(m_nDetectorID, Cmd_UploadOffsetTemplate, param, 1);
  2446. }
  2447. if (type == gain) {
  2448. return Execute_Ptr(m_nDetectorID, Cmd_UploadGainTemplate, param, 1);
  2449. }
  2450. if (type == firmware) {
  2451. return Execute_Ptr(m_nDetectorID, Cmd_UpdateFirmware, param, 1);
  2452. }
  2453. return Err_InvalidParam;
  2454. }