Avatar

Please consider registering
guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed Topic RSS sp_TopicIcon
Client SDK Bug? AddressSpace.getNode() is throwing an uncatchable StatusException
June 2, 2022
12:44, EEST
Avatar
MichaelBraveDigital
Member
Members
Forum Posts: 14
Member Since:
March 10, 2016
sp_UserOfflineSmall Offline

ERROR [Client 127.0.0.1] – readReferences
com.prosysopc.ua.StatusException: Bad_NotReadable (0x803A0000) “The access level does not allow reading or subscribing to the Node.”
at com.prosysopc.ua.client.UaClient.checkOperationResult(SourceFile:6823) ~[prosys-opc-ua-sdk-client-4.8.0-25.jar:?]
at com.prosysopc.ua.client.AddressSpace.checkOperationResult(SourceFile:2177) ~[prosys-opc-ua-sdk-client-4.8.0-25.jar:?]
at com.prosysopc.ua.client.AddressSpace.browse(SourceFile:1867) ~[prosys-opc-ua-sdk-client-4.8.0-25.jar:?]
at com.prosysopc.ua.client.AddressSpace.browse(SourceFile:367) ~[prosys-opc-ua-sdk-client-4.8.0-25.jar:?]
at com.prosysopc.ua.client.AddressSpace.readReferences(SourceFile:1404) [prosys-opc-ua-sdk-client-4.8.0-25.jar:?]
at com.prosysopc.ua.client.AddressSpace.getNode(SourceFile:977) [prosys-opc-ua-sdk-client-4.8.0-25.jar:?]

The following error is being thrown when I am attempting to get the data type of a node. Specifically when I try to execute getNode() on a writable node on the PLC. The return value of getNode() is 100% correct and the exception above does not affect the program. I use getNode() just to determine the node’s datatype before writing:

UaNode node = client.getAddressSpace().getNode(nid);

// Find the DataType
UaDataType dataType = null;
if (node instanceof UaVariable)
{
UaVariable v = (UaVariable) node;

// Initialize DataType node, if it is not initialized yet
if (v.getDataType() == null) v.setDataType(client.getAddressSpace().getDataType(v.getDataTypeId()));

dataType = v.getDataType();

Main.log(“Write Value DataType is: ” + dataType.getDisplayName().getText());
}

The error is being thrown on the getNode() function BUT if I try surround it with a try catch(StatusException) I get a compile time error that a StatusException is never thrown by that function. I’m not sure why it has to readReferences and browse through the addressspace if I only want to get the datatype of a single node. Is there a better function to use to do this or is this a shortcoming of the SDK?

June 2, 2022
14:27, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

It is not a thrown exception, but an ERROR level log message with a stacktrace component of an exception that was cached internally (as part of the getNode) and logged. This is to say, it is not something that can be catched. Typical logger configurations will show the stacktrace if an exception is given to the logging message.

In general on the client side the UaNode is the representation of the “whole node” with the Attributes and References of it (in the server side it is literally the node). The way it works in the client side SDK is that both info is Read+Browse’d when the node is created (and then returned). For Variables and Objects nodes the TypeDefinition Reference also determines the class of the returned node (i.e. this combines with our Codegen tool which creates more specific UaNode implementations that combine the TypeDefinition info as helper getter/setters and “nodegetters”; SDK contains generated classes internally for the base specification information model).

In general Browsing a Node should not fail (at least it is somewhat odd, assuming you are able to Read it). That might be somewhat due to historical reasons why that error gets logged and not thrown. In OPC UA 1.04 there is now a way to specification-wise forbid client from Browsing a node, but before 1.04 there was only limits on Read/Write on Attributes. Though also in practice we have not yet seen much adoption of the 1.04 Roles system (and we also have very little support for it ourselves), but it probably should be improved. Though it is more likely that the PLC’s given error code or logic is not exactly correct so it is a bit confusing (since that error statuscode is not exactly correct here, it should be related to the Read/Write rights on just the Value Attribute, but this might be some pre-1.04 implementation as well).

Anyway, if you have time you could ask the PLC vendor why it doesn’t allow Browsing the node here.

As to is there better way, well it depends on what you need the DataType for? Or more specifically, what part i.e. Attributes (or the whole i.e. all of them?) of the DataType node (as they are nodes as well)? For the NodeId it would be faster (maybe not as nice though) to just Read the DataType Attribute of the variable node (with UaClient.readAttribute), i.e. you would not use the UaNodes at all here (though you will get a DataValue, and must “know” that the Variant within the DataValue contains a NodeId instance). Getting any more info would need to then Read again (then using the returned NodeId as the node) on the DataType node.

But most of the time what you are doing is ok, though there are some notes I should make. There should be no need to do the “Initialize DataType node” shown in your code, i.e. this is all you should need to do, but it depends how well the server behaves:

try {
  UaVariable variable =
      client.getAddressSpace().getNode(VariableIdentifiers.Server_ServerStatus, UaVariable.class);
  UaDataType dataType = variable.getDataType();
  logger.info("DataType: {}", dataType.getDisplayName());
} catch (UaException e) {
  logger.error("Not a Variable or some other failure", e);
}

Here I used ‘VariableIdentifiers.Server_ServerStatus’ as an example, but any NodeId/ExpandedNodeId you know to be a Variable node (thus the Class taking overload) would do (or you will get the exception if not). This should log “DataType: ServerStatusDataType”.
NOTE! IF for some reason the DataType node cannot be getNode’d (getDataType will internally do that if not set) that would throw a RuntimeException. In general that situation should not happen, but in theory could if connected to some Nano Profile servers etc. which might not have types part of the address space in the server.

Note that I merged the thrown exceptions as UaException catch (as it is the super-exception-class of them; as that is how I would typically do it, it is somewhat rare that there would be different handling logics), but you can also catch them as ServiceException and AddressSpaceException separately (ServiceException if there is problems with doing the actual service call to the server, AddressSpace exception if there is problems interpreting the data e.g. something odd like non-Good results for a NodeClass or something and it would also be thrown if you gave it a Class to which the node java-instance was not castable).

June 2, 2022
14:49, EEST
Avatar
MichaelBraveDigital
Member
Members
Forum Posts: 14
Member Since:
March 10, 2016
sp_UserOfflineSmall Offline

Thanks so much for your detailed reply Bjarne! I understand now. I’m just using the UaDataType to convert a string to the correct data type prior to writing:

client.getAddressSpace().getDataTypeConverter().parseVariant(valueObject.toString(), dataType)

Perhaps this is unnecessary, but I will try reading the data type attribute straight from the node instead of reading the entire node as that seems the better way to do it. thanks!

June 2, 2022
15:37, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Technically for that specific use-case we do have nowadays:

(UaClient) client.writeValue(NodeId nodeId, Object value, boolean autoConvert)

(so you would pass in ‘nid’, the String and true in your original post)

If you pass true to for the autoConvert, it is a best-effort conversion. Note that calling this via UaClient will internally Read the DataType attribute from the node and then basically do what you shown (though with getAddressSpace().getDataTypeConverter().convert(..)).

IF you already have the UaNode at hand or are getting it for any other reasons, you could also change the getNode (or do a cast) in my prev example to get UaVariableImpl.class instead of UaVariable (this will get you the client-specific impl), it has client-specific helpers:

writeValue(Object value, boolean autoConvert)

Which is the same in functionality as UaClient, but this doesn’t read the DataType (as this info is already in the node’s Attributes in the UaNode object).

That being said, I might personally prefer to do the conversion outside to catch those errors separately before the method (though you can try to do that via catching DataTypeConversionException), as there are limited types the DataTypeConverter can work on or if you e.g. have some UI component on which you would wish to do validation on the String before allowing to e.g. chose a ‘Write’ option on a dialog and so on. But for simple type conversions in simple use-cases it should be OK (e.g. Structures do not work etc. basically it can do strings and numeric types and that’s mostly it).

June 2, 2022
16:53, EEST
Avatar
MichaelBraveDigital
Member
Members
Forum Posts: 14
Member Since:
March 10, 2016
sp_UserOfflineSmall Offline

Ah great, I didnt know about the autoConvert value as I cant seem to get IntelliJ to show properly annotated function completion for the SDK. Anywhere I can look to solve this?

https://i.imgur.com/ycEV4Df.pngImage Enlarger

June 2, 2022
18:19, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Find a way to attach javadocs from the ‘javadoc’ folder of the SDK distribution zip. For Eclipse we have a starting guide (see ‘tutorial’ folder of the SDK zip) which would show this (“2.3. Adding Javadoc documentation”). While it doesn’t directly help for IDEA, the same concept should apply (https://stackoverflow.com/questions/91307/attaching-additional-javadoc-in-intellij-idea).

Also note that if IDEA wants it as a .jar just rename the ending on the javadoc .zip to jar (as jar files are zip files, but to avoid confusion we ship it as a .zip)

You can also just open the unzipped javadoc via a web browser, but it easier to have it attached in the IDE as well.

June 3, 2022
10:32, EEST
Avatar
MichaelBraveDigital
Member
Members
Forum Posts: 14
Member Since:
March 10, 2016
sp_UserOfflineSmall Offline

I will try that thank you.

EDIT: It’s Control + Q in IntelliJ to show the javadoc documentation for a function or hover over the function name long enough. It doesnt actually convert the function arguments into useful human readable names.

Forum Timezone: Europe/Helsinki

Most Users Ever Online: 1919

Currently Online:
18 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

Heikki Tahvanainen: 402

hbrackel: 144

rocket science: 88

pramanj: 86

Francesco Zambon: 83

Ibrahim: 78

Sabari: 62

kapsl: 57

gjevremovic: 49

Xavier: 43

Member Stats:

Guest Posters: 0

Members: 738

Moderators: 7

Admins: 1

Forum Stats:

Groups: 3

Forums: 15

Topics: 1524

Posts: 6451

Newest Members:

jonathonmcintyre, fannielima, kristiewinkle8, rust, christamcdowall, redaahern07571, nigelbdhmp, travistimmons, AnnelCib, dalenegettinger

Moderators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1026, Jimmy Ni: 26, Matti Siponen: 346, Lusetti: 0

Administrators: admin: 1