open62541 1.5.7+3 copy "open62541: ^1.5.7+3" to clipboard
open62541: ^1.5.7+3 copied to clipboard

Dart FFI bindings to the open62541 OPC UA stack. Provides client and server APIs for OPC UA over TCP, with subscriptions, custom types and mbedTLS encryption.

open62541 for Dart #

Dart FFI bindings to the open62541 OPC UA stack. This package provides idiomatic Dart client and server APIs for OPC UA over TCP, including subscriptions, custom types and encrypted (mbedTLS) connections.

Status: work in progress. The API is functional but still evolving and may change between releases.

Features #

  • Client: connect / reconnect, browse and recursive tree browsing, read, subscriptions and monitored items, and secure connections with certificates (SignAndEncrypt).
  • Server: expose scalar, array and structure (custom type) variable nodes, data-type nodes, and monitor variables via streams.
  • PubSub (OPC UA Part 14, UDP + UADP): publish variable nodes via PublishedDataSets / WriterGroups / DataSetWriters, and subscribe with ReaderGroups / DataSetReaders that map received fields into local variable nodes (both sides configured on Server, per the OPC UA PubSub model). Received values can be observed with Server.onValueChanged.
  • Encryption via mbedTLS.
  • DynamicValue for ergonomic access to OPC UA values, including structures and arrays.

Supported platforms #

Linux, macOS, Windows, Android and iOS. (Web is not supported — this is a native FFI binding.)

How the native library is built #

This package does not ship a precompiled binary. It uses Dart's native build hooks (hook/build.dart together with the hooks, code_assets and native_toolchain_cmake packages). The first time the package is built, the hook:

  1. Downloads the open62541 and mbedTLS source archives over the network.
  2. Builds them from source with CMake for your target platform.
  3. Bundles the resulting shared library as a code asset.

Because of this you need a working C/C++ toolchain, CMake, and network access available at build time. The first build is slow; subsequent builds are cached.

Native build hooks are stable since Dart 3.10, so consumers need no experiment flag.

Installation #

dependencies:
  open62541: ^1.5.7

Then run dart pub get (allow extra time for the first native build).

Versioning #

The package version mirrors the bundled open62541 release exactly: 1.5.7 wraps open62541 v1.5.7. Dart-side fixes that ship the same native library version use a build-metadata suffix — 1.5.7+1, 1.5.7+2, … — which pub.flutter-io.cn orders after 1.5.7. So open62541: ^1.5.7 accepts 1.5.7, any binding-only +N revision, and later 1.x upstream releases.

Usage #

Read the current server time from an OPC UA server:

import 'package:open62541/open62541.dart';

void main(List<String> args) async {
  final client = Client();
  client.connect('opc.tcp://localhost:4840');

  // Drive the client event loop.
  () async {
    while (client.runIterate(Duration(milliseconds: 10))) {
      await Future.delayed(Duration(milliseconds: 10));
    }
  }();

  await client.awaitConnect();

  final time = await client.read(NodeId.serverStatusCurrentTime);
  print('Server time: ${time.asDateTime}');

  client.disconnect();
  await client.delete();
}

More examples are in the example/ directory: a minimal client (example.dart), address-space browsing (browse_test.dart), a server (server_example.dart) and a secure self-healing client (resilient_client.dart).

Threading note: open62541 is built with multithreading disabled, so the client/server event loop must be driven periodically by calling runIterate as shown above.

PubSub (UDP multicast) #

Both PubSub roles are configured on a Server (per OPC UA Part 14 the subscriber also lives on a server instance). Publisher:

final connection = server.addPubSubConnection(
  name: 'UADP Connection',
  url: 'opc.udp://224.0.0.22:4840/',
  publisherId: PubSubPublisherId.uint16(2234),
);
final pds = server.addPublishedDataSet(name: 'Demo PDS');
server.addDataSetField(pds, name: 'Counter', publishedVariable: counterNodeId);
final group = server.addWriterGroup(connection,
    name: 'WG', writerGroupId: 100, publishingInterval: Duration(milliseconds: 100));
server.addDataSetWriter(group, pds, name: 'DSW', dataSetWriterId: 62541);
server.enableAllPubSubComponents();

Subscriber (on another — or the same — server):

final connection = server.addPubSubConnection(name: 'Sub', url: 'opc.udp://224.0.0.22:4840/');
final readerGroup = server.addReaderGroup(connection, name: 'RG');
final reader = server.addDataSetReader(readerGroup,
    name: 'DSR',
    publisherId: PubSubPublisherId.uint16(2234),
    writerGroupId: 100,
    dataSetWriterId: 62541,
    dataSetName: 'Demo PDS',
    fields: [DataSetFieldMeta(name: 'Counter', dataType: NodeId.int32)]);
server.setDataSetReaderTargetVariables(reader, [targetNodeId]);
server.onValueChanged(targetNodeId).listen((v) => print('received: ${v.value}'));
server.enableAllPubSubComponents();

Development #

The sections below are only relevant if you are hacking on the package itself (for example regenerating the FFI bindings), not for normal use.

Regenerating the bindings #

The native library is built automatically by hook/build.dart, which downloads a pinned open62541 source archive and builds it with CMake (amalgamation enabled, so it also produces a single open62541.h). You do not need to build open62541 by hand for normal use.

To regenerate the FFI bindings (for example after bumping the open62541 version), build once, then copy the amalgamated header the hook produced and run the generator:

dart test test/verify_version_test.dart   # triggers the hook build

# Locate the amalgamated header (the path is OS/arch-specific):
find .dart_tool/hooks_runner -name open62541.h
# e.g. on macOS/arm64:
cp .dart_tool/hooks_runner/shared/open62541/build/dl/src/build/macos/arm64/open62541.h \
   third_party/open62541/open62541.h

bash open62541_tooling/patch_header.sh
dart run tool/ffigen.dart

ffigen needs libclang; on some Linux setups you may need to prefix the last command with CPATH=/usr/lib/clang/<version>/include:/usr/include.

The header patch removes the bitfields from UA_DiagnosticInfo, UA_DataValue, UA_DataTypeMember and UA_DataType, replacing each with a single field (the struct size is unchanged) so the generator does not drop the surrounding members.

Known limitations #

  • A multi-dimensional array that is a member of a structure is not modeled and decodes as an empty array. (Top-level multi-dimensional arrays are supported.)
  • Structure-field descriptions are not carried over the wire by open62541 (v1.5.x), so they do not surface from a remote server. For an in-process Dart Server + Client, descriptions are restored from the locally registered schema.
  • Monitored-item notifications do not surface per-notification status codes or timestamps on the value stream: a notification with a non-Good status is delivered as an error event on the stream (carrying the status), and its value/timestamps are dropped. Use Client.readValue to observe a node's value together with its status code and source/server timestamps.
  • Server.statistics exposes aggregate counters only (sessions, secure channels, subscriptions, total monitored items). Per-session and per-subscription diagnostic detail (client identity, publish rates, queue overflows, ...) exists in the NS0 diagnostics nodes but is not surfaced as a typed Dart API.
  • PubSub: only the UDP + UADP transport is enabled (no MQTT/raw Ethernet), and message security (SKS / PubSub security policies), delta frames and DataSetMetaData ConfigurationVersion handling are not exposed. Dataset fields on the subscriber side must use builtin namespace-0 data types.

License #

MIT. See LICENSE.

0
likes
160
points
65
downloads

Documentation

API reference

Publisher

verified publishercentroid.is

Weekly Downloads

Dart FFI bindings to the open62541 OPC UA stack. Provides client and server APIs for OPC UA over TCP, with subscriptions, custom types and mbedTLS encryption.

Repository (GitHub)
View/report issues

Topics

#network #industrial #opcua #open62541 #hmi

License

MIT (license)

Dependencies

archive, binarize, code_assets, crypto, ffi, hooks, http, logging, native_toolchain_cmake

More

Packages that depend on open62541