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
Cannot find data type of class com.prosysopc.ua.stack.builtintypes.ExtensionObject
August 31, 2022
14:17, EEST
Avatar
Hendrik Ulbrich
Member
Members
Forum Posts: 14
Member Since:
June 27, 2018
sp_UserOfflineSmall Offline

Subtopic = Array in custom structure (DataType) with FieldSpecification.Builder

We want to use an Array as a part of a custom structure.
We have implemented the following java method to generate an opc method from a given configuration (in this case List):

private Dynamic createMethodStructure(String structureTypeName, List vars) throws StatusException, TypeDictionaryException {
this.binIds++;

NodeId methodStructure = new NodeId(getNamespaceIndex(), structureTypeName+”Type”);
NodeId binaryEncodingId = new NodeId(getNamespaceIndex(), this.binIds);

// StructureSpecification
StructureSpecification.Builder builder = StructureSpecification.builder();
builder.setStructureType(StructureSpecification.StructureType.NORMAL);
builder.setName(structureTypeName);
builder.setTypeId(UaNodeId.fromLocal(methodStructure, getNamespaceTable()));
builder.setBinaryEncodeId(UaNodeId.fromLocal(binaryEncodingId, getNamespaceTable()));

FieldSpecification.Builder fieldBuilder;
for(int i=0;i<vars.size();i++) {
TandemVarDescriptor var = vars.get(i);

fieldBuilder = FieldSpecification.builder();
fieldBuilder.setName(var.getItem());
switch (var.getType()) {
case STRING:
fieldBuilder.setDataTypeId(UaNodeId.fromLocal(DataTypeIdentifiers.String, getNamespaceTable()));
fieldBuilder.setJavaClass(String.class);
break;

case BOOLEAN:
fieldBuilder.setDataTypeId(UaNodeId.fromLocal(DataTypeIdentifiers.Boolean, getNamespaceTable()));
fieldBuilder.setJavaClass(Boolean.class);
break;

case SHORT:
fieldBuilder.setDataTypeId(UaNodeId.fromLocal(DataTypeIdentifiers.Int16, getNamespaceTable()));
fieldBuilder.setJavaClass(Short.class);
break;

case INTEGER:
fieldBuilder.setDataTypeId(UaNodeId.fromLocal(DataTypeIdentifiers.Int32, getNamespaceTable()));
fieldBuilder.setJavaClass(Integer.class);
break;

case LONG:
fieldBuilder.setDataTypeId(UaNodeId.fromLocal(DataTypeIdentifiers.Int64, getNamespaceTable()));
fieldBuilder.setJavaClass(Long.class);
break;

case DOUBLE:
fieldBuilder.setDataTypeId(UaNodeId.fromLocal(DataTypeIdentifiers.Double, getNamespaceTable()));
fieldBuilder.setJavaClass(Double.class);
break;

case ARRAY:
Dynamic dynamicArray = this.createMethodStructure(structureTypeName + "Array" + var.getItem(), ((TandemArrayDescriptor)var).getStruct());
fieldBuilder.setDataTypeId(UaNodeId.fromLocal(dynamicArray.getNode(), getNamespaceTable()));
fieldBuilder.setArrayDimensions(10);
fieldBuilder.setValueRank(1);
fieldBuilder.setJavaClass(Array.class);
break;

default:
throw new TypeDictionaryException("unsupported type");
}
FieldSpecification field = fieldBuilder.build();
builder.addField(field);
}

StructureSpecification structureSpecification = builder.build();
getServer().getEncoderContext().addStructureSpecification(structureSpecification);

// This makes the actual DataType node in the address space
UaDataTypeNode dataTypeNode = new UaDataTypeNode(this, methodStructure,
new QualifiedName(getNamespaceIndex(), structureTypeName), new LocalizedText(structureTypeName));
UaType structureTypeNode = getNodeManagerTable().getType(DataTypeIdentifiers.Structure);
structureTypeNode.addSubType(dataTypeNode);

// Create Encodings nodes
DataTypeEncodingTypeNode binaryEncodingNode = createInstance(DataTypeEncodingTypeNode.class, binaryEncodingId,
new QualifiedName(0, "Default Binary"), new LocalizedText("Default Binary"));
addNode(binaryEncodingNode);
dataTypeNode.addReference(binaryEncodingNode, ReferenceTypeIdentifiers.HasEncoding, false);

return new Dynamic(methodStructure, structureSpecification, vars);
}

Everything seems to be ok. But when we call the opc method we get the following error from the lib:

13:16:49.687 [OPC-UA-Stack-Blocking-Work-Executor-51] ERROR com.prosysopc.ua.stack.application.ServiceHandlerComposition – While handling CallRequest [RequestHeader="RequestHeader [AuthenticationToken="b=qkmjJ+utbdtS8mVAsgx404rkq1P7WlfbGIBoBbR70Z0=", Timestamp="08/31/22 11:16:49.6728996 GMT", RequestHandle="1002526", ReturnDiagnostics="64", AuditEntryId="null", TimeoutHint="40000", AdditionalHeader="null"]", MethodsToCall="[CallMethodRequest [ObjectId="ns=2;s=ssbfzyxid", MethodId="ns=2;s=xy004id", InputArguments="[ExtensionObject [typeId=nsu=http%3A%2F%2Fwww.miele.com%2FOPCUA%2FTandemAddressSpace;i=17001, encodeType=Binary, object=[96] 0xffffffff000000000a000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff]]"]]"]
com.prosysopc.ua.stack.common.ServiceFaultException: ServiceFault [ResponseHeader="ResponseHeader [Timestamp="08/31/22 11:16:49.6810000 GMT", RequestHandle="null", ServiceResult="Bad_InternalError (0x80020000) "An internal error occurred as a result of a programming or configuration error."", ServiceDiagnostics="Diagnostic Info: java.lang.IllegalArgumentException: Cannot find data type of class com.prosysopc.ua.stack.builtintypes.ExtensionObject (Bad_InternalError (0x80020000) "An internal error occurred as a result of a programming or configuration error.")
at com.prosysopc.ua.DataTypeConverter.getDataTypesForJavaClass(SourceFile:307)
at com.prosysopc.ua.server.ServiceManagerBase.dataTypeEquals(SourceFile:240)
at com.prosysopc.ua.server.MethodManagerUaNode.checkInputArguments(SourceFile:170)
at com.prosysopc.ua.server.MethodManagerUaNode.callMethod(SourceFile:90)
at com.prosysopc.ua.server.NodeManager.callMethod(SourceFile:724)
at com.prosysopc.ua.server.NodeManagerTable.callMethod(SourceFile:2347)
at com.prosysopc.ua.server.NodeManagementServiceHandler.callMethod(SourceFile:723)
at com.prosysopc.ua.server.NodeManagementServiceHandler.call(SourceFile:695)
at com.prosysopc.ua.server.NodeManagementServiceHandler.onCall(SourceFile:226)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.prosysopc.ua.stack.application.ServiceHandlerComposition$1.serve(SourceFile:114)
at com.prosysopc.ua.stack.application.ServiceHandlerComposition.serve(SourceFile:235)
at com.prosysopc.ua.stack.transport.tcp.nio.OpcTcpServerSecureChannel.handleSecureMessage(SourceFile:333)
at com.prosysopc.ua.stack.transport.tcp.nio.OpcTcpServerConnection.handleSecureMessage(SourceFile:872)
at com.prosysopc.ua.stack.transport.tcp.nio.OpcTcpServerConnection$3.onMessageComplete(SourceFile:263)
at com.prosysopc.ua.stack.transport.tcp.nio.SecureInputMessageBuilder.fireComplete(SourceFile:442)
at com.prosysopc.ua.stack.transport.tcp.nio.SecureInputMessageBuilder.setMessage(SourceFile:493)
at com.prosysopc.ua.stack.transport.tcp.nio.SecureInputMessageBuilder$1.run(SourceFile:146)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)

", StringTable="[java.lang.IllegalArgumentException: Cannot find data type of class com.prosysopc.ua.stack.builtintypes.ExtensionObject]", AdditionalHeader="null"]"]
at com.prosysopc.ua.stack.application.ServiceHandlerComposition$1.serve(SourceFile:127) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.stack.application.ServiceHandlerComposition.serve(SourceFile:235) [prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.stack.transport.tcp.nio.OpcTcpServerSecureChannel.handleSecureMessage(SourceFile:333) [prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.stack.transport.tcp.nio.OpcTcpServerConnection.handleSecureMessage(SourceFile:872) [prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.stack.transport.tcp.nio.OpcTcpServerConnection$3.onMessageComplete(SourceFile:263) [prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.stack.transport.tcp.nio.SecureInputMessageBuilder.fireComplete(SourceFile:442) [prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.stack.transport.tcp.nio.SecureInputMessageBuilder.setMessage(SourceFile:493) [prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.stack.transport.tcp.nio.SecureInputMessageBuilder$1.run(SourceFile:146) [prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_332]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_332]
at java.lang.Thread.run(Thread.java:750) [?:1.8.0_332]
Caused by: java.lang.IllegalArgumentException: Cannot find data type of class com.prosysopc.ua.stack.builtintypes.ExtensionObject
at com.prosysopc.ua.DataTypeConverter.getDataTypesForJavaClass(SourceFile:307) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.server.ServiceManagerBase.dataTypeEquals(SourceFile:240) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.server.MethodManagerUaNode.checkInputArguments(SourceFile:170) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.server.MethodManagerUaNode.callMethod(SourceFile:90) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.server.NodeManager.callMethod(SourceFile:724) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.server.NodeManagerTable.callMethod(SourceFile:2347) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.server.NodeManagementServiceHandler.callMethod(SourceFile:723) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.server.NodeManagementServiceHandler.call(SourceFile:695) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at com.prosysopc.ua.server.NodeManagementServiceHandler.onCall(SourceFile:226) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_332]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_332]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_332]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_332]
at com.prosysopc.ua.stack.application.ServiceHandlerComposition$1.serve(SourceFile:114) ~[prosys-opc-ua-sdk-client-server-4.7.2-13.jar:?]
… 10 more

Can anyone see the mistake we are making?

August 31, 2022
14:49, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

Most of the times the StructureSpecifications come from loaded NodeSet2.xml models (or code-geneated from them), doing them by hand is not that convenient yet (and SDK doesn’t validate the java class, we might do that some day, but also that would mean the specifications could only be constructed in the context of an UaServer or UaClient).

Basically the line “fieldBuilder.setJavaClass(Array.class);” is wrong. The class should be an array class (since the ValueRank is 1 i.e. this is a single dimensional array field) that maps to the DataType id given in fieldBuilder.setDataTypeId(id), i.e. it must be the actual java class of the field as-if it would have been code-generated.

One way to get the mapping at runtime is by server.getAddressSpace().getType(dataTypeId).getJavaClass(). IMPORTANT! I would recommend you to update to the latest release 4.9.0 as things related to this was changed: https://downloads.prosysopc.com/opcua/Prosys_OPC_UA_SDK_for_Java_4_Release_Notes.html#version-4-9-0 as part of fixing some mappings. Though, it should be noted that they are valid only if the StructureType is NORMAL/OPTIONAL/UNION (for SUBTYPES/UNION_SUBTYPES the java class is different, but I see you used NORMAL thus skipping this part). If you get null, it means the type doesn’t have a mapping and cannot be used as a structure field. Please note that before 4.9.0 you would need to loop supertypes and some mappings might be missing.

Also, it must be of correct dimension, so thus pass it through MultiDimensionArrayUtils.arrayClassOf(class, dimensions) with value of 1 for dimensions (i.e. if it would be a Double array, you would give Double[].class as the input for the fieldspecification).

September 1, 2022
9:02, EEST
Avatar
Hendrik Ulbrich
Member
Members
Forum Posts: 14
Member Since:
June 27, 2018
sp_UserOfflineSmall Offline

I have not yet fully understood the concept of SUBTYPES. Maybe it is also the solution for our approach. That’s why I’d like to elaborate a bit more:

We want to bypass the limitation of max. 20 method arguments on Siemens PLCs at this point and for this we use CustomDataTypes or Structures.

For methods with less than 20 arguments we use another way without CustomDataTypes or Structures. In this case we simply use “new Argument();” with
setDataType(arrayDataType);
setValueRank(ValueRanks.OneDimension);
setArrayDimensions(new UnsignedInteger[] { UnsignedInteger.valueOf(arraySize) });

We generate arrayDataType with the same Java method createMethodStructure (see above). From the “Dynamic” object we then take with .getNode() the NodeId = arrayDataType.

If we want to bypass the limitation described above we put all arguments of the method into a custom structure (CustomDataTypes), like this:

CustomDataType: custom1Type
– text1 (string)
– number1 (int)
– text2 (string)
– number2 (int)
– array1 (CustomDataType array1Type) size = 10
— textArray (string)
— numberArray (int)
– text3 (string)
– number3 (int)

If this CustomDataType is to contain an array of a structure, our approach is again to create a CustomDataType (in the example “array1Type”). For this we use the JavaMethod createMethodStructure recursively so far.

However, maybe the SUBTYPE is available for exactly this case? Because the CustomDataType “array1Type” is only used in the custom1Type.

Is it clearer what we have in mind?

September 1, 2022
9:50, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Just to be sure, since my PLC-knowledge is limited, are we talking about PLC as OPC UA Server or a Client? Given that the stacktraces you posted are from our server side maybe it is the case that the PLC is a client here, but I still want to doubelcheck this first.

Normally I would assume PLC as a server. In that case, SDK automatically resolves custom structure types when UaClient connects (it reads all types by default), and can already provide the StructureSpecification for you via:

(UaClient) client.getEncoderContext().getStructureSpecification(…)

That is to say, no need to do them manually in that case.

September 1, 2022
9:59, EEST
Avatar
Hendrik Ulbrich
Member
Members
Forum Posts: 14
Member Since:
June 27, 2018
sp_UserOfflineSmall Offline

Yes, in this case the PLC is a client and our java implementation (with the prosys lib) is a server. So the java app provides methods for the plc.

September 1, 2022
10:40, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

These are complex topics. So we’ll probably have many more these question-answers.

Firstly for the SUBTYPES/UNION_SUBTYPES. I’ll probably have to try to explain them, but in short I do not yet see any use of them in this case. They are new StructureTypes defined in OPC UA 1.04.10 (1.04, errata 10) and only those and onwards can understand them. Not sure if the PLC would. Basically they are just type hints for raw BaseDataType (i=24) and Structure (i=22) fields. I probably need to explain that a bit more as reading the spec you might not see it as the same, but that is the short version (in a purely personal opinion, I say these were a mistake and should never been done like this, they just bring a ton of problems when trying to implement them, but skipping details now).

Secondly, what you are doing looks ok. Basically you will need to make a new Structure type whenever you have well a new Structure, including nested ones. This too might need more explanations.

Technically in a workaround mindset and and if this would be a one-off case and no other clients there are tricks you could do, but I would not call these proper OPC UA ideology. For example, if the limit is 20 args, maybe just have one, but have it be BaseDataType array, then there would be no limit (assuming arrays work), but this would lose semantic type information as the client would not know of the data types nor “argument names”.

September 1, 2022
11:08, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

So then a longer note on the StructureType.SUBTYPES/UNION_SUBTYPES. Specification-wise they are https://reference.opcfoundation.org/v104/Core/DataTypes/StructureType/ (this is generated as com.prosysopc.ua.stack.core.StructureType, and is different from com.prosysopc.ua.typedictionary.StructureSpecification.StructureType, as it predate the specification-one).

Normally you cannot use abstract types nor subtypes of Structure for Structure fields, as the top-lvl type defines everything. Binary-wise “there are no nested structure fields”, the fields of any “nested structure” are just taken in order as-if as part of the top-lvl type and there is no ‘type marker’ for a nested structure, thus encoders can only put the very exact structure defined in the top-lvl structure, otherwise the binary format would break. Abstract types wont work as decoders would not know which type to decode (or even how many bytes it is in the binary stream).

The only exceptions to this are fields of exactly i=24 (BaseDataType) and exactly i=22 (the raw Structure) type. They are encoded as Variant and ExtensionObject, respectively. These both hold type info which defines how many bytes the decoders read. These can be used in all StructureTypes.

But without the new SUBTYPES/UNION_SUBTYPES there is no info of what is the expected type. However, due to way SDK and OPC UA works, currently when we would codegen these types (or load information models or in your case doing it by hand) the java classes are exactly Object.class and ExtensionObject.class, because these are the only classes that can work this way.

If the type hint would be modeled e.g. as a known structure, let’s say BuildInfo, theoretically we could generate the field as a BuildInfo.class and just use encoder level tricks to contain it in an ExtensionObject. However, if then someone used a subtype, which is not generated we would normally use DynamicStructure. However DynamicStructure is not a subtype of BuildInfo, thus the field could not be assigned in java. While we might change in the future to allow subtypes of generated types via the generated type, currently it is only possible to represent exactly BuildInfo with the BuildInfo, not any subtypes, thus the only valid mapping we could use is the ExtensionObject (as it can contain any Structure). So basically the fields are exactly the same as they would have been with the old Structure types. Though now the FieldSpecifications’ DataType will tell the expected type.

September 1, 2022
11:15, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Anyway, typically when modeling types, the https://www.unified-automation.com/products/development-tools/uamodeler.html is the de-facto tool to do so. You can output NodeSets2.xmls from that and then load them to the UaServer. We also have a Codegen tool that ships with the SDK that allows you to generate the types from the model as java code. It is possible that your case is as such that this doesn’t work (e.g. if you get the info via some other system or that it is not static so that it could be contained in a model xml file), but when possible it would be typically the easiest way to do so.

September 1, 2022
11:18, EEST
Avatar
Hendrik Ulbrich
Member
Members
Forum Posts: 14
Member Since:
June 27, 2018
sp_UserOfflineSmall Offline

We updated to 4.9.0-43.

getServer().getAddressSpace().getType(dataTypeId).getJavaClass() =>
result = {Class@6602} “class com.prosysopc.ua.typedictionary.DynamicStructure”
cachedConstructor = null
newInstanceCallerCache = null
name = null
classLoader = {Launcher$AppClassLoader@5293}
reflectionData = null
classRedefinedCount = 0
genericInfo = null
enumConstants = null
enumConstantDirectory = null
annotationData = null
annotationType = null
classValueMap = null

You wrote ” If you get null, it means the type doesn’t have a mapping and cannot be used as a structure field.”.
The dataTypeId is a simple array with string and int:

– array1 (CustomDataType array1Type) size = 10
— textArray (string)
— numberArray (int)

Is it possible to add a mapping, when creating the CustomDataType?

September 1, 2022
11:21, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Though now that I understand this case better, I could also now mention that since all the nested structure types here seem to be custom, it means the java class mapping for them is DynamicStructure.class. So, for the 1-dim array, you would do

fieldBuilder.setJavaClass(DynamicStructure[].class)
September 1, 2022
14:36, EEST
Avatar
Hendrik Ulbrich
Member
Members
Forum Posts: 14
Member Since:
June 27, 2018
sp_UserOfflineSmall Offline

First of all, thank you for the detailed answers. It is correct that for our use case there is no xml model or static file, but everything is “generated” dynamically at runtime.

fieldBuilder.setJavaClass(DynamicStructure[].class)

This works very well. I still have a small problem with the array size or dimension.

For case (1) with less than 20 arguments, we create the array using an “argument” object as described:

setDataType(arrayDataType);
setValueRank(ValueRanks.OneDimension);
setArrayDimensions(new UnsignedInteger[] { UnsignedInteger.valueOf(arraySize) });

arraySize in this case is simply an integer, e.g. 10

For the other case (2) as Custom DataType via the FieldBuilder:

fieldBuilder.setDataTypeId(UaNodeId.fromLocal(arrayDataType, getNamespaceTable()));
fieldBuilder.setArrayDimensions(arraySize);
fieldBuilder.setValueRank(1);
fieldBuilder.setJavaClass(DynamicStructure[].class);

We are currently testing with UaExpert and there for the 1st case the array is displayed with a fixed length (here: 10). In the 2nd case UaExpert asks me for the array size. To me it looks like we are still doing something wrong at this point.

September 1, 2022
15:02, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Interesting.. because in these cases, it is the maximum number of elements per dimension, not a fixed size:

https://reference.opcfoundation.org/v104/Core/docs/Part3/8.51/
https://reference.opcfoundation.org/v104/Core/docs/Part3/8.6/

Though I have to note that I do not think we enforce the limit in the SDK yet, so it would depend on the client not to go over the limit (but I’ll have to check this).

P.S.
In the case of the Variant encodings the ArrayLength means absolute lenght https://reference.opcfoundation.org/Core/Part6/5.2.2/#5.2.2.16, mentioning because it is the same term, but different meaning in a different place.

P.S.2
Oh, the 20 limit is on the number of array entries… that is … odd (I assumed the number of arguments would have been the limit not the array size). Maybe I’m missing something here..

Forum Timezone: Europe/Helsinki

Most Users Ever Online: 1919

Currently Online:
6 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