Quick start

Quick start 1:

This documentation article only applies to the TwinCAT FTP Client from version 4.x.

This documentation article is intended to allow you an initial, quick start in how to use this product. You can also download the program code below at Samples. The program code for a quick start with older product versions can also be found there. Following successful installation and licensing, perform the following steps in order to establish a connection to an FTP/SFTP server and configure variables for the read/write access.

Configuring an FTP/SFTP server

This QuickStart article requires a pre-configured and functioning FTP/SFTP server. In principle, you can use any FTP/SFTP server application for this, e.g. FileZilla, Microsoft IIS, OpenSSH server, Tiny SFTP server, and many more.

In the rest of this article we will use the following settings, please replace the parameters with those of your test setup if necessary:

Property

Description

Server type

SFTP server

Host name

The server is installed on the local system and can therefore be reached via the IP address 127.0.0.1.

Port

23

User name

My_SFTP_User

Password

SomeSecurePassword##1

Root directory

\

Authorizations

User has read/write access to the directory

Using the Tc3_Ftp library for the FileUpload

We now want to establish a connection to the SFTP server and upload a file to the root directory of the above-mentioned user. To do this, create a new TwinCAT project and a PLC project and reference the Tc3_FTP library there. Then go to the MAIN program and add the following lines of code.

Declaration part:

PROGRAM MAIN
VAR
    fbSimpleUpload : FB_SimpleUpload;
END_VAR

Implementation part:

fbSimpleUpload();

Then add a POU and name it FB_SimpleUpload. Add the following lines of code there.

Declaration part:

FUNCTION_BLOCK FB_SimpleUpload
VAR
    bStart             : BOOL; // Starts the QuickStart sample

    fbConnection       : FB_FtpConnection(1) := (sNetID:= '', tTimeout:= T#60S);
    fbExplorer         : FB_FtpExplorer := (sNetID:= '', tTimeout:= T#60S);
    fbTransfer         : FB_FtpTransfer := (sNetID:= '', tTimeout:= T#60S);
  
    stTransferInfo     : ST_FtpTransferState;
    stNTDataProfile    : ST_FtpConfigProfile;
  
    sPathToOriginFile  : STRING(255) := 'C:\Temp\myFileUpload.txt';
    sPathToTargetDir   : STRING(255) := '\';

    bDone              : BOOL;
    bError             : BOOL;
    sErrorMSG          : STRING(255);
    nCase              : INT;
    nTransferHandle    : UDINT;
    fbTimer            : TON := (PT:=T#1S); 
END_VAR

Implementation part:

CASE nCase OF
    0: (* Start the QuickStart sample. *)
        IF bStart THEN
            bDone := FALSE;
            bStart := FALSE;
            nCase := 10;
        END_IF
        
    10: (* Connect to server by specifying the profile. Create a new profile if the connection profile does not exist, yet. *)
        IF fbConnection.Connect(
            sFtpConfigProfileFileName:='QuickStart'
        ) THEN
            nCase := 15;
        END_IF
        
    11: (* Connection profile does not exist, yet. Specify connection parameters and store in a new profile. *)
        stNTDataProfile.stConnection.eAuth := E_FtpConnectionAuth.sftp_user_pwd;
        stNTDataProfile.stConnection.nPort := 23;
        stNTDataProfile.stConnection.sHostname := '127.0.0.1';
        stNTDataProfile.stConnection.sUsername := 'My_SFTP_User';
        stNTDataProfile.stConnection.sPassword := 'SomeSecurePassword##1';
        stNTDataProfile.stConnection.sFileName := 'QuickStart';
        
        IF fbConnection.AddProfile(
            stFtpConfigProfile := stNTDataProfile
        ) THEN
            nCase := 16;
        END_IF

    15: (* Check connection establishment for any errors. *)
        IF fbConnection.bError THEN
            IF fbConnection.ipResultMessage.EqualsToEventClass(Global.TC_EVENT_CLASSES.TcFtpClientEventClass) THEN
                CASE fbConnection.ipResultMessage.nEventId OF
                    E_FtpClientErrorCode.Code_1101_HostConnectionOpen: (* Already connected to the correct host, continue*)
                        nCase := 20;
                    E_FtpClientErrorCode.Code_1100_AnyConnectionOpen: (* Already connected to another host. Abort.*)
                        nCase := 210;
                    E_FtpClientErrorCode.Code_1102_FileLocationError: (* Profile has not been created yet. *)
                        nCase := 11;
                ELSE
                    nCase := 210; (* an unexpected FtpClient error has occured *)
                END_CASE
            ELSE
                nCase := 210; (* an unexpected other error (Ads, Router, ...) has occured*) 
            END_IF
        ELSE
            nCase := 20; (* Start file upload. *)
        END_IF

    16: (* Check profile creation for any errors *)
        IF fbConnection.bError THEN
            IF fbConnection.ipResultMessage.EqualsToEventClass(Global.TC_EVENT_CLASSES.TcFtpClientEventClass) THEN
                CASE fbConnection.ipResultMessage.nEventId OF
                    E_FtpClientErrorCode.Code_1106_ParametersImproper: (* The profile is configured improperly (e.g. HostName empty or Port 0) *)
                        nCase := 210;
                ELSE
                    nCase := 210; (* an unexpected FtpClient error has occured *)
                END_CASE
            ELSE
                nCase := 210; (* an unexpected other error (Ads, Router, ...) has occured*) 
            END_IF
        ELSE
            (* now that the profile has been created, try connecting again *)
            nCase := 10;
        END_IF 

    20: (* Initiate file upload. *)
        IF fbTransfer.Upload(
            fbFtpConnection         := fbConnection, 
            sLocalSourcePath         := sPathToOriginFile,    
            sServerTargetDirectory     := sPathToTargetDir,
            nTransferHandle         => nTransferHandle
        ) THEN
            nCase := 25;
        END_IF

    25: (* Check file upload initiation for any errors*)
        IF fbTransfer.bError THEN
            IF fbTransfer.ipResultMessage.EqualsToEventClass(Global.TC_EVENT_CLASSES.TcFtpClientEventClass) THEN
                CASE fbTransfer.ipResultMessage.nEventId OF
                    E_FtpClientErrorCode.Code_1106_ParametersImproper: (* Source or Target could be empty *)
                        nCase := 210;
                    E_FtpClientErrorCode.Code_1110_Busy_TryAgain: (* The connection is busy (ONLY FTP). Try again later. *)
                        nCase := 210;
                ELSE
                    nCase := 210; (* an unexpected FtpClient error has occured *)
                END_CASE
            ELSE
                nCase := 210; (* an unexpected other error (Ads, Router, ...) has occured*) 
            END_IF
        ELSE
            (* now that the transfer has been initialised, check transfer state *)
            nCase := 30;
        END_IF 
        
    30: (* File upload has been started, now cyclically check transfer state. *)
        fbTimer(IN:=TRUE); 
        IF fbTimer.Q THEN
            fbTimer(IN:=FALSE);
            nCase := 40;
        END_IF

    40: (* Request transfer state *)
        IF fbTransfer.GetState(
            fbFtpConnection         := fbConnection,
            nTransferHandle         := nTransferHandle,
            stTransferState            => stTransferInfo
        ) THEN
            nCase := 45;
        END_IF
        
    45: (* Check GetState for any errors*)
        IF fbTransfer.bError THEN
            IF fbTransfer.ipResultMessage.EqualsToEventClass(Global.TC_EVENT_CLASSES.TcFtpClientEventClass) THEN
                CASE fbTransfer.ipResultMessage.nEventId OF
                    E_FtpClientErrorCode.Code_1106_ParametersImproper: (* The transfer for the provided handle could not be found *)
                        nCase := 210;
                ELSE
                    nCase := 210; (* an unexpected FtpClient error has occured *)
                END_CASE
            ELSE
                nCase := 210; (* an unexpected other error (Ads, Router, ...) has occured*) 
            END_IF
        ELSE
            nCase := 50;
        END_IF

    50: (* Check if file transfer is completed and has not produced any errors *)
        IF (stTransferInfo.eProblem = E_FtpTransferProblemType.None) AND (stTransferInfo.eStep = E_FtpTransferStep.TransferCompleted) THEN
            nCase := 60; // file transfer completed with no errors
        ELSIF stTransferInfo.eProblem <> E_FtpTransferProblemType.None THEN
            nCase := 210; //file transfer encountered an error
        ELSE
            nCase := 30; // not completed yet, check state again
        END_IF
        
    60: (* Disconnect from server. *)
        IF fbConnection.Disconnect() THEN
            nCase := 65;
        END_IF
        
    65: (* Check disconnect for any errors *)
        IF fbConnection.bError THEN
            nCase := 200; (* continue, but warn user that something happened on disconnect *)
        ELSE
            nCase := 70; (* All clear, connection terminated. *)
        END_IF 

    70: (* File upload completed. *)
        bDone := TRUE;
        nCase := 0;

    200: (* File upload completed but unexpected error on disconnect from server. *)
        bDone := TRUE;
        bError := TRUE;
        sErrorMSG := 'Upload was completed successfully, but received error on disconnect. Check [fbConnection.ipResultMessage] for details.';
        nCase := 0;

    210: (* An error has occured. *)
        bDone := TRUE;
        bError := TRUE;
        sErrorMSG := 'Failed to Upload. Check [fbConnection.ipResultMessage] and [stTransferInfo.eProblem]';
        nCase := 0;

END_CASE

Explanation of the program flow

When the program is started (setting the variable bStart to TRUE), the state machine executes a program sequence which first creates a connection profile if this does not yet exist. The system then checks whether a connection to the SFTP server already exists. If no, a connection is initiated with the specified connection parameters. In the next step, the file upload is started and the file "C:\Temp\myFileUpload.txt'" is uploaded to the SFTP server in its root directory. The state machine then immediately jumps one step further and monitors the progress of the file upload at regular intervals. Once the upload is complete, the state machine jumps to the final step and disconnects from the SFTP server. The state machine then returns to the initial step.