16:23, EET
September 18, 2017
Hello Support,
I am using SDK for Java 4.3.0.
I want to write a null value into a node of class “Variable”. The server is built on another toolkit but my client uses Prosys SDK. I tried it this way:
The data type of this node is NodeId. The server responds “Bad_TypeMismatch”. So I add a cast operator “(NodeId)” to that null value to specify a type. But it does not help.
I also tried another tool/kit: CTT. I wrote a user defined script. Here, in JavaScript, the Variant is a structure with properties DataType and ArrayType.
// dataValue.Value is of type UaVariant and empty by default
dataValue.Value.DataType = BuiltInType.NodeId; // set the data type
dataValue.Value.ArrayType = VariantArrayType.Scalar; // and specify the dimension
When I do not set these properties together with a null value I also get a “Bad_TypeMismatch” error from the server. When I provide these properties then the value can successfully be written. When the value is non-null I do not need to set these properties.
How can I achieve this with the Java SDK? All I found is to set only the value bot not the type information.
Can you help?
Best regards
Thomas Reuther
17:16, EET
April 3, 2012
Hi,
Note that according to what I know, a Good StatusCode’d Value should never be directly “NULL”, if the value is null, the statuscode should always be bad (or maybe uncertain). Though, that being said, I think this still doesn’t exactly read anywhere in the specification. Anyway, if possible, can you explain why you would want to do this?
Anyway, here is some options.
Short answer:
Try NodeId.NULL instead of “java null”, see below for why.
A bit longer answer:
SDK’s Variant having directly null value is “typeless” and matches the “builtin-type 0” in the Part 6 encodings of the specification. Otherwise the java class (of the instance inside the Variant) directly maps to a builtin type, thus it is not needed to be separately settable. NodeId’s binary encodings define a null form (or well, 4 of them), thus that NodeId.NULL (that is same as NULL_NUMERIC) should be used. Not all types have a Null form, such as e.g. Int32; a Structure having an Int32 field (so java.lang.Integer), set to null would be written as 0 instead.
Long answer:
It is a bit complicated..
Spec links for DataValue, Variant, NodeId binary encoding:
– DataValue: https://reference.opcfoundation.org/v104/Core/docs/Part6/5.2.2/#5.2.2.17
– Variant: https://reference.opcfoundation.org/v104/Core/docs/Part6/5.2.2/#5.2.2.16
– NodeId: https://reference.opcfoundation.org/v104/Core/docs/Part6/5.2.2/#5.2.2.9, plus https://reference.opcfoundation.org/v104/Core/docs/Part3/8.2.4/ for NodeId Null Values definitions (for some reason they seem to not be in Part 6, but were already defined in Part 3)
There is multiple possible binary forms you might mean.
1. DataValue’ EncodingMask might directly indicate that the Value is Null (no type info), no Variant at all in the binary stream
2. Variant’s EncodingMask byte is 0, per above links:” A value of 0 specifies a NULL and that no other fields are encoded”. This is what you are getting now. Probably it should be more correct, that case 1. would happen instead, since it basically means the same thing as far as I can see.
3. Variant contains NodeId.NULL (or NULL_NUMERIC), namespace index 0, value part 0.
4. Variant contains NodeId.NULL_STRING, namespace index 0, value “”.
5. Variant contains NodeId.NULL_GUID, namespace index 0, value equal to ‘new UUID(0, 0)’.
6. Variant contains NodeId.Null_OPAQUE, namespace index 0, value as ByteString with length 0.
The server might want one of cases 3-6. Though I would say it would be best for servers to accept all options (though, here, for some reason the OPC Foundation decided to go with 4 different NULL values for the NodeId instead of just defining it as the numeric variant, so for 1+2 the server would have to chose one of the forms maybe).
17:28, EET
April 3, 2012
P.S.
Java null is typeless, casting it wont change that. But if you have an overload of a method with multiple types the casting would chose which overload to call, but here it wont “change” the null type.
See e.g. https://stackoverflow.com/questions/18723596/no-exception-while-type-casting-with-a-null-in-java
22:51, EET
September 18, 2017
17:40, EET
February 21, 2014
Greetings,
Writing a “null” value can be accomplished by creating a Variant with the value ‘null’ and then writing that Variant. The Variant also has a method ‘isEmpty()’ which allows for checking its value for being ‘null’0.
In case the target server shall receive and deal with a ‘null’ value, it must first evaluate the received variant for containing a ‘null’ value and only for non-null values try to cast it to a NodeId type.
Cheers, HU
12:05, EET
April 3, 2012
hbrackel, There is 6 different binary forms for a “null” NodeId in this case (in my prev post), though the cases 1&2 doesn’t specify a type (and probably 2 should never be used; 1 shoud be done instead as it is same info and saves bytes; but currently you would get option 2 with our SDK), so they are the “typeless null” option in practice. I’m not sure should there be a distinction between them or not.
Based on some discussions on some OPC DAY events I’m at least currently under the impression that if the Value Attribute of a node is “null” (but which version/kind of null?), then the statusccode should be Bad (or uncertain, maybe). Thus it could also be that a server would just not accept a “null” in the first place as well (at least if the status is Good at the same time). It is also possible that I misunderstood something back then.
The null forms are at least needed in cases where the NodeId would be a Structure field, since in the binary encoding each field must always be present (unless structure with optional fields is used, but those were added in OPC UA 1.03) otherwise the binary stream would get corrupted, since readers would not know to not read that field. The service calls itself are also sort of Structures (or well, they have the same encoding rules), thus having the option to have a null NodeId parameter in a service call is useful.
A client.writeAttribute(nodeId, Attributes.Value, null) is the same as writing client.writeAttribute(nodeId, Attributes.Value, new Variant(null)) (or Variant.NULL)). If that method is given a DataValue, that is used directly. If Variant, it is converted to a Good statused DataValue with that Variant. Otherwise the given object is put to a new Variant(object) and then same as if a Variant would have been given directly. Thus I’m afaird the server would reject since it should see the same binary for the value.
Thus, I think the server would be expecting one of the 4 NULL-forms of NodeId (one for each IdType), since it probably compares the buildInType internally. Or it is not accepting a null at all.
Also I think the buildInType “0” was only introduced officiall in OPC UA 1.04 specification (and even there it is just inside the Variant’s EncodingMask definition https://reference.opcfoundation.org/v104/Core/docs/Part6/5.2.2/#5.2.2.16 but not in the actual builtin types table at https://reference.opcfoundation.org/v104/Core/docs/Part6/5.1.2/). I think most implementations have sort of accepted that before as well, but it is possible that some wont.
Hopefully this didn’t confuse you more 🙂
21:39, EET
February 21, 2014
Hi Bjarne,
Thomas and I are working on the same project
One argument, which had actually not been mentioned, is that we wanted to use ‘null’ (not NodeId.NULL) as an indicator for the absence of a value in a variable of type NodeId. The variable serves to configure the application, and a ‘null’ value in a variable means that its content should not be considered.
We can certainly also use NodeId.NULL, but this is technically a valid nodeId so the client has to have the same understanding of identifying NodeId.NULL (whichever of the 4 versions) as an indicator. Variant.NULL (aka ‘null’) would just avoid any misunderstandings and the need for conventions.
We can also upload a JSON configuration for the same purpose of setting those variable values through the server itself. In JSON we can obviously easily use null, and for consistency, we wanted to use the same value for a direct write into the variable.
Unfortunately, the (non-Java) server does not check for Variant.empty() rather immediately tries to cast to a NodeId – which fails and results in the story described by Thomas.
NB: The server, which currently does not accept ‘null’, is also a custom server developed by ourselves. So we could change its behaviour, although would have to “fight” the C++ toolkit implementation.
– Hans-Uwe
12:30, EET
April 3, 2012
Ok, that explains 🙂
Could you try to write a DataValue that has (just) a Bad StatusCode and see if that works?
The C++ implementation might enforce the “Note that according to what I know, a Good StatusCode’d Value should never be directly “NULL”” of my initial post in this chain. Since unless that SDK method is directly given a DataValue it is always wrapped to a Good Status’d DataValue.
I think typically the Bad code in these cases has been “Bad_AttributeIdInvalid” whose description doesn’t exactly make sense here “The attribute is not supported for the specified Node.” since it is the same code if it would not be supported at all.. (at least the C++ demo server uses that a lot)
I could be wrong here as well, but at least I have previously said that as well: https://forum.prosysopc.com/forum/opc-ua-simulation-server/bad_attributeidinvalid/ . Plus it is something that we at least some time in the past discussed shortly with Unified Automation, but since it is not written in the OPC UA Specification it is sort of a grey area how it should be handled.
If writing the Bad code works, then maybe there is a StatusCode that is more descriptive (e.g. Bad_ConfigurationError or Bad_WaitingForInitialData). And also if so we might need to discuss this with Unified again, maybe the java SDK should do it differently and/or ask the OPC Foundation how it should go and ask it to be written to the specification.
Alternatively, assuming it is sort of some Parameters-like Object under which the variables are, could you instead delete the node if it would be null/”empty”? Not a perfect solution, but might work?
Most Users Ever Online: 1919
Currently Online:
21 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: 735
Moderators: 7
Admins: 1
Forum Stats:
Groups: 3
Forums: 15
Topics: 1523
Posts: 6449
Newest Members:
rust, christamcdowall, redaahern07571, nigelbdhmp, travistimmons, AnnelCib, dalenegettinger, howardkennerley, Thomassnism, biancacraft16Moderators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1026, Jimmy Ni: 26, Matti Siponen: 346, Lusetti: 0
Administrators: admin: 1