| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Team.FFFeederService;
- using Team.FFFeederService.Interfaces;
- using TeamAAS_VP.Core.PLCs;
- using TeamAAS_VP.Core.Robots;
- using TeamAAS_VP.Interfaces;
- using TeamAAS_VP.Models;
- using TouchSocket.Core;
- using TouchSocket.Sockets;
- namespace TeamAAS_VP.Services
- {
- public class RobotService : IRobotService, IDisposable
- {
- private readonly IPlcService _plcService;
- private readonly Dictionary<Guid, IRobot> _robotCollection;
- private readonly object _sync = new object();
- public RobotService(IPlcService plcService)
- {
- _robotCollection = new Dictionary<Guid, IRobot>();
- _plcService = plcService;
- }
- /// <summary>
- /// 创建机器人
- /// </summary>
- /// <param name="id"></param>
- /// <param name="robotInfo"></param>
- /// <returns></returns>
- /// <exception cref="ArgumentNullException"></exception>
- public bool CreateRobot(Guid id, RobotInfo robotInfo)
- {
- if (robotInfo == null) throw new ArgumentNullException(nameof(robotInfo));
- var robot = CreateRobotInstance(robotInfo);
- robot.Id = id;
- lock (_sync)
- {
- if (_robotCollection.ContainsKey(id))
- {
- var currentRobot = _robotCollection[id];
- try
- {
- currentRobot.Dispose();
- }
- catch
- {
- // 忽略单个机器人 Dispose 异常,继续替换
- }
- }
- _robotCollection[id] = robot;
- }
- return true;
- }
- /// <summary>
- /// 创建机器人
- /// </summary>
- /// <param name="id"></param>
- /// <param name="robotInfo"></param>
- /// <returns></returns>
- public Task<bool> CreateRobotAsync(Guid id, RobotInfo robotInfo)
- {
- return Task.Run(() =>
- {
- return CreateRobot(id, robotInfo);
- });
- }
- public IRobot GetRobot(Guid id)
- {
- lock (_sync)
- {
- if (_robotCollection.TryGetValue(id, out var robot))
- {
- return robot;
- }
- }
- return null;
- }
- public Task<IRobot> GetRobotAsync(Guid id)
- {
- return Task.Run(() =>
- {
- return GetRobot(id);
- });
- }
- public void UnRegisterRobot(Guid id)
- {
- IRobot robot = null;
- lock (_sync)
- {
- if (_robotCollection.TryGetValue(id, out robot))
- {
- _robotCollection.Remove(id);
- }
- }
- if (robot != null)
- {
- try
- {
- robot.Dispose();
- }
- catch
- {
- // 忽略释放异常
- }
- }
- }
- public Task UnRegisterRobotAsync(Guid id)
- {
-
- return Task.Run(()=> UnRegisterRobot(id));
- }
- /// <summary>
- /// 获取所有机器人
- /// </summary>
- /// <returns></returns>
- public IReadOnlyCollection<IRobot> GetAllRobots()
- {
- lock (_sync)
- {
- return _robotCollection.Values.ToList().AsReadOnly();
- }
- }
- public Task<IReadOnlyCollection<IRobot>> GetAllRobotsAsync()
- {
- return Task.Run(() =>
- {
- return GetAllRobots();
- });
- }
- /// <summary>
- /// 尝试获取机器人
- /// </summary>
- /// <param name="id"></param>
- /// <param name="robot"></param>
- /// <returns></returns>
- public bool TryGetRobot(Guid id, out IRobot robot)
- {
- lock (_sync)
- {
- return _robotCollection.TryGetValue(id, out robot);
- }
- }
- public Task<(bool found, IRobot robot)> TryGetRobotAsync(Guid id)
- {
-
- return Task.Run(() =>
- {
- IRobot robot;
- bool found;
- lock (_sync)
- {
- found = _robotCollection.TryGetValue(id, out robot);
- }
- return (found, robot);
- });
- }
- /// <summary>
- /// 检查是否存在
- /// </summary>
- /// <param name="id"></param>
- /// <returns></returns>
- public bool ContainsRobot(Guid id)
- {
- lock (_sync)
- {
- return _robotCollection.ContainsKey(id);
- }
- }
- public Task<bool> ContainsRobotAsync(Guid id)
- {
- return Task.Run(() =>
- {
- return ContainsRobot(id);
- });
- }
- /// <summary>
- /// 移除机器人并释放资源,返回是否成功移除
- /// </summary>
- /// <param name="id"></param>
- /// <returns></returns>
- public bool RemoveRobot(Guid id)
- {
- IRobot robot = null;
- lock (_sync)
- {
- if (_robotCollection.TryGetValue(id, out robot))
- {
- _robotCollection.Remove(id);
- }
- }
- if (robot != null)
- {
- try
- {
- robot.Dispose();
- }
- catch
- {
- // 忽略释放异常
- }
- return true;
- }
- return false;
- }
- public Task<bool> RemoveRobotAsync(Guid id)
- {
- return Task.Run(() =>
- {
- return RemoveRobot(id);
- });
- }
- public IRobot GetRobotByNumber(int robotNo)
- {
- if (TryFindRobotByNumber(robotNo, out _, out var robot))
- {
- return robot;
- }
- return null;
- }
- public Task<IRobot> GetRobotByNumberAsync(int robotNo)
- {
- return Task.Run(() =>
- {
- return GetRobotByNumber(robotNo);
- });
- }
- public Task UnRegisterRobotByNumberAsync(int robotNo)
- {
- return Task.Run(() => UnRegisterRobotByNumber(robotNo));
- }
- public void UnRegisterRobotByNumber(int robotNo)
- {
- if (TryFindRobotByNumber(robotNo, out var id, out var robot))
- {
- // 复用已有的方法以保持行为一致(线程安全、异常处理)
- UnRegisterRobot(id);
- }
- }
- /// <summary>
- /// 移除所有机器人
- /// </summary>
- public void RemoveAllRobots()
- {
- //依次移除每个机器人,确保资源释放
- List<Guid> robotIds;
- lock (_sync)
- {
- robotIds = _robotCollection.Keys.ToList();
- }
- foreach (var id in robotIds)
- {
- RemoveRobot(id);
- }
- }
- /// <summary>
- /// 初始化所有机器人
- /// </summary>
- /// <param name="robots"></param>
- /// <returns></returns>
- public (bool IsSucceed, string Message) InitializeAllRobots(RobotInfo[] robots)
- {
- //清除现有机器人集合
- RemoveAllRobots();
- //根据传入的机器人信息数组,依次创建并注册机器人实例
- foreach (var robotInfo in robots)
- {
- var robot = CreateRobotInstance(robotInfo);
- lock (_sync)
- {
- _robotCollection[robot.Id] = robot;
- }
- }
- bool allConnected = true;
- StringBuilder errorMessages = new StringBuilder();
- //获取所有机器人并连接
- var allRobots = GetAllRobots();
- foreach (var robot in allRobots)
- {
- try
- {
- robot.Connect();
- }
- catch
- {
- //忽略单个机器人连接异常,继续连接其他机器人
- }
- if (!robot.IsConnected)
- {
- allConnected = false;
- errorMessages.AppendLine($"机器人[{robot.Name}]连接失败。");
- }
- }
- if (allConnected)
- {
- return (true, "所有机器人初始化并连接成功。");
- }
- else
- {
- return (false, errorMessages.ToString());
- }
- }
- /// <summary>
- /// 初始化所有机器人 (异步)
- /// </summary>
- /// <param name="robots"></param>
- /// <returns></returns>
- public Task<(bool IsSucceed, string Message)> InitializeAllRobotsAsync(RobotInfo[] robots)
- {
- return Task.Run(() =>
- {
- return InitializeAllRobots(robots);
- });
- }
- // 私有工厂方法,避免重复代码
- private IRobot CreateRobotInstance(RobotInfo robotInfo)
- {
- if (robotInfo == null) throw new ArgumentNullException(nameof(robotInfo));
- IRobot robot;
- if (robotInfo.RobotBrand == Enums.RobotBrand.EPSON)
- {
- robot = new EpsonRobot(robotInfo);
- }
- else if (robotInfo.RobotBrand == Enums.RobotBrand.FANUC)
- {
- robot = new FanucRobot(robotInfo);
- }
- else if (robotInfo.RobotBrand == Enums.RobotBrand.Schneider)
- {
- robot = new SchneiderRobot(robotInfo);
- }
- else if (robotInfo.RobotBrand == Enums.RobotBrand.XYZ_Platform || robotInfo.RobotBrand == Enums.RobotBrand.XYZU_Platform)
- {
- var plc= _plcService.GetPlc(robotInfo.PLC) as OpcUaClientPLC;
- if (robotInfo.PlcRobotParameter == null)
- robotInfo.PlcRobotParameter = new Models.PLC.PlcRobotParameter();
- if (robotInfo.PlcRobotParameter.AxixList == null)
- {
- robotInfo.PlcRobotParameter.AxixList = new List<Axis>();
- robotInfo.PlcRobotParameter.AxixList.Add(new Axis() { Index=1,Name="X", Command=new AxisCommand(),Parameter=new AxisParameter(),State=new AxisState()});
- robotInfo.PlcRobotParameter.AxixList.Add(new Axis() { Index = 2, Name = "Y", Command = new AxisCommand(), Parameter = new AxisParameter(), State = new AxisState() });
- robotInfo.PlcRobotParameter.AxixList.Add(new Axis() { Index = 3, Name = "Z", Command = new AxisCommand(), Parameter = new AxisParameter(), State = new AxisState() });
- }
- robot = new XYZU_Robot(robotInfo, plc);
- }
- else
- {
- robot = new EpsonRobot(robotInfo);
- }
- return robot;
- }
- /// <summary>
- /// 更新机器人编号
- /// </summary>
- /// <param name="id"></param>
- /// <param name="newNumber"></param>
- public void UpdateRobotNumber(Guid id, int newNumber)
- {
- IRobot robot;
- lock (_sync)
- {
- if (_robotCollection.TryGetValue(id, out robot))
- {
- robot.RobotNo = newNumber;
- }
- }
- }
- // 私有帮助方法:通过机器人编号查找字典中的条目(线程安全)
- private bool TryFindRobotByNumber(int robotNo, out Guid id, out IRobot robot)
- {
- lock (_sync)
- {
- foreach (var kvp in _robotCollection)
- {
- var r = kvp.Value;
- if (r == null) continue;
- object rawValue = null;
- var type = r.GetType();
- // 1. 直接在机器人对象上查找常见编号属性
- var prop = type.GetProperty("RobotNo") ??
- type.GetProperty("RobotNumber") ??
- type.GetProperty("Number") ??
- type.GetProperty("No");
- if (prop != null)
- {
- try
- {
- rawValue = prop.GetValue(r);
- }
- catch
- {
- rawValue = null;
- }
- }
- // 2. 如果未找到,尝试从 RobotInfo / Info 属性中获取编号
- if (rawValue == null)
- {
- var infoProp = type.GetProperty("RobotInfo") ?? type.GetProperty("Info");
- if (infoProp != null)
- {
- try
- {
- var infoObj = infoProp.GetValue(r);
- if (infoObj != null)
- {
- var infoType = infoObj.GetType();
- var numberProp = infoType.GetProperty("RobotNo") ??
- infoType.GetProperty("RobotNumber") ??
- infoType.GetProperty("Number") ??
- infoType.GetProperty("No");
- if (numberProp != null)
- {
- try
- {
- rawValue = numberProp.GetValue(infoObj);
- }
- catch
- {
- rawValue = null;
- }
- }
- }
- }
- catch
- {
- // 忽略反射读取错误
- rawValue = null;
- }
- }
- }
- if (rawValue != null)
- {
- int parsed;
- try
- {
- if (rawValue is int) parsed = (int)rawValue;
- else parsed = Convert.ToInt32(rawValue);
- }
- catch
- {
- // 不能转换则跳过
- continue;
- }
- if (parsed == robotNo)
- {
- id = kvp.Key;
- robot = r;
- return true;
- }
- }
- }
- }
- id = Guid.Empty;
- robot = null;
- return false;
- }
- // 实现 IDisposable,释放所有机器人并清空集合
- public void Dispose()
- {
- List<IRobot> robots;
- lock (_sync)
- {
- robots = _robotCollection.Values.ToList();
- _robotCollection.Clear();
- }
- foreach (var r in robots)
- {
- try
- {
- r.Dispose();
- }
- catch
- {
- // 忽略单个释放异常
- }
- }
- GC.SuppressFinalize(this);
- }
- }
- }
|