using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using AutoFocusTool.Serial;
namespace AutoFocusTool.Devices
{
///
/// 多舱室设备发现。复刻原工程开机枚举逻辑:
/// 1) 枚举相机 0..9,逐个 Init 读序列号,建 index→SN 字典;
/// 2) 扫描 COM 口(跳过 COM1/COM2),逐个握手得 houseSn + 读 EEPROM 的 CCDSN;
/// 3) 用 CCDSN 把舱室配对到相机 index。
///
/// 注意:相机 index 与 COM 口每次开机可能变,必须现场重扫,不能写死。
/// 两条总线相互独立,可只扫其一。
///
public class DeviceScanner
{
public Action Log;
/// 枚举相机 0..maxCameras-1,返回能读到序列号的相机列表。
public List ScanCameras(int maxCameras = 10)
{
var list = new List();
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;
}
///
/// 扫描所有 COM 口(跳过 COM1/COM2),握手得 houseSn、读 CCDSN。
/// 返回握手成功的舱室列表(此时 CcdIndex 还未配对)。
///
public List ScanHouses()
{
var houses = new List();
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;
}
///
/// 完整扫描:先枚举相机,再扫舱室,用 CCDSN 配对相机 index。
///
public List 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();
}
}
}