CameraService.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. using MvCamCtrl.NET;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using TeamAAS_VP.Core.Cameras;
  8. using TeamAAS_VP.Interfaces;
  9. using TeamAAS_VP.Models;
  10. namespace TeamAAS_VP.Services
  11. {
  12. public class CameraService : ICameraService, IDisposable
  13. {
  14. private readonly Dictionary<Guid, ICamera> _CameraCollection;
  15. private readonly object _sync = new object();
  16. public CameraService()
  17. {
  18. _CameraCollection = new Dictionary<Guid, ICamera>();
  19. }
  20. public bool CreateCamera(Guid id, CameraInfo cameraInfo)
  21. {
  22. if (cameraInfo == null) throw new ArgumentNullException(nameof(cameraInfo));
  23. var camera = CreateCameraInstance(id, cameraInfo);
  24. lock (_sync)
  25. {
  26. if (_CameraCollection.ContainsKey(id))
  27. {
  28. var currenCamera = _CameraCollection[id];
  29. try
  30. {
  31. currenCamera.CloseDevice();
  32. }
  33. catch
  34. {
  35. // 忽略关闭异常
  36. }
  37. }
  38. _CameraCollection[id] = camera;
  39. }
  40. return true;
  41. }
  42. public Task<bool> CreateCameraAsync(Guid id, CameraInfo cameraInfo)
  43. {
  44. return Task.Run(() => CreateCamera(id, cameraInfo));
  45. }
  46. public ICamera GetCamera(Guid id)
  47. {
  48. lock (_sync)
  49. {
  50. if (_CameraCollection.TryGetValue(id, out var cam))
  51. return cam;
  52. }
  53. return null;
  54. }
  55. public Task<ICamera> GetCameraAsync(Guid id)
  56. {
  57. return Task.Run(() =>
  58. {
  59. return GetCamera(id);
  60. });
  61. }
  62. public void UnRegisterCamera(Guid id)
  63. {
  64. ICamera camera = null;
  65. lock (_sync)
  66. {
  67. if (_CameraCollection.TryGetValue(id, out camera))
  68. {
  69. _CameraCollection.Remove(id);
  70. }
  71. }
  72. if (camera != null)
  73. {
  74. try
  75. {
  76. camera.CloseDevice();
  77. }
  78. catch
  79. {
  80. // 忽略关闭异常
  81. }
  82. }
  83. }
  84. public Task UnRegisterCameraAsync(Guid id)
  85. {
  86. return Task.Run(() => UnRegisterCamera(id));
  87. }
  88. public IReadOnlyCollection<ICamera> GetAllCameras()
  89. {
  90. lock (_sync)
  91. {
  92. return _CameraCollection.Values.ToList().AsReadOnly();
  93. }
  94. }
  95. public Task<IReadOnlyCollection<ICamera>> GetAllCamerasAsync()
  96. {
  97. return Task.Run(() =>
  98. {
  99. return GetAllCameras();
  100. });
  101. }
  102. public bool TryGetCamera(Guid id, out ICamera camera)
  103. {
  104. lock (_sync)
  105. {
  106. return _CameraCollection.TryGetValue(id, out camera);
  107. }
  108. }
  109. public Task<(bool found, ICamera camera)> TryGetCameraAsync(Guid id)
  110. {
  111. return Task.Run(() =>
  112. {
  113. ICamera camera;
  114. bool found;
  115. lock (_sync)
  116. {
  117. found = _CameraCollection.TryGetValue(id, out camera);
  118. }
  119. return (found, camera);
  120. });
  121. }
  122. public bool ContainsCamera(Guid id)
  123. {
  124. lock (_sync)
  125. {
  126. return _CameraCollection.ContainsKey(id);
  127. }
  128. }
  129. public Task<bool> ContainsCameraAsync(Guid id)
  130. {
  131. return Task.Run(() =>
  132. {
  133. return ContainsCamera(id);
  134. });
  135. }
  136. public bool RemoveCamera(Guid id)
  137. {
  138. ICamera camera = null;
  139. lock (_sync)
  140. {
  141. if (_CameraCollection.TryGetValue(id, out camera))
  142. {
  143. _CameraCollection.Remove(id);
  144. }
  145. }
  146. if (camera != null)
  147. {
  148. try
  149. {
  150. camera.CloseDevice();
  151. }
  152. catch
  153. {
  154. // 忽略关闭异常
  155. }
  156. return true;
  157. }
  158. return false;
  159. }
  160. public Task<bool> RemoveCameraAsync(Guid id)
  161. {
  162. return Task.Run(() =>
  163. {
  164. return RemoveCamera(id);
  165. });
  166. }
  167. public ICamera GetCameraByNumber(int number)
  168. {
  169. if (TryFindCameraByNumber(number, out _, out var camera))
  170. return camera;
  171. return null;
  172. }
  173. public Task<ICamera> GetCameraByNumberAsync(int number)
  174. {
  175. return Task.Run(() =>
  176. {
  177. return GetCameraByNumber(number);
  178. });
  179. }
  180. public Task UnRegisterCameraByNumberAsync(int number)
  181. {
  182. return Task.Run(() =>
  183. {
  184. UnRegisterCameraByNumber(number);
  185. });
  186. }
  187. public void UnRegisterCameraByNumber(int number)
  188. {
  189. if (TryFindCameraByNumber(number, out var id, out var camera))
  190. {
  191. UnRegisterCamera(id);
  192. }
  193. }
  194. /// <summary>
  195. /// 移除所有相机
  196. /// </summary>
  197. public void RemoveAllCameras()
  198. {
  199. //依次移除每一个相机,确保资源释放
  200. List<Guid> cameraIds;
  201. lock (_sync)
  202. {
  203. cameraIds = _CameraCollection.Keys.ToList();
  204. }
  205. foreach (var id in cameraIds)
  206. {
  207. RemoveCamera(id);
  208. }
  209. }
  210. /// <summary>
  211. /// 初始化所有相机
  212. /// </summary>
  213. /// <param name="cameras"></param>
  214. /// <returns></returns>
  215. public (bool IsSucceed, string Message) InitializeAllCameras(CameraInfo[] cameras)
  216. {
  217. //清除现有相机
  218. RemoveAllCameras();
  219. foreach (var camInfo in cameras)
  220. {
  221. var camera = CreateCameraInstance(camInfo.Id, camInfo);
  222. lock (_sync)
  223. {
  224. _CameraCollection[camInfo.Id] = camera;
  225. }
  226. }
  227. bool allConnected = true;
  228. StringBuilder errorMessages = new StringBuilder();
  229. //获取所有相机并尝试打开设备
  230. foreach (var camInfo in cameras)
  231. {
  232. if (TryGetCamera(camInfo.Id, out var camera))
  233. {
  234. bool opened = camera.OpenDevice();
  235. if (!opened)
  236. {
  237. allConnected = false;
  238. errorMessages.AppendLine($"相机 {camInfo.CameraName}(编号: {camInfo.CameraNo})打开失败: {camera.ErrorMessage}");
  239. }
  240. }
  241. else
  242. {
  243. allConnected = false;
  244. errorMessages.AppendLine($"未找到相机 {camInfo.CameraName}(编号: {camInfo.CameraNo})的实例。");
  245. }
  246. }
  247. if (allConnected)
  248. {
  249. return (true, "所有相机均已成功初始化并连接。");
  250. }
  251. else
  252. {
  253. return (false, errorMessages.ToString());
  254. }
  255. }
  256. /// <summary>
  257. /// 初始化所有相机(异步)
  258. /// </summary>
  259. /// <param name="cameras"></param>
  260. /// <returns></returns>
  261. public Task<(bool IsSucceed, string Message)> InitializeAllCamerasAsync(CameraInfo[] cameras)
  262. {
  263. return Task.Run(() => InitializeAllCameras(cameras));
  264. }
  265. /// <summary>
  266. /// 更新相机编号
  267. /// </summary>
  268. /// <param name="id"></param>
  269. /// <param name="newNumber"></param>
  270. public void UpdateCameraNumber(Guid id, int newNumber)
  271. {
  272. if (TryGetCamera(id, out var camera))
  273. {
  274. camera.Index = newNumber;
  275. }
  276. }
  277. private ICamera CreateCameraInstance(Guid id, CameraInfo cameraInfo)
  278. {
  279. ICamera camera;
  280. if (cameraInfo.CameraBrand == Enums.CameraBrand.Basler_Pylon)
  281. {
  282. camera = new BaslerCamera(id, cameraInfo.CameraNo, cameraInfo.CameraName, cameraInfo.SerialNumber, cameraInfo.CameraIp, cameraInfo.IsFindByIp);
  283. }
  284. else if (cameraInfo.CameraBrand == Enums.CameraBrand.HikRobot_MVS)
  285. {
  286. camera = new MvCamera(id, cameraInfo.CameraNo, cameraInfo.CameraName, cameraInfo.SerialNumber, cameraInfo.CameraIp, cameraInfo.IsFindByIp);
  287. }
  288. else if (cameraInfo.CameraBrand == Enums.CameraBrand.IRayple)
  289. {
  290. camera = new AHuaCamera(id, cameraInfo.CameraNo, cameraInfo.CameraName, cameraInfo.SerialNumber, cameraInfo.CameraIp, cameraInfo.IsFindByIp);
  291. }
  292. else if (cameraInfo.CameraBrand == Enums.CameraBrand.Cognex)
  293. {
  294. camera = new CognexCamera(id, cameraInfo.CameraNo, cameraInfo.CameraName, cameraInfo.SerialNumber, cameraInfo.CameraIp, cameraInfo.IsFindByIp);
  295. }
  296. else if (cameraInfo.CameraBrand == Enums.CameraBrand.Galaxy)
  297. {
  298. camera = new GalaxyCamera(id, cameraInfo.CameraNo, cameraInfo.CameraName, cameraInfo.SerialNumber, cameraInfo.CameraIp, cameraInfo.IsFindByIp);
  299. }
  300. else
  301. {
  302. camera = new MvCamera(id, cameraInfo.CameraNo, cameraInfo.CameraName, cameraInfo.SerialNumber, cameraInfo.CameraIp, cameraInfo.IsFindByIp);
  303. }
  304. return camera;
  305. }
  306. private bool TryFindCameraByNumber(int number, out Guid id, out ICamera camera)
  307. {
  308. lock (_sync)
  309. {
  310. foreach (var kvp in _CameraCollection)
  311. {
  312. var c = kvp.Value;
  313. if (c == null) continue;
  314. object rawValue = null;
  315. var type = c.GetType();
  316. var prop = type.GetProperty("CameraNo") ?? type.GetProperty("Number") ?? type.GetProperty("No");
  317. if (prop != null)
  318. {
  319. try
  320. {
  321. rawValue = prop.GetValue(c);
  322. }
  323. catch
  324. {
  325. rawValue = null;
  326. }
  327. }
  328. if (rawValue == null)
  329. {
  330. var infoProp = type.GetProperty("CameraInfo") ?? type.GetProperty("Info");
  331. if (infoProp != null)
  332. {
  333. try
  334. {
  335. var infoObj = infoProp.GetValue(c);
  336. if (infoObj != null)
  337. {
  338. var infoType = infoObj.GetType();
  339. var numberProp = infoType.GetProperty("CameraNo") ?? infoType.GetProperty("CameraNumber") ?? infoType.GetProperty("Number") ?? infoType.GetProperty("No");
  340. if (numberProp != null)
  341. {
  342. try
  343. {
  344. rawValue = numberProp.GetValue(infoObj);
  345. }
  346. catch
  347. {
  348. rawValue = null;
  349. }
  350. }
  351. }
  352. }
  353. catch
  354. {
  355. rawValue = null;
  356. }
  357. }
  358. }
  359. if (rawValue != null)
  360. {
  361. int parsed;
  362. try
  363. {
  364. if (rawValue is int) parsed = (int)rawValue;
  365. else parsed = Convert.ToInt32(rawValue);
  366. }
  367. catch
  368. {
  369. continue;
  370. }
  371. if (parsed == number)
  372. {
  373. id = kvp.Key;
  374. camera = c;
  375. return true;
  376. }
  377. }
  378. }
  379. }
  380. id = Guid.Empty;
  381. camera = null;
  382. return false;
  383. }
  384. public void Dispose()
  385. {
  386. List<ICamera> cameras;
  387. lock (_sync)
  388. {
  389. cameras = _CameraCollection.Values.ToList();
  390. _CameraCollection.Clear();
  391. }
  392. foreach (var c in cameras)
  393. {
  394. try
  395. {
  396. c.CloseDevice();
  397. }
  398. catch
  399. {
  400. // 忽略单个相机关闭异常
  401. }
  402. }
  403. GC.SuppressFinalize(this);
  404. }
  405. }
  406. }