You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is the last point on my list of experiences during writing the UaTypeGenerator. Actually, this is not just one point but two very similar issues, where the first is more important, but the second one could help to solve the first one. The OPC UA type system supports to subtype non structural types, e.g., Double (i=11), DateTime (i=13) or ByteString (i=15). C# itself does not have a notion like this, but I think, it is comparable to C's typedefs. Most notably those subtypes do not have an encoding id on their own.
the Duration is part of the standard schema and the following is part of a Siemens TIA nodeset:
<UADataTypeNodeId="ns=3;i=3006"BrowseName="3:TIME">
<DisplayName>TIME</DisplayName>
<DescriptionLocale="en-US">TIME is interpreted as milliseconds T#-24d20h31m23s648ms to T#+24d20h31m23s647ms. The representation contains information for days (d) hours (h) minutes (m) seconds (s) and milliseconds (ms).</Description>
<References>
<ReferenceReferenceType="HasSubtype"IsForward="false">i=6</Reference>
</References>
</UADataType>
This brings up some questions.
Why annotate this
It would be good, if there is a way for the type generator to get that information by means of reflection, i.e., without knowing the NodeSet2.xml file. At the moment I have hardcoded two data types IDs, that are commonly used. Theoretically I could add all standard type definitions, but this does not solve the situation where one companion specification uses an derived type of another.
What type should be used
While both types are similar to dotnet's TimeSpan, I would not use it for the first case (Duration), because a double has a different value range than a TimeSpan. In particular a double can denote values that cannot be represented by a TimeSpan. Hence I would not like to use TimeSpan here. So here one could use a plain double or a thin wrapper struct around a double. This wrapper could be autogenerated. A wrapper has the benefit, that it denotes the intention of the value in the types system. On the other hand I'm not a big fan of "typedefs" and quite thankful that they do not exist in C#. Personally I would use a simple double there. For the Siemens' TIME this looks completely different. There TimeSpan would be an appropriate data type. On the other hand an integer value that gives you the duration in milliseconds would also be ok.
Conclusion
I intentionally do not present a solution here, but I will post a possible solution later that is up to discussion.
The text was updated successfully, but these errors were encountered:
Sorry, for the long delay of the follow-up post. My initial idea was to add the parent-child mapping as an attribute to a converter class or struct. But as I mention in my initial post this is not a really important case (supporting conversion). And it would only work for the structural access and not for the direct access, because there we do not have the data type ID. On the other hand it was the only idea I had, how we can put those information into attributes. In the meantime, I found another way. We could simply have an dictionary that maps the (expanded) node ids of the derived data types to the (expanded) node id of the parent. We would probably need some attribute, to mark those dictionaries.
The TypeLibrary can than expose a method to collect and merge all available dictonaries. One question is if we would include there all parents or only non-structural types. Because for structural types one can already query the inheritance by the net type system.
This is the last point on my list of experiences during writing the
UaTypeGenerator
. Actually, this is not just one point but two very similar issues, where the first is more important, but the second one could help to solve the first one. The OPC UA type system supports to subtype non structural types, e.g., Double (i=11), DateTime (i=13) or ByteString (i=15). C# itself does not have a notion like this, but I think, it is comparable to C'stypedef
s. Most notably those subtypes do not have an encoding id on their own.Let me give you two examples:
the
Duration
is part of the standard schema and the following is part of a Siemens TIA nodeset:This brings up some questions.
Why annotate this
It would be good, if there is a way for the type generator to get that information by means of reflection, i.e., without knowing the NodeSet2.xml file. At the moment I have hardcoded two data types IDs, that are commonly used. Theoretically I could add all standard type definitions, but this does not solve the situation where one companion specification uses an derived type of another.
What type should be used
While both types are similar to dotnet's
TimeSpan
, I would not use it for the first case (Duration), because a double has a different value range than aTimeSpan
. In particular a double can denote values that cannot be represented by aTimeSpan
. Hence I would not like to useTimeSpan
here. So here one could use a plain double or a thin wrapperstruct
around a double. This wrapper could be autogenerated. A wrapper has the benefit, that it denotes the intention of the value in the types system. On the other hand I'm not a big fan of "typedefs" and quite thankful that they do not exist in C#. Personally I would use a simpledouble
there. For the Siemens'TIME
this looks completely different. ThereTimeSpan
would be an appropriate data type. On the other hand an integer value that gives you the duration in milliseconds would also be ok.Conclusion
I intentionally do not present a solution here, but I will post a possible solution later that is up to discussion.
The text was updated successfully, but these errors were encountered: