MotionManager.cs 5.5 KB

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