Detector_TiRayDR.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. #pragma once
  2. #include <filesystem>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <variant>
  6. #include <future>
  7. #include <chrono>
  8. #include "ResDataObject.h"
  9. #include "CCOS.Dev.FPD.TiRayDR.h"
  10. #include "errors.h"
  11. #include "ZSKKCalibration.h"
  12. #include "TiRayApi.h"
  13. #include "TiRayDef.h"
  14. //#include "TirayApiImport.h"
  15. struct image_info {
  16. std::vector<char> data;
  17. int width;
  18. int height;
  19. };
  20. constexpr auto SCAN_EVENT_COUNT = 8;
  21. //typedef void(*ResultCallback)(TiRayVariant argv[], int argc);
  22. using EventListener = std::function<void(TiRayEvent, TiRayVariant[], int)>;
  23. using event_param = std::variant<int, float, long long, std::string, image_info>;
  24. using event_params = std::vector<event_param>;
  25. using event_listener = std::function<void(TiRayEvent, event_params&)>;
  26. #define INT_MAX 2147483647
  27. struct ModelResolveResult {
  28. TiRayModel model;
  29. bool isValid;
  30. };
  31. class Detector_TiRayDR
  32. {
  33. struct scan_result {
  34. std::string sn;
  35. std::string model;
  36. std::string upper_ip;
  37. std::string detector_ip;
  38. };
  39. enum class eDetStatus
  40. {
  41. DetStatus_NotIni,
  42. DetStatus_NotConn,
  43. DetStatus_Sleep,
  44. DetStatus_Standby,
  45. DetStatus_Work,
  46. DetStatus_Acquire,
  47. DetStatus_Offset,
  48. DetStatus_XrayCalibration,
  49. };
  50. //探测器信息
  51. struct CPanelStatus
  52. {
  53. bool bInitOver; //是否初始化完成
  54. bool bConnectState; //是否连接
  55. SYNC_MODE eSyncMode; //同步模式
  56. int nSoftAcqState;
  57. eDetStatus eFPDStatus; //探测器状态
  58. CPanelStatus()
  59. {
  60. bInitOver = false;
  61. bConnectState = false;
  62. eSyncMode = SYNC_SOFTWARE; //暂时使用软同步作为缺省值
  63. nSoftAcqState = 0;
  64. eFPDStatus = eDetStatus::DetStatus_NotIni;
  65. }
  66. };
  67. public:
  68. Detector_TiRayDR();
  69. ~Detector_TiRayDR();
  70. bool ScanDetector(string& strDetectorInfo);
  71. bool DriverEntry(FPDDeviceTiRay* pDrvDPC, ResDataObject& Configuration);
  72. bool Connect(FPDDeviceTiRay* pDrvDPC, const char* szWorkPath);
  73. bool Disconnect();
  74. void EnterExamMode(int nExamMode);
  75. bool SetExposureTimes(int nTimes);
  76. bool SetAcqMode(int nMode);
  77. bool SetSyncMode(int nSyncMode);
  78. bool PrepareAcquisition(FPDDeviceTiRay* pDrvDPC);
  79. bool StartAcquisition(FPDDeviceTiRay* pDrvDPC);
  80. bool StopAcquisition(FPDDeviceTiRay* pDrvDPC);
  81. bool ActiveCalibration(FPDDeviceTiRay* pDrvDPC, CCOS_CALIBRATION_TYPE eType);
  82. bool PrepareCalibration(FPDDeviceTiRay* pDrvDPC);
  83. bool StartCalibration(FPDDeviceTiRay* pDrvDPC);
  84. bool StopCalibration(FPDDeviceTiRay* pDrvDPC);
  85. RET_STATUS AbortCalibration(FPDDeviceTiRay* pDrvDPC);
  86. bool CompleteCalibration(FPDDeviceTiRay* pDrvDPC);
  87. bool SaveCalibrationFile();
  88. bool SetCalibRounds(int nCalibRounds);
  89. bool GetCalibrationStep(int nCalibCurrentCalibrationRound, int nCalibrationRounds, int nCalibCurrentExposureIndex, int nExposureNumCurrentRound);
  90. bool AcceptCalibration();
  91. bool RejectCalibration();
  92. CCOS_CALIBRATION_TYPE GetCalibType();
  93. bool UpdateCalibMode(CCOS_CALIBRATION_MODE eCalibMode);
  94. void SetNotifyStatusTimePeriod(int nTime);
  95. void SetReconnectTimePeriod(int nTime);
  96. int TiRay_GetSdkVersion();
  97. TiRayError TiRay_Execute(int detectorId, int commandId, TiRayVariant argv[], int argc);
  98. TiRayError TiRay_Scan(ResultCallback fn, const char* interfaceIp, int scanDuration);
  99. TiRayError TiRay_SetIp(const char* detectorSN, const char* upperIp, const char* lowerIp, const char* interfaceIp);
  100. TiRayError TiRay_Startup(TiRayModel model, EventCallback fn, const StartupOption* option);
  101. void TiRay_Stop();
  102. TiRayError TiRay_ApplyPreset(int detectorId, TiRayVariant argv[], int argc, ResultCallback fn);
  103. TiRayError TiRay_GenerateTemplate(TemplateType type, TiRayVariant images[], int count, void* templateBuffer, int bufferSize);
  104. void register_event_listener(const EventListener& fn);
  105. void unregister_event_listener(const EventListener& fn);
  106. bool cropImage(unsigned short* srcData,
  107. int srcWidth, int srcHeight,
  108. unsigned short* destData,
  109. int destWidth, int destHeight);
  110. static std::string saveProcessedImage(Detector_TiRayDR& detector, unsigned short* data, size_t size, const std::string& baseTimestamp);
  111. static void saveRawImage(Detector_TiRayDR& detector, unsigned short* data, size_t size, const std::string& baseTimestamp);
  112. static void cleanOldFiles(const std::string& dirPath, const std::string& filePrefix,size_t maxCount, bool checkSize, const std::string& currentSessionTimestamp = "");
  113. static void handleHardwareSyncImage(Detector_TiRayDR& detector, TiRayVariant argv[]);
  114. static void handleSoftwareSyncImage(Detector_TiRayDR& detector, TiRayVariant argv[]);
  115. static void handleAedSyncImage(Detector_TiRayDR& detector, TiRayVariant argv[]);
  116. static void handleDarkCalibration(Detector_TiRayDR& detector, TiRayVariant argv[]);
  117. static void handleGainCalibration(Detector_TiRayDR& detector, TiRayVariant argv[]);
  118. static void handleImageReceived(Detector_TiRayDR& detector, TiRayVariant argv[]);
  119. static void on_event_callback(int detectorId, TiRayEvent eventType, TiRayVariant argv[], int argc, void* reservedArg, int reservedArgLen);
  120. static void* onReconnectThread(PVOID pvoid);
  121. int make_notifier_key(int main, int sub) {
  122. return (main << 16) + sub;
  123. }
  124. std::promise<event_params>& add_notifier(int key)
  125. {
  126. std::lock_guard<std::mutex> guard(notifiers_mutex_);
  127. auto& promise = notifiers_[key];
  128. notifiers_[key] = {};
  129. return promise;
  130. }
  131. void remove_notifier(int key) {
  132. std::lock_guard<std::mutex> guard(notifiers_mutex_);
  133. notifiers_.erase(key);
  134. }
  135. enum upload_type : uint8_t {
  136. offset,
  137. gain,
  138. firmware,
  139. };
  140. TiRayError upload(upload_type type, char* data, int size);
  141. template<typename Func>
  142. TiRayError scan(Func fn) {
  143. static std::unique_ptr<Func> callback;
  144. callback = std::make_unique<Func>(std::move(fn));
  145. auto err = TiRay_Scan([](TiRayVariant argv[], int argc) {
  146. (*callback)(scan_result{ argv[0].DataValue, argv[1].DataValue, argv[2].DataValue, argv[3].DataValue });
  147. }, nullptr, 2000);
  148. return err;
  149. }
  150. //template<typename T>
  151. //std::tuple<TiRayError, T> read_attribute(TiRayAttribute attribute, std::chrono::seconds timeout = std::chrono::seconds(2)) {
  152. // TiRayVariant param[1]{};
  153. // param[0].Type = TiRayVariant::TiRayInt;
  154. // param[0].IntValue = attribute;
  155. // // 执行命令
  156. // auto err = Execute(m_nDetectorID, Cmd_ReadAttribute, param, 1);
  157. // if (err != Err_Success) {
  158. // return { err, {} };
  159. // }
  160. // // 处理event_params类型(实际是std::vector<event_param>)
  161. // if constexpr (std::is_same_v<T, event_params>) {
  162. // event_params result;
  163. // // 根据参数类型构造对应的event_param并添加到vector中
  164. // switch (param[0].Type) {
  165. // case TiRayVariant::TiRayInt:
  166. // result.emplace_back(param[0].IntValue);
  167. // break;
  168. // case TiRayVariant::TiRayInt64:
  169. // result.emplace_back(param[0].Int64Value);
  170. // break;
  171. // case TiRayVariant::TiRayFloat:
  172. // result.emplace_back(param[0].FloatValue);
  173. // break;
  174. // case TiRayVariant::TiRayBuffer:
  175. // result.emplace_back(std::string(param[0].DataValue, param[0].DataLen));
  176. // break;
  177. // }
  178. // return { Err_Success, std::move(result) };
  179. // }
  180. // else {
  181. // T result;
  182. // bool typeMismatch = false;
  183. // // 根据参数类型和目标类型进行转换
  184. // if constexpr (std::is_integral_v<T> && sizeof(T) <= 4 || std::is_enum_v<T>) {
  185. // if (param[0].Type == TiRayVariant::TiRayInt) {
  186. // result = static_cast<T>(param[0].IntValue);
  187. // }
  188. // else {
  189. // typeMismatch = true;
  190. // }
  191. // }
  192. // else if constexpr (std::is_integral_v<T> && sizeof(T) > 4) {
  193. // if (param[0].Type == TiRayVariant::TiRayInt64) {
  194. // result = static_cast<T>(param[0].Int64Value);
  195. // }
  196. // else {
  197. // typeMismatch = true;
  198. // }
  199. // }
  200. // else if constexpr (std::is_floating_point_v<T>) {
  201. // if (param[0].Type == TiRayVariant::TiRayFloat) {
  202. // result = static_cast<T>(param[0].FloatValue);
  203. // }
  204. // else {
  205. // typeMismatch = true;
  206. // }
  207. // }
  208. // else {
  209. // // 处理其他类型(如自定义类型)
  210. // typeMismatch = true;
  211. // }
  212. // if (typeMismatch) {
  213. // return { err, {} }; // 假设存在类型不匹配的错误码
  214. // }
  215. // return { Err_Success, result };
  216. // }
  217. //}
  218. template<typename T>
  219. TiRayError write_attribute(TiRayAttribute attribute, T value, std::chrono::seconds timeout = std::chrono::seconds(2)) {
  220. std::cout << "--TiRay Function-- write_attribute Start" << std::endl;
  221. std::cout << "Writing attribute: " << static_cast<int>(attribute)
  222. << ", Timeout: " << timeout.count() << "s" << std::endl;
  223. std::unique_ptr<char[]> buffer;
  224. TiRayVariant param[2]{};
  225. param[0].Type = TiRayVariant::TiRayInt;
  226. param[0].IntValue = attribute;
  227. if constexpr (std::is_integral_v<T> && sizeof(T) <= 4 || std::is_enum_v<T>) {
  228. param[1].Type = TiRayVariant::TiRayInt;
  229. param[1].IntValue = value;
  230. std::cout << "Using TiRayInt type, value: " << value << std::endl;
  231. }
  232. else if constexpr (std::is_integral_v<T> && sizeof(T) > 4) {
  233. param[1].Type = TiRayVariant::TiRayInt64;
  234. param[1].Int64Value = value;
  235. std::cout << "Using TiRayInt64 type, value: " << value << std::endl;
  236. }
  237. else if constexpr (std::is_floating_point_v<T>) {
  238. param[1].Type = TiRayVariant::TiRayFloat;
  239. param[1].FloatValue = value;
  240. std::cout << "Using TiRayFloat type, value: " << value << std::endl;
  241. }
  242. else if constexpr (std::is_same_v<T, std::string>) {
  243. param[1].Type = TiRayVariant::TiRayBuffer;
  244. buffer = std::make_unique<char[]>(param[1].DataLen);
  245. param[1].DataLen = static_cast<int>(value.size());
  246. param[1].DataValue = buffer.get();
  247. memcpy(param[1].DataValue, value.c_str(), param[1].DataLen);
  248. std::cout << "Using TiRayBuffer type, string length: " << param[1].DataLen
  249. << ", value: " << value << std::endl;
  250. }
  251. else {
  252. static_assert(!std::is_same_v<T, T>, "Unsupported type T");
  253. }
  254. auto err = TiRay_Execute(m_nDetectorID, Cmd_WriteAttribute, param, 2);
  255. if (err != Err_Success) {
  256. std::cout << "Error: TiRay_Execute failed with code: " << static_cast<int>(err) << std::endl;
  257. return err;
  258. }
  259. std::cout << "Success: Attribute " << static_cast<int>(attribute) << " written successfully" << std::endl;
  260. return Err_Success;
  261. }
  262. std::vector<image_info> m_gainCalibImages; // 存储Gain模式下的所有30张图像
  263. std::vector<image_info> m_currentDoseImages; // 存储当前剂量组的6张图像
  264. std::vector<image_info> m_gainV2MeanImages; // 存储每个剂量组生成的均值图
  265. int m_currentDoseIndex = 0; // 当前处理的剂量组索引(0-4,共5组)
  266. private:
  267. map<FPDDeviceTiRay*, int>* m_pDPC2PanelID;
  268. map<int, FPDDeviceTiRay*>* m_pPanelID2DPC;
  269. std::list<EventListener> m_listeners;
  270. ResDataObject m_ModeConfig; //保存DPC模块下发的配置
  271. CPanelStatus* m_pStPanelStatus[2]; //
  272. void* m_hTiRayDRModule;
  273. APP_STATUS m_nAppStatus; //记录软件状态
  274. CCOS_CALIBRATION_TYPE m_eCaliType; // 记录当前校正类型
  275. CCOS_CALIBRATION_MODE m_nCalibrationMode;//校正模式 ecom校正/厂商校正
  276. CZSKKCalibrationCtrl* m_pZSKKCalib;
  277. std::map<int32_t, std::promise<event_params>> notifiers_;
  278. std::mutex notifiers_mutex_;
  279. int m_nPanelCount; //探测器数量
  280. int m_nDetectorID;
  281. int m_nCurrentPanelID;
  282. int m_nSyncMode; //记录选择模式时使用的同步模式
  283. bool m_bIsMultiFrame;
  284. int m_nImageWidth;
  285. int m_nImageHeight;
  286. int m_nWidthOffset;
  287. int m_nHeightOffset;
  288. int m_nRawImgWidth; //SDK反馈的图像宽
  289. int m_nRawImgHeight; //SDK反馈的图像高
  290. int m_nCalibrationRounds;//校正轮数
  291. int m_nCalibCurrentCalibrationRound;//当前校正轮数
  292. int m_nCalibCurrentExposureIndex;//当前轮次曝光第几次
  293. int m_nExposureNumCurrentRound;//当前轮次需要曝光的总次数
  294. int m_nImageNum;
  295. int m_nReconnectTimePeriod;
  296. int m_nNotifyStatusTimePeriod;
  297. bool m_bIpInitialized; // IP是否已初始化
  298. bool m_bFirstConnect; // IP设置进行中标志
  299. int m_nXWindow; // 曝光间隔时间(PhotoInterval),用于PF模式等多帧采集
  300. bool m_bSaveRaw;
  301. bool m_bConnected;
  302. bool m_bExitRadAcqStatus;
  303. bool m_bAEDReady;
  304. bool m_bAEDWorkFlag;
  305. bool m_bMonitorFlag;
  306. bool m_bUseGainV2 = false;
  307. std::string m_strWorkPath; //保存工作路径,用于加载SDK和配置
  308. std::string m_strDetectorType; //探测器类型
  309. std::string m_strWiredIP;
  310. std::string m_strWirelessIP;
  311. std::string m_strLocalIP;
  312. std::string m_strSerialNum;
  313. std::string m_strCurrentSessionTimestamp; //当前拍摄会话的时间戳(同一次拍摄的所有图片共享)
  314. int m_nSessionFrameCounter; //当前会话的帧计数器
  315. // 拍摄完成检测相关
  316. std::chrono::steady_clock::time_point m_lastExposureEndTime; // 最后一次曝光结束时间
  317. bool m_bIsAcquiring; // 是否正在采集
  318. bool m_bAcquisitionCompleted; // 采集是否已完成(用于防止重复通知)
  319. bool m_bWaitingForNextExposure; // 是否在等待下一次曝光
  320. WORD* m_pRawImgBuffer; //原始图
  321. WORD* m_pImgBuffer; //裁剪后图像
  322. //辅助线程事件
  323. std::shared_ptr<LinuxEvent> m_hInitEvent;
  324. std::shared_ptr<LinuxEvent> m_hExitEvent; //退出辅助线程事件
  325. std::shared_ptr<LinuxEvent> m_hReConnectEvent;
  326. std::shared_ptr<LinuxEvent> m_hRadEvent;
  327. std::vector<std::shared_ptr<LinuxEvent>> m_hArrayEvent;
  328. pthread_t m_hReconnectThread = 0;
  329. bool m_bReconnectThreadRunning = false;
  330. std::shared_ptr<LinuxEvent> m_hToggleEvent; //辅助线程退出通知事件
  331. pthread_t m_hFPDScanThread = 0; //辅助线程
  332. pthread_t m_hRadAcquisitionThread = 0;
  333. pthread_t m_hStatusMonitorThread = 0;
  334. pthread_t m_hAcquisitionCheckThread = 0; // 采集完成检测线程
  335. bool m_bAcquisitionCheckThreadRunning = false; // 检测线程是否在运行
  336. std::shared_ptr<LinuxEvent> m_hExitRadAcqStatus;
  337. ModelResolveResult ResolveModelType(const std::string& detectorType);
  338. bool LoadDll(string strWorkPath);
  339. bool ReleaseDll();
  340. bool OpenDetector();
  341. bool CheckConnect(string strIP);
  342. bool OpenStatusMonitor();
  343. static void* TiRayStatusMonitorThread(PVOID pvoid);
  344. bool StatusMonitor();
  345. bool CloseStatusMonitor();
  346. bool StartAcquisitionCheckThread();
  347. static void* AcquisitionCheckThread(PVOID pvoid);
  348. bool StopAcquisitionCheckThread();
  349. bool CloseDetectorScan();
  350. bool LoadCalibrationFiles(int nCalibrationMode);
  351. bool TestError(TiRayError nErrorCode);
  352. //辅助线程
  353. static void* onFPDScanThread(PVOID pvoid);
  354. void OnReconnectFPD();
  355. void OnProcessInitFPD();
  356. int DarkAcquisition();
  357. bool GetEffectiveImage(WORD* pOutImg, WORD* pInImg, int nInWidth);
  358. eDetStatus GetTiRayDPCStatus(int nDetectorIndex = -1);
  359. bool SetTiRayDPCStatus(eDetStatus status, int nDetectorIndex = -1);
  360. bool IsConnected(string strIP);
  361. bool CheckConnection();
  362. bool ReConnectFPD();
  363. bool OpenRadAcquisition();
  364. static void* RadAcquisitionThread(void* pParam);
  365. bool PerformRadAcquisition();
  366. bool CloseRadAcquisition();
  367. void ConfFeedback(int nEventID, int nDetectorID = -1, const char* pszMsg = "", int nParam1 = 0, float fParam2 = 0, int nPtrParamLen = 0, void* pParam = NULL);
  368. void InfoFeedback(int nEventID, int nDetectorID = -1, int nParam1 = 0, float fParam2 = 0, const char* pszMsg = "", int nPtrParamLen = 0, void* pParam = NULL);
  369. void StatusFeedback(int nEventID, int nParam1 = 0, const char* pszMsg = "", int nDetectorID = -1, float fParam2 = 0, int nPtrParamLen = 0, void* pParam = NULL);
  370. void DataFeedback(int nEventID, void* pParam = NULL, int nParam1 = 0, float fParam2 = 0, const char* pszMsg = "", int nPtrParamLen = 0, int nDetectorID = -1);
  371. void WarnFeedback(int nEventID, const char* pszMsg = "", int nParam1 = 0, float fParam2 = 0, int nPtrParamLen = 0, void* pParam = NULL, int nDetectorID = -1);
  372. void ErrorFeedback(int nEventID, const char* pszMsg = "", int nDetectorID = -1, int nParam1 = 0, float fParam2 = 0, int nPtrParamLen = 0, void* pParam = NULL);
  373. };