Skip to content

Instantly share code, notes, and snippets.

@kevinherron
Created October 5, 2023 19:12
Show Gist options
  • Save kevinherron/75ebdca52bbaf4fc433c0886c00208bc to your computer and use it in GitHub Desktop.
Save kevinherron/75ebdca52bbaf4fc433c0886c00208bc to your computer and use it in GitHub Desktop.
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.NodeIds;
import org.eclipse.milo.opcua.stack.core.UaException;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseDirection;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseResultMask;
import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseResult;
import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
class Scratch {
public static void main(String[] args) throws UaException {
var client = OpcUaClient.create("opc.tcp://localhost:4840");
client.connect();
BrowseResult result = client.browse(new BrowseDescription(
NodeIds.Server_ServerStatus,
BrowseDirection.Forward,
NodeIds.HasTypeDefinition,
false,
uint(NodeClass.ObjectType.getValue() | NodeClass.VariableType.getValue()),
uint(BrowseResultMask.All.getValue())
));
System.out.println("Browse returned " + result.getReferences().length + " references");
}
}
@impet14
Copy link

impet14 commented Oct 18, 2023

Thanks for sharing code.

may I know the version of milo for this code?

@kevinherron
Copy link
Author

This was written against the dev/1.0 branch. How did you find this?

@impet14
Copy link

impet14 commented Oct 18, 2023

I release this issue with the team. I am working with freeopcua

@impet14
Copy link

impet14 commented Oct 18, 2023

So I have to build milo with this code since in maven has only 0.6.11 latest.

@kevinherron
Copy link
Author

Here is a variation that will compile and run with 0.6.11:

import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.Identifiers;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseDirection;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseResultMask;
import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseResult;

import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;

class Scratch {
    public static void main(String[] args) throws Exception {
        var client = OpcUaClient.create("opc.tcp://localhost:4840");
        client.connect().get();

        BrowseResult result = client.browse(new BrowseDescription(
            Identifiers.Server_ServerStatus,
            BrowseDirection.Forward,
            Identifiers.HasTypeDefinition,
            false,
            uint(NodeClass.ObjectType.getValue() | NodeClass.VariableType.getValue()),
            uint(BrowseResultMask.All.getValue())
        )).get();

        System.out.println("Browse returned " + result.getReferences().length + " references");
    }
}

@impet14
Copy link

impet14 commented Oct 19, 2023

Thank you so much for you help.
I appreciate your time.

I tested among freeopcua/open62541/milo devices using this code.
I got 0 reference from freeopcua device but open62541 and milo device are read correctly

Result of freeopcua device.
[main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Java version: 11.0.20.1
[main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Eclipse Milo OPC UA Stack version: 0.6.11
[main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Eclipse Milo OPC UA Client SDK version: 0.6.11
[milo-nonce-util-secure-random] INFO org.eclipse.milo.opcua.stack.core.util.NonceUtil - SecureRandom seeded in 0ms.
freeopc Browse returned 0 references
BrowseResult(statusCode=StatusCode{name=Good, value=0x00000000, quality=good}, continuationPoint=ByteString{bytes=null}, references=[])

Result of milo device.
[main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Java version: 11.0.20.1
[main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Eclipse Milo OPC UA Stack version: 0.6.11
[main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Eclipse Milo OPC UA Client SDK version: 0.6.11
[milo-nonce-util-secure-random] INFO org.eclipse.milo.opcua.stack.core.util.NonceUtil - SecureRandom seeded in 0ms.
milo Browse returned 1 references
BrowseResult(statusCode=StatusCode{name=Good, value=0x00000000, quality=good}, continuationPoint=ByteString{bytes=null}, references=[ReferenceDescription(referenceTypeId=NodeId{ns=0, id=40}, isForward=true, nodeId=ExpandedNodeId{ns=0, id=2138, serverIndex=0}, browseName=QualifiedName{name=ServerStatusType, namespaceIndex=0}, displayName=LocalizedText{text=ServerStatusType, locale=en}, nodeClass=VariableType, typeDefinition=ExpandedNodeId{ns=0, id=0, serverIndex=0})])

Result of open62541 device.
[main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Java version: 11.0.20.1
[main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Eclipse Milo OPC UA Stack version: 0.6.11
[main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Eclipse Milo OPC UA Client SDK version: 0.6.11
[milo-nonce-util-secure-random] INFO org.eclipse.milo.opcua.stack.core.util.NonceUtil - SecureRandom seeded in 2ms.
open62541 Browse returned 1 references
BrowseResult(statusCode=StatusCode{name=Good, value=0x00000000, quality=good}, continuationPoint=ByteString{bytes=null}, references=[ReferenceDescription(referenceTypeId=NodeId{ns=0, id=40}, isForward=true, nodeId=ExpandedNodeId{ns=0, id=2138, serverIndex=0}, browseName=QualifiedName{name=ServerStatusType, namespaceIndex=0}, displayName=LocalizedText{text=ServerStatusType, locale=}, nodeClass=VariableType, typeDefinition=ExpandedNodeId{ns=0, id=0, serverIndex=0})])

I notice something when I use freeopcua to browse the ServerStatus Node 2256. I could read all from freeopcua/milo/open62541 devices.
but it seem the node type is difference. from freeopcua result is NumericNodeId but from milo/open62541 is FourByteNodeId
result of freeopcua device
Node: Node(NumericNodeId(i=2257))
Node id: NumericNodeId(i=2257)
Browse name: QualifiedName(0:StartTime)
Display name: LocalizedText(Encoding:2, Locale:None, Text:StartTime)
Description: LocalizedText(Encoding:0, Locale:None, Text:None)
Value: 2023-10-17 03:10:06.778950

result of milo device
Requested session timeout to be 3600000ms, got 120000ms instead
Node: Node(FourByteNodeId(i=2257))
Node id: FourByteNodeId(i=2257)
Browse name: QualifiedName(0:StartTime)
Display name: LocalizedText(Encoding:3, Locale:en, Text:StartTime)
Description: LocalizedText(Encoding:0, Locale:None, Text:None)
Value: 2023-10-19 02:29:48.174000

result of open62541 device
Node: Node(FourByteNodeId(i=2257))
Node id: FourByteNodeId(i=2257)
Browse name: QualifiedName(0:StartTime)
Display name: LocalizedText(Encoding:3, Locale:, Text:StartTime)
Description: LocalizedText(Encoding:0, Locale:None, Text:None)
Value: 1970-01-01 00:00:00.255000

Do you have any Idea please?

Thank you.
I appreciate your help.

@kevinherron
Copy link
Author

This seems to be an implementation detail leaked by freeopcua about how the NodeId was encoded or decoded at the binary encoding level.

i=2257 can be encoded in the compact 4-byte encoding described here. Maybe the freeopcua server is not using this compact encoding, but rather, the standard encoding.

I don't think this should matter except that it's less efficient.

@impet14
Copy link

impet14 commented Oct 24, 2023

Now, with the contribution from freeopcua developer. he has suggested >>

BrowseResult result = client.browse(new BrowseDescription(
            Identifiers.Server_ServerStatus,
            BrowseDirection.Forward,
            Identifiers.HasComponent,
            false,
            uint(NodeClass.Object.getValue() | NodeClass.Variable.getValue()),
            uint(BrowseResultMask.All.getValue())
        )).get();

System.out.println("freeopcua Browse returned " + result.getReferences().length + " references\r\n" + result.toString());

result :
freeopc Browse returned 6 references
BrowseResult(statusCode=StatusCode{name=Good, value=0x00000000, quality=good}, continuationPoint=ByteString{bytes=null}, references=[ReferenceDescription(referenceTypeId=NodeId{ns=0, id=47}, isForward=true, nodeId=ExpandedNodeId{ns=0, id=2257, serverIndex=0}, browseName=QualifiedName{name=StartTime, namespaceIndex=0}, displayName=LocalizedText{text=StartTime, locale=null}, nodeClass=Variable, typeDefinition=ExpandedNodeId{ns=0, id=63, serverIndex=0}), ReferenceDescription(referenceTypeId=NodeId{ns=0, id=47}, isForward=true, nodeId=ExpandedNodeId{ns=0, id=2258, serverIndex=0}, browseName=QualifiedName{name=CurrentTime, namespaceIndex=0}, displayName=LocalizedText{text=CurrentTime, locale=null}, nodeClass=Variable, typeDefinition=ExpandedNodeId{ns=0, id=63, serverIndex=0}), ReferenceDescription(referenceTypeId=NodeId{ns=0, id=47}, isForward=true, nodeId=ExpandedNodeId{ns=0, id=2259, serverIndex=0}, browseName=QualifiedName{name=State, namespaceIndex=0}, displayName=LocalizedText{text=State, locale=null}, nodeClass=Variable, typeDefinition=ExpandedNodeId{ns=0, id=63, serverIndex=0}), ReferenceDescription(referenceTypeId=NodeId{ns=0, id=47}, isForward=true, nodeId=ExpandedNodeId{ns=0, id=2260, serverIndex=0}, browseName=QualifiedName{name=BuildInfo, namespaceIndex=0}, displayName=LocalizedText{text=BuildInfo, locale=null}, nodeClass=Variable, typeDefinition=ExpandedNodeId{ns=0, id=3051, serverIndex=0}), ReferenceDescription(referenceTypeId=NodeId{ns=0, id=47}, isForward=true, nodeId=ExpandedNodeId{ns=0, id=2992, serverIndex=0}, browseName=QualifiedName{name=SecondsTillShutdown, namespaceIndex=0}, displayName=LocalizedText{text=SecondsTillShutdown, locale=null}, nodeClass=Variable, typeDefinition=ExpandedNodeId{ns=0, id=63, serverIndex=0}), ReferenceDescription(referenceTypeId=NodeId{ns=0, id=47}, isForward=true, nodeId=ExpandedNodeId{ns=0, id=2993, serverIndex=0}, browseName=QualifiedName{name=ShutdownReason, namespaceIndex=0}, displayName=LocalizedText{text=ShutdownReason, locale=null}, nodeClass=Variable, typeDefinition=ExpandedNodeId{ns=0, id=63, serverIndex=0})])

now we can read the reference but got 6 references from freeopcua server. do you have any idea please?

@kevinherron
Copy link
Author

You changed the requested reference type from HasTypeDefinition to HasComponent. This is asking for a different set of references.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment