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
}
}