Open Fliens opened 1 month ago
A way to get all paths of a node would be nice too This way you could export the paths and later on reconstruct the address space 1:1
A way to get all paths of a node would be nice too This way you could export the paths and later on reconstruct the address space 1:1
as far as i know not part of OPC UA Spec.! For TranslateBrowsePaths the client needs to know the path to the node, from which the client wants the nodeid from!
A way to get all paths of a node would be nice too This way you could export the paths and later on reconstruct the address space 1:1
as far as i know not part of OPC UA Spec.! For TranslateBrowsePaths the client needs to know the path to the node, from which the client wants the nodeid from!
Yeah that's what I want to do but the get_path
function returns a path in the case above that can't be translated to the actual node.
From my understanding the get_path
function should always return a valid path that can be translated but that does not seem to be the case.
the only difference is: "/Objects" "/0:Objects" right?
the only difference is: "/Objects" "/0:Objects" right?
No this does not affect the translate_browsepaths()
function
The node in question is referenced twice (as shown in the screenshot on the right side).
Both paths are valid by eye (when following the nodes in the browser gui) but only the first path (exported from the prosys gui) works with the translate_browsepaths()
function.
get_path just uses the first reference see: https://github.com/FreeOpcUa/opcua-asyncio/blob/1343fa761ce5b2ece79b64041463b86486b81534/asyncua/common/node.py#L538
browsename is correctly formatted: https://github.com/FreeOpcUa/opcua-asyncio/blob/1343fa761ce5b2ece79b64041463b86486b81534/asyncua/ua/uatypes.py#L679
and the relative path implementation looks right on the first look https://github.com/FreeOpcUa/opcua-asyncio/blob/master/asyncua/ua/relative_path.py https://reference.opcfoundation.org/Core/Part4/v105/docs/A.2#TableA.2
Yeah I guess so but this seems counterintuitive since I would assume that I could directly put the path from the get_path function (transformed into a valid string) into the translate_path function and would get the same node back
but both paths are valid!
but both paths are valid!
But the second one does not work.
('BadNoMatch', 'The requested operation has no match to return.')
You can run the code yourself and connect to the server yourself (via gui), the opcua server in the example is public.
I've extended the example code to include the just read path via get_path()
import asyncio
from asyncua import Client, Node, ua
from asyncua.ua.status_codes import get_name_and_doc
async def main():
url = "opc.tcp://uademo.prosysopc.com:53530/OPCUA/SimulationServer/"
async with Client(url=url) as client:
# The node these paths should lead to:
# ns=4;s=1001/0:Direction
# Working path: /Objects/3:Simulation/3:Counter/2:Signal/4:Direction
test_node: Node = client.get_node("ns=4;s=1001/0:Direction")
test_path = "/".join(
(await test_node.get_path(as_string=True))[1:]
) # 0:Objects/0:Server/2:ValueSimulations/2:Signal/4:Direction
results: ua.BrowsePathResult = await client.translate_browsepaths(
starting_node=client.nodes.root.nodeid,
relative_paths=[
"0:Objects/3:Simulation/3:Counter/2:Signal/4:Direction",
"0:Objects/0:Server/2:ValueSimulations/2:Signal/4:Direction",
test_path, # same as the one above
],
)
for x in results:
print(get_name_and_doc(x.StatusCode.value), x)
# Result:
# ('Good', 'The operation succeeded.') BrowsePathResult(StatusCode_=StatusCode(value=0), Targets=[BrowsePathTarget(TargetId=ExpandedNodeId(Identifier='1001/0:Direction', NamespaceIndex=4, NodeIdType=<NodeIdType.String: 3>, NamespaceUri=None, ServerIndex=0), RemainingPathIndex=4294967295)])
# ('BadNoMatch', 'The requested operation has no match to return.') BrowsePathResult(StatusCode_=StatusCode(value=2154758144), Targets=[])
# ('BadNoMatch', 'The requested operation has no match to return.') BrowsePathResult(StatusCode_=StatusCode(value=2154758144), Targets=[])
if __name__ == "__main__":
asyncio.run(main())
"BadNoMatch" is a response from Server! The Paths are correct and valid according to the OPC UA Spec.!
We just use the first hierarchical Reference and follow them up ("inverse" direction)... it does not matter which you chose because they point to the same NodeId/Node...
Yes I understand that the error is a response from the server. And yeah I checked with the spec, the paths are valid.
I would prefer that the get_path would return all paths but that is my issue since that functionality is not a part of the spec.
But I still don't understand why the translate_browsepaths()
function does not find a match.
The code in this comment creates a valid path that the translate service on the server somehow can't resolve.
This is a BUG REPORT for issues in the existing code.
Describe the bug
I'm using the
get_path(as_string=True)
function from the node class. The function chooses a 'wrong' path so that thetranslate_browsepaths()
function generates the status code "BadNoMatch"The Prosys Browser can also export a browse path (right click on node) which does find a match via the
translate_browsepaths()
function.The node 'exists' in both paths but only the path from prosys works.
To Reproduce
Steps to reproduce the behavior incl code:
The browse path that was exported from Prosys works:
/Objects/3:Simulation/3:Counter/2:Signal/4:Direction
Expected behavior
The function
get_path(as_string=True)
should generate a path that works with thetranslate_browsepaths()
function.Screenshots
Version
Python-Version:3.11.5
opcua-asyncio Version (e.g. master branch, 0.9):