<@U114Z86N6> I decided to start with client. I am ...
# science
a
@kevinherron I decided to start with client. I am currently working slowly through your Java code and I already see why you took the idea of using kotlin so well. It could help a lot with code duplication and other things. My question is more about opc-ua stack. I currently can't see a way to encode key-value map. Also I can't see a way to interpret custom structure without knowing beforehand what it is. Is it possible to encode a map without using array of custom key-value structure?
k
No, there isn’t a built-in datatype or structure that represents a dictionary or generic key-value. Custom structs can be interpreted dynamically using either GenericBsdParser or JsonBsdParser. The UnifiedAutomationReadCustomDataTypeExample shows how this sort of works.
I’m not sure how much use the GenericBsdParser / Struct implementation gets. We use the JSON parser instead at work.
a
OK. If it is not built-in, then it is probably rarely used and I do not need to implement it now. About Json parsers, is it common practice to use json implementation for devices?
k
It just depends on your client implementation.
a
I would happily use Json directly since it is almost isomorphic to tree structures I use, but my question is can I focus only on Json and do not work with other protocols? Are devices enforced to support it?
k
our SCADA system has a native “Document” (JSON) type, so for us it makes sense to deal with the JSON representation.
this is purely a client side decoding of the OPC UA binary structure, devices don’t know or care whether the client turns it into a JSON object, a
Struct
, or any other representation
a
Json nowadays shows almost the same performance as binary representation, so it almost always makes sense to use it. I am more concerned about legacy devices
k
the codecs in the client are responsible for conversion between the binary encoding used on the wire and the JSON or Struct repr you get as a user of the client SDK
a
Ah, I see, it simplifies things greatly
Now I need to understand how to get Json instead of Variant
k
follow that example I mentioned, but instead of using
GenericBsdParser
use
JsonBsdParser
. When you decode the ExtensionObject you’ll end up with a GSON
JsonElement
this is all only applicable when decoding structures
non-structured values will always be a Variant containing a value of the built-in OPC UA types.
(or null)
a
No problems with nulls or primitives. Let me check that example
k
Variant is just a “container” that is supposed to be basically a union of all the builtin types.
a
The basic read methods returns Variant. This is why I've started working with it.
It seems that I was doing the same thing you are doing here: https://github.com/eclipse/milo/blob/d484f18a756e29837a2a1305eee8e1c640f57d57/opc-[…]rg/eclipse/milo/opcua/binaryschema/gson/JsonStructureCodec.java. So I guess I can just do the same and encode the result directly to kotlin structure.
k
Yeah if you want to pretend the OPC UA types don’t exist and just deal with JSON everywhere that might be a place to reference. I’m working on some changes to that encoding soon, though…
OPC UA 1.04 defined its own JSON encoding and I’m modifying that implementation to follow it.
a
I've read about it in documentation and was a bit confused when you said about client-only thing. I've taken your codec (in Kotlin it is almost two times shorter) and it seems that it is exactly what I need to convert directly to my trees without using double conversion and Gson. Thank you for your help. If we are talking about kotlin, one can create a backend for kotlinx-serialization, which would produce those schemas. It is rather easy to do and it means that you can use any arbitrary kotlin-serializable class.
k
So the whole OPC UA encoding thing is a bit confusing. As of there are three defined: Binary, XML, and JSON. These encodings are used only in two places: on wire, depending on the transport, and to encode the values inside ExtensionObjects (structures, generally). With the introduction of the JSON encoding in 1.04 you could theoretically request from the server that structure values be encoded in this JSON format instead, which would make the whole generation of structures that convert to GSON that you're seeing unnecessary.
BUT support for anything but the Binary encoding is not required of servers, and if you're talking about the servers embedded on PLCs then it's even more unlikely to be supported. Nevermind that this is all new to OPC UA 1.04 and Milo is currently 1.03.
a
Yes, I guessed something like this (based on previous experience with such systems)
k
The OPC UA TCP transport and binary encoding is the only thing that every implementation must support.
a
I need to interop with legacy hardware and software anyway
k
The JSON encoding in the 1.04 spec was introduced so that, theoretically, some kind of web/JS based client could read data from a server, including structures, and not have to worry about decoding some binary format because the encoding is already JSON.
a
Actually all that confusion is the reason why we stick to simple Json or at least tree-like representations in our current work. All this "type safety" never makes it better because you can never be sure about the device you are working with.