MotionManager.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using Newtonsoft.Json;
  6. using TeamAAS.Global.Devices;
  7. namespace TeamAAS.Motion
  8. {
  9. /// <summary>
  10. /// 运动控制设备管理器(懒汉单例)。
  11. /// 职责:加载/保存 Config\MotionDevices.json;按配置实例化品牌适配器(仿真/雷赛/固高/IMC60G/GR20T);
  12. /// 对上层(主程序状态栏、流程节点、调试页)提供统一的 IMotionCard/IIOCard 访问。
  13. /// 与 CameraManager/RobotManager 同构:App 启动时 LoadConfig,退出时 CloseAll。
  14. /// </summary>
  15. public class MotionManager
  16. {
  17. private static MotionManager _instance;
  18. public static MotionManager Instance => _instance ?? (_instance = new MotionManager());
  19. private readonly object _sync = new object();
  20. /// <summary>全部运动/IO 设备实例(含运动卡与 IO 卡)。</summary>
  21. public List<object> Devices { get; } = new List<object>();
  22. /// <summary>设备配置列表(与 Devices 一一对应)。</summary>
  23. public List<MotionDeviceConfig> Configs { get; private set; } = new List<MotionDeviceConfig>();
  24. /// <summary>
  25. /// 配置文件路径(Config\MotionDevices.json)。
  26. /// 由系统配置文件的目录派生(SystemConfigurationFile 在 Config\ 下),不引入新的 PathHelper 成员。
  27. /// </summary>
  28. public static string ConfigPath
  29. {
  30. get
  31. {
  32. var sysCfg = TeamAAS.PathHelper.SystemConfigurationFile;
  33. var dir = string.IsNullOrEmpty(sysCfg) ? AppDomain.CurrentDomain.BaseDirectory : Path.GetDirectoryName(sysCfg);
  34. return Path.Combine(dir ?? "", "MotionDevices.json");
  35. }
  36. }
  37. /// <summary>
  38. /// 从配置实例化全部设备(已存在实例时先释放)。仅创建,不自动连接。
  39. /// </summary>
  40. public void LoadConfig()
  41. {
  42. lock (_sync)
  43. {
  44. CloseAllUnsafe();
  45. try
  46. {
  47. if (File.Exists(ConfigPath))
  48. {
  49. var json = File.ReadAllText(ConfigPath);
  50. Configs = JsonConvert.DeserializeObject<List<MotionDeviceConfig>>(json) ?? new List<MotionDeviceConfig>();
  51. }
  52. }
  53. catch { Configs = new List<MotionDeviceConfig>(); }
  54. foreach (var cfg in Configs)
  55. {
  56. var dev = CreateDevice(cfg);
  57. if (dev != null) Devices.Add(dev);
  58. }
  59. }
  60. }
  61. /// <summary>保存配置到 Config\MotionDevices.json。</summary>
  62. public void SaveConfig()
  63. {
  64. lock (_sync)
  65. {
  66. try
  67. {
  68. var dir = Path.GetDirectoryName(ConfigPath);
  69. if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir);
  70. File.WriteAllText(ConfigPath, JsonConvert.SerializeObject(Configs, Formatting.Indented));
  71. }
  72. catch (Exception ex)
  73. {
  74. AppLogger.Error("运动设备配置保存失败", ex, nameof(MotionManager));
  75. }
  76. }
  77. }
  78. /// <summary>按名称取运动卡。</summary>
  79. public IMotionCard GetMotion(string name)
  80. => Devices.OfType<IMotionCard>().FirstOrDefault(d => string.Equals(d.Name, name, StringComparison.OrdinalIgnoreCase));
  81. /// <summary>按名称取 IO 卡。</summary>
  82. public IIOCard GetIO(string name)
  83. => Devices.OfType<IIOCard>().FirstOrDefault(d => string.Equals(d.Name, name, StringComparison.OrdinalIgnoreCase));
  84. /// <summary>断开并清空全部设备(App 退出时调用)。</summary>
  85. public void CloseAll()
  86. {
  87. lock (_sync) { CloseAllUnsafe(); }
  88. }
  89. private void CloseAllUnsafe()
  90. {
  91. foreach (var d in Devices)
  92. {
  93. try { (d as IConnectableDevice)?.Close(); } catch { }
  94. }
  95. Devices.Clear();
  96. }
  97. /// <summary>
  98. /// 按配置创建设备实例(品牌适配器工厂)。
  99. /// 新品牌接入:实现 IMotionCard/IIOCard → 在此 switch 增加分支即可。
  100. /// </summary>
  101. private static object CreateDevice(MotionDeviceConfig cfg)
  102. {
  103. switch (cfg.DeviceType)
  104. {
  105. case MotionDeviceType.仿真运动卡:
  106. return new SimulatedMotionCard(cfg);
  107. case MotionDeviceType.仿真IO卡:
  108. return new SimulatedIOCard(cfg);
  109. // ── 品牌适配位:SDK(雷赛 leadshine.dll / 固高 gts.dll / IMC60G / GR20T EtherCAT)到位后实现 ──
  110. // case MotionDeviceType.雷赛运动卡: return new LeadshineMotionCard(cfg);
  111. // case MotionDeviceType.固高运动卡: return new GoogolMotionCard(cfg);
  112. // case MotionDeviceType.IMC60G运动卡: return new Imc60GMotionCard(cfg);
  113. // case MotionDeviceType.GR20T_IO模块: return new Gr20TIOCard(cfg);
  114. default:
  115. AppLogger.Warning($"运动设备[{cfg.Name}] 类型 {cfg.DeviceType} 尚未适配,已跳过", nameof(MotionManager));
  116. return null;
  117. }
  118. }
  119. }
  120. }