SSZNCamera.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  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(0, 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(0, -1, SR7IF_SETTING_ITEM.BATCH_ON_OFF, out nReadBastchValue);
  182. if (nReadBastchValue != 1)
  183. {
  184. nSetParamRet = iSR7APi.SetParams(0, (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(0, (int)SAVEPOWEROFF.ESAPO_SAVE, -1, SR7IF_SETTING_ITEM.CYCLICAL_PATTERN, 0);
  188. int nSetParamRet1 = iSR7APi.SetParams(0, (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(0,0,2000, GetDataDelegate);
  192. }
  193. LogHelper.WriteLogInfo($"Connect Camera {nOpenRet} {GetSDKErrMsgByCode(nOpenRet)}");
  194. }
  195. if (!IsConnected)
  196. {
  197. if (iSR7APi.CameraBOnline)
  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. int nRet = iSR7APi.Close();
  235. LogHelper.WriteLogInfo($"Close Camera: {nRet}{GetSDKErrMsgByCode(nRet)}");
  236. }
  237. finally
  238. {
  239. _operationSemaphore.Release();
  240. }
  241. }
  242. /// <summary>
  243. /// 采集图像
  244. /// </summary>
  245. /// <returns></returns>
  246. public ICogImage Grab()
  247. {
  248. _operationSemaphore.Wait();
  249. try
  250. {
  251. return Image;
  252. }
  253. finally
  254. {
  255. _operationSemaphore.Release();
  256. }
  257. }
  258. /// <summary>
  259. /// 开始采集图像
  260. /// </summary>
  261. public void StartGrabbing()
  262. {
  263. lock (_stateLock)
  264. {
  265. if (IsGrabbing)
  266. return;
  267. IsGrabbing = true;
  268. }
  269. m_hReceiveThread = new Thread(GetStreamThreadProc) { IsBackground = true };
  270. m_hReceiveThread.Start();
  271. }
  272. /// <summary>
  273. /// 停止采集图像
  274. /// </summary>
  275. public void StopGrabbing()
  276. {
  277. try
  278. {
  279. lock (_stateLock)
  280. {
  281. IsGrabbing = false;
  282. }
  283. Thread.Sleep(1000);
  284. if (m_hReceiveThread != null)
  285. {
  286. m_hReceiveThread.Abort();
  287. m_hReceiveThread = null;
  288. }
  289. }
  290. catch (Exception)
  291. {
  292. }
  293. }
  294. /// <summary>
  295. /// 设置曝光时间
  296. /// </summary>
  297. /// <param name="ExposureTime"></param>
  298. /// <returns></returns>
  299. public bool SetExposureTime(float ExposureTime)
  300. {
  301. //_operationSemaphore.Wait();
  302. //try
  303. //{
  304. // if (!mvCameraAcq.bIsOpened)
  305. // return false;
  306. // mvCameraAcq.ExposureTime = (double)ExposureTime;
  307. // return true;
  308. //}
  309. //finally
  310. //{
  311. // _operationSemaphore.Release();
  312. //}
  313. return true;
  314. }
  315. /// <summary>
  316. /// 获取曝光时间
  317. /// </summary>
  318. /// <returns></returns>
  319. public float GetExposureTime()
  320. {
  321. //_operationSemaphore.Wait();
  322. //try
  323. //{
  324. // if (!mvCameraAcq.bIsOpened)
  325. // return 0;
  326. // return (float)mvCameraAcq.ExposureTime;
  327. //}
  328. //finally
  329. //{
  330. // _operationSemaphore.Release();
  331. //}
  332. return 0;
  333. }
  334. /// <summary>
  335. /// 设置增益
  336. /// </summary>
  337. /// <param name="Gain"></param>
  338. /// <returns></returns>
  339. public bool SetGain(float Gain)
  340. {
  341. //_operationSemaphore.Wait();
  342. //try
  343. //{
  344. // if (!mvCameraAcq.bIsOpened)
  345. // return false;
  346. // mvCameraAcq.AnalogGain = (double)Gain;
  347. // return true;
  348. //}
  349. //finally
  350. //{
  351. // _operationSemaphore.Release();
  352. //}
  353. return true;
  354. }
  355. /// <summary>
  356. /// 获取增益
  357. /// </summary>
  358. /// <returns></returns>
  359. public float GetGain()
  360. {
  361. //_operationSemaphore.Wait();
  362. //try
  363. //{
  364. // if (!mvCameraAcq.bIsOpened)
  365. // return 0;
  366. // return (float)mvCameraAcq.AnalogGain;
  367. //}
  368. //finally
  369. //{
  370. // _operationSemaphore.Release();
  371. //}
  372. return 0;
  373. }
  374. private void GetStreamThreadProc()
  375. {
  376. //while (IsGrabbing)
  377. //{
  378. // try
  379. // {
  380. // Grab();
  381. // ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  382. // }
  383. // catch (Exception)
  384. // {
  385. // }
  386. // Thread.Sleep(10);
  387. //}
  388. IsGrabbing = false;
  389. }
  390. /// <summary>
  391. ///
  392. /// </summary>
  393. /// <param name="nProfileWidth">单条轮廓宽度数据 / Returns a single contour width data</param>
  394. /// <param name="nHighlen">返回的批处理行数 / The number of rows in the batch returned</param>
  395. /// <param name="nFlag">回调函数执行状态,根据不同模式自定义 / Callback function execution status, customized according to different modes</param>
  396. /// <param name="nStatusCode">错误码,0无错误 / Error code, 0 no error</param>
  397. /// <param name="ProfileBits">Sync callback 0:32bit data, 1:16bit data</param>
  398. private void GetDataCallBack(int nProfileWidth, int nHighlen, int nFlag, int nStatusCode, int ProfileBits)
  399. {
  400. profile16Bits = (uint)ProfileBits;
  401. if (nStatusCode == 0)
  402. {
  403. //Log($"Into GetDataFunc W:{nProfileWidth},H:{nHighlen},ErrCode:{nStatusCode}({GetSDKErrMsgByCode(nStatusCode)})");
  404. //这里拿到相机数据做显示,可以根据其他具体业务实现自己的逻辑
  405. //The camera data is obtained here for display, and you can implement your own logic according to other specific businesses
  406. int nTempWidth = nProfileWidth;// iSR7APi.GetProfileDataWidth();
  407. //双相机时,一次回调和异步回调nProfileWidth=3200,无限循环回调nProfileWidth=6400
  408. //For dual cameras, nProfileWidth=3200 for one-time callback and asynchronous callback, and nProfileWidth=6400 for infinite loop callback
  409. //if (iSR7APi.CameraBOnline && m_callbackMode == 2)//双相机 / dual camera
  410. // nTempWidth /= 2;
  411. int offset = coutCallbackPoints * nTempWidth;
  412. //iSR7APi.BatchPoints = nHighlen;
  413. SImagePro.SPointCloudHead pcHead = new SImagePro.SPointCloudHead(0, 0, 0, 0, 0);
  414. pcHead.width = (uint)nTempWidth;
  415. pcHead.height = (uint)iSR7APi.BatchPoints;
  416. pcHead.xInterval = iSR7APi.GetProfileData_XPitch();
  417. pcHead.yInterval = iSR7APi.GetProfileData_XPitch();
  418. if (ProfileBits == 0)
  419. {
  420. int[] tempHeightDataA = new int[nTempWidth * nHighlen];
  421. byte[] tempGrayDataA = new byte[nTempWidth * nHighlen];
  422. iSR7APi.GetData(tempHeightDataA, tempGrayDataA, Encoder[0], (int)pcHead.width, (int)nHighlen, 0);
  423. Array.Copy(tempHeightDataA, 0, ImgBuff32[0], offset, nTempWidth * nHighlen);
  424. Array.Copy(tempGrayDataA, 0, GrayBuff[0], offset, nTempWidth * nHighlen);
  425. //if (ImgBuff32 != null && ImgBuff32.Length != 0 && ImgBuff32[0] != null)
  426. //{
  427. // ShowRGBImage(ImgBuff32[0], pcHead, pictureBoxA);
  428. //}
  429. CogImage16Range cogImage16Range = SSZNCognexParser.SSZNParser.LoadSSZN3DImage(ImgBuff32[0], (int)pcHead.width, (int)pcHead.height, pcHead.xInterval, pcHead.yInterval);
  430. Image= cogImage16Range;
  431. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  432. }
  433. else
  434. {
  435. short[] temp16bitDataA = new short[nTempWidth * nHighlen];
  436. byte[] tempGrayDataA = new byte[nTempWidth * nHighlen];
  437. iSR7APi.GetData(temp16bitDataA, tempGrayDataA, Encoder[0], (int)pcHead.width, (int)nHighlen, 0);
  438. Array.Copy(temp16bitDataA, 0, ImgBuff16[0], offset, nTempWidth * nHighlen);
  439. Array.Copy(tempGrayDataA, 0, GrayBuff[0], offset, nTempWidth * nHighlen);
  440. CogImage16Range cogImage16Range = SSZNCognexParser.SSZNParser.LoadSSZN3DImage(ImgBuff32[0], (int)pcHead.width, (int)pcHead.height, pcHead.xInterval, pcHead.yInterval);
  441. Image = cogImage16Range;
  442. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  443. //int[] showtemp16bitDataA = new int[pcHead.width * pcHead.height];
  444. //ShowTiff16Data(ImgBuff16[0], showtemp16bitDataA);
  445. //if (ImgBuff16 != null && ImgBuff16.Length != 0 && ImgBuff16[0] != null)
  446. //{
  447. // ShowRGBImage(showtemp16bitDataA, pcHead, pictureBoxA);
  448. //}
  449. }
  450. //if (iSR7APi.CameraBOnline && ImgBuff32[1] != null)
  451. //{
  452. // if (ProfileBits == 0)
  453. // {
  454. // int[] tempHeightDataB = new int[nTempWidth * nHighlen];
  455. // byte[] tempGrayDataB = new byte[nTempWidth * nHighlen];
  456. // iSR7APi.GetData(tempHeightDataB, tempGrayDataB, Encoder[1], (int)pcHead.width, (int)nHighlen, 1);
  457. // Array.Copy(tempHeightDataB, 0, ImgBuff32[1], offset, nTempWidth * nHighlen);
  458. // Array.Copy(tempGrayDataB, 0, GrayBuff[1], offset, nTempWidth * nHighlen);
  459. // //ShowRGBImage(ImgBuff32[1], pcHead, pictureBoxB);
  460. // }
  461. // else
  462. // {
  463. // short[] tempHeightDataB = new short[nTempWidth * nHighlen];
  464. // byte[] tempGrayDataB = new byte[nTempWidth * nHighlen];
  465. // iSR7APi.GetData(tempHeightDataB, tempGrayDataB, Encoder[1], (int)pcHead.width, (int)nHighlen, 1);
  466. // Array.Copy(tempHeightDataB, 0, ImgBuff16[1], offset, nTempWidth * nHighlen);
  467. // Array.Copy(tempGrayDataB, 0, GrayBuff[1], offset, nTempWidth * nHighlen);
  468. // int[] showtemp16bitDataB = new int[pcHead.width * pcHead.height];
  469. // //ShowTiff16Data(ImgBuff16[1], showtemp16bitDataB);
  470. // //ShowRGBImage(showtemp16bitDataB, pcHead, pictureBoxB);
  471. // }
  472. //}
  473. coutCallbackPoints += nHighlen;
  474. }
  475. else
  476. {
  477. LogHelper.WriteLogInfo($"Data CallBack Exception:{nStatusCode}({GetSDKErrMsgByCode(nStatusCode)})");
  478. //callbackEvent.Set();
  479. }
  480. }
  481. public void ErrConnectFunc(int dwDeviceId, int nErrCode)
  482. {
  483. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{GetSDKErrMsgByCode(nErrCode)}");
  484. iSR7APi.CameraAOnline = false;
  485. iSR7APi.CameraBOnline = false;
  486. //:1:Data overflow,3:Disconnect, 4:Wrong version
  487. //Non-asynchronous mode: -1 represents a general error, such as link failure, setup failure, data acquisition failure, etc., -1000;
  488. switch (nErrCode)
  489. {
  490. case 1:
  491. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_1")}");
  492. break;
  493. case 3:
  494. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_3")}");
  495. break;
  496. case 4:
  497. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_3")}");
  498. break;
  499. case -1:
  500. LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_N1")}");
  501. break;
  502. default:
  503. break;
  504. }
  505. }
  506. public string GetSDKErrMsgByCode(int nErrCode)
  507. {
  508. string strErrMsg;
  509. switch ((SR7Link.SR7IF_ERROR)nErrCode)
  510. {
  511. case SR7IF_ERROR.SR7IF_ERROR_NOT_FOUND: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_NOT_FOUND"); break;
  512. case SR7IF_ERROR.SR7IF_ERROR_COMMAND: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_COMMAND"); break;
  513. case SR7IF_ERROR.SR7IF_ERROR_PARAMETER: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_PARAMETER"); break;
  514. case SR7IF_ERROR.SR7IF_ERROR_UNIMPLEMENTED: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_UNIMPLEMENTED"); break;
  515. case SR7IF_ERROR.SR7IF_ERROR_HANDLE: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_HANDLE"); break;
  516. case SR7IF_ERROR.SR7IF_ERROR_MEMORY: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_MEMORY"); break;
  517. case SR7IF_ERROR.SR7IF_ERROR_TIMEOUT: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_TIMEOUT"); break;
  518. case SR7IF_ERROR.SR7IF_ERROR_DATABUFFER: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_DATABUFFER"); break;
  519. case SR7IF_ERROR.SR7IF_ERROR_STREAM: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_STREAM"); break;
  520. case SR7IF_ERROR.SR7IF_ERROR_CLOSED: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_CLOSED"); break;
  521. case SR7IF_ERROR.SR7IF_ERROR_VERSION: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_VERSION"); break;
  522. case SR7IF_ERROR.SR7IF_ERROR_ABORT: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ABORT"); break;
  523. case SR7IF_ERROR.SR7IF_ERROR_ALREADY_EXISTS: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ALREADY_EXISTS"); break;
  524. case SR7IF_ERROR.SR7IF_ERROR_FRAME_LOSS: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_FRAME_LOSS"); break;
  525. case SR7IF_ERROR.SR7IF_ERROR_ROLL_DATA_OVERFLOW: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ROLL_DATA_OVERFLOW"); break;
  526. case SR7IF_ERROR.SR7IF_ERROR_ROLL_BUSY: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ROLL_BUSY"); break;
  527. case SR7IF_ERROR.SR7IF_ERROR_MODE: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_MODE"); break;
  528. case SR7IF_ERROR.SR7IF_ERROR_CAMERA_NOT_ONLINE: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_CAMERA_NOT_ONLINE"); break;
  529. case SR7IF_ERROR.SR7IF_ERROR: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR"); break;
  530. case SR7IF_ERROR.SR7IF_NORMAL_STOP: strErrMsg = srcsharpTools.GetTranslation("SR7IF_NORMAL_STOP"); break;
  531. case SR7IF_ERROR.SR7IF_OK: strErrMsg = ""; break;
  532. default:
  533. strErrMsg = "";
  534. break;
  535. }
  536. return strErrMsg;
  537. }
  538. #endregion
  539. #region 属性通知
  540. /// <summary>
  541. /// Occurs when a property value changes.
  542. /// </summary>
  543. public event PropertyChangedEventHandler PropertyChanged;
  544. /// <summary>
  545. /// Checks if a property already matches a desired value. Sets the property and
  546. /// notifies listeners only when necessary.
  547. /// </summary>
  548. /// <typeparam name="T">Type of the property.</typeparam>
  549. /// <param name="storage">Reference to a property with both getter and setter.</param>
  550. /// <param name="value">Desired value for the property.</param>
  551. /// <param name="propertyName">Name of the property used to notify listeners. This
  552. /// value is optional and can be provided automatically when invoked from compilers that
  553. /// support CallerMemberName.</param>
  554. /// <returns>True if the value was changed, false if the existing value matched the
  555. /// desired value.</returns>
  556. protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
  557. {
  558. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  559. storage = value;
  560. RaisePropertyChanged(propertyName);
  561. return true;
  562. }
  563. /// <summary>
  564. /// Checks if a property already matches a desired value. Sets the property and
  565. /// notifies listeners only when necessary.
  566. /// </summary>
  567. /// <typeparam name="T">Type of the property.</typeparam>
  568. /// <param name="storage">Reference to a property with both getter and setter.</param>
  569. /// <param name="value">Desired value for the property.</param>
  570. /// <param name="propertyName">Name of the property used to notify listeners. This
  571. /// value is optional and can be provided automatically when invoked from compilers that
  572. /// support CallerMemberName.</param>
  573. /// <param name="onChanged">Action that is called after the property value has been changed.</param>
  574. /// <returns>True if the value was changed, false if the existing value matched the
  575. /// desired value.</returns>
  576. protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
  577. {
  578. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  579. storage = value;
  580. onChanged?.Invoke();
  581. RaisePropertyChanged(propertyName);
  582. return true;
  583. }
  584. /// <summary>
  585. /// Raises this object's PropertyChanged event.
  586. /// </summary>
  587. /// <param name="propertyName">Name of the property used to notify listeners. This
  588. /// value is optional and can be provided automatically when invoked from compilers
  589. /// that support <see cref="CallerMemberNameAttribute"/>.</param>
  590. protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
  591. {
  592. OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
  593. }
  594. /// <summary>
  595. /// Raises this object's PropertyChanged event.
  596. /// </summary>
  597. /// <param name="args">The PropertyChangedEventArgs</param>
  598. protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
  599. {
  600. PropertyChanged?.Invoke(this, args);
  601. }
  602. #endregion
  603. }
  604. }