Dynamic NodeSet updating without server restart

Questions regarding the use of the .NET SDK 2.0 for Server or Client development or integration into customer products ...

Moderator: uasdknet

Post Reply
Matchless6846
Jr. Member
Jr. Member
Posts: 1
Joined: 09 Jul 2024, 02:44

Dynamic NodeSet updating without server restart

Post by Matchless6846 »

I'm currently developing an OPC UA server that requires to dynamically load a NodeSet XML file (exported from the client side), and update its information model when the XML file changes. Since the structure of the model cannot be pre-defined, I tried to use ImportUaNodeset to load the model during startup:

Code: Select all

internal class TestServerManager : ServerManager
{
    protected override void OnRootNodeManagerStarted(RootNodeManager nodeManager)
    {
        BaseNodeManager nm = new TestNodeManager(this);
        nm.Startup();
    }
}

internal partial class TestNodeManager : BaseNodeManager
{
    public override void Startup()
    {
        ImportUaNodeset(new FileInfo(GetNodeSetPath()));
    }
}
And if there is xml file change event, a server restart is triggered

Code: Select all

serverManager.Stop();
serverManager.Start();
However, this approach causes a short disconnection for the client.

I tried directly deleting the root node, reloading the model and notifying the client about the change. But although the client received the notification of the change, the NodeSet did not update. The code is as follows:

Code: Select all

public void ImportUaNodesetAndNotify(FileInfo istrm)
{
    ClearAllNodes();
    ImportUaNodeset(istrm);
    ReportModelChangeEvent();
}

private void ClearAllNodes()
{
    // delete root node
    NodeId rootFolderId = UnifiedAutomation.UaBase.ObjectIds.RootFolder;
    DeleteNode(Server.DefaultRequestContext, rootFolderId, true);
}

private void ReportModelChangeEvent()
{
    // Create a ModelChange event
    var modelChangeEvent = new GenericEvent(Server.FilterManager);
    modelChangeEvent.Initialize(
        eventId: null,
        eventType: UnifiedAutomation.UaBase.ObjectTypeIds.GeneralModelChangeEventType,
        sourceNode: UnifiedAutomation.UaBase.ObjectIds.Server,
        sourceName: "Server",
        severity: EventSeverity.Low,
        message: new LocalizedText("The address space has changed.")
    );
    var changes = new List<ModelChangeStructureDataType>
    {
        new ModelChangeStructureDataType
        {
            Affected = UnifiedAutomation.UaBase.ObjectIds.Server,
            AffectedType = UnifiedAutomation.UaBase.ObjectTypeIds.BaseObjectType
        }
    };
    Server.ReportEvent(UnifiedAutomation.UaBase.ObjectIds.Server, modelChangeEvent);
}
Could you please guide my the correct way of doing this?

User avatar
Support Team
Hero Member
Hero Member
Posts: 3137
Joined: 18 Mar 2011, 15:09

Re: Dynamic NodeSet updating without server restart

Post by Support Team »

Hi,

the problem with exchanging the Nodeset file is not that you need to remove all nodes from that namespace, but that you also need to remove all references to its nodes from other namespaces. For example any type that is defined in that nodeset, be it DataType or ObjectType, could be used by another namespace. If a Variable is referencing a non-existing DataType or has no data type at all, you end up with a corrupted address space.
We recently had a similar discussion here: https://forum.unified-automation.com/viewtopic.php?f=38&t=8297

So indeed the best option is stop and restart the server. This gives the client the opportunity to react to those (possibly fundamental) changes. If you want to prevent the restart, you have to make the changes more granular, but the nodeset file format is not made for this, especially since type information can change.

A word or two about your previous attempts:
1. It is NOT allowed to remove a mandatory node (the RootFolder) in particular from Namespace 0.
2. If a server implements the GeneralModelChangeEvent it also MUST implement the NodeVersion node.
3. The ModelChangeStructureDataType.Affected field should be either the parent NodeId with the Verb ReferenceDeleted or the NodeId of the removed node with the verb NodeDeleted. Usually you list both model changes. Obviously, the RootFolder does not have a parent.
Best regards
Unified Automation Support Team

Post Reply