我正在使用OPC Foundation SDK构建OPC UA客户端。我可以创建一个包含一些Monitoreditems的订阅。
在OPC UA服务器上,这些受监视的项目会不断更改值(每秒左右)。
我想断开客户端连接(模拟连接断开),使订阅保持活动状态,然后等待一段时间。然后,我重新连接以恢复订阅,但是我也希望所有断开连接期间受监视的Item值排队。现在,我只能获得重新连接时的最后一个服务器值。
我正在设置队列大小:
monitoredItem.QueueSize = 100;
为了模拟连接错误,我在ClosesSession上将“删除订阅”设置为false: m_session.CloseSession(new RequestHeader(),false);
我的问题是断开/连接错误后如何捕获队列的内容?
客户端重新连接后,“丢失的值”是否应为“新的MonitoredItem_Notification”?
SubscriptionId是否应与断开连接之前相同?
sessionId应该相同还是新的SessionId让med保留现有订阅?模拟连接错误的最佳方法是什么?
许多问题:-)
我在其中创建包含一些MonitoredItems和MonitoredItem_Notification事件方法的订阅的代码示例。
外面有OPC UA大师吗?
if (node.Displayname == "node to monitor")
{
MonitoredItem mon = CreateMonitoredItem((NodeId)node.reference.NodeId, node.Displayname);
m_subscription.AddItem(mon);
m_subscription.ApplyChanges();
}
private MonitoredItem CreateMonitoredItem(NodeId nodeId, string displayName)
{
if (m_subscription == null)
{
m_subscription = new Subscription(m_session.DefaultSubscription);
m_subscription.PublishingEnabled = true;
m_subscription.PublishingInterval = 3000;//1000;
m_subscription.KeepAliveCount = 10;
m_subscription.LifetimeCount = 10;
m_subscription.MaxNotificationsPerPublish = 1000;
m_subscription.Priority = 100;
bool cache = m_subscription.DisableMonitoredItemCache;
m_session.AddSubscription(m_subscription);
m_subscription.Create();
}
// add the new monitored item.
MonitoredItem monitoredItem = new MonitoredItem(m_subscription.DefaultItem);
//Each time a monitored item is sampled, the server evaluates the sample using a filter defined for each monitoreditem.
//The server uses the filter to determine if the sample should be reported. The type of filter is dependent on the type of item.
//DataChangeFilter for Variable, Eventfilter when monitoring Events. etc
//MonitoringFilter f = new MonitoringFilter();
//DataChangeFilter f = new DataChangeFilter();
//f.DeadbandValue
monitoredItem.StartNodeId = nodeId;
monitoredItem.AttributeId = Attributes.Value;
monitoredItem.DisplayName = displayName;
//Disabled, Sampling, (Report (includes sampling))
monitoredItem.MonitoringMode = MonitoringMode.Reporting;
//How often the Client wish to check for new values on the server. Must be 0 if item is an event.
//If a negative number the SamplingInterval is set equal to the PublishingInterval (inherited)
//The Subscriptions KeepAliveCount should always be longer than the SamplingInterval/PublishingInterval
monitoredItem.SamplingInterval = 500;
//Number of samples stored on the server between each reporting
monitoredItem.QueueSize = 100;
monitoredItem.DiscardOldest = true;//Discard oldest values when full
monitoredItem.CacheQueueSize = 100;
monitoredItem.Notification += m_MonitoredItem_Notification;
if (ServiceResult.IsBad(monitoredItem.Status.Error))
{
return null;
}
return monitoredItem;
}
private void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MonitoredItemNotificationEventHandler(MonitoredItem_Notification), monitoredItem, e);
return;
}
try
{
if (m_session == null)
{
return;
}
MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
if (notification == null)
{
return;
}
string sess = m_session.SessionId.Identifier.ToString();
string s = string.Format(" MonitoredItem: {0}\t Value: {1}\t Status: {2}\t SourceTimeStamp: {3}", monitoredItem.DisplayName, (notification.Value.WrappedValue.ToString().Length == 1) ? notification.Value.WrappedValue.ToString() : notification.Value.WrappedValue.ToString(), notification.Value.StatusCode.ToString(), notification.Value.SourceTimestamp.ToLocalTime().ToString("HH:mm:ss.fff"));
richTextBox1.AppendText(s + "SessionId: " + sess);
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}e here
答案 0 :(得分:0)
我不知道您使用的SDK能为您提供多少,但是重新连接的方法通常是:
尝试恢复(重新激活)您的旧会话。如果成功完成,则您的订阅将已经存在,您需要做的就是发送更多的PublishRequests。由于您尝试通过关闭会话进行测试,因此这可能无法正常工作。
创建一个新会话,然后调用TransferSubscription服务将以前的订阅转移到您的新会话中。然后,您可以开始发送PublishRequests,您将获得排队的通知。
同样,根据您使用的堆栈/ SDK /工具包的不同,可能不会为您处理其中的某些情况。