Showing results for 
Search instead for 
Did you mean: 
Showing results for 
Search instead for 
Did you mean: 

Community Tip - You can Bookmark boards, posts or articles that you'd like to access again easily! X

C SDK Tutorial Part 4

No ratings


Step 9: File Transfer Example


To handle file transfers, a virtual directory is created in the SteamSensor1 entity and in the [C SDK HOME DIR]/examples/FileTransferExample application directory. The source code used for this example is found in [C SDK HOME DIR]/examples/FileTransferExample/src/main.c.


  1. Inside of the [C SDK HOME DIR]/examples/FileTransferExample folder, create the folder structure shown below:




  2. Inside of the /transfer/outgoing/ directory, create and open a file with the name outgoing.txt.

  3. Once the outgoing.txt document is open, add the following text, save, and close the file:

    Hello. This is a file coming from the client application.
  4. Navigate to the [C SDK HOME DIR]/examples/FileTransferExample/src/main.c code and update the lines below with the appropriate information for your IP, port, and the “admin_key Application Key’s keyId value in the ThingWorx Composer:


    /* Server Details */
    #define TW_HOST ""
    #define TW_PORT 80
    #define TW_APP_KEY "ce22e9e4-2834-419c-9656-ef9f844c784c"


  5. To support file transfers in your client application, you must use the   twFileManager_AddVirtualDir function in order to create the virtual directories in the entity with such a capability. It will also define the directories available for file operations. A virtual directory maps a unique name to an absolute path of a directory in the file system. All subdirectories of the specified directory are exposed to the server. You can define multiple virtual directories. The directories do not need to be contiguous.

Staging Directory


As an optional, but recommended step, you should set the directory that the application should use for staging when performing file transfers. This can be seen in the line below and should be done before initializing the FileManager. The default directory of the FileManager is most likely owned by root and will require a change to either the location of the staging directory and the ownership of the staging directory, or running the application as a User with the correct permissions.


twcfg.file_xfer_staging_dir = "staging";


The example provided uses the TW_SHARE_DIRECTORY macro to create two virtual directories that will act as the root directories in the virtual file system of this application are added. The client is then started as follows with the necessary TW_ADD_FILE_TRANSFER_SHAPE function being called:


TW_SHARE_DIRECTORY("in", "/transfer/incoming/");
TW_SHARE_DIRECTORY("out", "/transfer/outgoing/");


The creations of the payloads used to create the remote directories on the platform have been moved to a helper function below to make the design cleaner:


int setupSystemRepo(const char * remoteInPath, const char * remoteOutPath, const char * remoteFile);


After our remote directories and files have been setup, it is time to perform the file transfers. Normally, this would mean invoking the Copy service for a Subsystem, but two functions have been created to make this process easier:


int twFileManager_GetFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid)

int twFileManager_SendFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid)


The table below displays an example of the first set of parameters:


sourceRepoSystemRepositoryThe name of FileRepository or RemoteThing to transfer the file FROM.
sourcePathoutgoingThe path specifying the location of the source file.
sourceFileThe name of the source file. 
targetRepoSteamSensor1The name of FileRepository or RemoteThing to transfer the file TO.
targetPathincomingThe path specifying the destination location of the file.
targetFileincoming.txtThe name of the file at the target. This name can differ from the sourceName.
timeout15,000The amount of time (in seconds) to wait for a synchronous transfer to complete before cancelling the transfer.
asyncfalseIf false, the service call will block for timeout seconds or until the transfer completes.
tidincoming0123The unique TID associated with the file.


The C SDK also provides the ability to create a FileCallback function that the FileManager will call that function when any file transfer events occur. You can provide a wildcard filter so that only file transfer Events of files that match the filter call the callback function. In addition, callbacks can be set up as “one-shots” such that the callback is unregistered automatically after it is invoked the first time.


NOTE: An optional file transfer callback is registered in the code and provided. You will see the output from the function as files are sent and received.


After running this application, you will notice a new file in the transfer/incoming folder after refreshing. This is the file that we created in the ThingWorx Composer file system for the SystemRepository Entity and was able to copy from that location to our local project. We have also sent a file to the server’s SystemRepository. The BrowseFileSystem and GetFileListing services can be used to check for the folders and files created.


twFileManager_RegisterFileCallback(fileCallbackFunc, NULL, FALSE, NULL);

Step 10: Support Other Platforms


All Websocket errors indicate some general issue communicating with the ThingWorx platform. If you experience an issue connecting, refer to the table below for a list of websocket errors, their corresponding codes, and an explanation of the issue.


200TW_UNKNOWN_WEBSOCKET_ERRORAn unknown error occurred on the websocket.
201TW_ERROR_INITIALIZING_WEBSOCKETAn error occurred while initializing the websocket. Check your websocket configuration parameters for validity.
202TW_TIMEOUT_INITIALIZING_WEBSOCKETA timeout occurred while initializing the websocket. Check the status of the connection to ThingWorx.
203TW_WEBSOCKET_NOT_CONNECTEDThe websocket is not connected to ThingWorx. The requested operation cannot be performed.
204TW_ERROR_PARSING_WEBSOCKET_DATAAn error occurred while parsing websocket data. The parser could not break down the data from the websocket.
205TW_ERROR_READING_FROM_WEBSOCKETAn error occurred while reading data from the websocket. Retry the read operation. If necessary, resend the data.
206TW_WEBSOCKET_FRAME_TOO_LARGEThe SDK is attempting to send a websocket frame that is too large. The Maximum Frame Size is set when calling twAPI_Initialize and should always be set to the Message Chunk Size (twcfg.message_chunk_size).
207TW_INVALID_WEBSOCKET_FRAME_TYPEThe type of the frame coming in over the websocket is invalid.
208TW_WEBSOCKET_MSG_TOO_LARGEThe application is attempting to send a message that has been broken up in to chunks that are too large to fit in a frame. You should not see this error.
209TW_ERROR_WRITING_TO_WEBSOCKETAn error occurred while writing to the Web socket.
210TW_INVALID_ACCEPT_KEYThe Accept key sent earlier from ThingWorx is not valid.

Step 11: Next Steps


Congratulations! You've successfully completed the C SDK Tutorial, and learned how to utilize the resources provided in the Edge SDK to create your own application.


Learn More


We recommend the following resources to continue your learning experience:


BuildDesign Your Data Model
BuildImplement Services, Events, and Subscriptions


Additional Resources


If you have questions, issues, or need additional information, refer to:


CommunityDeveloper Community Forum
SupportC Edge SDK Help Center
Version history
Last update:
‎Oct 14, 2022 03:01 PM
Updated by:
Labels (2)