Skip to content

Commit

Permalink
make get_child use realtive path from spec as default, update examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Olivier authored and oroulet committed Dec 20, 2023
1 parent d9d360e commit 0ae1cec
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 20 deletions.
26 changes: 16 additions & 10 deletions asyncua/common/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,14 +574,17 @@ async def get_child(
"""
get a child specified by its path from this node.
A path might be:
* a string representing a qualified name.
* a string representing a relative path as per UA spec
* a qualified name
* a list of string
* a list of string representing browsenames (legacy)
* a list of qualified names
"""
if isinstance(path, (ua.QualifiedName, str)):
path = [path]
rpath = self._make_relative_path(path)
if isinstance(path, str):
rpath = ua.RelativePath.from_string(path)
else:
if isinstance(path, ua.QualifiedName):
path = [path]
rpath = self._make_relative_path(path)
bpath = ua.BrowsePath()
bpath.StartingNode = self.nodeid
bpath.RelativePath = rpath
Expand All @@ -600,16 +603,19 @@ async def get_children_by_path(
"""
get children specified by their paths from this node.
A path might be:
* a string representing a qualified name.
* a string representing a relative path as per UA spec
* a qualified name
* a list of string
* a list of string representing browsenames (legacy)
* a list of qualified names
"""
bpaths: List[ua.BrowsePath] = []
for path in paths:
if isinstance(path, (ua.QualifiedName, str)):
path = [path]
rpath = self._make_relative_path(path)
if isinstance(path, str):
rpath = ua.RelativePath.from_string(path)
else:
if isinstance(path, (ua.QualifiedName, str)):
path = [path]
rpath = self._make_relative_path(path)
bpath = ua.BrowsePath()
bpath.StartingNode = self.nodeid
bpath.RelativePath = rpath
Expand Down
4 changes: 2 additions & 2 deletions examples/client-example.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ async def main():
#await var.write_value(3.9) # set node value using implicit data type

# Now getting a variable node using its browse path
myvar = await client.nodes.root.get_child(["0:Objects", "2:MyObject", "2:MyVariable"])
obj = await client.nodes.root.get_child(["0:Objects", "2:MyObject"])
myvar = await client.nodes.root.get_child("/Objects/2:MyObject/2:MyVariable")
obj = await client.nodes.root.get_child("Objects/2:MyObject")
_logger.info("myvar is: %r", myvar)

# subscribing to a variable node
Expand Down
2 changes: 1 addition & 1 deletion examples/client-minimal.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ async def main():

# Get the variable node for read / write
var = await client.nodes.root.get_child(
["0:Objects", f"{nsidx}:MyObject", f"{nsidx}:MyVariable"]
f"0:Objects/{nsidx}:MyObject/{nsidx}:MyVariable"
)
value = await var.read_value()
print(f"Value of MyVariable ({var}): {value}")
Expand Down
2 changes: 1 addition & 1 deletion examples/client-subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async def main():
client = Client(url='opc.tcp://localhost:4840/freeopcua/server/')
async with client:
idx = await client.get_namespace_index(uri="http://examples.freeopcua.github.io")
var = await client.nodes.objects.get_child([f"{idx}:MyObject", f"{idx}:MyVariable"])
var = await client.nodes.objects.get_child(f"{idx}:MyObject/{idx}:MyVariable")
handler = SubscriptionHandler()
# We create a Client Subscription.
subscription = await client.create_subscription(500, handler)
Expand Down
12 changes: 6 additions & 6 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,16 +442,16 @@ async def test_browse_references(opc):

async def test_browsename_with_spaces(opc):
o = opc.opc.nodes.objects
v = await o.add_variable(3, "BNVariable with spaces and %&+?/", 1.3)
v2 = await o.get_child("3:BNVariable with spaces and %&+?/")
v = await o.add_variable(3, "BNVariable with spaces and %+?", 1.3)
v2 = await o.get_child("/3:BNVariable with spaces and %+?")
assert v == v2
await opc.opc.delete_nodes([v])


async def test_non_existing_path(opc):
root = opc.opc.nodes.root
with pytest.raises(ua.UaStatusCodeError):
await root.get_child(["0:Objects", "0:Server", "0:nonexistingnode"])
await root.get_child("0:Objects/0:Server/0:nonexistingnode")


async def test_bad_attribute(opc):
Expand All @@ -463,7 +463,7 @@ async def test_bad_attribute(opc):
async def test_get_node_by_nodeid(opc):
root = opc.opc.nodes.root
server_time_node = await root.get_child(
["0:Objects", "0:Server", "0:ServerStatus", "0:CurrentTime"]
"/Objects/Server/ServerStatus.CurrentTime"
)
correct = opc.opc.get_node(ua.NodeId(ua.ObjectIds.Server_ServerStatus_CurrentTime))
assert server_time_node == correct
Expand Down Expand Up @@ -657,13 +657,13 @@ async def test_same_browse_name(opc):
o2 = await f.add_object("ns=2;i=204;", "2:MyBName")
v2 = await o2.add_variable("ns=2;i=205;", "2:MyBNameTarget", 2.0)
nodes = await objects.get_child(
["2:MyBNameFolder", "2:MyBName", "2:MyBNameTarget"], return_all=True
"/2:MyBNameFolder/2:MyBName/2:MyBNameTarget", return_all=True
)
assert len(nodes) == 2
assert nodes[0] == v
assert nodes[1] == v2
[nodes] = await objects.get_children_by_path(
[["2:MyBNameFolder", "2:MyBName", "2:MyBNameTarget"]]
["/2:MyBNameFolder/2:MyBName/2:MyBNameTarget"]
)
assert len(nodes) == 2
assert nodes[0] == v
Expand Down

0 comments on commit 0ae1cec

Please sign in to comment.