.NET Based OPC UA Client/Server SDK  3.1.0.500
ModelChangeEvent Example

ModelChange events can be fired by the server if nodes or references are added or deleted during runtime. A client that subscribes to ModelChanegEvents is able to detect these changes to the information model. E.g. UaExpert can refresh the information model tree view automatically so that the user doesn’t need to call rebrowse manually.

The folder 008_DynamicNodes in the address space contains a property called NodeVersion. The OPC UA Specification defines that such a property is required if ModelChangeEvents are being fired for a node. In the following example, a node will be added to the folder 008_DynamicNodes, resulting in a ModelChangeEvent being fired. Thus, it is necessary to add a NodeVersion property to the folder. In our example, the property is already part of the address space imported from the XML file.

The OPC UA specification defines the method CreateDynamicNode. The .NET implementation is the method DoCreateDynamicNode which can be found in the file DemoNodeManager.Methods.cs. The following code snippet shows how to add the node.

string name = "DynamicNode";
CreateVariableSettings settings = new CreateVariableSettings()
{
ParentNodeId = new NodeId("Demo.DynamicNodes", DefaultNamespaceIndex),
ReferenceTypeId = ReferenceTypeIds.HasComponent,
RequestedNodeId = new NodeId("Demo.DynamicNodes." + name, DefaultNamespaceIndex),
BrowseName = new QualifiedName(name, DefaultNamespaceIndex),
DisplayName = name,
AccessLevel = AccessLevels.CurrentReadOrWrite,
DataType = DataTypeIds.UInt32,
ValueRank = ValueRanks.Scalar,
Historizing = false,
TypeDefinitionId = VariableTypeIds.BaseDataVariableType
};
VariableNode parentNode = CreateVariable(Server.DefaultRequestContext, settings);

In this example, the ModelChangeEvent is not fired directly from the method which creates the dynamic node. Instead the method AfterAddReference (which can be found in the file DemoNodeManager.cs) is used, which is called by the SDK after a reference has been added. The UpdateNodeVersion method tries to update the NodeVersion property and to fire the event.

First, the method checks the UserData wheter node versioning is supported.

NodeWithVersioning data = node.UserData as NodeWithVersioning;
if (data == null)
{
return false;
}

If so, the node version is updated.

lock (m_datasources)
{
DataVariableDataSource datasource = data.Source;
int version = datasource.Value.ToInt32();
version++;
datasource.Value = version.ToString();
ReportChange(context, datasource, 0);
}

Finally, the event is fired.

GenericEvent e = new GenericEvent(Server.FilterManager);
e.Initialize(
null,
ObjectTypeIds.GeneralModelChangeEventType,
ObjectIds.Server,
BrowseNames.Server,
"The address space has changed.");
ModelChangeStructureDataType[] changes = new ModelChangeStructureDataType[1];
changes[0] = new ModelChangeStructureDataType();
changes[0].Affected = node.NodeId;
changes[0].AffectedType = (instance != null) ? instance.TypeDefinitionId : null;
changes[0].Verb = (byte)verb;
e.Set(BrowseNames.Changes, new Variant(changes));
// report the event.
Server.ReportEvent(e);