| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- using System;
- using System.Collections.Generic;
- using System.IO.Ports;
- using System.Linq;
- using AutoFocusTool.Serial;
- namespace AutoFocusTool.Devices
- {
- /// <summary>
- /// 多舱室设备发现。复刻原工程开机枚举逻辑:
- /// 1) 枚举相机 0..9,逐个 Init 读序列号,建 index→SN 字典;
- /// 2) 扫描 COM 口(跳过 COM1/COM2),逐个握手得 houseSn + 读 EEPROM 的 CCDSN;
- /// 3) 用 CCDSN 把舱室配对到相机 index。
- ///
- /// 注意:相机 index 与 COM 口每次开机可能变,必须现场重扫,不能写死。
- /// 两条总线相互独立,可只扫其一。
- /// </summary>
- public class DeviceScanner
- {
- public Action<string> Log;
- /// <summary>枚举相机 0..maxCameras-1,返回能读到序列号的相机列表。</summary>
- public List<CameraDevice> ScanCameras(int maxCameras = 10)
- {
- var list = new List<CameraDevice>();
- for (int i = 0; i < maxCameras; i++)
- {
- Camera.Camera cam = null;
- try
- {
- cam = new Camera.Camera(i, 100, 100, 100); // 小尺寸快速探测
- int init = cam.Init();
- if (init != 0)
- {
- Log?.Invoke($"相机#{i} 初始化失败(code={init}),跳过");
- continue;
- }
- int sr = cam.ReadSerial();
- string sn = cam.SerialNumber;
- if (sr == 0 && !string.IsNullOrWhiteSpace(sn))
- {
- list.Add(new CameraDevice { Index = i, SerialNumber = sn.Trim() });
- Log?.Invoke($"发现 相机#{i} SN={sn.Trim()}");
- }
- else
- {
- Log?.Invoke($"相机#{i} 读序列号失败(code={sr})");
- }
- }
- catch (Exception ex)
- {
- Log?.Invoke($"相机#{i} 探测异常: {ex.Message}");
- }
- finally
- {
- try { cam?.UnInit(); cam?.Dispose(); } catch { }
- }
- }
- Log?.Invoke($"相机枚举完成,共 {list.Count} 台");
- return list;
- }
- /// <summary>
- /// 扫描所有 COM 口(跳过 COM1/COM2),握手得 houseSn、读 CCDSN。
- /// 返回握手成功的舱室列表(此时 CcdIndex 还未配对)。
- /// </summary>
- public List<HouseDevice> ScanHouses()
- {
- var houses = new List<HouseDevice>();
- string[] ports = SerialPort.GetPortNames()
- .Where(p => p != null && p.ToUpper().StartsWith("COM"))
- .Where(p => p.ToUpper() != "COM1" && p.ToUpper() != "COM2")
- .Distinct()
- .ToArray();
- Log?.Invoke($"待探测串口: {string.Join(", ", ports)}");
- foreach (var port in ports)
- {
- HouseMotor motor = null;
- try
- {
- motor = new HouseMotor(port) { Log = Log };
- if (!motor.Open())
- {
- Log?.Invoke($"{port} 打开失败,跳过");
- continue;
- }
- int houseSn = motor.ShakeHands();
- if (houseSn < 0)
- {
- Log?.Invoke($"{port} 握手无回复,非舱室口");
- continue;
- }
- int ccdSnInt = motor.ReadCCDSN();
- var hd = new HouseDevice
- {
- HouseSn = houseSn,
- PortName = port,
- CcdSn = ccdSnInt < 0 ? "" : ccdSnInt.ToString(),
- };
- houses.Add(hd);
- Log?.Invoke($"发现 舱室{houseSn} @ {port} CCDSN={hd.CcdSn}");
- }
- catch (Exception ex)
- {
- Log?.Invoke($"{port} 探测异常: {ex.Message}");
- }
- finally
- {
- try { motor?.Close(); motor?.Dispose(); } catch { }
- }
- }
- Log?.Invoke($"舱室扫描完成,共 {houses.Count} 个");
- return houses;
- }
- /// <summary>
- /// 完整扫描:先枚举相机,再扫舱室,用 CCDSN 配对相机 index。
- /// </summary>
- public List<HouseDevice> ScanAll()
- {
- var cameras = ScanCameras();
- var houses = ScanHouses();
- foreach (var h in houses)
- {
- if (string.IsNullOrEmpty(h.CcdSn)) continue;
- var cam = cameras.FirstOrDefault(c => c.SerialNumber == h.CcdSn);
- if (cam != null)
- {
- h.CcdIndex = cam.Index;
- Log?.Invoke($"配对: 舱室{h.HouseSn} ←→ 相机#{cam.Index}");
- }
- else
- {
- Log?.Invoke($"舱室{h.HouseSn} 的 CCDSN={h.CcdSn} 在相机列表中未找到");
- }
- }
- return houses.OrderBy(h => h.HouseSn).ToList();
- }
- }
- }
|