|
|
@@ -125,6 +125,159 @@ namespace YSAI.Opc.ua.client
|
|
|
#endregion
|
|
|
|
|
|
#region 私有函数
|
|
|
+ /// <summary>
|
|
|
+ /// OPCUA 订阅状态集合
|
|
|
+ /// </summary>
|
|
|
+ private Dictionary<SubscriptionChangeMask, string> StateChangedStatus = new Dictionary<SubscriptionChangeMask, string>
|
|
|
+ {
|
|
|
+ { SubscriptionChangeMask.None, "订阅没有改变" },
|
|
|
+ { SubscriptionChangeMask.Created,"在服务器上创建订阅" },
|
|
|
+ { SubscriptionChangeMask.Deleted,"在服务器上删除订阅" },
|
|
|
+ { SubscriptionChangeMask.Modified,"在服务器上修改订阅" },
|
|
|
+ { SubscriptionChangeMask.ItemsAdded,"被监视的项目被添加到订阅中(但没有在服务器上创建)" },
|
|
|
+ { SubscriptionChangeMask.ItemsRemoved,"被监控的项目被删除到订阅(但没有在服务器上删除)" },
|
|
|
+ { SubscriptionChangeMask.ItemsCreated,"在服务器上创建监视项" },
|
|
|
+ { SubscriptionChangeMask.ItemsDeleted,"在服务器上删除监控项" },
|
|
|
+ { SubscriptionChangeMask.ItemsModified,"在服务器上修改监控项" },
|
|
|
+ { SubscriptionChangeMask.Transferred,"订阅在服务器上被转移" }
|
|
|
+ };
|
|
|
+
|
|
|
+ private Dictionary<PublishStateChangedMask, string> PublishStatusChangedStatus = new Dictionary<PublishStateChangedMask, string>
|
|
|
+ {
|
|
|
+ { PublishStateChangedMask.None, "发布状态没有改变" },
|
|
|
+ { PublishStateChangedMask.Stopped,"停止发布" },
|
|
|
+ { PublishStateChangedMask.Recovered,"发布恢复" },
|
|
|
+ { PublishStateChangedMask.KeepAlive,"收到keep alive消息" },
|
|
|
+ { PublishStateChangedMask.Republish,"重新发布丢失的消息" },
|
|
|
+ { PublishStateChangedMask.Transferred,"发布被转移到其他节点" },
|
|
|
+ { PublishStateChangedMask.Timeout,"发布超时" }
|
|
|
+ };
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 枚举类型
|
|
|
+ /// </summary>
|
|
|
+ private enum EnumType
|
|
|
+ {
|
|
|
+ StateChanged,
|
|
|
+ PublishStatusChanged
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 订阅状态枚举解析
|
|
|
+ /// </summary>
|
|
|
+ /// <param name=""></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private string EnumParse(string enumStr,EnumType type)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (enumStr.Contains(","))
|
|
|
+ {
|
|
|
+ string[] Es = enumStr.Split(",");
|
|
|
+ string Info = string.Empty;
|
|
|
+ foreach (var item in Es)
|
|
|
+ {
|
|
|
+ switch (type)
|
|
|
+ {
|
|
|
+ case EnumType.StateChanged:
|
|
|
+ Info += $"( {StateChangedStatus[(SubscriptionChangeMask)Enum.Parse(typeof(SubscriptionChangeMask), item)]} )";
|
|
|
+ break;
|
|
|
+ case EnumType.PublishStatusChanged:
|
|
|
+ Info += $"( {PublishStatusChangedStatus[(PublishStateChangedMask)Enum.Parse(typeof(PublishStateChangedMask), item)]} )";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Info.Replace(")(", ") (");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ switch (type)
|
|
|
+ {
|
|
|
+ case EnumType.StateChanged:
|
|
|
+ return StateChangedStatus[(SubscriptionChangeMask)Enum.Parse(typeof(SubscriptionChangeMask), enumStr)];
|
|
|
+ case EnumType.PublishStatusChanged:
|
|
|
+ return PublishStatusChangedStatus[(PublishStateChangedMask)Enum.Parse(typeof(PublishStateChangedMask), enumStr)];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return ex.Message;
|
|
|
+ }
|
|
|
+ return "null";
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 订阅状态
|
|
|
+ /// </summary>
|
|
|
+ private void Subscription_StateChanged(Subscription subscription, SubscriptionStateChangedEventArgs e, string tag)
|
|
|
+ {
|
|
|
+#if DEBUG
|
|
|
+ string Message = EnumParse(e.Status.ToString(), EnumType.StateChanged);
|
|
|
+ string MessageJson = "{" + $"\"Uri\":\"{basics.ServerUrl}\",\"CustomName\":\"{basics.CustomName}\",\"StatusCode\":\"{e.Status}\",\"StatusMessage\":\"{Message}\"" + "}";
|
|
|
+ LogHelper.Verbose($"订阅状态\r\n{MessageJson.JsonFormatting()}", $"{TAG}/StateChanged.log");
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 指示订阅的发布状态已停止或已恢复
|
|
|
+ /// </summary>
|
|
|
+ private void Subscription_PublishStatusChanged(Subscription subscription, PublishStateChangedEventArgs e)
|
|
|
+ {
|
|
|
+#if DEBUG
|
|
|
+ string Message = EnumParse(e.Status.ToString(), EnumType.PublishStatusChanged);
|
|
|
+ string MessageJson = "{" + $"\"Uri\":\"{basics.ServerUrl}\",\"CustomName\":\"{basics.CustomName}\",\"StatusCode\":\"{e.Status}\",\"StatusMessage\":\"{Message}\"" + "}";
|
|
|
+ LogHelper.Verbose($"指示订阅的发布状态已停止或已恢复\r\n{MessageJson.JsonFormatting()}", $"{TAG}/PublishError.log");
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 处理发布响应时发生异常
|
|
|
+ /// </summary>
|
|
|
+ private void ClientSession_PublishError(ISession session, PublishErrorEventArgs e)
|
|
|
+ {
|
|
|
+#if DEBUG
|
|
|
+ string MessageJson = "{" + $"\"Uri\":\"{basics.ServerUrl}\",\"CustomName\":\"{basics.CustomName}\",\"StatusCode\":\"{e.Status}\"" + "}";
|
|
|
+ LogHelper.Verbose($"处理发布响应时发生异常\r\n{MessageJson.JsonFormatting()}", $"{TAG}/PublishError.log");
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 发布请求即将确认序列号
|
|
|
+ /// </summary>
|
|
|
+ private void ClientSession_PublishSequenceNumbersToAcknowledge(ISession session, PublishSequenceNumbersToAcknowledgeEventArgs e)
|
|
|
+ {
|
|
|
+#if DEBUG
|
|
|
+ string MessageJson = "{" + $"\"Uri\":\"{basics.ServerUrl}\",\"CustomName\":\"{basics.CustomName}\"" + "}";
|
|
|
+ LogHelper.Verbose($"发布请求即将确认序列号\r\n{MessageJson.JsonFormatting()}", $"{TAG}/PublishSequenceNumbersToAcknowledge.log");
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 会话正在结束
|
|
|
+ /// </summary>
|
|
|
+ private void ClientSession_SessionClosing(object? sender, EventArgs e)
|
|
|
+ {
|
|
|
+#if DEBUG
|
|
|
+ string MessageJson = "{" + $"\"Uri\":\"{basics.ServerUrl}\",\"CustomName\":\"{basics.CustomName}\"" + "}";
|
|
|
+ LogHelper.Verbose($"会话正在结束\r\n{MessageJson.JsonFormatting()}", $"{TAG}/SessionClosing.log");
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 会话配置更改
|
|
|
+ /// </summary>
|
|
|
+ private void ClientSession_SessionConfigurationChanged(object? sender, EventArgs e)
|
|
|
+ {
|
|
|
+#if DEBUG
|
|
|
+ string MessageJson = "{" + $"\"Uri\":\"{basics.ServerUrl}\",\"CustomName\":\"{basics.CustomName}\"" + "}";
|
|
|
+ LogHelper.Verbose($"会话配置更改\r\n{MessageJson.JsonFormatting()}", $"{TAG}/SessionConfigurationChanged.log");
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 添加或删除订阅
|
|
|
+ /// </summary>
|
|
|
+ private void ClientSession_SubscriptionsChanged(object? sender, EventArgs e)
|
|
|
+ {
|
|
|
+#if DEBUG
|
|
|
+ string MessageJson = "{" + $"\"Uri\":\"{basics.ServerUrl}\",\"CustomName\":\"{basics.CustomName}\"" + "}";
|
|
|
+ LogHelper.Verbose($"添加或删除订阅\r\n{MessageJson.JsonFormatting()}", $"{TAG}/SubscriptionsChanged.log");
|
|
|
+#endif
|
|
|
+ }
|
|
|
|
|
|
int ConnectedCounet = 0;
|
|
|
/// <summary>
|
|
|
@@ -245,9 +398,6 @@ namespace YSAI.Opc.ua.client
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// 当数据变化更新
|
|
|
/// </summary>
|
|
|
@@ -946,7 +1096,7 @@ namespace YSAI.Opc.ua.client
|
|
|
subscription.DisplayName = Tag; //订阅的显示名称
|
|
|
subscription.TimestampsToReturn = TimestampsToReturn.Both; //与通知消息一起返回的时间戳
|
|
|
subscription.StateChanged += delegate (Subscription subscription, SubscriptionStateChangedEventArgs e) { Subscription_StateChanged(subscription, e, Tag); }; //订阅状态
|
|
|
-
|
|
|
+ subscription.PublishStatusChanged += Subscription_PublishStatusChanged; //指示订阅的发布状态已停止或已恢复
|
|
|
//监控项集合
|
|
|
List<MonitoredItem> monitoredItems = new List<MonitoredItem>();
|
|
|
|
|
|
@@ -989,55 +1139,7 @@ namespace YSAI.Opc.ua.client
|
|
|
}
|
|
|
return Break("AddSubscribe", true);
|
|
|
}
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// OPCUA 订阅状态集合
|
|
|
- /// </summary>
|
|
|
- private Dictionary<SubscriptionChangeMask, string> SubscribeStatus = new Dictionary<SubscriptionChangeMask, string>
|
|
|
- {
|
|
|
- { SubscriptionChangeMask.None, "订阅没有改变" },
|
|
|
- { SubscriptionChangeMask.Created,"在服务器上创建订阅" },
|
|
|
- { SubscriptionChangeMask.Deleted,"在服务器上删除订阅" },
|
|
|
- { SubscriptionChangeMask.Modified,"在服务器上修改订阅" },
|
|
|
- { SubscriptionChangeMask.ItemsAdded,"被监视的项目被添加到订阅中(但没有在服务器上创建)" },
|
|
|
- { SubscriptionChangeMask.ItemsRemoved,"被监控的项目被删除到订阅(但没有在服务器上删除)" },
|
|
|
- { SubscriptionChangeMask.ItemsCreated,"在服务器上创建监视项" },
|
|
|
- { SubscriptionChangeMask.ItemsDeleted,"在服务器上删除监控项" },
|
|
|
- { SubscriptionChangeMask.ItemsModified,"在服务器上修改监控项" },
|
|
|
- { SubscriptionChangeMask.Transferred,"订阅在服务器上被转移" }
|
|
|
- };
|
|
|
- /// <summary>
|
|
|
- /// 订阅状态枚举解析
|
|
|
- /// </summary>
|
|
|
- /// <param name=""></param>
|
|
|
- /// <returns></returns>
|
|
|
- private string EnumParse(string enumStr)
|
|
|
- {
|
|
|
- if (enumStr.Contains(","))
|
|
|
- {
|
|
|
- string[] Es = enumStr.Split(",");
|
|
|
- string Info = string.Empty;
|
|
|
- foreach (var item in Es)
|
|
|
- {
|
|
|
- Info += $"( {SubscribeStatus[(SubscriptionChangeMask)Enum.Parse(typeof(SubscriptionChangeMask), item)]} )";
|
|
|
- }
|
|
|
- return Info.Replace(")(", ") (");
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return SubscribeStatus[(SubscriptionChangeMask)Enum.Parse(typeof(SubscriptionChangeMask), enumStr)];
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //订阅状态
|
|
|
- private void Subscription_StateChanged(Subscription subscription, SubscriptionStateChangedEventArgs e, string tag)
|
|
|
- {
|
|
|
- string Message = EnumParse(e.Status.ToString());
|
|
|
- string MessageJson = "{" + $"\"Uri\":\"{basics.ServerUrl}\",\"CustomName\":\"{basics.CustomName}\",\"StatusCode\":\"{e.Status}\",\"StatusMessage\":\"{Message}\"" + "}";
|
|
|
-#if DEBUG
|
|
|
- OnEventHandler(this, new EventResult(true, Message, MessageJson));
|
|
|
-#endif
|
|
|
- }
|
|
|
+
|
|
|
|
|
|
/// <summary>
|
|
|
/// 移除订阅 通过节点来移除订阅,移除指定节点的订阅,没有也返回成功
|
|
|
@@ -1360,6 +1462,17 @@ namespace YSAI.Opc.ua.client
|
|
|
//当从服务器到达一个存活状态或检测到一个错误时将被引发
|
|
|
clientSession.KeepAlive += new KeepAliveEventHandler(Session_KeepAlive);
|
|
|
|
|
|
+ //添加或删除订阅
|
|
|
+ clientSession.SubscriptionsChanged += ClientSession_SubscriptionsChanged;
|
|
|
+ //会话配置更改
|
|
|
+ clientSession.SessionConfigurationChanged += ClientSession_SessionConfigurationChanged;
|
|
|
+ //会话正在结束
|
|
|
+ clientSession.SessionClosing += ClientSession_SessionClosing;
|
|
|
+ //发布请求即将确认序列号
|
|
|
+ clientSession.PublishSequenceNumbersToAcknowledge += ClientSession_PublishSequenceNumbersToAcknowledge;
|
|
|
+ //处理发布响应时发生异常
|
|
|
+ clientSession.PublishError += ClientSession_PublishError;
|
|
|
+
|
|
|
//当队列为空,初始化队列
|
|
|
if (DataQueue == null)
|
|
|
{
|
|
|
@@ -1389,6 +1502,8 @@ namespace YSAI.Opc.ua.client
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
public Task<OperateResult> OffAsync()
|
|
|
{
|
|
|
return Task.Run(() => Off());
|