File transfer via OPC UA
By now, there is now a broad consensus that OPC UA can be used for many different applications. It can also be said that OPC UA offers many different ways to achieve the same result. One topic that is frequently discussed in OPC UA working groups is file transfer. The new document structure makes it clear that OPC UA provides options for this: since version 1.5.2, file transfer has been removed from Part 5 and given its own section (UA Part 20: File Transfer). This article will present the different options for file transfer via OPC UA, provide application examples, and then compare OPC UA file transfer with other protocols.
The mechanisms and types for file transfer have been available in OPC UA for a long time. The FileType (as ObjectType) and the ImageType (as ByteString) have long been part of the built-in model and are also used in many Companion Specifications (e.g.; Machine Vision, CNC, Flat Glass).
There are three basic variants for file transfer via OPC UA (with Variant 3 being an extension of Variant 2):
Variant 1: Via data access of a variable
Variant 2: Via method call of the FileType
Variant 3: Via method call of the TemporaryFileType and the FileType
Variant 1: Data access of a variable
A variable is created on the server that can be read and written via data access. The OPC UA standard suggests using ByteString as the DataType, and even provides subtypes for audio data (AudioDataType) and images (ImageType) in various image file formats such as GIF or JPG.
In OPC UA for Devices (OPC UA DI), this type of file transfer is implemented in the ISupportInfoType interface. Figure 1 shows a schematic diagram of the interface. It consists of five folders, each of which contains files. DeviceTypeImage and ImageSet each contain a MandatoryPlaceholder for variables with the DataTypeImageType. The Documentation and ProtocolSupport folders each contain MandatoryPlaceholders of DataTypeByteString and can contain text files or PDF files, for example. Alternatively, the folder DocumentationFiles may also contain documentation files which are transferred via FileType. Their use is described in variant 2.
While the file format of the (image) file is clear when using the subtype of the ImageType, this is not the case with ByteString (Documentation/ ProtocolSupport). OPC UA DI therefore requires that the BrowseName of each variable consists of the file name, including the extension (e.g.; "readme.txt", "instruction.pdf"). This makes it possible to identify the file format.
The biggest potential limitation of this variant is file size. Both the OPC UA DI Companion Specification and UA Part 20: File Transfer state that large contents (which are to be expected with this type of variable) may lead to limitations due to (resource) constraints in the client or server stack. A common empirical value of just how large these files can actually be in practice does not yet exist. OPC UA DI specifies the standard maximum size for an array of bytes as 1 megabyte. However, files up to 16 megabyte have already been used in some applications. An OPC UA server can use the optional ByteStringStringLength property (under Server.ServerCapabilities) to specify the maximum size of a ByteString variable.
The advantage of this variant is that it is straightforward to implement and use (one request is sufficient), but it is only suitable for smaller files like images.
Variant 2: Method call of the FileType
The second file transfer variant uses the OPC UA object structure and methods. The ObjectTypeFileType, which represents a file and is addressed with methods or described with properties, exists for this purpose.
The methods of the FileType correspond to the methods in programming languages such as C or C++, as can be seen in Table 1:
OPC UA method | C/C++ methods (see [1]) | Comment |
---|---|---|
Open | fopen | Both methods open a file and require a mode as information on how the file should be handled (e.g.; read-only, read/write). Both return a fileHandle which must be used by all other methods. The fileHandle contains information about the access rights and the position within the file. |
Close | fclose | Opposite of the open method; releases the file. |
Read | fread | Both methods require the fileHandle and the number of elements to be read as input, and then output the read elements. |
Write | fwrite | Both methods have the fileHandle and the data to be written to the file as input. |
GetPosition | fgetpos | In both cases, the fileHandle is used as input and the current position at which the file is written/read is returned. |
SetPosition | fsetpos | In both cases, the new position of the fileHandle is specified in addition to the fileHandle and the position is reset accordingly. |
Table 1: comparison between OPC UA FileType and C/C++ file methods
The sequence for handling the file is also the same in both cases (reading/writing). First, the file is opened (call Open method) and locked for other applications if necessary. The mode specifies whether the file is read only, write only, or read and write. The Open method then returns a so-called fileHandle, which must be specified in the following methods. The fileHandle is generated by the server and is unique for the session. It contains both the access rights to the file and the current position at which it is written. Finally, the Close method releases the file.
One difference to many programming languages is that the mode is not specified as a string (e.g., “r” for read), but as an 8-bit bitmask (e.g.; 0 for read). Table 2 shows a comparison of the OPC UA mode with the C++ mode . Due to the bitmask, the mode from C++ can also be mapped in OPC UA.
OPC UA | C++ | Comment | 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 |
Table 2: Comparison between OPC UA file mode and C/C++ file mode
The FileType can either be used in single locations such as in the DocumentationFiles folder of the ISupportInfoType (see Figure 1), or in combination with the FileDirectoryType and FileSystemType to map a complete file system (see UA Part 20: File Transfer for details). For example, this is implemented in the CncInterfaceType of the OPC UA for CNC Companion Specification.
By splitting the file into smaller chunks, even large files can be transferred via OPC UA without problems. However, this is accompanied by increased effort for both the server and the client. Especially if an entire file system is to be mapped, large files are to be transferred, or the file size cannot yet be determined, FileType is preferable to “Variant 1: via Data Access of a variable”. Another advantage is that simultaneous access can be handled better by the method.
Variant 3: Method call of the TemporaryFileType
The last variant represents an extension of the FileType concept. Sometimes files should only be stored on the server temporarily or should only be temporarily available (e.g.; firmware update, recipe upload, or result report download). This requires additional steps to prepare the file transfer. The TemporatryFileType can be used in this case.
This has two generator methods (GenerateFileForRead/GenerateFileForWrite), each of which creates a temporary FileType object with the content of the (GenerateFileForRead) file and returns the NodeId of this object as well as theFileHandle for accessing the file. The file object cannot be accessed in the AddressSpace and can only be accessed with the NodeId returned by the GenerateFileForRead or GenerateFileForWrite method.
If the creation or preparation is asynchronous to the method call or takes a long time, an additional transfer state machine (type: FileTransferStateMachineType) can be provided which indicates the current status of the transfer.
As with Variant 2, the handling of the file object takes place after the creation. However, the Open method does not need to be called and the CloseAndCommit method is called in place of the Close method at the end when writing. This applies the content and then deletes the temporary file after the transaction.
In OPC UA DI, this method is used to download and upload software. Another successful use case is with the ResultTransferType from Machinery, which is designed to generate a corresponding report for a measurement result and transfer it to the client. Especially for devices with few resources, it makes sense to generate the report only when the file is transferred to the client with GenerateFileForRead.
The advantage of this variant is that it saves resources on the server, but it is accompanied by additional complexity. However, it is identical to Variant 2 with regard to the transfer quality.
Comparison with other protocols
Many factors play a role in comparing the transmission quality of different protocols, such as the programs used, packet dropout, and the bandwidth among other things. For the purpose of this article, a simplified comparison is made which ignores most of these factors. Thus, this experiment has no scientific claim and should only be used for a rudimentary comparison between OPC UA, FTP, and HTTP. The source code used is available under open source at GitHub (https://github.com/Kantiran91/opcua-filetransfer-comparison).
The hardware setup consists of two laptops connected via Wi-Fi. One machine is running an OPC UA server (eclipse Milo), an FTP server (ftp docker), and an HTTP server (apache2), each hosting a 79.6 MB file. A python script is started on the other machine which downloads the file via the OPC UA (asyncua), FTP (ftplib), and HTTP (requests) clients, respectively. This comparison is repeated 10 times in each case. Table 3 shows the maximum, minimum, and average transfer times.
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] |
Table 3: Comparison of the transfer times for an 80 MB file via HTTP, FTP, OPC UA binary
Generally speaking, the results for the OPC UA protocol are slightly better than those for HTTP or FTP. However, since the difference between max transfer time and min transfer timer of the protocols (e.g., the difference in HTTP is 19,95[s]) are significantly higher, it can be assumed that the network itself has a greater influence on the transmission than the selection of the protocol.
Summary
OPC UA offers multiple options for transferring files. For small files, a variable of the ByteString type can be used without major compromises. For larger files, file systems, or temporary files, two ObjectType methods are available with FileType or TemporatryFileType. These offer the advantage that the file can be divided into multiple chunks.
File transmission speeds via OPC UA are comparable to common protocols. Therefore, it represents a viable alternative for transferring files without needing to open additional communication channels on the devices or implement further authorization and authentication mechanisms.
[1] https://en.cppreference.com/w/cpp/io/c
[2] In OPC UA, the behavior depends on the server implementation