Dateitransfer über OPC UA

Dass OPC UA für viele verschiedene Anwendungen genutzt werden kann, ist inzwischen breiter Konsens. Gleiches gilt für die Tatsache, dass es in OPC UA viele verschiedene Wege gibt, das gleiche Ergebnis zu erreichen. Allerdings sorgt das Thema Dateitransfer regelmäßig für Diskussionen in den OPC UA Arbeitskreisen. Durch die neue Dokumentenstruktur ist es offensichtlich, dass OPC UA auch hierfür Möglichkeiten bereitstellt. Seit der Version 1.5.2 gibt es einen eigenen Part (UA Part 20: File Transfer), der die Typen zum Dateitransfer aus dem Part 5 ausgliedert. In diesem Beitrag werden die verschiedenen Möglichkeiten des Dateitransfers über OPC UA anhand von Anwendungsbeispielen vorgestellt und der OPC UA File Transfer anschließend mit den anderen Protokollen verglichen.

Die Mechanismen und Typen für die Datenübertragung sind in OPC UA schon sehr lange vorhanden. Sowohl der FileType (als ObjectType) als auch der ImageType (als ByteString) gehören zum Build-In Modell und befinden sich in vielen verschiedenen Companion Specifications (z.B. in Machine Vision, CNC, Flat Glass) im Einsatz.

Grundsätzlich lassen sich drei Varianten für den Dateitransfer über OPC UA unterscheiden, wobei Variante 3 eine Erweiterung von Variante 2 darstellt:

  • Variante 1: Via Data Access einer Variable
  • Variante 2: Via Methodenaufruf des FileTypes
  • Variante 3: Via Methodenaufruf des TemporaryFileType und des FileTypes

Variante 1: Data Access einer Variable

Im Server wird eine Variable angelegt, die per Data Access aus- und eingelesen werden kann. Der OPC UA Standard schlägt hierzu ByteString als DataType vor und bietet zudem Subtypen für Audiodaten (AudioDataType), für Bilder (ImageType) oder für die verschiedenen Bilddateiformate, wie zum Beispiel GIF oder JPG, an.

In OPC UA for Devices (OPC UA DI) wird diese Art der Dateiübertragung in dem Interface ISupportInfoType umgesetzt. Abbildung 1 zeigt eine schematische Darstellung des Interfaces. Es besteht aus fünf Ordnern, die jeweils Dateien enthalten. DeviceTypeImage und ImageSet enthalten jeweils einen MandatoryPlaceholder für Variablen mit dem DataTypeImageType. Die Ordner Documentation und ProtocolSupport enthalten jeweils MandatoryPlaceholder vom DataTypeByteString und können z.B. Text- oder PDF-Dateien sein. Der letzte Ordner DocumentationFiles enthält alternativ ebenfalls Dokumentationsdateien, die jedoch mittels FileType übertragen werden. Deren Verwendung wird in Variante 2 beschrieben.

Während es bei der Nutzung von Subtype des ImageType klar ist, welches Format die Datei (das Bild) hat, ist dies bei ByteString (Documentation / ProtocolSupport) nicht eindeutig. Daher verlangt OPC UA DI, dass der BrowseName aller Variablen aus dem Dateinamen einschließlich der Erweiterung besteht (z.B. “readme.txt”, “instruction.pdf”). So kann das Dateiformat anhand der Erweiterung identifiziert werden.

Der größte Nachteil dieser Variante ist die mögliche Größe der Datei. Sowohl die OPC UA DI Companion Specification als auch UA Part 20: File Transfer weisen darauf hin, dass großen Inhalte (die bei dieser Art von Daten zu erwarten sind) zu Einschränkungen im Client- oder im Server-Stack führen können. Diese sind auf (Ressourcen-) Beschränkungen zurückzuführen. Einen Erfahrungswert, wie groß diese Dateien in der Praxis tatsächlich sein können, gibt es bisher nicht. In OPC UA DI ist die maximale Größe für ein Array von Bytes standardmäßig mit 1 Megabyte angegeben. In Anwendungen wurden jedoch bereits Dateien mit einer Größe von bis zu 16 Megabyte realisiert. Einen Hinweis kann das Property MaxByteStringLength (unter Server.ServerCapabilities) geben, dass ein OPC UA Server optional angeben kann.

Die Variante 1 hat den Vorteil, dass sie sehr einfach zu implementieren und anzuwenden ist. Eine einfache Anfrage reicht bereits aus. Allerdings kann sie nur für kleinere Dateien wie Bilder genutzt werden.

Variante 2: Methodenaufruf des FileTypes

Die zweite Variante nutzt die OPC UA Objektstruktur und OPC UA Methoden, um Dateien zu übertragen. Hierfür kommt der ObjectTypeFileType ins Spiel, der eine Datei repräsentiert und mit Methoden angesprochen oder mit Eigenschaften beschrieben wird.

Die Methoden des FileTypes entsprechen dabei den Methoden in klassischen Programmiersprachen wie zum Beispiel C oder C++, wie die Tabelle 1 zeigt:

OPC UA Methode

C/C++ methods (see [1])

Kommentar

Open

fopen

Beide Methoden öffnen eine Datei und benötigen einen mode als Information, wie die Datei behandelt werden soll (z.B. readonly, read/write). Beide geben ein FileHandle zurück, das von allen anderen Methoden verwendet werden muss. Der FileHandle enthält Informationen über die Zugriffsrechte und die Position innerhalb der Datei.

Close

fclose

Der Gegenspieler zu der Methode Open; Gibt die Datei wieder frei.

Read

fread

Beide Methoden benötigen als Eingabe den FileHandle und die Anzahl der zu lesenden Elemente und geben dann die gelesenen Elemente aus.

Write

fwrite

Beide Methoden haben als Eingabe den FileHandle und die Daten, die in die Datei geschrieben werden sollen.

GetPosition

fgetpos

In beiden Fällen wird der FileHandle als Eingabe genutzt und die aktuelle Position, an der geschrieben/gelesen wird, zurückgegeben.

SetPosition

fsetpos

In beiden Fällen wird neben dem FileHandle auch die neue Position von FileHandle angegeben und die Position entsprechend neu gesetzt.

Tabelle 1: Comparison between OPC UA FileType and C/C++ file methods

Hierbei ist der Ablauf zur Interaktion mit der Datei in beiden Fällen derselbe, ob lesend oder schreibend. Zuerst wird die Datei geöffnet (call Open method) und ggf. für andere Applikationen gesperrt. Über den mode wird festgelegt, ob der Zugriff auf die Datei nur schreibend, lesend oder schreibend und lesend erfolgen soll. Die Open-Methode gibt anschließend einen sogenannten FileHandle zurück, der in den folgenden Methoden angegeben werden muss. Der FileHandle wird vom Server generiert und ist für die Session eindeutig. Er enthält sowohl die Zugriffsrechte auf die Datei als auch die aktuelle Position, an der sie geschrieben wird. Abschließend wird die Datei mit der Methode Close wieder freigegeben.

Ein Unterschied zu vielen Programmiersprachen besteht darin, dass der mode nicht als String (z.B. „r“ für Read), sondern als 8-Bit-Bitmask (z.B. 0 für Read) angegeben wird. Tabelle 2 zeigt eine Gegenüberstellung des OPC UA mode mit dem C++ mode. Durch die Bitmask kann der mode von C++ auch in OPC UA abgebildet werden.

OPC UA

C++

Kommentar

Action if file already exists

Action if file does not exist

Append

 EraseExisting

Write

Read

0

0

0

1

"r"

Open a file for reading

read from start

error

0

1

1

0

"w"

Create a file for writing

destroy contents

create new

1

0

1

0

"a"

Append to a file for writing

write to end

create new

0

0

1

1

"r+"

Open a file for read/write

read from start

Error in C/C++ [2]

0

1

1

1

"w+"

Create a file for read/write

destroy contents

create new

1

0

1

1

"a+"

Open a file for read/write

write to end

create new

Tabelle 2: Comparison between OPC UA file mode and C/C++ file mode

Der FileType kann sowohl nur an einzelnen Stellen wie z.B. im Ordner DocumentationFiles des ISupportInfoType (siehe Abbildung 1) als auch in Kombination mit dem FileDirectoryType und dem FileSystemType verwendet werden, um ein gesamtes Filesystem abzubilden (für Details siehe UA Part 20: File Transfer). Dies wird z.B. im CncInterfaceType der Companion Specification OPC UA for CNC umgesetzt.

Durch das Aufteilen der Datei in kleinere Chunks können auch große Dateien problemlos über OPC UA übertragen werden. Dies geht jedoch mit einem höheren Verwaltungsaufwand sowohl im Server als auch im Client einher. Gerade wenn ein gesamtes Dateisystem abgebildet werden soll, große Dateien übertagen werden sollen oder die Dateigröße noch nicht absehbar ist, sollte ein FileType gegenüber Variante 1 (Via Data Access einer Variable) bevorzugt werden. Ein weiterer Vorteil von Variante 2 ist, dass die Methoden den gleichzeitigen Zugriff besser bewältigen können.

Variante 3: Methodenaufruf des TemporaryFileTypes

Die letzte Variante stellt eine Erweiterung des Konzepts um den FileType dar. Manchmal sind Dateien nur temporär auf dem Server zugänglich oder sollen nur temporär zur Verfügung stehen, z.B. bei Firmware-Updates, Recipe-Uploads oder Result Report-Downloads. In diesen Fällen sind zusätzliche Schritte zur Vorbereitung der Dateiübertragung notwendig. Für solche Zwecke kann der TemporatryFileType genutzt werden.

Dieser hat zwei Generatormethoden (GenerateFileForRead/ GenerateFileForWrite), die jeweils ein temporäres FileType-Objekt mit dem Inhalt der Datei erzeugen (GenerateFileForRead) und die NodeId diesesObjekts sowie den FileHandle für den Zugriff auf die Datei zurückgeben. Auf das Dateiobjekt kann nicht im Addressbereich zugegriffen werden, sondern nur mit der von der Methode GenerateFileForRead oder GenerateFileForWrite zurückgegebenen Nodeld.

Sollte die Erzeugung oder Vorbereitung asynchron zum Methodenaufruf erfolgen oder längere Zeit in Anspruch nehmen, kann zusätzlich ein Transfer-Zustandsapparat (type: FileTransferStateMachineType) bereitgestellt werden, der den aktuellen Zustand des Transfers angibt.

Die Handhabung des Dateiobjekts erfolgt nach dem Erstellen analog zu der Variante 2. Hierzu muss die Open-Methode nicht aufgerufen werden und beim Schreiben am Ende sollte die CloseAndCommit-Methode statt der Close-Methode aufgerufen werden. Damit werden die Inhalte angewendet und die temporäre Datei wird nach der Transaktion gelöscht.

In OPC UA DI wird diese Methode für den Download und Upload der Software eingesetzt. Ein weiterer Einsatz erfolgt beim ResultTransferType aus OPC UA for Machinery, der für die Übertragung komplexer Prüfergebnisse vorgesehen ist. Hierzu wird ein entsprechender Report für ein Messergebnis erzeugt und an den Client übertragen. Insbesondere bei Geräten mit wenigen Ressourcen ist es sinnvoll, den Report erst dann zu erzeugen, wenn die Datei mit GenerateFileForRead an den Client übertragen wird.

Der Vorteil dieser 3. Variante liegt darin, dass die Datei und damit auch der Speicherplatz nicht auf dem Server vorgehalten werden müssen. Als Nachteil ist die Erhöhung der Komplexität zu nennen. In Bezug auf die Übertragungsqualität ist sie jedoch identisch mit Variante 2.

Vergleich mit anderen Protokollen

Um die Übertragungsqualität verschiedener Protokolle zu vergleichen, spielen viele Faktoren eine Rolle. Unter anderem die verwendeten Programme, Paketausfälle und die Bandbreite. Für diesen Artikel wird ein minimaler Vergleich durchgeführt, der die meisten dieser Faktoren außer Acht lässt. Daher hat der Versuch keinen wissenschaftlichen Anspruch und soll nur einen rudimentären Vergleich zwischen OPC UA, FTP und HTTP ermöglichen. Der verwendete Quellcode steht als Open Source unter GitHub zur Verfügung (https://github.com/Kantiran91/opcua-filetransfer-comparison).

Der Hardwareaufbau besteht aus zwei Laptops, die über Wifi verbunden sind. Auf einem von ihnen laufen ein OPC UA Server (eclipse Milo), ein FTP Server (ftp docker) und ein HTTP Server (apache2), die jeweils eine Datei mit 79,6 MB bereitstellen. Auf dem anderen Rechner wird ein Python-Skript gestartet, das die Datei jeweils per OPC UA (asyncua), FTP (ftplib) und HTTP (requests) client herunterlädt. Der Vergleich wird jeweils zehnmal wiederholt. Tabelle 3 zeigt jeweils die maximale, minimale und durchschnittliche Transferzeit.

Protocol

Max transfer time

Min transfer time

Average transfer time

HTTP

36.96 [s]

17.01 [s]

22.27 [s]

FTP

34.73 [s]

19.41 [s]

22.99 [s]

OPC UA

23.88 [s]

18.21 [s]

20.53 [s]

Tabelle 3: Comparison of transfer time of 83 MB file via HTTP, FTP, OPC UA binary

Grundsätzlich sind die Ergebnisse des OPC UA Protokolls etwas besser als die von HTTP oder FTP. Da die Schwankungen innerhalb des Protokolls jedoch deutlich höher sind (mehr als 19 Sek. bei HTTP), ist zu vermuten, dass das Netzwerk selbst einen höheren Einfluss auf die Übertragung hat als die Auswahl des Protokolls.

Zusammenfassung

OPC UA bietet verschiedene Möglichkeiten zur Übertragung von Dateien. Für kleine Dateien kann problemlos eine Variable vom Type ByteString gewählt werden. Für größere Dateien, Dateisysteme oder temporär erzeugte Dateien stehen mit dem FileType oder TemporatryFileType zwei ObjectType mit Methoden zur Verfügung. Diese bieten den Vorteil, dass die Datei in mehrere Chunks aufgeteilt werden kann.

Die Übertragungsgeschwindigkeit von Dateien über OPC UA ist vergleichbar mit den gängigen Protokollen und stellt daher eine vollwertige Alternative zu diesen da. Es bietet damit die Möglichkeit, Dateien zu übertragen, ohne weitere Kommunikationskanäle zu den Geräten aufzumachen oder weitere Autorisierungs- und Authentifizierungsmechanismen einzubauen.

 

[1] https://en.cppreference.com/w/cpp/io/c
[2] In OPC UA the behavior is depending on the server implementation