united-manufacturing-hub / benthos-umh

Apache License 2.0
29 stars 9 forks source link

Using Expanded-NodeId-Strings rather then regular NodeId-String in configuration #5

Open AndreasHeine opened 1 year ago

AndreasHeine commented 1 year ago

Example:

NodeId -> ns=2;s=IoTSensors Expanded-NodeId -> nsu=http://myIoTSensorNamspace/UA;s=IoTSensors

In scenarios in which changes happen on the shopfloor (OPC UA Server) there is the chance that the NamespaceIndex changes and your configuration will be broken.

Using the NamespaceIndex in a configuration is not a good practice, you should consider switch to the Expanded-NodeId format which uses the NamespaceUri instead of the index. In order to leverage the benefits of the expanded format the OPC UA Client needs to:

  1. Connect
  2. read the NamespaceArray
  3. convert the Expanded-NodeIds once to the correct Index (verification that, i am on the correct server with the correct namespaces, which i would expect)
  4. continue with reading/subscribing/...

this would lead to a much more robust behavior of the OPC UA Client. And if something changes e.g. someone imports a UA-Model or a CS your config will still be valid. This is a issue most commercial products get wrong in implementation!

devantler commented 11 months ago

I have a need for this as well. I tried implementing a PR earlier but got stuck when I discovered I had to include the NamespaceArray in the ParseExpandedNodeIds function call.

func ParseNodeIDs(incomingNodes []string) []*ua.ExpandedNodeID {

    // Parse all nodeIDs to validate them.
    // loop through all nodeIDs, parse them and put them into a slice
    parsedNodeIDs := make([]*ua.ExpandedNodeID, len(incomingNodes))
    // Get NamespaceArray from the server
    // How do I do this?
    namespaceArray := []string{"http://opcfoundation.org/UA/"}

    for _, id := range incomingNodes {
        parsedNodeID, err := ua.ParseExpandedNodeID(id, namespaceArray)
        if err != nil {
            return nil
        }

        parsedNodeIDs = append(parsedNodeIDs, parsedNodeID)
    }

    return parsedNodeIDs
}

Do you have any suggestions on how to get the namespace array from the server?

Check out the draft here: #14

AndreasHeine commented 11 months ago

you need to read the value of the nodeid "i=2255" which is present in every server and then you need to resolve the namepace name with the index in the array.

devantler commented 11 months ago

Thanks, I will hopefully have time to give it a try this coming week 🙂

Edit: I am not working on this anyway https://github.com/united-manufacturing-hub/benthos-umh/pull/14#issuecomment-1814348494