using System; using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json; using TeamAAS.Global.Devices; namespace TeamAAS.Motion { /// /// 运动控制设备管理器(懒汉单例)。 /// 职责:加载/保存 Config\MotionDevices.json;按配置实例化品牌适配器(仿真/雷赛/固高/IMC60G/GR20T); /// 对上层(主程序状态栏、流程节点、调试页)提供统一的 IMotionCard/IIOCard 访问。 /// 与 CameraManager/RobotManager 同构:App 启动时 LoadConfig,退出时 CloseAll。 /// public class MotionManager { private static MotionManager _instance; public static MotionManager Instance => _instance ?? (_instance = new MotionManager()); private readonly object _sync = new object(); /// 全部运动/IO 设备实例(含运动卡与 IO 卡)。 public List Devices { get; } = new List(); /// 设备配置列表(与 Devices 一一对应)。 public List Configs { get; private set; } = new List(); /// /// 配置文件路径(Config\MotionDevices.json)。 /// 由系统配置文件的目录派生(SystemConfigurationFile 在 Config\ 下),不引入新的 PathHelper 成员。 /// public static string ConfigPath { get { var sysCfg = TeamAAS.PathHelper.SystemConfigurationFile; var dir = string.IsNullOrEmpty(sysCfg) ? AppDomain.CurrentDomain.BaseDirectory : Path.GetDirectoryName(sysCfg); return Path.Combine(dir ?? "", "MotionDevices.json"); } } /// /// 从配置实例化全部设备(已存在实例时先释放)。仅创建,不自动连接。 /// public void LoadConfig() { lock (_sync) { CloseAllUnsafe(); try { if (File.Exists(ConfigPath)) { var json = File.ReadAllText(ConfigPath); Configs = JsonConvert.DeserializeObject>(json) ?? new List(); } } catch { Configs = new List(); } foreach (var cfg in Configs) { var dev = CreateDevice(cfg); if (dev != null) Devices.Add(dev); } } } /// 保存配置到 Config\MotionDevices.json。 public void SaveConfig() { lock (_sync) { try { var dir = Path.GetDirectoryName(ConfigPath); if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir); File.WriteAllText(ConfigPath, JsonConvert.SerializeObject(Configs, Formatting.Indented)); } catch (Exception ex) { AppLogger.Error("运动设备配置保存失败", ex, nameof(MotionManager)); } } } /// 按名称取运动卡。 public IMotionCard GetMotion(string name) => Devices.OfType().FirstOrDefault(d => string.Equals(d.Name, name, StringComparison.OrdinalIgnoreCase)); /// 按名称取 IO 卡。 public IIOCard GetIO(string name) => Devices.OfType().FirstOrDefault(d => string.Equals(d.Name, name, StringComparison.OrdinalIgnoreCase)); /// 断开并清空全部设备(App 退出时调用)。 public void CloseAll() { lock (_sync) { CloseAllUnsafe(); } } private void CloseAllUnsafe() { foreach (var d in Devices) { try { (d as IConnectableDevice)?.Close(); } catch { } } Devices.Clear(); } /// /// 按配置创建设备实例(品牌适配器工厂)。 /// 新品牌接入:实现 IMotionCard/IIOCard → 在此 switch 增加分支即可。 /// private static object CreateDevice(MotionDeviceConfig cfg) { switch (cfg.DeviceType) { case MotionDeviceType.仿真运动卡: return new SimulatedMotionCard(cfg); case MotionDeviceType.仿真IO卡: return new SimulatedIOCard(cfg); // ── 品牌适配位:SDK(雷赛 leadshine.dll / 固高 gts.dll / IMC60G / GR20T EtherCAT)到位后实现 ── // case MotionDeviceType.雷赛运动卡: return new LeadshineMotionCard(cfg); // case MotionDeviceType.固高运动卡: return new GoogolMotionCard(cfg); // case MotionDeviceType.IMC60G运动卡: return new Imc60GMotionCard(cfg); // case MotionDeviceType.GR20T_IO模块: return new Gr20TIOCard(cfg); default: AppLogger.Warning($"运动设备[{cfg.Name}] 类型 {cfg.DeviceType} 尚未适配,已跳过", nameof(MotionManager)); return null; } } } }