Skip to content

Added functions for ftp support #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4693,6 +4693,76 @@ SARA_R5_error_t SARA_R5::ftpGetFile(const String& filename)
free(command);
return err;
}
SARA_R5_error_t SARA_R5::ftpChangeWorkingDirectory(const String& dirName)
{
char *command;

command = sara_r5_calloc_char(strlen(SARA_R5_FTP_COMMAND) + dirName.length() + 16);
if (command==NULL)
{
return SARA_R5_ERROR_OUT_OF_MEMORY;
}

sprintf(command, "%s=%d,\"%s\"", SARA_R5_FTP_COMMAND, SARA_R5_FTP_COMMAND_CHANGE_DIR, dirName.c_str());

SARA_R5_error_t err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL,
SARA_R5_STANDARD_RESPONSE_TIMEOUT);
free(command);
return err;
}

SARA_R5_error_t SARA_R5::ftpCreateDirectory(const String &dirName) {

char * command;

command = sara_r5_calloc_char(strlen(SARA_R5_FTP_COMMAND) + dirName.length() + 16);
if (command==NULL)
{
return SARA_R5_ERROR_OUT_OF_MEMORY;
}

sprintf(command, "%s=%d,\"%s\"", SARA_R5_FTP_COMMAND, SARA_R5_FTP_COMMAND_MKDIR, dirName.c_str());

SARA_R5_error_t err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, NULL,
SARA_R5_STANDARD_RESPONSE_TIMEOUT);
free(command);
return err;
}

SARA_R5_error_t SARA_R5::ftpList(const String &dirName, char * response) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming this to ftpListFiles

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Humm. Thinking about this more...
The response could be quite large, depending on how many files are in the system. You could easily overrun response if you're not careful...
(I know I cheated with this overload of getFileContents because there you can know in advance how much data is coming.)
So, here, it would be best to use a String - which can grow as required - or pass in the size of response so you can stop writing before you overrun. String gets my vote - same as this overload of getFileContents.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where possible I avoided the use of String in my changes to avoid heap problems, even though we're using an ESP32 so heap problems go away on deep sleep :)

I had originally changed a lot of existing methods to use char buffers too, but decided that was too much of an ask for a pull request so reverted them.

I'd be wary of using so many Strings on our Cortex M0+ based nodes which don't reboot after waking up.

You haven't found any problems with long running sketches?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi David (@dajtxx ),
We haven't noticed any problems but: we also tend to run this on ESP32; and we generally don't put the processor to sleep. In this case you're welcome to twist my arm and go with a char buffer, with size.
Cheers,
Paul


char * command;

command = sara_r5_calloc_char(strlen(SARA_R5_FTP_COMMAND) + dirName.length() + 16);
if (command==NULL)
{
return SARA_R5_ERROR_OUT_OF_MEMORY;
}

sprintf(command, "%s=%d,\"%s\"", SARA_R5_FTP_COMMAND, SARA_R5_FTP_COMMAND_LS, dirName.c_str());

SARA_R5_error_t err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR, response,
SARA_R5_STANDARD_RESPONSE_TIMEOUT);
free(command);
return err;
}

SARA_R5_error_t SARA_R5::ftpPutFile(const String &localFilename, const String &remoteFileName) {
char * command;

command = sara_r5_calloc_char(strlen(SARA_R5_FTP_COMMAND) + localFilename.length() + remoteFileName.length() + 16);
if (command==NULL)
{
return SARA_R5_ERROR_OUT_OF_MEMORY;
}

sprintf(command, "%s=%d,\"%s\",\"%s\"", SARA_R5_FTP_COMMAND, SARA_R5_FTP_COMMAND_PUT_FILE, localFilename.c_str(), remoteFileName.c_str());

SARA_R5_error_t err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR,NULL,
SARA_R5_STANDARD_RESPONSE_TIMEOUT);
free(command);
return err;
}

SARA_R5_error_t SARA_R5::getFTPprotocolError(int *error_code, int *error_code2)
{
Expand Down Expand Up @@ -5648,6 +5718,69 @@ SARA_R5_error_t SARA_R5::getFileBlock(const String& filename, char* buffer, size

return SARA_R5_ERROR_SUCCESS;
}
SARA_R5_error_t SARA_R5::getAvailableSize(size_t * size)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming this to getAvailableFreeSpace

{

// Get the remaining space available on the modem in bytes
char * command;
char * response;

command = sara_r5_calloc_char(strlen(SARA_R5_FILE_SYSTEM_LIST_FILES) + 3);
if (command==NULL)
{
return SARA_R5_ERROR_OUT_OF_MEMORY;
}

sprintf(command, "%s=1", SARA_R5_FILE_SYSTEM_LIST_FILES);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here that AT+ULSTFILE=1 returns the Remaining free FS space expressed in bytes.
(I was worried it was doing a full LS - and would overflow the minimumResponseAllocation)


response = sara_r5_calloc_char(minimumResponseAllocation);
if (response == nullptr)
{
free(command);
return SARA_R5_ERROR_OUT_OF_MEMORY;
}
SARA_R5_error_t err = sendCommandWithResponse(command, SARA_R5_RESPONSE_OK_OR_ERROR,response,
SARA_R5_STANDARD_RESPONSE_TIMEOUT);

// Process result
if (err != SARA_R5_ERROR_SUCCESS)
{
if (_printDebug == true)
{
_debugPort->print(F("getAvailableSize: Fail: Error: "));
_debugPort->print(err);
_debugPort->print(F(" Response: {"));
_debugPort->print(response);
_debugPort->println(F("}"));
}
free(command);
free(response);
return err;
}
char *responseStart = strstr(response, "+ULSTFILE:");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

David's changes - which I like - move us away from hard-coded strings in the code. Is there an elegant way to append the ":" to SARA_R5_FILE_SYSTEM_LIST_FILES ? I.e. avoid hard-coding here; also avoid 'cheating' by defining SARA_R5_FILE_SYSTEM_LIST_FILES_RESPONSE (which includes the colon). Maybe create a new helper function which will append the colon to whatever command is passed?

if (responseStart == nullptr)
{
if (_printDebug == true)
{
_debugPort->print(F("getAvailableSize: Failure: {"));
_debugPort->print(response);
_debugPort->println(F("}"));
}
free(command);
free(response);
return SARA_R5_ERROR_UNEXPECTED_RESPONSE;
}

size_t availableSpace;
responseStart += strlen("+ULSTFILE:"); // Move searchPtr to first char
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

while (*responseStart == ' ') responseStart++; // skip spaces
sscanf(responseStart, "%d", &availableSpace);
*size = availableSpace;

free(command);
free(response);
return err;
}

SARA_R5_error_t SARA_R5::getFileSize(String filename, int *size)
{
Expand Down
6 changes: 6 additions & 0 deletions src/SparkFun_u-blox_SARA-R5_Arduino_Library.h
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,10 @@ class SARA_R5 : public Print
SARA_R5_error_t connectFTP(void);
SARA_R5_error_t disconnectFTP(void);
SARA_R5_error_t ftpGetFile(const String& filename);
SARA_R5_error_t ftpChangeWorkingDirectory(const String& dirName);
SARA_R5_error_t ftpCreateDirectory(const String& dirName);
SARA_R5_error_t ftpList(const String& dirName, char * response);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

SARA_R5_error_t ftpPutFile(const String& localFilename, const String& remoteFileName);
SARA_R5_error_t getFTPprotocolError(int *error_code, int *error_code2);

// Configure security profiles
Expand Down Expand Up @@ -1011,6 +1015,8 @@ class SARA_R5 : public Print
SARA_R5_error_t getFileContents(String filename, char *contents); // OK for binary files. Make sure contents can hold the entire file. Get the size first with getFileSize.
SARA_R5_error_t getFileBlock(const String& filename, char* buffer, size_t offset, size_t length, size_t& bytes_read); // OK for binary files. Make sure buffer can hold the requested block size.

SARA_R5_error_t getAvailableSize(size_t * size); // Get available FS space
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto


// Append data to a file, delete file first to not appends the data.
SARA_R5_error_t appendFileContents(String filename, String str);
SARA_R5_error_t appendFileContents(String filename, const char *str, int len);
Expand Down