.NET Based OPC UA Client/Server SDK  3.2.1.522
Temporary File Transfer Example

The temporary file transfer allows either to generate a file by the server and transfer it to the client or to write a file from the client to the server and apply the file content. In both cases, the file is only available in the address space for the specific client while it is transferred.

Reading Files

Typical use cases for reading temporary files are providing specific reports, the current configuration of the system or a module, or the current log. The temporary file transfer allows the client to parameterize the file creation, for example defining the format of the report.

In order to provide temporary file transfer an object of TemporaryFileTransferType or a subtype needs to be provided. In order to provide temporary file transfer an object of TemporaryFileTransferType or a subtype needs to be provided. The client first calls GenerateFileForRead (which may contain configuration parameters) and gets back a NodeId and FileHandle of an already opened file object. Then the client transfers the file by reading it. When closing the file, the file object is removed. Since the file generation may take some time, the GenerateFileForRead may also return a state machine object indicating when the file is actually ready to be accessed.

Writing Files

A typical use case for writing temporary files is that a new configuration shall be applied to the server. The configuration might effect the whole system or just a specific part. Like for the read, the temporary file transfers allows the client to parameterize the file to be written, for example defining the configuration format.

Like for the read, an object of TemporaryFileTransferType or a subtype needs to be provided. The client first calls GenerateFileForWrite and gets back a NodeId and FileHandle of an already opened file object to be written. The client then writes the content into the file and afterwards calls CloseAndCommit. This method either directly returns a status if the operation was successful, or in case the deployment takes some time a state machine object that finally returns the status of the operation.

Example in Demo Server

The demo server provides an example of the temporary file transfer for reading a parameterized file, without returning a state machine, since the generation is fast.

Creating an ObjectType

In order to use parameterization, a subtype of TemporaryFileTransferType needed to be created. This is done in the model (Model\demoserver.xml) and code is generated for the new ObjectType SpecialTemporaryFileTransferModel (Model\ModelClasses.cs). The SpecialTemporaryFileTransferModel has changed the GenerateFileForRead method to take a string as GenerateOptions.

Creating an Object

The creation of an instance can be found in UnifiedAutomation.Demo.DemoNodeManager.SpecialTemporaryFileTransfer.cs.

public void SetupSpecialTemporaryFileTransfer()
{
m_temporaryFiles = new Dictionary<TemporaryFile, uint>();
CreateObjectSettings settings = new CreateObjectSettings()
{
ParentNodeId = new NodeId(Model.Objects.Demo_Files, DefaultNamespaceIndex),
ReferenceTypeId = ReferenceTypeIds.Organizes,
RequestedNodeId = new NodeId("Demo.Files.TempFile", DefaultNamespaceIndex),
BrowseName = new QualifiedName("TempFile", DefaultNamespaceIndex),
TypeDefinitionId = new NodeId(Model.ObjectTypes.SpecialTemporaryFileTransferType, DefaultNamespaceIndex),
Description = new LocalizedText("This object can be used to generate a temporary file on the server to " +
"provide information to the client. The temporary file is deleted after a time period defined in " +
"\"ClientProcessingTimeout\" of non-use, or if the client closes the file.")
};
var objectNode = CreateObject(Server.DefaultRequestContext, settings);
var objectImplementation = new Model.SpecialTemporaryFileTransferModel();
objectImplementation.TemporaryFileTransferMethods = this;
objectImplementation.ClientProcessingTimeout = 10000; // important to set, if default (0) it will not work
LinkModelToNode(objectNode.NodeId, objectImplementation, null, null, 100);
}

The DemoManager calls the SetupSpecialTemporaryFileTransfer method during startup which creates the object TempFile under Root -> Objects -> Demo -> 014_Files. You can access this object with the UaExpert and right click and select Read to local file ... to try out the mechanism.

Implementation of methods

The implementation of the methods can be found in Demo\DemoNodeManager.SpecialTemporaryFileTransfer.cs. The implementation of GenerateFileForRead is actually creating a local text file taking the generateOptions string as content and uses the FileModel as base to manage it as object in the server.

public StatusCode GenerateFileForRead(RequestContext context,
Model.SpecialTemporaryFileTransferModel model,
string GenerateOptions,
out NodeId FileNodeId,
out uint FileHandle,
out NodeId CompletionStateMachine)
{
var fileModel = CreateFile(GenerateOptions, (int)model.ClientProcessingTimeout, context.Session, out FileNodeId);
fileModel.Open(context, fileModel, (byte)FileAccessModes.Read, out FileHandle);
fileModel.Timeout += FileModel_Timeout;
fileModel.Closed += FileModel_Closed;
CompletionStateMachine = null; // we can directly generate the file so we do not need this state machine
m_temporaryFiles.Add(fileModel, FileHandle);
return StatusCodes.Good;
}

This is just used for demonstration purposes, in a real application you would generate something more reasonable. When the transfer is completed and the client closes the file, the server removes the temporary file object and deletes the temporary file created on disk.

private void DeleteFile(TemporaryFile model)
{
DeleteNode(Server.DefaultRequestContext, model.UserData as NodeId, true);
m_temporaryFiles.Remove(model);
model.FileOnDisk.Delete();
model.Dispose();
}

Timeout

The temporary file transfer object defines a timeout (ClientProcessingTimeout). When the client is not accessing the file for the duration of the timeout, the server is supposed to remove the temporary file. The timeout is defined when creating the object.

ObjectImplementation.ClientProcessingTimeout = 10000; // important to set, if default (0) it will not work

The implementation resets the timeout each time the file is accessed (typically by calling the Read method).

public override StatusCode Read(RequestContext context, FileModel model, uint fileHandle, int length, out byte[] data)
{
if (m_session != context.Session)
{
data = null;
return StatusCodes.BadUserAccessDenied;
}
ResetTimer();
return base.Read(context, model, fileHandle, length, out data);
}

If the timeout is hit, it removes the temporary file object and deletes the file created on disk.

private void FileModel_Timeout(TemporaryFile model, EventArgs e)
{
// if running into timeout, file probably needs to be closed first
try
{
model.CloseFile(Server.DefaultRequestContext, m_temporaryFiles[model]);
}
catch (Exception) { }
finally
{
DeleteFile(model);
}
}