DeviceScanner.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO.Ports;
  4. using System.Linq;
  5. using AutoFocusTool.Serial;
  6. namespace AutoFocusTool.Devices
  7. {
  8. /// <summary>
  9. /// 多舱室设备发现。复刻原工程开机枚举逻辑:
  10. /// 1) 枚举相机 0..9,逐个 Init 读序列号,建 index→SN 字典;
  11. /// 2) 扫描 COM 口(跳过 COM1/COM2),逐个握手得 houseSn + 读 EEPROM 的 CCDSN;
  12. /// 3) 用 CCDSN 把舱室配对到相机 index。
  13. ///
  14. /// 注意:相机 index 与 COM 口每次开机可能变,必须现场重扫,不能写死。
  15. /// 两条总线相互独立,可只扫其一。
  16. /// </summary>
  17. public class DeviceScanner
  18. {
  19. public Action<string> Log;
  20. /// <summary>枚举相机 0..maxCameras-1,返回能读到序列号的相机列表。</summary>
  21. public List<CameraDevice> ScanCameras(int maxCameras = 10)
  22. {
  23. var list = new List<CameraDevice>();
  24. for (int i = 0; i < maxCameras; i++)
  25. {
  26. Camera.Camera cam = null;
  27. try
  28. {
  29. cam = new Camera.Camera(i, 100, 100, 100); // 小尺寸快速探测
  30. int init = cam.Init();
  31. if (init != 0)
  32. {
  33. Log?.Invoke($"相机#{i} 初始化失败(code={init}),跳过");
  34. continue;
  35. }
  36. int sr = cam.ReadSerial();
  37. string sn = cam.SerialNumber;
  38. if (sr == 0 && !string.IsNullOrWhiteSpace(sn))
  39. {
  40. list.Add(new CameraDevice { Index = i, SerialNumber = sn.Trim() });
  41. Log?.Invoke($"发现 相机#{i} SN={sn.Trim()}");
  42. }
  43. else
  44. {
  45. Log?.Invoke($"相机#{i} 读序列号失败(code={sr})");
  46. }
  47. }
  48. catch (Exception ex)
  49. {
  50. Log?.Invoke($"相机#{i} 探测异常: {ex.Message}");
  51. }
  52. finally
  53. {
  54. try { cam?.UnInit(); cam?.Dispose(); } catch { }
  55. }
  56. }
  57. Log?.Invoke($"相机枚举完成,共 {list.Count} 台");
  58. return list;
  59. }
  60. /// <summary>
  61. /// 扫描所有 COM 口(跳过 COM1/COM2),握手得 houseSn、读 CCDSN。
  62. /// 返回握手成功的舱室列表(此时 CcdIndex 还未配对)。
  63. /// </summary>
  64. public List<HouseDevice> ScanHouses()
  65. {
  66. var houses = new List<HouseDevice>();
  67. string[] ports = SerialPort.GetPortNames()
  68. .Where(p => p != null && p.ToUpper().StartsWith("COM"))
  69. .Where(p => p.ToUpper() != "COM1" && p.ToUpper() != "COM2")
  70. .Distinct()
  71. .ToArray();
  72. Log?.Invoke($"待探测串口: {string.Join(", ", ports)}");
  73. foreach (var port in ports)
  74. {
  75. HouseMotor motor = null;
  76. try
  77. {
  78. motor = new HouseMotor(port) { Log = Log };
  79. if (!motor.Open())
  80. {
  81. Log?.Invoke($"{port} 打开失败,跳过");
  82. continue;
  83. }
  84. int houseSn = motor.ShakeHands();
  85. if (houseSn < 0)
  86. {
  87. Log?.Invoke($"{port} 握手无回复,非舱室口");
  88. continue;
  89. }
  90. int ccdSnInt = motor.ReadCCDSN();
  91. var hd = new HouseDevice
  92. {
  93. HouseSn = houseSn,
  94. PortName = port,
  95. CcdSn = ccdSnInt < 0 ? "" : ccdSnInt.ToString(),
  96. };
  97. houses.Add(hd);
  98. Log?.Invoke($"发现 舱室{houseSn} @ {port} CCDSN={hd.CcdSn}");
  99. }
  100. catch (Exception ex)
  101. {
  102. Log?.Invoke($"{port} 探测异常: {ex.Message}");
  103. }
  104. finally
  105. {
  106. try { motor?.Close(); motor?.Dispose(); } catch { }
  107. }
  108. }
  109. Log?.Invoke($"舱室扫描完成,共 {houses.Count} 个");
  110. return houses;
  111. }
  112. /// <summary>
  113. /// 完整扫描:先枚举相机,再扫舱室,用 CCDSN 配对相机 index。
  114. /// </summary>
  115. public List<HouseDevice> ScanAll()
  116. {
  117. var cameras = ScanCameras();
  118. var houses = ScanHouses();
  119. foreach (var h in houses)
  120. {
  121. if (string.IsNullOrEmpty(h.CcdSn)) continue;
  122. var cam = cameras.FirstOrDefault(c => c.SerialNumber == h.CcdSn);
  123. if (cam != null)
  124. {
  125. h.CcdIndex = cam.Index;
  126. Log?.Invoke($"配对: 舱室{h.HouseSn} ←→ 相机#{cam.Index}");
  127. }
  128. else
  129. {
  130. Log?.Invoke($"舱室{h.HouseSn} 的 CCDSN={h.CcdSn} 在相机列表中未找到");
  131. }
  132. }
  133. return houses.OrderBy(h => h.HouseSn).ToList();
  134. }
  135. }
  136. }