Qt OPC UA: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
m (JKSH moved page QtOpcua to Qt OPC UA: Title format (see https://wiki.qt.io/Spelling_Module_Names_in_Qt_Documentation ))

Revision as of 05:08, 28 September 2017

QtOpcUa as a wrapper

The current design of QtOpcUa assumes that it is a thin wrapper around an existing OPC-UA (client-)stack.

Negative consequences

  • Open-Source stacks: There is as of today no (nearly) feature complete C/C++ open source stack with a suitable license.
  • Closed-Source stacks: There are a number of feature complete stacks written in C/C++ but integration requires the cooperation of the respective vendor. This touches on topics such as
    • availability is limited to certain platforms
    • the stacks embed (static) copies of third parties such as libxml or openssl. This can clash with Qt third-parties (openssl is a known case).
    • vendors might not be too cooperative as it makes their stack replaceable.
  • One needs to create and maintain a CI-setup for 'x' different stacks
  • One needs to learn the client side API of 'x' different stacks to create the necessary backends.
  • Certain stacks only provide a synchronous API which creates a burden for the Qt-side (which needs to provide an asynchronous API)
  • The qt io/networking abstraction is bypassed.

Positive consequences

  • A lot of heavy lifting has already been done as the existing stacks implement all the complicated things and we just provide a wrapper (unclear if there is actually so much complicated stuff on the client-side).

QtOpcUa as a standalone implementation of (client-side) OpcUa

Assumption: most of the complicated stuff is on the server side. It might be a workable approach to re-implement the client-side of OPC-UA from scratch. A lot of projects use a code-generator to translate the XMl-based protocol/interface description published by the opcuafoundation into code to provide protocol primitives (enums/structs) as well as serialization and deserialization. One could take an existing generator and modify it to generate Qtish code.

Negative consequences

  • More actually knowledge of the inner workings of OPC-UA are needed.
  • The crypto transport might be a lot of work (it is not actually SSL/TLS but close). Open-Source projects typically don't implement it.

Positive consequences

  • Much less CI hassle
  • All Qt plattforms are automatically supported
  • Better integrated with the rest of Qt (other modules like networking, ssl or the eventloop).
  • Full control over the API. It can be done asynchronous without threading constructs and other workarounds.
  • No reliance on the goodwill of commercial vendors.

API limitations

  • Events: the current API does not allow to specify select or where clauses. Select-clauses are used to select fields to be contained in the event notification. The where-clauses are used to filter which events should be notified. Its not uncommon to have a single object with an event notifier attribute for the whole server. Not having the possibility to specify where-clauses means that a client always gets all event notifications.
  • Arrays are currently not correctly handled. We map them to a single QVariantList. This does not respect their dimensions.
  • We give a bad example how to "address" nodes. "ns=1;someidstring" is bad practice. Namespace indexes can change. Hardcoding them in strings is brittle. The correct way to do this is by asking the server for its namespace array. It contains ns-URNs to index mappings. We should offer constructors which support this.
  • What kind of node is the QOpcUaNode really? There are eight node types in OPC-UA. A base type inherited by the seven others. Should there be specialized node types in QOpcUa? Why does QOpcua offer a call() method? Isn't this one specific to MethodNodes?
  • Should the QOpcUa client offer "translateBrowsePath" functionality? This is a server-side way to find the nodeid of a node via a path of namespace-indexes/browsenames.
  • QOpcUaNode::name() returns the display name. What about the browseName?
  • QOpcUaNode has no method to access the node description.

Handling large namespaces

Sometimes a (QML) HMI only needs to deal with a handful of OPC-UA nodes. It is possible to code this by hand. In other case there are hundreds of nodes (think a PLC/SPS providing access to its internal data). It would be very cumbersome to hand code this. It would be nice if it would be possible to just hand a tree/graph of QObjects - representing the nodes of the OPC-UA namespace - into the QML application.

If we look at modules such as QtDBus or QtRemoteObjects two approaches can be seen.

Static

A description of the remote-side is feed into a tool at build/compilation time and C++/Qt code is generated. For OPC-UA this could be an XML description of the namespace. There is established tooling for that on the OPC-UA side. Caveat: this will not work for certain scenarios where nodes are added or removed during operations. This is AFAIK not a show stopper for the overall approach. It just doesn't provide for certain applications of OPC-UA.

Dynamic

A description of the remote-side is discovered at run-time. Unlike OPC-classic, OPC-UA is self-describing. It can be discovered/enumerated at runtime.