using Opc.Ua; using Opc.Ua.Client; using OpcUaHelper; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using TeamAAS_VP.Enums; using TeamAAS_VP.Interfaces; using TeamAAS_VP.Models; namespace TeamAAS_VP.Core.PLCs { public class OpcUaClientPLC : IPlc { public Guid Id{ get; private set; } public CommunicationType CommunicationType { get; private set; } public string EndpointUrl { get; private set; } public int Index { get; set; } public string Name { get; private set; } public OpcUaClient OpcUaClient { get; private set; } public bool IsConnected { get { return OpcUaClient.Connected; } } /// /// 节点头 /// public string NodeHeader { get; private set; } public event Action ConnectChangedEvent; public OpcUaClientPLC(Guid id,int index, string name, string endpointUrl,string nodeHeader, CommunicationType communicationType) { Id = id; Index = index; Name = name; EndpointUrl = endpointUrl; NodeHeader = nodeHeader; CommunicationType = communicationType; OpcUaClient = new OpcUaClient(); // 初始化PLC连接 OpcUaClient.UserIdentity = new UserIdentity(new AnonymousIdentityToken()); // connect to server, this is a sample try { OpcUaClient.ConnectComplete += OpcUaClient_ConnectComplete; OpcUaClient.ReconnectStarting += OpcUaClient_ReconnectStarting; OpcUaClient.ReconnectComplete += OpcUaClient_ReconnectComplete; OpcUaClient.OpcStatusChange += OpcUaClient_OpcStatusChange; } catch (Exception) { return; } } public OpcUaClientPLC(PlcInfo plcInfo) { Id = plcInfo.Id; Index=plcInfo.Index; Name = plcInfo.Name; NodeHeader=plcInfo.NodeHeader; EndpointUrl = plcInfo.EndpointUrl; CommunicationType = plcInfo.CommunicationType; OpcUaClient = new OpcUaClient(); // 初始化PLC连接 OpcUaClient.UserIdentity = new UserIdentity(new AnonymousIdentityToken()); // connect to server, this is a sample try { OpcUaClient.ConnectComplete += OpcUaClient_ConnectComplete; OpcUaClient.ReconnectStarting += OpcUaClient_ReconnectStarting; OpcUaClient.ReconnectComplete += OpcUaClient_ReconnectComplete; OpcUaClient.OpcStatusChange += OpcUaClient_OpcStatusChange; } catch (Exception) { return; } } public void Connect() { OpcUaClient.ConnectServer(EndpointUrl); } public Task ConnectAsync() { return OpcUaClient.ConnectServer(EndpointUrl); } public void Disconnect() { OpcUaClient.Disconnect(); } public void Dispose() { OpcUaClient.Disconnect(); OpcUaClient.ConnectComplete -= OpcUaClient_ConnectComplete; OpcUaClient.ReconnectStarting -= OpcUaClient_ReconnectStarting; OpcUaClient.ReconnectComplete -= OpcUaClient_ReconnectComplete; OpcUaClient.OpcStatusChange -= OpcUaClient_OpcStatusChange; } /// /// 读取多个节点的值 /// /// /// public Dictionary ReadNodes(string[] nodeIds) { var result = new Dictionary(); var readNodeIds = nodeIds.Select(s => { if (s.StartsWith(NodeHeader)) { return s; } else { return NodeHeader + s; } }).ToArray(); List readNodeIdList = new List(); foreach (var readNodeId in readNodeIds) { readNodeIdList.Add(new NodeId(readNodeId)); } var values = OpcUaClient.ReadNodes(readNodeIdList.ToArray()); for (int i = 0; i < nodeIds.Length; i++) { result[nodeIds[i]] = values[i].Value; } return result; } /// /// 异步读取多个节点的值 /// /// /// public async Task> ReadNodesAsync(string[] nodeIds) { var result = new Dictionary(); var readNodeIds = nodeIds.Select(s => { if (s.StartsWith(NodeHeader)) { return s; } else { return NodeHeader + s; } }).ToArray(); List readNodeIdList = new List(); foreach (var readNodeId in readNodeIds) { readNodeIdList.Add(new NodeId(readNodeId)); } var values = await OpcUaClient.ReadNodesAsync(readNodeIdList.ToArray()); for (int i = 0; i < nodeIds.Length; i++) { result[nodeIds[i]] = values[i].Value; } return result; } /// /// 读取单个节点的值 /// /// /// public object ReadNode(string nodeId) { string readNodeId = nodeId; if (!nodeId.StartsWith(NodeHeader)) { readNodeId = NodeHeader + nodeId; } var value = OpcUaClient.ReadNode(new NodeId(readNodeId)); return value.Value; } /// /// 异步读取单个节点的值 /// /// /// public Task ReadNodeAsync(string nodeId) { return Task.Run(() => { return ReadNode(nodeId); }); } /// /// 读取单个节点的值 /// /// /// /// public T ReadNode(string nodeId) { string readNodeId = nodeId; if (!nodeId.StartsWith(NodeHeader)) { readNodeId = NodeHeader + nodeId; } return OpcUaClient.ReadNode(readNodeId); } /// /// 异步读取单个节点的值 /// /// /// /// public async Task ReadNodeAsync(string nodeId) { string readNodeId = nodeId; if (!nodeId.StartsWith(NodeHeader)) { readNodeId = NodeHeader + nodeId; } return await OpcUaClient.ReadNodeAsync(readNodeId); } /// /// 写入单个节点的值 /// /// /// /// /// public bool WriteNode(string nodeId, T value) { string writeNodeId = nodeId; if (!nodeId.StartsWith(NodeHeader)) { writeNodeId = NodeHeader + nodeId; } return OpcUaClient.WriteNode(writeNodeId, value); } /// /// 异步写入单个节点的值 /// /// /// /// /// public async Task WriteNodeAsync(string nodeId, T value) { string writeNodeId = nodeId; if (!nodeId.StartsWith(NodeHeader)) { writeNodeId = NodeHeader + nodeId; } return await OpcUaClient.WriteNodeAsync(writeNodeId, value); } /// /// 写入多个节点 /// /// /// public bool WriteNodes(Dictionary nodeValues) { var writeNodeValues = new Dictionary(); foreach (var kvp in nodeValues) { string writeNodeId = kvp.Key; if (!kvp.Key.StartsWith(NodeHeader)) { writeNodeId = NodeHeader + kvp.Key; } writeNodeValues[writeNodeId] = kvp.Value; } return OpcUaClient.WriteNodes(writeNodeValues.Keys.ToArray(), writeNodeValues.Values.ToArray()); } /// /// 写入多个节点异步 /// /// /// public Task WriteNodesAsync(Dictionary nodeValues) { return Task.Run(() => { return WriteNodes(nodeValues); }); } /// /// 订阅多个节点 /// /// /// /// public void SubscribeNodes(string key, List nodeIds, Action<(string key,string nodeId,object value)> dataChangeHandler) { OpcUaClient.AddSubscription(key, nodeIds.Select(s => { if (s.StartsWith(NodeHeader)) { return s; } else { return NodeHeader + s; } }).ToArray(), (key1, monitoredItem, args) => { MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification; if (notification == null) { return; } string nodeId = monitoredItem.StartNodeId.ToString(); if (nodeId.StartsWith(NodeHeader)) { nodeId= nodeId.Substring(NodeHeader.Length); } // 触发数据变化事件 dataChangeHandler?.Invoke((key1, nodeId, notification.Value.WrappedValue.Value)); }); } #region OPC事件 private void OpcUaClient_OpcStatusChange(object sender, OpcUaStatusEventArgs e) { //LogHelper.WriteLogInfo($"OPC状态发生改变:Error:{e.Error},Time:{e.Time},Text:{e.Text}"); } private void OpcUaClient_ReconnectComplete(object sender, EventArgs e) { ConnectChangedEvent?.Invoke(this, OpcUaClient.Connected); } private void OpcUaClient_ReconnectStarting(object sender, EventArgs e) { ConnectChangedEvent?.Invoke(this, OpcUaClient.Connected); } private void OpcUaClient_ConnectComplete(object sender, EventArgs e) { ConnectChangedEvent?.Invoke(this, OpcUaClient.Connected); } #endregion } }