11

I am working on OPCUA in python. I am using freeopc. I have used their server_minimal & client_minimal example and it is running fine. I am having some issues understanding the code. As far as I know the OPCUA stack, it has address space which is like a collection of all the nodes. These nodes then further contains objects and these objects have variable from where we can read write data. Please correct me if I am wrong.

---------------------------------
         Address space
---------------------------------
   |                    |
   |                    |
   V                    V
  Node1               Node2
   |
   Object1
    |
    Var1, Var2

So on the server side I want to know what is namespace

# setup our own namespace, not really necessary but should as spec
uri = "http://examples.freeopcua.github.io"
idx = server.register_namespace(uri)

What is the namespace used for.? What to put inside uri.?

On client side, I want to know:

After connecting to server, we are doing:

    # Client has a few methods to get proxy to UA nodes that should always be in address space such as Root or Objects
    root = client.get_root_node()
    print("Objects node is: ", root)

What does get_root_node() means. Is it like we are connecting to address space of server where all the nodes are defined.?

    # Node objects have methods to read and write node attributes as well as browse or populate address space
    print("Children of root are: ", root.get_children())

root.get_children()-- Does this means getting the objects of the nodes.?

    # Now getting a variable node using its browse path
    myvar = root.get_child(["0:Objects", "2:MyObject", "2:MyVariable"])
    obj = root.get_child(["0:Objects", "2:MyObject"])

root.get_child what does it means.?

Client output:

 ('Objects node is: ', Node(TwoByteNodeId(i=84)))
 ('Children of root are: ', [Node(NumericNodeId(i=85)), Node(NumericNodeId(i=86)), Node(NumericNodeId(i=87))])

Above code is taken from server_minimal.py client_minimal.py

Can anyone please explain these. I tried reading their docs but this is not mentioned there.

Thanks.

S Andrew
  • 5,592
  • 27
  • 115
  • 237

2 Answers2

9

I'm working with freeopcua too and on some questions I think I have an answer

root = client.get_root_node()

will get you the node of the root of your server so basically 'adress space' in your diagram.

root.get_children()

will return a list of all nodes that are direct children of the root so in the example of your tree. [node1, node2]. However add the root node this is 0:Objects, 0:Types, 0:Views

To see the tree of the server you can best use the opcua-client this is a GUI that will allow you to see the tree.

to do this start your server and then in your terminal typ;

 $ opcua-client

(when on linux)

You can add limitation to get children e.g.:

        objects = root.get_children(refs=ua.ObjectIds.HasChild, nodeclassmask=ua.NodeClass.Object)

This will only return other objects not methods or properties of your node.

The output you get is because Node doesn't have a real 'ToString()' the i is the id of the node (can also be seen with the GUI client).

the

Node.getChild(NodeId)

will return a node object if you're certain you added a value you can get it,s value by calling .get_value() on the return of this. NodeId is the specification of what child you want. So say you want var1 this would be

# First the code needed to add the node
node1 = root.add_object(2, "Node1") # root is the root node which can be obtained by either client.get_root_node or server.get_root_node
object1 = node1.add_object(3, "Object1")
object1.add_variable(4, "Var1", 42)
object1.add_variable(4, "Var2", 13)
# Now the code to ask the server for the node
var1_node = root.getChild(["2:Node1", "3:Object1", "4:Var1"])

# And to get its value
var1_node.get_value()

Important here is that to get a child you need to know where you are (you can get children from any Node object not only root) and then go down with a combination of "idx:Name" which is what you add when you added the value to the server in the first place.

Hoped this helped a bit (did not test the code so it might need some adjustments to actually run)

davy gillebert
  • 307
  • 1
  • 11
  • Great. Nice information. Thanks. Only thing I need to know, what do you mean by `However add the root node this is 0:Objects, 0:Types, 0:Views`. What does objects types view means in node. Also when we do `root.get_child()` we get output with `i=84` or `i=85`. What does this i means.? Is this the NodeId. Can we access that particular node using this id.? Thanks again.! – S Andrew Aug 28 '17 at 15:20
  • That's the id they have in the entire structure. When they are stored in 0: then this will always be a single i=NodeId. when sotered in a different idx then this will be of the form ns=;i=id. If you have a nodeId you can always get the node by using this instead of the names. **EDIT:* The basic Server already has a few standard nodes no matter if you have added nodes or not you start with 3 nodes already on it being the Objects, Types and Views nodes. Which can also be accessed using server.nodes.objects As the opcua server knows which ones this will be – davy gillebert Aug 29 '17 at 06:54
  • @davygillebert Could you please get back to me? I needed to discuss something related to the OPC ua stack. – Akash Jan 15 '18 at 07:12
  • @Akash, Yes I can I am in the middle of exams at school right now but I'll help in anyway I can. – davy gillebert Jan 25 '18 at 12:42
0

To understand this better you can use, Unified Automation UA Expert as a client. https://www.unified-automation.com/downloads/opc-ua-clients.html Start the server_minimal.py, open UA Expert add server using 'Custom Discovery' with "opc.tcp://localhost:4840/freeopcua/server/". You can easily view the entire address space.

Reena
  • 1