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
Issue with invoking methods using the UAClient call method
October 26, 2021
10:38, EEST
Avatar
AnttiMatik
Member
Members
Forum Posts: 9
Member Since:
January 31, 2021
sp_UserOfflineSmall Offline

Hello,
I’m presently utilizing the Prosys OPC UA SDK as part of my thesis project at the Aalto University of Technology. As part of my thesis I am implementing a simple client program which can invoke methods on a device server. I have recently however run into issues with the UAClient call method.

Presently my implementation traverses the server address space by first retrieving the address space with the UAClient.getAddressSpace() method. This is then traversed by using the browse() method and iterating through the list of references. The nodeID of the wanted object form this is then saved to a temporary variable and used to travel deeper into the address space hierarchy with the browse method.

This is done until the wanted object and method are reached. The NodeIds for both are saved however when attempting to invoke a method on the server with the client call method the method instead throws a MethodCallStatusException with the following information: “Bad_MethodInvalid (0x80750000) “The method id does not refer to a method for the specified object.” StatusCode=Bad_MethodInvalid (0x80750000) “The method id does not refer to a method for the specified object.””

I have checked that both the node id and method id that are given as parameters for the call method are correct in addition to checking that the hierarchy is as intended by using the OPC UA Browser. Any ideas for troubleshooting would be greatly appreciated as I’ve run out of ideas.

Thank you for any assistance you may be able to provide.

October 26, 2021
11:20, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 982
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

Is the Method (methodId) directly below the Object (objectId) or “more deep”? Rest of the answer assumes “more deep”.

You can only call a Method of an Object it is, i.e. the Method must be directly below the Object. Techinically due to erratas and spec updates in some cases it could also be just defined in the type, but not all servers support this (anyway, this is the relevant spec part: https://reference.opcfoundation.org/Core/docs/Part4/5.11.2/).

So in general you can think that the objectId must be the source node of the HasComponent for which the Method node is the target node (i.e. is the methodId).

Since you mention “a device server”, I could interpret that to mean the server uses the DI companion specification information model. That is a bit weird model that has the “MethodSet” (https://reference.opcfoundation.org/DI/docs/4.3/) folder below the top-lvl instance node that had the methods. In that case the “MethodSet” folder’s NodeId must be used as the objectId (and not the top-lvl one).

October 26, 2021
16:41, EEST
Avatar
AnttiMatik
Member
Members
Forum Posts: 9
Member Since:
January 31, 2021
sp_UserOfflineSmall Offline

The method being called is a direct child object yes. In practice I’m saving the node id of the object into a temporary variable and then retrieving the methods with the GetMethods() method. While I am using the DI-companion specification I’ve opted against a MethodSet for these specific objects. What makes things more confusing is that the method can be invoked just fine with the Browser which narrows the issue down to my implementation of the client.

I don’t know if this will help but here is the relevant section for browsing the address space (barring sections commented out during testing and variable declarations):

//Connect to the chosen server
connect(tmpClient);
tmpClient.getAddressSpace().setMaxReferencesPerNode(1000);
tmpClient.getAddressSpace().setReferenceTypeId(Identifiers.HierarchicalReferences);

//Browse the address space to get the namespace table and device skills
tmpSpace = tmpClient.getAddressSpace();
refDescs = tmpSpace.browse(Identifiers.ObjectsFolder);
tmpTable = tmpSpace.getNamespaceTable();

//Iterate to find the device Set
for(ReferenceDescription tempRef : refDescs) {
if(tempRef.getDisplayName().getText().equals(“DeviceSet”)) {
tmpId = tmpTable.toNodeId(tempRef.getNodeId());
}
}

//Iterate again to find Device Skills
refDescs = tmpSpace.browse(tmpId);
for(ReferenceDescription tempRef : refDescs) {
if(tempRef.getDisplayName().getText().contains(“DeviceSkills”)) {
tmpId = tmpTable.toNodeId(tempRef.getNodeId());
}
}

//Get refs from DeviceSkills to build list of skills
skillRefs = new ArrayList();
refDescs = tmpSpace.browse(tmpId);
for(ReferenceDescription tempRef : refDescs) {
if(tempRef.getNodeClass().toString().equals(“Object”)) {
skillRefs.add(tempRef);
}
}

//Browse the methods
for (ReferenceDescription tempRef : skillRefs) {
if (tempRef.getDisplayName().getText().contains(skillName)) {
skillId = tmpTable.toNodeId(tempRef.getNodeId());
skillMethods = tmpSpace.getMethods(skillId);
}
}

//Get method id
for(UaMethod tempSkill : skillMethods) {
if (tempSkill.getDisplayName().getText().contains(action)) {
testId = tempSkill.getNodeId();
}
}

//Call selected method
Variant[] outputs = tmpClient.call(skillId,testId);
System.out.println(“Method output: ” + outputs);

I must apologize for the long-windedness however at the time I could not think of a more elegant method of retrieving the selected object and method except for browsing the address space a layer at a time. SkillName and action are strings which are previously selected names of objects in the hierarchy. I would also like to apologize for the formatting as the forums are eating my indentation for some unknown reason.

October 26, 2021
17:14, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 982
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Unless performance is really critical you are most likely easier by using the “UaNode”-based API of the SDK (you sort of are using it with the getMethods of AddressSpace as UaMethod is also an UaNode).

e.g. something like:

    // This is the "well known" NodeId for the DeviceSet object
    final UaNodeId deviceSetId = UaNodeId.from("http://opcfoundation.org/UA/DI/", UnsignedInteger.valueOf(5001));
    final UaNode deviceSet = client.getAddressSpace().getNode(deviceSetId.asExpandedNodeId());

    for (UaReference ref : deviceSet.getReferences(Identifiers.HierarchicalReferences, false)) {
      UaNode device = ref.getOppositeNode(deviceSet);

      for (UaMethod method : client.getAddressSpace().getMethods(device.getNodeId())) {
        // something here
      }
    }

(Note that I didn’t run this code, but it is as an example)

Also, in general it is not a good idea to make conditional logic using the DisplayName Attribute, as it (at least in theory) could be in some other locale. BrowseName Attribute should be used instead.

Also, the formatting of code might work better with ‘pre’ html tags, though yes it is not that great either. We should get a better forum implementation…

October 27, 2021
11:31, EEST
Avatar
AnttiMatik
Member
Members
Forum Posts: 9
Member Since:
January 31, 2021
sp_UserOfflineSmall Offline

It would appear that a part of my initial diagnosis of the issue was wrong. I made minor modifications so that instead of calling the method with the saved NodeIds as input paramters I instead re-retrieved the nodes from the address space before getting their NodeId:s. I am still getting the same Bad_MethodInvalid call status exceptions however quite confusingly the server method handler is still executing the method that was called.

I will continue tweaking the code to see if I can find a solution. Thank you for taking the time to help with troubleshooting.

EDIT: I have found the cause. It was actually nothing to do with the method call itself. The device server method handler was set to return a failed result in case it was unable to contact the PLC corresponding to the server. For some reason the client interpreted this instead as a MethodInvalid error. This issue is resolved and was entirely due to a mistake (maybe?) I made in an entirely different part of the code.

Forum Timezone: Europe/Helsinki

Most Users Ever Online: 518

Currently Online:
15 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

hbrackel: 135

pramanj: 86

Francesco Zambon: 81

ibrahim: 75

rocket science: 75

Sabari: 62

kapsl: 57

gjevremovic: 49

Xavier: 43

fred: 41

Member Stats:

Guest Posters: 0

Members: 708

Moderators: 16

Admins: 1

Forum Stats:

Groups: 3

Forums: 15

Topics: 1465

Posts: 6252

Newest Members:

christi10l, ahamad1, Flores Frederick, ellenmoss, harriettscherer, shanonhumphreys, KupimotoblokfuB, tamhollander5, paulinafcf, bridgette18l

Moderators: Jouni Aro: 1009, Otso Palonen: 32, Tuomas Hiltunen: 5, Pyry: 1, Petri: 0, Bjarne Boström: 982, Heikki Tahvanainen: 402, Jukka Asikainen: 1, moldzh08: 0, Jimmy Ni: 26, Teppo Uimonen: 21, Markus Johansson: 42, Niklas Nurminen: 0, Matti Siponen: 319, Lusetti: 0, Ari-Pekka Soikkeli: 5

Administrators: admin: 1