Detector_TiRayDR.cpp 86 KB

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