SR7ApiBase.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. 
  2. /******************************************************************************
  3. * @file SR7ApiBase.h
  4. * @brief 封装相机图API / Encapsulate camera image API
  5. * @author
  6. * @date 2025-03-17
  7. * @version 1.0.0.0
  8. * @note
  9. *
  10. * 封装取图API,使得调用相机库更简单、直观
  11. * Encapsulate the image acquisition API to make calling the camera library simpler and more intuitive
  12. * -查找相机 / Find camera
  13. * -打开相机 / Open camera
  14. * -初始化相机 / Initialize camera
  15. * -获取数据 / Get data
  16. * -设置相机参数 / Set camera parameters
  17. * -关闭相机 / Turn off camera
  18. *
  19. * @history
  20. * <Date> <Author> <Version> <Description>
  21. * 2025-04-01 GK v1.0.0 初始版本/initial version
  22. *
  23. * @copyright Copyright (c) 2014-2025 SinceVision. All rights reserved.
  24. ******************************************************************************/
  25. using SR7Link;
  26. using System;
  27. using System.Collections.Generic;
  28. using System.Runtime.InteropServices;
  29. using System.Text;
  30. namespace SRAPI
  31. {
  32. public class SRAPIException : Exception
  33. {
  34. public SRAPIException(string message) : base(message) { }
  35. }
  36. // 定义用户数据指针
  37. //using SR7IF_UserData = System.IntPtr;
  38. /// <summary>
  39. /// SR7 API 抽象基类
  40. /// </summary>
  41. public abstract class SR7ApiBase : ISR7Api
  42. {
  43. // 设备控制器ID,默认不可更改
  44. public int ControllerID { get; set; } = 0;
  45. //扫描行数 / Number of scan lines
  46. public int BatchPoints { get; set; } = 0;
  47. //无限循环回调行数 / Infinite loop callback line number
  48. //public int CallBackPoints { get; set; } = 0;
  49. public bool CameraAOnline { get; set; } = false;
  50. public bool CameraBOnline { get; set; } = false;
  51. //数据临时缓存 / Data temporary cache
  52. public IntPtr[] ImgBuff32 = new IntPtr[2];
  53. public IntPtr[] ImgBuff16 = new IntPtr[2];
  54. public IntPtr[] GrayBuff = new IntPtr[2];
  55. public IntPtr[] Encoder = new IntPtr[2];
  56. public SR7IFGetDataCallBack GetDataCallBack;
  57. //method
  58. public abstract int Open(int lDeviceId, string strIP, int timeout, ErrConnectCallBack pfErrCallBack);
  59. /// <summary>
  60. /// 初始化设备
  61. /// </summary>
  62. public abstract int Init(int dwProfileCnt, uint ProfileBits, int nTimeout, SR7IFGetDataCallBack pfGetDataCallBack);
  63. /// <summary>
  64. /// 启动设备
  65. /// </summary>
  66. public abstract int Start(bool bIOTrigger, int timeout);
  67. /// <summary>
  68. /// 停止设备(提供默认参数的重载)
  69. /// </summary>
  70. public int Stop() => Stop(0);
  71. public abstract int Stop(int instantStop);
  72. /// <summary>
  73. /// Close() 断开与相机的连接./Disconnect from the camera.
  74. /// </summary>
  75. /// <returns> <0:失败./Fail. =0:成功./Success</returns>
  76. public virtual int Close()
  77. {
  78. int nRet = Stop();
  79. nRet = SR7LinkFunc.SR7IF_CommClose(ControllerID);
  80. CameraAOnline = false;
  81. CameraBOnline = false;
  82. return nRet;
  83. }
  84. public virtual int GetData(int[] pHighData, byte[] pGrayData, int[] pEncoderData, int nProfileWidth, int nHighlen, int ABCam)
  85. {
  86. if (ABCam < 0 || ABCam >= 2)
  87. return -1;
  88. int totalPoints = nProfileWidth * nHighlen;
  89. if (pHighData != null && ImgBuff32[ABCam] != IntPtr.Zero)
  90. Marshal.Copy(ImgBuff32[ABCam], pHighData, 0, Math.Min(totalPoints, pHighData.Length));
  91. if (pGrayData != null && GrayBuff[ABCam] != IntPtr.Zero)
  92. Marshal.Copy(GrayBuff[ABCam], pGrayData, 0, Math.Min(totalPoints, pGrayData.Length));
  93. if (pEncoderData != null && Encoder[ABCam] != IntPtr.Zero)
  94. Marshal.Copy(Encoder[ABCam], pEncoderData, 0, Math.Min(nHighlen, pEncoderData.Length));
  95. return 0;
  96. }
  97. public virtual int GetData1(int[] pHighData, byte[] pGrayData, int nProfileWidth, int nHighlen, int ABCam)
  98. {
  99. if (ABCam < 0 || ABCam >= 2)
  100. return -1;
  101. int totalPoints = nProfileWidth * nHighlen;
  102. if (pHighData != null && ImgBuff32[ABCam] != IntPtr.Zero)
  103. Marshal.Copy(ImgBuff32[ABCam], pHighData, 0, Math.Min(totalPoints, pHighData.Length));
  104. if (pGrayData != null && GrayBuff[ABCam] != IntPtr.Zero)
  105. Marshal.Copy(GrayBuff[ABCam], pGrayData, 0, Math.Min(totalPoints, pGrayData.Length));
  106. return 0;
  107. }
  108. public virtual int GetData(short[] pHighData, byte[] pGrayData, int[] pEncoderData, int nProfileWidth, int nHighlen, int ABCam)
  109. {
  110. if (ABCam < 0 || ABCam >= 2)
  111. return -1;
  112. int totalPoints = nProfileWidth * nHighlen;
  113. if (pHighData != null && ImgBuff16[ABCam] != IntPtr.Zero)
  114. Marshal.Copy(ImgBuff16[ABCam], pHighData, 0, Math.Min(totalPoints, pHighData.Length));
  115. if (pGrayData != null && GrayBuff[ABCam] != IntPtr.Zero)
  116. Marshal.Copy(GrayBuff[ABCam], pGrayData, 0, Math.Min(totalPoints, pGrayData.Length));
  117. if (pEncoderData != null && Encoder[ABCam] != IntPtr.Zero)
  118. Marshal.Copy(Encoder[ABCam], pEncoderData, 0, Math.Min(nHighlen, pEncoderData.Length));
  119. return 0;
  120. }
  121. /// <summary>
  122. /// 搜索可用摄像头IP(基类提供默认实现,但不强制子类实现)
  123. /// </summary>
  124. public virtual bool SearchCameraIP(out List<string> cameraIPs)
  125. {
  126. cameraIPs = new List<string>();
  127. int[] readNum = new int[1];
  128. try
  129. {
  130. // 使用传统的 using 语法
  131. using (var pin = new PinnedObject(readNum))
  132. {
  133. IntPtr str_Setting = SR7Link.SR7LinkFunc.SR7IF_SearchOnline(pin.Pointer, 3000);
  134. int deviceCount = readNum[0];
  135. if (deviceCount <= 0)
  136. {
  137. return false;
  138. }
  139. byte[][] ipAddressList = new byte[deviceCount][];
  140. for (int i = 0; i < deviceCount; i++)
  141. {
  142. byte[] ip = new byte[4];
  143. Marshal.Copy(str_Setting + 4 * i, ip, 0, 4);
  144. ipAddressList[i] = ip;
  145. cameraIPs.Add(string.Join(".", ip));
  146. }
  147. return true;
  148. }
  149. }
  150. catch (Exception ex)
  151. {
  152. throw new SRAPIException($"Failed to search camera IPs: {ex.Message}");
  153. }
  154. }
  155. public int GetProfileDataWidth()
  156. {
  157. return SR7LinkFunc.SR7IF_ProfileDataWidth(ControllerID, IntPtr.Zero);
  158. }
  159. public int GetProfilePointSetCount()
  160. {
  161. return SR7LinkFunc.SR7IF_ProfilePointSetCount(ControllerID, IntPtr.Zero);
  162. }
  163. public double GetProfileData_XPitch()
  164. {
  165. return SR7LinkFunc.SR7IF_ProfileData_XPitch(ControllerID, IntPtr.Zero);
  166. }
  167. public int SR7IFGet25DSingleProfile(int[] pHighData, uint[] pEncoder)
  168. {
  169. return SR7LinkFunc.SR7IF_GetSingleProfile((uint)ControllerID, pHighData, pEncoder);
  170. }
  171. public int SR7IFGet3DSingleProfile(int[] pHighData)
  172. {
  173. return SR7LinkFunc.SR7IF_GetSingleProfile3DMode((uint)ControllerID, pHighData);
  174. }
  175. ///
  176. /// \brief SetParams SetSetting.
  177. /// \param nAB [in] 相机A为0,B为1 / Camera A is 0, B is 1
  178. /// \param nConfigNum [in] 配方编号 -1:当前配方,0-63指定配方 / Recipe number -1: current recipe, 0-63 specifies the recipe
  179. /// \param nParamItemEnums [in] 参数项枚举,参考SRSettingHeader.h SR7IF_SETTING_ITEM中定义
  180. /// Parameter item enumeration, refer to the definition in SR7IF_SETTING_ITEM in SRSettingHeader.h
  181. /// \param nSetData [in] 设置数据 / Set data
  182. /// \return
  183. /// <0: 失败./Fail.
  184. /// =0: 成功./Success
  185. ///
  186. public int SetParams(int nAB, int nSavePowerOff, int nConfigNum, SR7IF_SETTING_ITEM nParamItemEnums, int nSetData)
  187. {
  188. int nCategory = 0x00;
  189. int nItem = 0x00;
  190. int nDataSize = 1;
  191. if (GetParamsCategory(nParamItemEnums,ref nCategory,ref nItem,ref nDataSize) != 0)
  192. {
  193. return -2;
  194. }
  195. if (nConfigNum != -1)
  196. nConfigNum += 0x10;
  197. //强制小端模式传数据 / Force little-endian mode to transfer data
  198. byte[] pData = new byte[nDataSize];
  199. for (int i = 0; i < nDataSize; i++)
  200. {
  201. pData[i] = (byte)((nSetData >> (i * 8)) & 0xFF);
  202. }
  203. int nRet = 0;
  204. using (PinnedObject pin = new PinnedObject(pData))
  205. {
  206. nRet = SetParams(ControllerID, nSavePowerOff, nConfigNum, nCategory, nItem, nAB, pin, nDataSize);
  207. }
  208. return nRet;
  209. }
  210. ///
  211. /// \brief SetParams 设置参数 SetSetting.
  212. /// \param nDeviceId [in] 控制器ID. / Controller ID
  213. /// \param nDepth [in] 参数是否断电保存,0x01断电不保存,0x02断电保存
  214. /// Whether the parameters are saved when the power is off, 0x01 is not saved when the power is off, 0x02 is saved when the power is off
  215. /// \param nFormulaNum [in] 配方编号 -1:当前配方,0-63指定配方 / Recipe number -1: current recipe, 0-63 specifies the recipe
  216. /// \param nCategory [in] 对应Edgeimage软件中,指定参数页,0:触发设定页面;1:拍摄设定页面;2:轮廓设定页面
  217. /// Corresponding to the Edgeimage software, specify the parameter page, 0: trigger setting page; 1: shooting setting page; 2: contour setting page
  218. /// \param nItem [in] 指定发送 / 接收 nCategory 指定项中的设定项 / Specifies to send/receive the setting items in the specified item of nCategory
  219. /// \param nAB [in] 相机A为0,B为1 / Camera A is 0, B is 1
  220. /// \param pData [in] 写入数据 / Write data
  221. /// \param nDataSize [in] 写入数据的长度 / The length of the written data
  222. /// \return
  223. /// <0: 失败./Fail.
  224. /// =0: 成功./Success
  225. ///
  226. public int SetParams(int nDeviceId, int nSavePowerOff, int nFormulaNum, int nCategory, int nItem, int nAB, PinnedObject pData, int nDataSize)
  227. {
  228. int[] arrayTarget = new int[4] { nAB, 0, 0, 0 };
  229. int nRet = SR7LinkFunc.SR7IF_SetSetting((uint)ControllerID, nSavePowerOff, nFormulaNum, nCategory, nItem, arrayTarget, pData.Pointer, nDataSize);
  230. return nRet;
  231. }
  232. ///
  233. /// \brief GetParams 获取参数 GetSetting.
  234. /// \param nABCamera [in] 相机A为0,B为1 / Camera A is 0, B is 1
  235. /// \param nConfigNum [in] 配方编号 -1:当前配方,0-63指定配方 / Recipe number -1: current recipe, 0-63 specifies the recipe
  236. /// \param nParamItemEnums [in] 参数项枚举,参考SRSettingHeader.h SR7IF_SETTING_ITEM中定义
  237. /// Parameter item enumeration, refer to the definition in SR7IF_SETTING_ITEM in SRSettingHeader.h
  238. /// \param nOutData [out] 获取参数值. / Get parameter value.
  239. /// \return
  240. /// <0: 失败./Fail.
  241. /// =0: 成功./Success
  242. ///
  243. public int GetParams(int nABCamera, int nConfigNum, SR7IF_SETTING_ITEM nParamItemEnums, out int nOutData)
  244. {
  245. nOutData = 0;
  246. int nCategory = 0x00;
  247. int nItem = 0x00;
  248. int nDataSize = 1;
  249. if (GetParamsCategory(nParamItemEnums,ref nCategory,ref nItem,ref nDataSize) != 0)
  250. {
  251. return -3;
  252. }
  253. if (nConfigNum != -1)
  254. nConfigNum += 0x10;
  255. int[] arrayTarget = new int[4] { nABCamera, 0, 0, 0 };
  256. byte[] pData = new byte[nDataSize];
  257. using (PinnedObject pin = new PinnedObject(pData))
  258. {
  259. int nRet = SR7LinkFunc.SR7IF_GetSetting((uint)ControllerID, nConfigNum, nCategory, nItem, arrayTarget, pin.Pointer, nDataSize);
  260. if (0 != nRet)
  261. {
  262. return nRet;
  263. }
  264. //Get Data
  265. for (int i = 0; i < pData.Length; i++)
  266. {
  267. nOutData += pData[i] * (int)Math.Pow(256, i);
  268. }
  269. }
  270. return 0;
  271. }
  272. public int GetParamsCategory(SR7IF_SETTING_ITEM nParamItemEnums, ref int nCategory, ref int nItem, ref int nDataSize)
  273. {
  274. switch (nParamItemEnums)
  275. {
  276. //00
  277. case SR7IF_SETTING_ITEM.TRIG_MODE://触发模式 / Trigger mode
  278. nCategory = 0x00;
  279. nItem = 0x01;
  280. nDataSize = 1;
  281. break;
  282. case SR7IF_SETTING_ITEM.BATCH_OUTPUT://批处理输出 / Batch processing output
  283. nCategory = 0x00;
  284. nItem = 0x21;
  285. nDataSize = 1;
  286. break;
  287. case SR7IF_SETTING_ITEM.SAMPLED_CYCLE://采样周期 / Sampling cycle
  288. nCategory = 0x00;
  289. nItem = 0x02;
  290. nDataSize = 4;
  291. break;
  292. case SR7IF_SETTING_ITEM.BATCH_ON_OFF://批处理开关 / Batch processing switch
  293. nCategory = 0x00;
  294. nItem = 0x03;
  295. nDataSize = 1;
  296. break;
  297. case SR7IF_SETTING_ITEM.ENCODER_TYPE://编码器类型 / Encoder type
  298. nCategory = 0x00;
  299. nItem = 0x0b;
  300. nDataSize = 1;
  301. break;
  302. case SR7IF_SETTING_ITEM.ENCODER_INPUTMODE://编码器输入模式 / Encoder input mode
  303. nCategory = 0x00;
  304. nItem = 0x07;
  305. nDataSize = 1;
  306. break;
  307. case SR7IF_SETTING_ITEM.REFINING_POINTS://细化点数(触发间隔) / Refining points
  308. nCategory = 0x00;
  309. nItem = 0x09;
  310. nDataSize = 2;
  311. break;
  312. case SR7IF_SETTING_ITEM.BATCH_POINT://批处理点数 / Batch processing points
  313. nCategory = 0x00;
  314. nItem = 0x0a;
  315. nDataSize = 2;
  316. break;
  317. case SR7IF_SETTING_ITEM.CYCLICAL_PATTERN://循环模式 0 关闭 1 打开 / Cyclical pattern (0: Off, 1: On)
  318. nCategory = 0x00;
  319. nItem = 0x10;
  320. nDataSize = 1;
  321. break;
  322. case SR7IF_SETTING_ITEM.SEGMENT_BUFER:// 分段存储 0 关闭 1 打开 / Segmented buffer (0: Off, 1: On)
  323. nCategory = 0x00;
  324. nItem = 0x11;
  325. nDataSize = 1;
  326. break;
  327. //01
  328. case SR7IF_SETTING_ITEM.Z_MEASURING_RANGE://Z方向测量范围 / Z-axis measuring range
  329. nCategory = 0x01;
  330. nItem = 0x03;
  331. nDataSize = 1;
  332. break;
  333. case SR7IF_SETTING_ITEM.SENSITIVITY://感光灵敏度 / Sensitivity
  334. nCategory = 0x01;
  335. nItem = 0x05;
  336. nDataSize = 1;
  337. break;
  338. case SR7IF_SETTING_ITEM.EXP_TIME://曝光时间 / Exposure time
  339. nCategory = 0x01;
  340. nItem = 0x06;
  341. nDataSize = 1;
  342. break;
  343. case SR7IF_SETTING_ITEM.LIGHT_CONTROL://光亮控制 / Light control
  344. nCategory = 0x01;
  345. nItem = 0x0B;
  346. nDataSize = 1;
  347. break;
  348. case SR7IF_SETTING_ITEM.LIGHT_MAX://激光亮度上限 / Laser brightness upper limit
  349. nCategory = 0x01;
  350. nItem = 0x0C;
  351. nDataSize = 1;
  352. break;
  353. case SR7IF_SETTING_ITEM.LIGHT_MIN://激光亮度下限 / Laser brightness lower limit
  354. nCategory = 0x01;
  355. nItem = 0x0D;
  356. nDataSize = 1;
  357. break;
  358. case SR7IF_SETTING_ITEM.PEAK_SENSITIVITY://峰值灵敏度 / Peak sensitivity
  359. nCategory = 0x01;
  360. nItem = 0x0F;
  361. nDataSize = 1;
  362. break;
  363. case SR7IF_SETTING_ITEM.PEAK_SELECT://峰值选择 / Peak selection
  364. nCategory = 0x01;
  365. nItem = 0x11;
  366. nDataSize = 1;
  367. break;
  368. //02
  369. case SR7IF_SETTING_ITEM.X_SAMPLING://X轴压缩设定 / X-axis compression setting
  370. nCategory = 0x02;
  371. nItem = 0x02;
  372. nDataSize = 1;
  373. break;
  374. case SR7IF_SETTING_ITEM.FILTER_X_MEDIAN://X轴中位数滤波 / X-axis median filter
  375. nCategory = 0x02;
  376. nItem = 0x0A;
  377. nDataSize = 1;
  378. break;
  379. case SR7IF_SETTING_ITEM.FILTER_Y_MEDIAN://Y轴(时间轴)中位数滤波 / Y-axis (time axis) median filter
  380. nCategory = 0x02;
  381. nItem = 0x0C;
  382. nDataSize = 1;
  383. break;
  384. case SR7IF_SETTING_ITEM.FILTER_X_SMOOTH://X轴平滑滤波 / X-axis smooth filter
  385. nCategory = 0x02;
  386. nItem = 0x0B;
  387. nDataSize = 1;
  388. break;
  389. case SR7IF_SETTING_ITEM.FILTER_Y_SMOOTH://Y轴平滑滤波(平均滤波) / Y-axis smooth filter (mean filter)
  390. nCategory = 0x02;
  391. nItem = 0x0D;
  392. nDataSize = 2;
  393. break;
  394. //30
  395. case SR7IF_SETTING_ITEM.CHANGE_3D_25D://3D/2.5D模式切换 / 3D/2.5D switch (In 2.5D mode, X-axis compression setting changes to default automatically)
  396. nCategory = 0x30;
  397. nItem = 0x00;
  398. nDataSize = 1;
  399. break;
  400. default:
  401. nCategory = 0x00;
  402. nItem = 0x00;
  403. nDataSize = 1;
  404. return -1;
  405. }
  406. return 0;
  407. }
  408. ///
  409. /// \brief SR7IF_Get16BitScale 获取16bit高度数据物理单位 / Get 16-bit height data in physical units
  410. /// \param Scale [out] 16bit高度数据 单位(mm) / 16bit height data Unit (mm)
  411. /// \return
  412. /// <0: 失败./Fail.
  413. /// =0: 成功./Success
  414. ///
  415. public int Get16BitScale(out float Scale)
  416. {
  417. float[] scale1 = new float[1];
  418. int ret = 0;
  419. using (PinnedObject pin_size = new PinnedObject(scale1))
  420. {
  421. ret = SR7LinkFunc.SR7IF_Get16BitScale(0, pin_size.Pointer);
  422. }
  423. Scale = scale1[0];
  424. return ret;
  425. }
  426. }
  427. }