|
@@ -127,9 +127,14 @@ namespace YSAI.Opc.ua.client
|
|
|
private SessionReconnectHandler? sessionReconnectHandler { get; set; }
|
|
private SessionReconnectHandler? sessionReconnectHandler { get; set; }
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
- /// 系统所有的节点信息
|
|
|
|
|
|
|
+ /// 系统所有的订阅节点信息
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
- private ConcurrentDictionary<string, Subscription> allSubscriptions;
|
|
|
|
|
|
|
+ private ConcurrentDictionary<string, Subscription> allSubscriptions = new ConcurrentDictionary<string, Subscription>();
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// 重新订阅的标识
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ private string reSubscribeTag = "re-subscribe";
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// token
|
|
/// token
|
|
@@ -460,6 +465,8 @@ namespace YSAI.Opc.ua.client
|
|
|
{
|
|
{
|
|
|
//休眠时间
|
|
//休眠时间
|
|
|
int sleep = 60000;
|
|
int sleep = 60000;
|
|
|
|
|
+ //订阅失败的地址
|
|
|
|
|
+ List<AddressDetails> details = new List<AddressDetails>();
|
|
|
return Task.Run(() =>
|
|
return Task.Run(() =>
|
|
|
{
|
|
{
|
|
|
while (true)
|
|
while (true)
|
|
@@ -478,9 +485,41 @@ namespace YSAI.Opc.ua.client
|
|
|
{
|
|
{
|
|
|
if (!monitoredItem.Status.Created)
|
|
if (!monitoredItem.Status.Created)
|
|
|
{
|
|
{
|
|
|
- LogHelper.Error($"{monitoredItem.DisplayName} 地址未能在服务器上创建订阅,请检查地址是否正常", $"{TAG}/SubscribeCheckStatus.log", consoleShow: false);
|
|
|
|
|
|
|
+ AddressDetails? addressDetails = monitoredItem.Handle as AddressDetails;
|
|
|
|
|
+ if (addressDetails != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ details.Add(addressDetails);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (details.Count > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ LogHelper.Error($"存在 {details.Count} 个地址未能在服务器上创建订阅,正在执行重新订阅", $"{TAG}/SubscribeCheckStatus.log", consoleShow: false);
|
|
|
|
|
+ //移除这些点位成功后,在来进行订阅
|
|
|
|
|
+ OperateResult operateResult = RemoveSubscribe(new Address { AddressArray = details });
|
|
|
|
|
+ if (operateResult.State)
|
|
|
|
|
+ {
|
|
|
|
|
+ operateResult = AddSubscribe(new ConcurrentDictionary<string, Address>
|
|
|
|
|
+ {
|
|
|
|
|
+ [reSubscribeTag] = new Address { AddressArray = details }
|
|
|
|
|
+ });
|
|
|
|
|
+ if (operateResult.State)
|
|
|
|
|
+ {
|
|
|
|
|
+ LogHelper.Info($"重新订阅成功", $"{TAG}/SubscribeCheckStatus.log", consoleShow: false);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ LogHelper.Error($"重新订阅失败,{operateResult.Message}", $"{TAG}/SubscribeCheckStatus.log", consoleShow: false);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ LogHelper.Error($"重新订阅失败,{operateResult.Message}", $"{TAG}/SubscribeCheckStatus.log", consoleShow: false);
|
|
|
|
|
+ }
|
|
|
|
|
+ //清空
|
|
|
|
|
+ details.Clear();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Thread.Sleep(sleep);
|
|
Thread.Sleep(sleep);
|
|
@@ -1061,6 +1100,7 @@ namespace YSAI.Opc.ua.client
|
|
|
return Break("AddSubscribe", false, $"地址不能为空");
|
|
return Break("AddSubscribe", false, $"地址不能为空");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ //移除虚拟点
|
|
|
List<AddressDetails> Nodes = p.Value.RemoveVirtualAddress();
|
|
List<AddressDetails> Nodes = p.Value.RemoveVirtualAddress();
|
|
|
|
|
|
|
|
try
|
|
try
|
|
@@ -1072,6 +1112,8 @@ namespace YSAI.Opc.ua.client
|
|
|
//判断是否存在此节点订阅
|
|
//判断是否存在此节点订阅
|
|
|
for (int i = 0; i < Nodes.Count; i++)
|
|
for (int i = 0; i < Nodes.Count; i++)
|
|
|
{
|
|
{
|
|
|
|
|
+ if (!Nodes[i].IsEnable) continue;
|
|
|
|
|
+
|
|
|
foreach (var alls in allSubscriptions)
|
|
foreach (var alls in allSubscriptions)
|
|
|
{
|
|
{
|
|
|
//节点与键对应
|
|
//节点与键对应
|
|
@@ -1111,6 +1153,7 @@ namespace YSAI.Opc.ua.client
|
|
|
if (!item.IsEnable) continue;
|
|
if (!item.IsEnable) continue;
|
|
|
|
|
|
|
|
MonitoredItem monitoredItem = new MonitoredItem(allSubscriptions[Tag].DefaultItem);
|
|
MonitoredItem monitoredItem = new MonitoredItem(allSubscriptions[Tag].DefaultItem);
|
|
|
|
|
+ monitoredItem.Handle = item; //分配给被监视项的本地句柄
|
|
|
monitoredItem.StartNodeId = new NodeId(item.AddressName); //标识要监视的节点的浏览路径的开始节点
|
|
monitoredItem.StartNodeId = new NodeId(item.AddressName); //标识要监视的节点的浏览路径的开始节点
|
|
|
monitoredItem.AttributeId = Attributes.Value; //要监视的属性
|
|
monitoredItem.AttributeId = Attributes.Value; //要监视的属性
|
|
|
monitoredItem.SamplingInterval = basics.SamplingInterval; //多少秒采集一次数据
|
|
monitoredItem.SamplingInterval = basics.SamplingInterval; //多少秒采集一次数据
|
|
@@ -1162,6 +1205,7 @@ namespace YSAI.Opc.ua.client
|
|
|
if (!item.IsEnable) continue;
|
|
if (!item.IsEnable) continue;
|
|
|
|
|
|
|
|
MonitoredItem monitoredItem = new MonitoredItem(subscription.DefaultItem);
|
|
MonitoredItem monitoredItem = new MonitoredItem(subscription.DefaultItem);
|
|
|
|
|
+ monitoredItem.Handle = item; //分配给被监视项的本地句柄
|
|
|
monitoredItem.StartNodeId = new NodeId(item.AddressName); //标识要监视的节点的浏览路径的开始节点
|
|
monitoredItem.StartNodeId = new NodeId(item.AddressName); //标识要监视的节点的浏览路径的开始节点
|
|
|
monitoredItem.AttributeId = Attributes.Value; //要监视的属性
|
|
monitoredItem.AttributeId = Attributes.Value; //要监视的属性
|
|
|
monitoredItem.SamplingInterval = basics.SamplingInterval; //多少秒采集一次数据
|
|
monitoredItem.SamplingInterval = basics.SamplingInterval; //多少秒采集一次数据
|
|
@@ -1543,8 +1587,6 @@ namespace YSAI.Opc.ua.client
|
|
|
{
|
|
{
|
|
|
return Break("On", false, "已连接");
|
|
return Break("On", false, "已连接");
|
|
|
}
|
|
}
|
|
|
- //实例化对象
|
|
|
|
|
- allSubscriptions = new ConcurrentDictionary<string, Subscription>();
|
|
|
|
|
//OPCUA证书验证
|
|
//OPCUA证书验证
|
|
|
CertificateValidator certificateValidator = new CertificateValidator();
|
|
CertificateValidator certificateValidator = new CertificateValidator();
|
|
|
//当发生证书验证错误时引发
|
|
//当发生证书验证错误时引发
|