using OxyPlot; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using TeamAAS_VP.Core.PLCs; using TeamAAS_VP.Core.Robots; using TeamAAS_VP.Interfaces; using TeamAAS_VP.Models; namespace TeamAAS_VP.Services { public class PlcService : IPlcService, IDisposable { private readonly Dictionary _plcCollection; private readonly object _sync = new object(); public PlcService() { _plcCollection = new Dictionary(); } public bool CreatePlc(Guid id, PlcInfo plcInfo) { if (plcInfo == null) throw new ArgumentNullException(nameof(plcInfo)); var plc = CreatePlcInstance(plcInfo); if (plc == null) return false; lock (_sync) { if (_plcCollection.ContainsKey(id)) { try { _plcCollection[id].Dispose(); } catch { // 忽略单个 Dispose 异常 } } _plcCollection[id] = plc; } return true; } public Task CreatePlcAsync(Guid id, PlcInfo plcInfo) { return Task.Run(() => CreatePlc(id, plcInfo)); } public IPlc GetPlc(Guid id) { lock (_sync) { if (_plcCollection.TryGetValue(id, out var plc)) return plc; } return null; } public Task GetPlcAsync(Guid id) { var plc = GetPlc(id); return Task.FromResult(plc); } public void UnRegisterPlc(Guid id) { IPlc plc = null; lock (_sync) { if (_plcCollection.TryGetValue(id, out plc)) { _plcCollection.Remove(id); } } if (plc != null) { try { plc.Dispose(); } catch { // 忽略释放异常 } } } public Task UnRegisterPlcAsync(Guid id) { UnRegisterPlc(id); return Task.CompletedTask; } public IReadOnlyCollection GetAllPlcs() { lock (_sync) { return _plcCollection.Values.ToList().AsReadOnly(); } } public Task> GetAllPlcsAsync() { var snapshot = GetAllPlcs(); return Task.FromResult(snapshot); } public bool TryGetPlc(Guid id, out IPlc plc) { lock (_sync) { return _plcCollection.TryGetValue(id, out plc); } } public Task<(bool found, IPlc plc)> TryGetPlcAsync(Guid id) { IPlc plc; bool found; lock (_sync) { found = _plcCollection.TryGetValue(id, out plc); } return Task.FromResult((found, plc)); } public bool ContainsPlc(Guid id) { lock (_sync) { return _plcCollection.ContainsKey(id); } } public Task ContainsPlcAsync(Guid id) { var exists = ContainsPlc(id); return Task.FromResult(exists); } public bool RemovePlc(Guid id) { IPlc plc = null; lock (_sync) { if (_plcCollection.TryGetValue(id, out plc)) { _plcCollection.Remove(id); } } if (plc != null) { try { plc.Dispose(); } catch { // 忽略释放异常 } return true; } return false; } public Task RemovePlcAsync(Guid id) { var removed = RemovePlc(id); return Task.FromResult(removed); } public IPlc GetPlcByNumber(int number) { if (TryFindPlcByNumber(number, out _, out var plc)) return plc; return null; } public Task GetPlcByNumberAsync(int number) { var plc = GetPlcByNumber(number); return Task.FromResult(plc); } public Task UnRegisterPlcByNumberAsync(int number) { UnRegisterPlcByNumber(number); return Task.CompletedTask; } public void UnRegisterPlcByNumber(int number) { if (TryFindPlcByNumber(number, out var id, out var plc)) { UnRegisterPlc(id); } } private IPlc CreatePlcInstance(PlcInfo plcInfo) { if (plcInfo == null) return null; if (plcInfo.CommunicationType == Enums.CommunicationType.OPC_UA_Client) { return new OpcUaClientPLC(plcInfo); } return null; } private bool TryFindPlcByNumber(int number, out Guid id, out IPlc plc) { lock (_sync) { foreach (var kvp in _plcCollection) { var p = kvp.Value; if (p == null) continue; if (p.Index==number) { id = kvp.Key; plc = kvp.Value; return true; } } } id = Guid.Empty; plc = null; return false; } public void Dispose() { List plcs; lock (_sync) { plcs = _plcCollection.Values.ToList(); _plcCollection.Clear(); } foreach (var p in plcs) { try { p.Dispose(); } catch { // 忽略单个释放异常 } } GC.SuppressFinalize(this); } public (bool IsSucceed, string Message) InitializePlc(PlcInfo[] plcs) { if (plcs == null) { return (false, "plcs 参数为 null。"); } if (plcs.Length == 0) { return (true, "没有需要初始化的 PLC。"); } var failures = new List(); var successes = 0; for (var i = 0; i < plcs.Length; i++) { var info = plcs[i]; if (info == null) { failures.Add($"索引 {i}: PlcInfo 为 null。"); continue; } // 尝试从 plcInfo 中提取编号(若有) int? number = null; try { var infoType = info.GetType(); var numberProp = infoType.GetProperty("PlcNo") ?? infoType.GetProperty("PlcNumber") ?? infoType.GetProperty("Number") ?? infoType.GetProperty("No"); if (numberProp != null) { var raw = numberProp.GetValue(info); if (raw != null) { if (raw is int ri) number = ri; else { try { number = Convert.ToInt32(raw); } catch { number = null; } } } } } catch { number = null; } // 如果存在相同编号的 PLC,则先卸载它 try { if (number.HasValue) { if (TryFindPlcByNumber(number.Value, out var existingId, out var existingPlc)) { try { UnRegisterPlc(existingId); } catch { // 忽略单个卸载异常,之后尝试创建新的实例 } } } } catch { // 忽略查找/卸载过程中的异常,继续尝试创建 } var id = Guid.NewGuid(); bool created; try { created = CreatePlc(id, info); } catch (Exception ex) { created = false; failures.Add($"索引 {i}{(number.HasValue ? $" (编号 {number.Value})" : "")}: 创建 PLC 时抛出异常:{ex.Message}"); } if (!created) { failures.Add($"索引 {i}{(number.HasValue ? $" (编号 {number.Value})" : "")}: 创建 PLC 失败。"); } else { successes++; } } if (failures.Count == 0) { return (true, $"已成功初始化 {successes} 个 PLC。"); } var message = $"初始化完成:成功 {successes},失败 {failures.Count}。失败原因:{string.Join(" | ", failures)}"; return (false, message); } public Task<(bool IsSucceed, string Message)> InitializePlcAsync(PlcInfo[] plcs) { return Task.Run(() => InitializePlc(plcs)); } public bool RemoveAllPlcs() { List plcs; lock (_sync) { if (_plcCollection.Count == 0) return false; plcs = _plcCollection.Values.ToList(); _plcCollection.Clear(); } var removedAny = false; foreach (var p in plcs) { if (p == null) continue; try { p.Dispose(); removedAny = true; } catch { // 忽略单个释放异常 removedAny = true; // 已尝试移除,仍视为移除过 } } return removedAny; } public Task RemoveAllPlcsAsync() { var result = RemoveAllPlcs(); return Task.FromResult(result); } /// /// 更新PLC编号 /// /// /// public void UpdatePlcNumber(Guid id, int newNumber) { lock (_sync) { if (_plcCollection.TryGetValue(id, out var plc)) { if (plc != null) { plc.Index=newNumber; } } } } } }