Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to implement a method to a node that load from a xml nodeset file #2918

Open
1 of 5 tasks
xky0007 opened this issue Dec 30, 2024 · 3 comments
Open
1 of 5 tasks

How to implement a method to a node that load from a xml nodeset file #2918

xky0007 opened this issue Dec 30, 2024 · 3 comments

Comments

@xky0007
Copy link
Contributor

xky0007 commented Dec 30, 2024

Type of issue

  • Bug
  • Enhancement
  • Compliance
  • Question
  • Help wanted

Current Behavior

How to implement a method to a node that load from a xml nodeset file?
I know the nsu and id for the method node. How to bind it to C# method?

Thanks.

Expected Behavior

No response

Steps To Reproduce

No response

Environment

No response

Anything else?

No response

@romanett
Copy link
Contributor

romanett commented Jan 5, 2025

@xky0007
To allow you to implement methods the best procedure is to generate the needed boilerplate code using the OPC Foundation Model Compiler:

https://github.com/OPCFoundation/UA-ModelCompiler

Afterwards you could override the LoadPredefined Nodes method to load the generated nodes:

protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context)

Now you override the AddBehaviourToPredefined Nodes method to link you implementation:

protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context, NodeState predefinedNode)

Hope this helps.

@xky0007
Copy link
Contributor Author

xky0007 commented Jan 6, 2025

@romanett Thanks. I override the AddBehaviourToPredefinedNode and try to add input args and bind to a method as follow.
But it seems the input args are not binded.
image

if(predefinedNode.DisplayName == "TestMethod2")
{
    Debug.WriteLine(predefinedNode.DisplayName);

    var node = predefinedNode as MethodState;

    node.InputArguments = new PropertyState<Argument[]>(node.Parent)
    {
        NodeId = new NodeId($"iiiii_InputArguments", 4),
        BrowseName = BrowseNames.InputArguments,
        DisplayName = new Opc.Ua.LocalizedText("Input Arguments"),
        TypeDefinitionId = VariableTypeIds.PropertyType,
        DataType = DataTypeIds.Argument,
        ValueRank = ValueRanks.OneDimension,
        Value = new Argument[]
            {
                new Argument
                {
                    Name = "Input1",
                    Description = new Opc.Ua.LocalizedText("First input parameter"),
                    DataType = DataTypeIds.String,
                    ValueRank = ValueRanks.Scalar
                },
                new Argument
                {
                    Name = "Input2",
                    Description = new Opc.Ua.LocalizedText("Second input parameter"),
                    DataType = DataTypeIds.Int32,
                    ValueRank = ValueRanks.Scalar
                }
            }
                };
    node.OnCallMethod = new GenericMethodCalledEventHandler(OnStart);


}

return base.AddBehaviourToPredefinedNode(context, predefinedNode);

@romanett
Copy link
Contributor

romanett commented Jan 7, 2025

@xky0007 if you define the method in your nodeset2 xml with input arguments then the modelCompiler will create an override for MethodState with an intialization vector that represents the arguments, therefore the client will know the input / output arguments, then you can use this code to intialize:

MethodState passiveMethod = predefinedNode as MethodState;
if (passiveMethod == null)
{
    return predefinedNode;
}

if (passiveMethod.NodeId == MethodIds.TestMethod2)
{
    TestMethod2MethodState activeNode = new TestMethod2MethodState (passiveMethod.Parent);
    activeNode.Create(context, passiveMethod);

    // replace the node in the parent.
    if (passiveMethod.Parent != null)
    {
        passiveMethod.Parent.ReplaceChild(context, activeNode);
    }

    activeNode.OnCall = OnTestMethod2Call;

    return activeNode;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants