Community Tip - If community subscription notifications are filling up your inbox you can set up a daily digest and get all your notifications in a single email. X
I have a C SDK agent running in a device. That device has got some log files (approx size - 100 MB).
I want to download the log files on to the local machine via ThingWorx UI using the file transfer mechanism.
My thing is of template RemoteThingWithTunnelsAndFileTransfer.
As per the C SDK developer guide, I have done the following for enabling file transfer alongwith the rest of the implementation -
#define ENABLE_FILE_XFER 1 //done at the top to enable file transfer
twcfg.file_xfer_staging_dir="/opt/thingworx/";
twFileManager_Create();
twFileManager_AddVirtualDir(thingName, "tw", "/opt/thingworx/staging_dir/"); //thingName points to name of a valid thing
twFileManager_AddVirtualDir(thingName, "tw2", "/opt/thingworx/staging_dir/out");
twFileManager_RegisterFileCallback(fileCallbackFunc, NULL, FALSE, NULL);
err = twApi_Connect(CONNECT_TIMEOUT, twcfg.connect_retries);
if (!err) {
/* Register our File Watcher with the tasker */
twApi_CreateTask(FILE_WATCHER_RATE_MSEC, fileWatcherTask);
}
When I run my program, my remote thing is connected(in ThingWorx, its 'isConnected' property gets set to 'true', I am able to invoke remote services on this remote thing as well).
When i try to test FileTransfer services(inherited) of my thing, like GetDirectoryStructure, I get an error - Unable to Invoke Service GetDirectoryStructure on <thingName> : null.
Please let me know if I am following the correct approach and how can I download the log file from the device.
Please note that fileCallbackFunc and fileWatcherTask are implemented as done in the bundled example. C SDK dev guide 1.3.0. C SDK agent ver - version.major=1version.minor=3version.revision=0version.build=502
Is there an actual directory at that path (you should have to make this manually, I believe)? Like does /opt/thingworx/staging_dir actually exist on your system?
Yes, /opt/thingworx/staging_dir is an actual dir in the file system of the device on which C SDK agent is running. I need to download files from the device on the local system (from where thingworx UI is being accessed).
#define ENABLE_FILE_XFER 1 Should not be done in main.c, it needs to be done in twConfig.h or in your Makefile. If it is only defined in main.c it will not get picked up by any of the other header or c files that use it. Best bet is to start with the SteamSensorWithFIleTransferAndTunneling example project.
Also, it you are only doing file transfers "on command" by a user, you do not need the fileWatcherTask. That is simply there as an example of how to watch a certain directory for new or changed files and have them automatically sent to the server. Also, that task as written is fairly rudimentary and doesn't cover all the corner cases, so I wouldn't recommend it for production.
hello:
I meet the same question, are you resolve the problem? Could you show me about your process or anything to me to deal this problem
Thanks,
yi
Hi yi huang,
I am not working anymore on this task, but I can provide you an update of what I did and what worked and what not. In case you manage to get it working, please let me also know what worked for you.
I had two environments, CentOS 6.5 and Angstrom OS. What I did works on CentOS, but not on Angstrom OS.
I can suggest the following to you:
1. Please go through the file transfer course at precision LMS(this is really good and it will help you in making the UI for file transfer) - https://precisionlms.ptc.com/viewer/course/en/23003439/page/23594904
2. For the back end code, you take a clue from my pseudo code below (as i said earlier, it works in CentOS 6.5, but I am not sure if it will work in your OS). You can also go through the Thingworx Connectivity course to see if I missed something or if they have added something new to solve this issue.
Code in my main.c:
/* Initialize the API */
err = twApi_Initialize(TW_HOST, TW_PORT, TW_URI, TW_APP_KEY, NULL, MESSAGE_CHUNK_SIZE, MESSAGE_CHUNK_SIZE, TRUE);
//Define and Register our callback services which will be called by TW platform - custom code
definePlatformCallBacks();
//get data and register Things - custom code, deleted from here
/******************************************/
/* File Transfer Initialization */
/******************************************/
int fileMgrCreationStatus = twFileManager_Create();
/* Create our virtual directories, 'thingNameToRegister' has been initialized earlier */
twFileManager_AddVirtualDir(thingNameToRegister, "tw", "/opt/abc");
twFileManager_AddVirtualDir(thingNameToRegister, "tw2", "/twFile_tmp");
/* Register the file transfer callback function - 'fileCallbackFunc' is copied from the SteamSensor example */
twFileManager_RegisterFileCallback(fileCallbackFunc, NULL, FALSE, NULL);
/* Connect to server */
err = twApi_Connect(CONNECT_TIMEOUT, twcfg.connect_retries);
// Error handling
/* Test Code for testing file transfer. file name 'last_idReadingLog.txt' should exist in the thingworx virtual
directory '/tw/config'. see definition of virtual directory "tw" above - the real path on disk is /opt/abc/config. So, file /opt/abc/config/last_idReadingLog.txt will be transferred to the Thingworx 'SystemRepository'. You can use FileTransferSubsystem on Thingworx platform server to find out whether the file was transferred. Its name in destination will be 'last_idReadingLogAA.txt' and it will be copied directly under 'SystemRepository' */
char * tid = 0;
int status = twFileManager_SendFile(thingNameToRegister, "/tw/config", "last_idReadingLog.txt", "SystemRepository", "/", "last_idReadingLogAA.txt", 60, TRUE, &tid);
if (status != 0 && status != 308) {
TW_LOG(TW_ERROR,"main - test: Error initiating file transfer");
}
3. There are some extensions on Thingworx marketplace. You can search for "file transfer" and you will find three extensions. You can also test them out if they are of any interest to you.
Thanks and I wish you all the best.