I have a FactoryTalk server with some nodes and I need to monitor several attribute values.
I made a client which reads and writes data succesfully, but I can't get the subscription to work.
Here's the subscription configuration:
subscription = new Subscription(session.DefaultSubscription)
{
DisplayName = "Test subscription",
PublishingEnabled = true,
PublishingInterval = 500,
LifetimeCount = 0,
};
My monitored items:
monitoredItems = nodeAttrs
.Select(nodeId => new MonitoredItem(subscription.DefaultItem)
{
StartNodeId = nodeId,
AttributeId = Attributes.Value,
QueueSize = 1,
SamplingInterval = 500,
MonitoringMode = MonitoringMode.Reporting,
})
.ToList();
And I assign them the notification handler (I need the protocol object instance here, so I tweaked it):
MonitoredItemNotificationEventHandler monitoredItemEventHandler = (monitoredItem, e) => AttributeNotification(monitoredItem, e, protocol);
Then I add the event handlers:
foreach (var monitoredItem in monitoredItems)
{
monitoredItem.Notification += monitoredItemEventHandler;
}
And I add the items to the subscription and create it:
subscription.AddItems(monitoredItems);
session.AddSubscription(subscription);
subscription.Create();
I've checked through the console and the subscription gets created and assigned an ID by the server. I check all the monitored items as well, CreateMonitoredItems
service call succeeds, and they also get client handles assigned, NodeId
's are correctly resolved, with no error StatusCode
s.
I make changes to the attributes via a 3rd party client application called UaExpert.
Yet I can't get the notification event handler to fire off.
Did I do something wrong? Does anyone have advice on how to resolve/debug this?
Today I struggled at the same point. The documentation of the UA-.NETStandard is not, what it should be. After all I found the clue in this example: https://github.com/OPCFoundation/UA-.NETStandard/blob/54f7f8aa9b2e07531f73dadd6e4bd933566302ee/Applications/ConsoleReferenceClient/UAClient.cs#L387
To Add a monitoredItem with Notification to an OPCUA Subscription in .NET try the following code.
Add monitored Item
/**
* Add monitored items to Subscription
*/
public void AddMonitoredItemGroup(List<clsOPCUAElement> nodesToMonitor)
{
try
{
if(this.Subscription == null) throw new Exception("No subscription present!");
if (nodesToMonitor.Count == 0) throw new Exception("No items to monitor!");
foreach (clsOPCUAElement element in nodesToMonitor)
{
//Configure MonitoredItem
MonitoredItem m = new MonitoredItem(this.Subscription.DefaultItem);
m.StartNodeId = element.NodeID;
m.AttributeId = Attributes.Value;
m.DiscardOldest = true;
m.MonitoringMode = MonitoringMode.Reporting;
m.QueueSize = 0;
m.SamplingInterval = 200;
//Add eventhandler
m.Notification += this.MonitoredItemHandler;
//Add to subscription
this.Subscription.AddItem(m);
}
//This is essential!
this.Subscription.ApplyChanges();
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.ToString());
}
}
MonitoredItemHandler - picks up the notification, serialize it to clsOPCUAElement and fire a new Event, wich can be subscribed from other objects
public virtual void MonitoredItemHandler(MonitoredItem item, MonitoredItemNotificationEventArgs args)
{
try
{
Console.WriteLine("MonitoredItemHandler: " + item.StartNodeId.ToString());
OnMonitoredItemChanged?.Invoke(new clsOPCUAElement(item.StartNodeId.ToString(), item.LastValue, item.LastValue.GetType()));
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.ToString());
}
}
clsOPCUAElement (it's just a container, we deserialize the elements from a json structure containing the whole variable tree)
public class clsOPCUAElement
{
/**
*
*/
public clsOPCUAElement(String _NodeID, Object _Value = default, Type _Type = default)
{
if (_NodeID.Length == 0) throw new ArgumentException("NodeID mustn't be empty!");
this.NodeID = _NodeID;
this.Value = _Value;
this.Type = _Type;
}
public String NodeID;
public Object Value;
public Type Type;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With