|
|
@@ -32,20 +32,20 @@ namespace YSAI.Opc.ua.client
|
|
|
/// </summary>
|
|
|
/// <param name="OpcUaData.Basics">基础数据</param>
|
|
|
/// <returns></returns>
|
|
|
- public static OpcUaClientOperate Instance(Basics opcUaData)
|
|
|
+ public static OpcUaClientOperate Instance(Basics basics)
|
|
|
{
|
|
|
- OpcUaClientOperate? exp = ThisObjList.FirstOrDefault(c => c.opcUaData.Equals(opcUaData));
|
|
|
+ OpcUaClientOperate? exp = ThisObjList.FirstOrDefault(c => c.basics.Equals(basics));
|
|
|
if (exp == null)
|
|
|
{
|
|
|
lock (Lock)
|
|
|
{
|
|
|
- if (ThisObjList.Count(c => c.opcUaData.Equals(opcUaData)) > 0)
|
|
|
+ if (ThisObjList.Count(c => c.basics.Equals(basics)) > 0)
|
|
|
{
|
|
|
- return ThisObjList.First(c => c.opcUaData.Equals(opcUaData));
|
|
|
+ return ThisObjList.First(c => c.basics.Equals(basics));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- OpcUaClientOperate exp2 = new OpcUaClientOperate(opcUaData);
|
|
|
+ OpcUaClientOperate exp2 = new OpcUaClientOperate(basics);
|
|
|
ThisObjList.Add(exp2);
|
|
|
return exp2;
|
|
|
}
|
|
|
@@ -58,10 +58,10 @@ namespace YSAI.Opc.ua.client
|
|
|
/// 构造函数
|
|
|
/// </summary>
|
|
|
/// <param name="OpcUaData.Basics">基础数据</param>
|
|
|
- public OpcUaClientOperate(Basics opcUaData)
|
|
|
+ public OpcUaClientOperate(Basics basics)
|
|
|
{
|
|
|
//设置参数
|
|
|
- this.opcUaData = opcUaData;
|
|
|
+ this.basics = basics;
|
|
|
}
|
|
|
|
|
|
#region 公共属性
|
|
|
@@ -76,7 +76,7 @@ namespace YSAI.Opc.ua.client
|
|
|
/// <summary>
|
|
|
/// 基础数据
|
|
|
/// </summary>
|
|
|
- private Basics opcUaData { get; set; }
|
|
|
+ private Basics basics { get; set; }
|
|
|
/// <summary>
|
|
|
/// OPCUA 安装、配置、运行
|
|
|
/// </summary>
|
|
|
@@ -695,12 +695,12 @@ namespace YSAI.Opc.ua.client
|
|
|
protected override string LogHead => "[ OpcUaClientOperate 操作 ]";
|
|
|
protected override string ClassName => "OpcUaClientOperate";
|
|
|
|
|
|
- public Task<OperateResult> AddSubscribeAsync(ConcurrentDictionary<string, List<AddressDetails>> param, byte Priority = 100)
|
|
|
+ public Task<OperateResult> AddSubscribeAsync(ConcurrentDictionary<string, Address> param)
|
|
|
{
|
|
|
- return Task.Run(()=> AddSubscribe(param,Priority));
|
|
|
+ return Task.Run(()=> AddSubscribe(param));
|
|
|
}
|
|
|
|
|
|
- public OperateResult AddSubscribe(ConcurrentDictionary<string, List<AddressDetails>> param, byte Priority = 100)
|
|
|
+ public OperateResult AddSubscribe(ConcurrentDictionary<string, Address> param)
|
|
|
{
|
|
|
//开始记录运行时间
|
|
|
Depart("AddSubscribe");
|
|
|
@@ -721,7 +721,7 @@ namespace YSAI.Opc.ua.client
|
|
|
{
|
|
|
string Tag = p.Key;
|
|
|
|
|
|
- List<AddressDetails> Nodes = p.Value;
|
|
|
+ List<AddressDetails> Nodes = p.Value.AddressArray;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
@@ -772,7 +772,7 @@ namespace YSAI.Opc.ua.client
|
|
|
intMonitoredItem.StartNodeId = new NodeId(item.AddressName); //标识要监视的节点的浏览路径的开始节点
|
|
|
intMonitoredItem.AttributeId = Attributes.Value; //要监视的属性
|
|
|
intMonitoredItem.DisplayName = item.AddressName; //被监控项的显示名称
|
|
|
- intMonitoredItem.SamplingInterval = opcUaData.SamplingInterval; //采样间隔
|
|
|
+ intMonitoredItem.SamplingInterval = basics.SamplingInterval; //采样间隔
|
|
|
intMonitoredItem.Notification += async delegate (MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { OnMonitoredItemNotification(monitoredItem, e, item); }; //重写事件添加一个参数
|
|
|
|
|
|
allSubscriptions[Tag].AddItem(intMonitoredItem); //添加订阅
|
|
|
@@ -802,7 +802,7 @@ namespace YSAI.Opc.ua.client
|
|
|
subscription.KeepAliveCount = uint.MaxValue; //存活数量
|
|
|
subscription.LifetimeCount = uint.MaxValue; //生命周期
|
|
|
subscription.MaxNotificationsPerPublish = uint.MaxValue; //每个发布请求的最大通知数
|
|
|
- subscription.Priority = Priority; //分配给订阅的优先级
|
|
|
+ subscription.Priority = basics.Priority; //分配给订阅的优先级
|
|
|
subscription.DisplayName = Tag; //订阅的显示名称
|
|
|
|
|
|
//循环添加
|
|
|
@@ -814,7 +814,7 @@ namespace YSAI.Opc.ua.client
|
|
|
intMonitoredItem.StartNodeId = new NodeId(item.AddressName); //标识要监视的节点的浏览路径的开始节点
|
|
|
intMonitoredItem.AttributeId = Attributes.Value; //要监视的属性
|
|
|
intMonitoredItem.DisplayName = item.AddressName; //被监控项的显示名称
|
|
|
- intMonitoredItem.SamplingInterval = opcUaData.SamplingInterval; //采样间隔
|
|
|
+ intMonitoredItem.SamplingInterval = basics.SamplingInterval; //采样间隔
|
|
|
intMonitoredItem.Notification += async delegate (MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { OnMonitoredItemNotification(monitoredItem, e, item); }; //重写事件添加一个参数
|
|
|
subscription.AddItem(intMonitoredItem); //添加订阅通知项
|
|
|
}
|
|
|
@@ -847,12 +847,12 @@ namespace YSAI.Opc.ua.client
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public Task<OperateResult> RemoveSubscribeAsync(List<AddressDetails> Nodes)
|
|
|
+ public Task<OperateResult> RemoveSubscribeAsync(Address Nodes)
|
|
|
{
|
|
|
return Task.Run(() => RemoveSubscribe(Nodes));
|
|
|
}
|
|
|
|
|
|
- public OperateResult RemoveSubscribe(List<AddressDetails> Nodes)
|
|
|
+ public OperateResult RemoveSubscribe(Address Nodes)
|
|
|
{
|
|
|
//开始记录运行时间
|
|
|
Depart("RemoveSubscribe");
|
|
|
@@ -862,7 +862,7 @@ namespace YSAI.Opc.ua.client
|
|
|
{
|
|
|
return Break("RemoveSubscribe", false, "未连接");
|
|
|
}
|
|
|
- foreach (var node in Nodes)
|
|
|
+ foreach (var node in Nodes.AddressArray)
|
|
|
{
|
|
|
foreach (var alls in allSubscriptions)
|
|
|
{
|
|
|
@@ -950,72 +950,6 @@ namespace YSAI.Opc.ua.client
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public Task<OperateResult> InitAsync()
|
|
|
- {
|
|
|
- return Task.Run(()=> Init());
|
|
|
- }
|
|
|
-
|
|
|
- public OperateResult Init()
|
|
|
- {
|
|
|
- //开始记录运行时间
|
|
|
- Depart("Init");
|
|
|
- try
|
|
|
- {
|
|
|
- //实例化对象
|
|
|
- allSubscriptions = new ConcurrentDictionary<string, Subscription>();
|
|
|
- //OPCUA证书验证
|
|
|
- CertificateValidator certificateValidator = new CertificateValidator();
|
|
|
- //当发生证书验证错误时引发
|
|
|
- certificateValidator.CertificateValidation += (sender, eventArgs) =>
|
|
|
- {
|
|
|
- if (ServiceResult.IsGood(eventArgs.Error)) //验证状态码是否正常
|
|
|
- {
|
|
|
- eventArgs.Accept = true;
|
|
|
- }
|
|
|
- else if (eventArgs.Error.StatusCode.Code == StatusCodes.BadCertificateUntrusted) //验证证书状态
|
|
|
- {
|
|
|
- eventArgs.Accept = true;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- throw new Exception(string.Format("证书验证错误:{0},{1}", eventArgs.Error.Code, eventArgs.Error.AdditionalInfo));
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
- //用配置的当前状态更新验证器。
|
|
|
- certificateValidator.Update(new SecurityConfiguration
|
|
|
- {
|
|
|
- //获取或设置一个值,该值指示是否应自动接受不受信任的证书
|
|
|
- AutoAcceptUntrustedCertificates = true,
|
|
|
- //获取或设置一个值,该值指示是否接受SHA-1签名的证书
|
|
|
- RejectSHA1SignedCertificates = false,
|
|
|
- //获取或设置一个值,该值指示接受的最小证书密钥强度
|
|
|
- MinimumCertificateKeySize = 1024
|
|
|
- }).Wait();
|
|
|
- //实例化
|
|
|
- if (AI == null)
|
|
|
- {
|
|
|
- AI = new ApplicationInstance();
|
|
|
- }
|
|
|
- //初始化配置
|
|
|
- AI.ApplicationType = ApplicationType.Client;
|
|
|
- //配置文件的名称
|
|
|
- AI.ConfigSectionName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Opc.Ua.Client");
|
|
|
- //加载应用程序配置
|
|
|
- AC = AI.LoadApplicationConfiguration(false).Result;
|
|
|
- AC.ApplicationName = opcUaData.Name;
|
|
|
- AC.ApplicationType = ApplicationType.Client;
|
|
|
- AC.CertificateValidator = certificateValidator;
|
|
|
-
|
|
|
- return Break("Init", true);
|
|
|
- }
|
|
|
- catch (Exception ex)
|
|
|
- {
|
|
|
- return Break("Init", false, ex.Message);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
public Task<OperateResult> OnAsync()
|
|
|
{
|
|
|
return Task.Run(() => On());
|
|
|
@@ -1033,22 +967,69 @@ namespace YSAI.Opc.ua.client
|
|
|
{
|
|
|
return Break("On", false, "已连接");
|
|
|
}
|
|
|
+ //实例化对象
|
|
|
+ allSubscriptions = new ConcurrentDictionary<string, Subscription>();
|
|
|
+ //OPCUA证书验证
|
|
|
+ CertificateValidator certificateValidator = new CertificateValidator();
|
|
|
+ //当发生证书验证错误时引发
|
|
|
+ certificateValidator.CertificateValidation += (sender, eventArgs) =>
|
|
|
+ {
|
|
|
+ if (ServiceResult.IsGood(eventArgs.Error)) //验证状态码是否正常
|
|
|
+ {
|
|
|
+ eventArgs.Accept = true;
|
|
|
+ }
|
|
|
+ else if (eventArgs.Error.StatusCode.Code == StatusCodes.BadCertificateUntrusted) //验证证书状态
|
|
|
+ {
|
|
|
+ eventArgs.Accept = true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new Exception(string.Format("证书验证错误:{0},{1}", eventArgs.Error.Code, eventArgs.Error.AdditionalInfo));
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ //用配置的当前状态更新验证器。
|
|
|
+ certificateValidator.Update(new SecurityConfiguration
|
|
|
+ {
|
|
|
+ //获取或设置一个值,该值指示是否应自动接受不受信任的证书
|
|
|
+ AutoAcceptUntrustedCertificates = true,
|
|
|
+ //获取或设置一个值,该值指示是否接受SHA-1签名的证书
|
|
|
+ RejectSHA1SignedCertificates = false,
|
|
|
+ //获取或设置一个值,该值指示接受的最小证书密钥强度
|
|
|
+ MinimumCertificateKeySize = 1024
|
|
|
+ }).Wait();
|
|
|
+ //实例化
|
|
|
+ if (AI == null)
|
|
|
+ {
|
|
|
+ AI = new ApplicationInstance();
|
|
|
+ }
|
|
|
+ //初始化配置
|
|
|
+ AI.ApplicationType = ApplicationType.Client;
|
|
|
+ //配置文件的名称
|
|
|
+ AI.ConfigSectionName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Opc.Ua.Client");
|
|
|
+ //加载应用程序配置
|
|
|
+ AC = AI.LoadApplicationConfiguration(false).Result;
|
|
|
+ AC.ApplicationName = basics.Name;
|
|
|
+ AC.ApplicationType = ApplicationType.Client;
|
|
|
+ AC.CertificateValidator = certificateValidator;
|
|
|
+
|
|
|
//查找与当前设置最匹配的端点
|
|
|
- EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(opcUaData.ServerUrl, false);
|
|
|
+ EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(basics.ServerUrl, false);
|
|
|
//使用合理的默认值创建配置的实例
|
|
|
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(AC);
|
|
|
//配置终端
|
|
|
ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration);
|
|
|
|
|
|
//证书跟密钥的设置,首选证书设置,如两个都为空则是匿名访问
|
|
|
- if (!opcUaData.Cer.IsEmpty() && !opcUaData.SecreKey.IsEmpty())//设置证书
|
|
|
+ if (!basics.Cer.IsEmpty() && !basics.SecreKey.IsEmpty())//设置证书
|
|
|
{
|
|
|
- X509Certificate2 certificate = new X509Certificate2(opcUaData.Cer, opcUaData.SecreKey, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
|
|
+ X509Certificate2 certificate = new X509Certificate2(basics.Cer, basics.SecreKey, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
|
|
UserIdentity = new UserIdentity(certificate);
|
|
|
}
|
|
|
- else if (!opcUaData.UserName.IsEmpty() && !opcUaData.Password.IsEmpty())//设置账户密码
|
|
|
+ else if (!basics.UserName.IsEmpty() && !basics.Password.IsEmpty())//设置账户密码
|
|
|
{
|
|
|
- UserIdentity = new UserIdentity(opcUaData.UserName, opcUaData.Password);
|
|
|
+ UserIdentity = new UserIdentity(basics.UserName, basics.Password);
|
|
|
}
|
|
|
//通过调用CreateSession服务创建与服务器的新通信会话
|
|
|
clientSession = Session.Create(AC, endpoint, false, false, AC.ApplicationName, 60000, UserIdentity, null).Result;
|