SSZNCamera.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. using Cognex.VisionPro;
  2. using Cognex.VisionPro.ToolBlock;
  3. using CSScripting;
  4. using Microsoft.Win32;
  5. using NPOI.SS.Formula.Functions;
  6. using SR7Link;
  7. using SRAPI;
  8. using SRCSharpDemo;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.ComponentModel;
  12. using System.Diagnostics;
  13. using System.IO;
  14. using System.Linq;
  15. using System.Runtime.CompilerServices;
  16. using System.Runtime.InteropServices;
  17. using System.Text;
  18. using System.Threading;
  19. using System.Threading.Tasks;
  20. using System.Windows.Forms;
  21. using TeamAAS_VP.Enums;
  22. using TeamAAS_VP.Interfaces;
  23. using TeamAAS_VP.Models;
  24. namespace TeamAAS_VP.Core.Cameras
  25. {
  26. public class SSZNCamera : ICamera, INotifyPropertyChanged
  27. {
  28. #region 字段
  29. private Thread m_hReceiveThread;
  30. // 用于序列化对同一相机实例的操作,防止同一实例被并发操作
  31. private readonly SemaphoreSlim _operationSemaphore = new SemaphoreSlim(1, 1);
  32. // 用于保护状态变量(例如 IsGrabbing)的并发访问
  33. private readonly object _stateLock = new object();
  34. private SR7ApiOneTimeCallbackImpl iSR7APi = new SR7ApiOneTimeCallbackImpl();
  35. public SRCSharpTools srcsharpTools = new SRCSharpTools();
  36. private SR7IFGetDataCallBack GetDataDelegate;
  37. #endregion
  38. #region define
  39. private int lastTotalPoints = 0; // 记录上次的总点数 / Record the last total points
  40. public int coutCallbackPoints;//统计总回调行数 / Count the total number of callback rows
  41. public uint profile16Bits = 0;//0:32bit 1:16bit
  42. //define
  43. public const int INVALID_VALUE_MIN = -1000000000;
  44. public const int INVALID_VALUE_MAX = 1000000000;
  45. #endregion
  46. #region Image cache variable
  47. //image cache
  48. public int[][] ImgBuff32; // 32-bit height data
  49. public short[][] ImgBuff16; // 16-bit height data
  50. public byte[][] GrayBuff; // Grayscale data
  51. public int[][] Encoder; // Encoder data
  52. #endregion
  53. #region 属性
  54. public CameraBrand CameraBrand { get => CameraBrand.SSZN; }
  55. public string Name { get; private set; }
  56. public Guid ID { get; private set; }
  57. public int Index { get; set; }
  58. public string ManufacturerName { get; private set; }
  59. public bool IsFindByIp { get; private set; }
  60. public string ModelName { get; private set; }
  61. public string SerialNumber { get; private set; }
  62. public string CameraIp { get; private set; }
  63. public CameraType CameraType { get; private set; }
  64. public UInt32 ImageWidth { get; private set; }
  65. public UInt32 ImageHeight { get; private set; }
  66. private bool _IsGrabbing;
  67. /// <summary>
  68. /// 正在采集
  69. /// </summary>
  70. public bool IsGrabbing
  71. {
  72. get { return _IsGrabbing; }
  73. private set { SetProperty(ref _IsGrabbing, value); }
  74. }
  75. private ICogImage _Image;
  76. public ICogImage Image
  77. {
  78. get { return _Image; }
  79. private set { SetProperty(ref _Image, value); }
  80. }
  81. public bool IsConnected { get; private set; }
  82. /// <summary>
  83. /// 采集用时
  84. /// </summary>
  85. public TimeSpan TotalTime { get; private set; }
  86. /// <summary>
  87. /// 错误信息
  88. /// </summary>
  89. public string ErrorMessage { get; private set; }
  90. #endregion
  91. #region 事件
  92. public event Action<ICogImage, TimeSpan, string> ImageCallbackEvent;
  93. public event Action<Guid, bool> CameraConnectChangedEvent;
  94. #endregion
  95. public SSZNCamera(Guid id, int index, string name, string serialNumber, string cameraip, bool isFindByIp)
  96. {
  97. ID = id;
  98. Name = serialNumber;
  99. Index = index;
  100. CameraIp = cameraip;
  101. SerialNumber = serialNumber;
  102. IsFindByIp = isFindByIp;
  103. IsConnected = false;
  104. }
  105. #region 方法
  106. /// <summary>
  107. /// 获取设备
  108. /// </summary>
  109. /// <returns></returns>
  110. public static CameraInfo[] GetDevices()
  111. {
  112. List<CameraInfo> cameras = new List<CameraInfo>();
  113. try
  114. {
  115. if (!CheckSoftwareInstalled().isInstalled)
  116. {
  117. LogHelper.WriteLogInfo("未安装MVS");
  118. return cameras.ToArray();
  119. }
  120. SR7ApiOneTimeCallbackImpl sR7Api=new SR7ApiOneTimeCallbackImpl();
  121. List<string> cameraIPs = new List<string>();
  122. if (!sR7Api.SearchCameraIP(out cameraIPs))
  123. {
  124. return cameras.ToArray();
  125. }
  126. else
  127. {
  128. for (int i = 0; i < cameraIPs.Count; i++)
  129. {
  130. cameras.Add(new CameraInfo()
  131. {
  132. CameraNo = i + 1,
  133. CameraName = "SSZN_" + cameraIPs[i],
  134. CameraBrand = CameraBrand.SSZN,
  135. CameraType = CameraType.GIGE,
  136. ManufacturerName = "SSZN",
  137. Model = "SSZN_Model",
  138. SerialNumber = "SSZN_SerialNumber",
  139. CameraIp = cameraIPs[i],
  140. IsFindByIp = true,
  141. });
  142. }
  143. }
  144. }
  145. catch (Exception ex)
  146. {
  147. LogHelper.WriteLogError("搜索深视3D相机列表时出错!", ex);
  148. }
  149. return cameras.ToArray();
  150. }
  151. /// <summary>
  152. /// 检查相机软件是否安装
  153. /// </summary>
  154. /// <returns></returns>
  155. public static (bool isInstalled, string version) CheckSoftwareInstalled()
  156. {
  157. return (true, "");
  158. }
  159. /// <summary>
  160. /// 打开相机
  161. /// </summary>
  162. /// <returns></returns>
  163. /// <exception cref="Exception"></exception>
  164. public bool OpenDevice()
  165. {
  166. _operationSemaphore.Wait();
  167. try
  168. {
  169. if (!iSR7APi.CameraBOnline)
  170. {
  171. SR7Link.ErrConnectCallBack ErrConnectDelegate = new SR7Link.ErrConnectCallBack(ErrConnectFunc);
  172. ErrConnectDelegate = new ErrConnectCallBack(ErrConnectFunc);
  173. int nOpenRet = iSR7APi.Open(Index-1, CameraIp, 2000, ErrConnectDelegate);
  174. if (nOpenRet == (int)SR7Link.SR7IF_ERROR.SR7IF_OK)
  175. {
  176. //设置相机参数,否则无法取图 / Set the camera parameters, otherwise you will not be able to take pictures
  177. //一次回调和无限回调可以设置批处理测量On,批处理数据接收无和循环 / One-time callback and infinite callback can set batch measurement On, batch data receiving None and loop
  178. //异步回调必须在Ed软件中设置 / Asynchronous callbacks must be set in the EdgeImaging software
  179. int nReadBastchValue = -1;
  180. int nSetParamRet = -1;
  181. int getParamRet = iSR7APi.GetParams(Index - 1, -1, SR7IF_SETTING_ITEM.BATCH_ON_OFF, out nReadBastchValue);
  182. if (nReadBastchValue != 1)
  183. {
  184. nSetParamRet = iSR7APi.SetParams(Index - 1, (int)SAVEPOWEROFF.ESAPO_SAVE, -1, SR7IF_SETTING_ITEM.BATCH_ON_OFF, 1);
  185. LogHelper.WriteLogInfo($"Set Batch On Off: {nSetParamRet}");
  186. }
  187. nSetParamRet = iSR7APi.SetParams(Index - 1, (int)SAVEPOWEROFF.ESAPO_SAVE, -1, SR7IF_SETTING_ITEM.CYCLICAL_PATTERN, 0);
  188. int nSetParamRet1 = iSR7APi.SetParams(Index - 1, (int)SAVEPOWEROFF.ESAPO_SAVE, -1, SR7IF_SETTING_ITEM.SEGMENT_BUFER, 0);
  189. LogHelper.WriteLogInfo($"Set Batch Data Receive: {nSetParamRet1}{nSetParamRet1}");
  190. GetDataDelegate = new SR7IFGetDataCallBack(GetDataCallBack);
  191. iSR7APi.Init(Index - 1, 0,2000, GetDataDelegate);
  192. }
  193. LogHelper.WriteLogInfo($"Connect Camera {nOpenRet} {GetSDKErrMsgByCode(nOpenRet)}");
  194. }
  195. if (!IsConnected)
  196. {
  197. if (iSR7APi.CameraAOnline)
  198. {
  199. CameraConnectChangedEvent?.Invoke(ID, true);
  200. }
  201. }
  202. IsConnected = iSR7APi.CameraBOnline;
  203. return IsConnected;
  204. }
  205. finally
  206. {
  207. _operationSemaphore.Release();
  208. }
  209. }
  210. /// <summary>
  211. /// 打开相机异步
  212. /// </summary>
  213. /// <returns></returns>
  214. public Task<bool> OpenDeviceAsync()
  215. {
  216. return Task.Run(() =>
  217. {
  218. return OpenDevice();
  219. });
  220. }
  221. /// <summary>
  222. /// 关闭相机
  223. /// </summary>
  224. public void CloseDevice()
  225. {
  226. // ch:关闭设备 | en:Close Device
  227. _operationSemaphore.Wait();
  228. try
  229. {
  230. if (iSR7APi==null)
  231. {
  232. return;
  233. }
  234. iSR7APi.Stop();
  235. int nRet = iSR7APi.Close();
  236. LogHelper.WriteLogInfo($"Close Camera: {nRet}{GetSDKErrMsgByCode(nRet)}");
  237. }
  238. finally
  239. {
  240. _operationSemaphore.Release();
  241. }
  242. }
  243. /// <summary>
  244. /// 采集图像
  245. /// </summary>
  246. /// <returns></returns>
  247. public ICogImage Grab()
  248. {
  249. _operationSemaphore.Wait();
  250. try
  251. {
  252. return Image;
  253. }
  254. finally
  255. {
  256. _operationSemaphore.Release();
  257. }
  258. }
  259. /// <summary>
  260. /// 开始采集图像
  261. /// </summary>
  262. public void StartGrabbing()
  263. {
  264. lock (_stateLock)
  265. {
  266. if (IsGrabbing)
  267. return;
  268. IsGrabbing = true;
  269. }
  270. m_hReceiveThread = new Thread(GetStreamThreadProc) { IsBackground = true };
  271. m_hReceiveThread.Start();
  272. }
  273. /// <summary>
  274. /// 停止采集图像
  275. /// </summary>
  276. public void StopGrabbing()
  277. {
  278. try
  279. {
  280. lock (_stateLock)
  281. {
  282. IsGrabbing = false;
  283. }
  284. Thread.Sleep(1000);
  285. if (m_hReceiveThread != null)
  286. {
  287. m_hReceiveThread.Abort();
  288. m_hReceiveThread = null;
  289. }
  290. }
  291. catch (Exception)
  292. {
  293. }
  294. }
  295. /// <summary>
  296. /// 设置曝光时间
  297. /// </summary>
  298. /// <param name="ExposureTime"></param>
  299. /// <returns></returns>
  300. public bool SetExposureTime(float ExposureTime)
  301. {
  302. //_operationSemaphore.Wait();
  303. //try
  304. //{
  305. // if (!mvCameraAcq.bIsOpened)
  306. // return false;
  307. // mvCameraAcq.ExposureTime = (double)ExposureTime;
  308. // return true;
  309. //}
  310. //finally
  311. //{
  312. // _operationSemaphore.Release();
  313. //}
  314. return true;
  315. }
  316. /// <summary>
  317. /// 获取曝光时间
  318. /// </summary>
  319. /// <returns></returns>
  320. public float GetExposureTime()
  321. {
  322. //_operationSemaphore.Wait();
  323. //try
  324. //{
  325. // if (!mvCameraAcq.bIsOpened)
  326. // return 0;
  327. // return (float)mvCameraAcq.ExposureTime;
  328. //}
  329. //finally
  330. //{
  331. // _operationSemaphore.Release();
  332. //}
  333. return 0;
  334. }
  335. /// <summary>
  336. /// 设置增益
  337. /// </summary>
  338. /// <param name="Gain"></param>
  339. /// <returns></returns>
  340. public bool SetGain(float Gain)
  341. {
  342. //_operationSemaphore.Wait();
  343. //try
  344. //{
  345. // if (!mvCameraAcq.bIsOpened)
  346. // return false;
  347. // mvCameraAcq.AnalogGain = (double)Gain;
  348. // return true;
  349. //}
  350. //finally
  351. //{
  352. // _operationSemaphore.Release();
  353. //}
  354. return true;
  355. }
  356. /// <summary>
  357. /// 获取增益
  358. /// </summary>
  359. /// <returns></returns>
  360. public float GetGain()
  361. {
  362. //_operationSemaphore.Wait();
  363. //try
  364. //{
  365. // if (!mvCameraAcq.bIsOpened)
  366. // return 0;
  367. // return (float)mvCameraAcq.AnalogGain;
  368. //}
  369. //finally
  370. //{
  371. // _operationSemaphore.Release();
  372. //}
  373. return 0;
  374. }
  375. private void GetStreamThreadProc()
  376. {
  377. //while (IsGrabbing)
  378. //{
  379. // try
  380. // {
  381. // Grab();
  382. // ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  383. // }
  384. // catch (Exception)
  385. // {
  386. // }
  387. // Thread.Sleep(10);
  388. //}
  389. IsGrabbing = false;
  390. }
  391. /// <summary>
  392. ///
  393. /// </summary>
  394. /// <param name="nProfileWidth">单条轮廓宽度数据 / Returns a single contour width data</param>
  395. /// <param name="nHighlen">返回的批处理行数 / The number of rows in the batch returned</param>
  396. /// <param name="nFlag">回调函数执行状态,根据不同模式自定义 / Callback function execution status, customized according to different modes</param>
  397. /// <param name="nStatusCode">错误码,0无错误 / Error code, 0 no error</param>
  398. /// <param name="ProfileBits">Sync callback 0:32bit data, 1:16bit data</param>
  399. private void GetDataCallBack(int nProfileWidth, int nHighlen, int nFlag, int nStatusCode, int ProfileBits)
  400. {
  401. profile16Bits = (uint)ProfileBits;
  402. if (nStatusCode == 0)
  403. {
  404. //Log($"Into GetDataFunc W:{nProfileWidth},H:{nHighlen},ErrCode:{nStatusCode}({GetSDKErrMsgByCode(nStatusCode)})");
  405. //这里拿到相机数据做显示,可以根据其他具体业务实现自己的逻辑
  406. //The camera data is obtained here for display, and you can implement your own logic according to other specific businesses
  407. int nTempWidth = nProfileWidth;// iSR7APi.GetProfileDataWidth();
  408. //双相机时,一次回调和异步回调nProfileWidth=3200,无限循环回调nProfileWidth=6400
  409. //For dual cameras, nProfileWidth=3200 for one-time callback and asynchronous callback, and nProfileWidth=6400 for infinite loop callback
  410. //if (iSR7APi.CameraBOnline && m_callbackMode == 2)//双相机 / dual camera
  411. // nTempWidth /= 2;
  412. int offset = coutCallbackPoints * nTempWidth;
  413. //iSR7APi.BatchPoints = nHighlen;
  414. SImagePro.SPointCloudHead pcHead = new SImagePro.SPointCloudHead(0, 0, 0, 0, 0);
  415. pcHead.width = (uint)nTempWidth;
  416. pcHead.height = (uint)iSR7APi.BatchPoints;
  417. pcHead.xInterval = iSR7APi.GetProfileData_XPitch();
  418. pcHead.yInterval = iSR7APi.GetProfileData_XPitch();
  419. if (ProfileBits == 0)
  420. {
  421. int[] tempHeightDataA = new int[nTempWidth * nHighlen];
  422. byte[] tempGrayDataA = new byte[nTempWidth * nHighlen];
  423. iSR7APi.GetData(tempHeightDataA, tempGrayDataA, Encoder[Index - 1], (int)pcHead.width, (int)nHighlen, Index - 1);
  424. Array.Copy(tempHeightDataA, 0, ImgBuff32[0], offset, nTempWidth * nHighlen);
  425. Array.Copy(tempGrayDataA, 0, GrayBuff[0], offset, nTempWidth * nHighlen);
  426. //if (ImgBuff32 != null && ImgBuff32.Length != 0 && ImgBuff32[0] != null)
  427. //{
  428. // ShowRGBImage(ImgBuff32[0], pcHead, pictureBoxA);
  429. //}
  430. CogImage16Range cogImage16Range = SSZNCognexParser.SSZNParser.LoadSSZN3DImage(ImgBuff32[Index - 1], (int)pcHead.width, (int)pcHead.height, pcHead.xInterval, pcHead.yInterval);
  431. Image= cogImage16Range;
  432. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  433. }
  434. else
  435. {
  436. short[] temp16bitDataA = new short[nTempWidth * nHighlen];
  437. byte[] tempGrayDataA = new byte[nTempWidth * nHighlen];
  438. iSR7APi.GetData(temp16bitDataA, tempGrayDataA, Encoder[0], (int)pcHead.width, (int)nHighlen, 0);
  439. Array.Copy(temp16bitDataA, 0, ImgBuff16[0], offset, nTempWidth * nHighlen);
  440. Array.Copy(tempGrayDataA, 0, GrayBuff[0], offset, nTempWidth * nHighlen);
  441. CogImage16Range cogImage16Range = SSZNCognexParser.SSZNParser.LoadSSZN3DImage(ImgBuff32[0], (int)pcHead.width, (int)pcHead.height, pcHead.xInterval, pcHead.yInterval);
  442. Image = cogImage16Range;
  443. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  444. //int[] showtemp16bitDataA = new int[pcHead.width * pcHead.height];
  445. //ShowTiff16Data(ImgBuff16[0], showtemp16bitDataA);
  446. //if (ImgBuff16 != null && ImgBuff16.Length != 0 && ImgBuff16[0] != null)
  447. //{
  448. // ShowRGBImage(showtemp16bitDataA, pcHead, pictureBoxA);
  449. //}
  450. }
  451. //if (iSR7APi.CameraBOnline && ImgBuff32[1] != null)
  452. //{
  453. // if (ProfileBits == 0)
  454. // {
  455. // int[] tempHeightDataB = new int[nTempWidth * nHighlen];
  456. // byte[] tempGrayDataB = new byte[nTempWidth * nHighlen];
  457. // iSR7APi.GetData(tempHeightDataB, tempGrayDataB, Encoder[1], (int)pcHead.width, (int)nHighlen, 1);
  458. // Array.Copy(tempHeightDataB, 0, ImgBuff32[1], offset, nTempWidth * nHighlen);
  459. // Array.Copy(tempGrayDataB, 0, GrayBuff[1], offset, nTempWidth * nHighlen);
  460. // //ShowRGBImage(ImgBuff32[1], pcHead, pictureBoxB);
  461. // }
  462. // else
  463. // {
  464. // short[] tempHeightDataB = new short[nTempWidth * nHighlen];
  465. // byte[] tempGrayDataB = new byte[nTempWidth * nHighlen];
  466. // iSR7APi.GetData(tempHeightDataB, tempGrayDataB, Encoder[1], (int)pcHead.width, (int)nHighlen, 1);
  467. // Array.Copy(tempHeightDataB, 0, ImgBuff16[1], offset, nTempWidth * nHighlen);
  468. // Array.Copy(tempGrayDataB, 0, GrayBuff[1], offset, nTempWidth * nHighlen);
  469. // int[] showtemp16bitDataB = new int[pcHead.width * pcHead.height];
  470. // //ShowTiff16Data(ImgBuff16[1], showtemp16bitDataB);
  471. // //ShowRGBImage(showtemp16bitDataB, pcHead, pictureBoxB);
  472. // }
  473. //}
  474. coutCallbackPoints += nHighlen;
  475. }
  476. else
  477. {
  478. LogHelper.WriteLogInfo($"Data CallBack Exception:{nStatusCode}({GetSDKErrMsgByCode(nStatusCode)})");
  479. //callbackEvent.Set();
  480. }
  481. }
  482. public void ErrConnectFunc(int dwDeviceId, int nErrCode)
  483. {
  484. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{GetSDKErrMsgByCode(nErrCode)}");
  485. iSR7APi.CameraAOnline = false;
  486. iSR7APi.CameraBOnline = false;
  487. //:1:Data overflow,3:Disconnect, 4:Wrong version
  488. //Non-asynchronous mode: -1 represents a general error, such as link failure, setup failure, data acquisition failure, etc., -1000;
  489. switch (nErrCode)
  490. {
  491. case 1:
  492. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_1")}");
  493. break;
  494. case 3:
  495. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_3")}");
  496. break;
  497. case 4:
  498. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_3")}");
  499. break;
  500. case -1:
  501. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_N1")}");
  502. break;
  503. default:
  504. break;
  505. }
  506. }
  507. public string GetSDKErrMsgByCode(int nErrCode)
  508. {
  509. string strErrMsg;
  510. switch ((SR7Link.SR7IF_ERROR)nErrCode)
  511. {
  512. case SR7IF_ERROR.SR7IF_ERROR_NOT_FOUND: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_NOT_FOUND"); break;
  513. case SR7IF_ERROR.SR7IF_ERROR_COMMAND: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_COMMAND"); break;
  514. case SR7IF_ERROR.SR7IF_ERROR_PARAMETER: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_PARAMETER"); break;
  515. case SR7IF_ERROR.SR7IF_ERROR_UNIMPLEMENTED: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_UNIMPLEMENTED"); break;
  516. case SR7IF_ERROR.SR7IF_ERROR_HANDLE: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_HANDLE"); break;
  517. case SR7IF_ERROR.SR7IF_ERROR_MEMORY: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_MEMORY"); break;
  518. case SR7IF_ERROR.SR7IF_ERROR_TIMEOUT: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_TIMEOUT"); break;
  519. case SR7IF_ERROR.SR7IF_ERROR_DATABUFFER: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_DATABUFFER"); break;
  520. case SR7IF_ERROR.SR7IF_ERROR_STREAM: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_STREAM"); break;
  521. case SR7IF_ERROR.SR7IF_ERROR_CLOSED: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_CLOSED"); break;
  522. case SR7IF_ERROR.SR7IF_ERROR_VERSION: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_VERSION"); break;
  523. case SR7IF_ERROR.SR7IF_ERROR_ABORT: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ABORT"); break;
  524. case SR7IF_ERROR.SR7IF_ERROR_ALREADY_EXISTS: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ALREADY_EXISTS"); break;
  525. case SR7IF_ERROR.SR7IF_ERROR_FRAME_LOSS: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_FRAME_LOSS"); break;
  526. case SR7IF_ERROR.SR7IF_ERROR_ROLL_DATA_OVERFLOW: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ROLL_DATA_OVERFLOW"); break;
  527. case SR7IF_ERROR.SR7IF_ERROR_ROLL_BUSY: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ROLL_BUSY"); break;
  528. case SR7IF_ERROR.SR7IF_ERROR_MODE: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_MODE"); break;
  529. case SR7IF_ERROR.SR7IF_ERROR_CAMERA_NOT_ONLINE: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_CAMERA_NOT_ONLINE"); break;
  530. case SR7IF_ERROR.SR7IF_ERROR: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR"); break;
  531. case SR7IF_ERROR.SR7IF_NORMAL_STOP: strErrMsg = srcsharpTools.GetTranslation("SR7IF_NORMAL_STOP"); break;
  532. case SR7IF_ERROR.SR7IF_OK: strErrMsg = ""; break;
  533. default:
  534. strErrMsg = "";
  535. break;
  536. }
  537. return strErrMsg;
  538. }
  539. #endregion
  540. #region 属性通知
  541. /// <summary>
  542. /// Occurs when a property value changes.
  543. /// </summary>
  544. public event PropertyChangedEventHandler PropertyChanged;
  545. /// <summary>
  546. /// Checks if a property already matches a desired value. Sets the property and
  547. /// notifies listeners only when necessary.
  548. /// </summary>
  549. /// <typeparam name="T">Type of the property.</typeparam>
  550. /// <param name="storage">Reference to a property with both getter and setter.</param>
  551. /// <param name="value">Desired value for the property.</param>
  552. /// <param name="propertyName">Name of the property used to notify listeners. This
  553. /// value is optional and can be provided automatically when invoked from compilers that
  554. /// support CallerMemberName.</param>
  555. /// <returns>True if the value was changed, false if the existing value matched the
  556. /// desired value.</returns>
  557. protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
  558. {
  559. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  560. storage = value;
  561. RaisePropertyChanged(propertyName);
  562. return true;
  563. }
  564. /// <summary>
  565. /// Checks if a property already matches a desired value. Sets the property and
  566. /// notifies listeners only when necessary.
  567. /// </summary>
  568. /// <typeparam name="T">Type of the property.</typeparam>
  569. /// <param name="storage">Reference to a property with both getter and setter.</param>
  570. /// <param name="value">Desired value for the property.</param>
  571. /// <param name="propertyName">Name of the property used to notify listeners. This
  572. /// value is optional and can be provided automatically when invoked from compilers that
  573. /// support CallerMemberName.</param>
  574. /// <param name="onChanged">Action that is called after the property value has been changed.</param>
  575. /// <returns>True if the value was changed, false if the existing value matched the
  576. /// desired value.</returns>
  577. protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
  578. {
  579. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  580. storage = value;
  581. onChanged?.Invoke();
  582. RaisePropertyChanged(propertyName);
  583. return true;
  584. }
  585. /// <summary>
  586. /// Raises this object's PropertyChanged event.
  587. /// </summary>
  588. /// <param name="propertyName">Name of the property used to notify listeners. This
  589. /// value is optional and can be provided automatically when invoked from compilers
  590. /// that support <see cref="CallerMemberNameAttribute"/>.</param>
  591. protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
  592. {
  593. OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
  594. }
  595. /// <summary>
  596. /// Raises this object's PropertyChanged event.
  597. /// </summary>
  598. /// <param name="args">The PropertyChangedEventArgs</param>
  599. protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
  600. {
  601. PropertyChanged?.Invoke(this, args);
  602. }
  603. #endregion
  604. }
  605. }