Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2fd66ae

Browse files
committedJan 17, 2022
Add getFileContents(String filename, char *contents)
1 parent 1503630 commit 2fd66ae

File tree

2 files changed

+132
-2
lines changed

2 files changed

+132
-2
lines changed
 

‎src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4165,6 +4165,7 @@ SARA_R5_error_t SARA_R5::gpsAidingServerConf(const char *primaryServer, const ch
41654165
return err;
41664166
}
41674167

4168+
// OK for text files. But will fail with binary files (containing \0) on some platforms.
41684169
SARA_R5_error_t SARA_R5::getFileContents(String filename, String *contents)
41694170
{
41704171
SARA_R5_error_t err;
@@ -4251,6 +4252,9 @@ SARA_R5_error_t SARA_R5::getFileContents(String filename, String *contents)
42514252
while (bytesRead < readFileSize)
42524253
{
42534254
searchPtr++; // Increment searchPtr then copy file char into contents
4255+
// Important Note: some implementations of concat, like the one on ESP32, are binary-compatible.
4256+
// But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's.
4257+
// The only true binary-compatible solution is to use getFileContents(String filename, char *contents)...
42544258
contents->concat(*(searchPtr)); // Append file char to contents
42554259
bytesRead++;
42564260
}
@@ -4283,6 +4287,124 @@ SARA_R5_error_t SARA_R5::getFileContents(String filename, String *contents)
42834287
return err;
42844288
}
42854289

4290+
// OK for binary files. Make sure contents can hold the entire file. Get the size first with getFileSize.
4291+
SARA_R5_error_t SARA_R5::getFileContents(String filename, char *contents)
4292+
{
4293+
SARA_R5_error_t err;
4294+
char *command;
4295+
char *response;
4296+
4297+
// Start by getting the file size so we know in advance how much data to expect
4298+
int fileSize = 0;
4299+
err = getFileSize(filename, &fileSize);
4300+
if (err != SARA_R5_SUCCESS)
4301+
{
4302+
if (_printDebug == true)
4303+
{
4304+
_debugPort->print(F("getFileContents: getFileSize returned err "));
4305+
_debugPort->println(err);
4306+
}
4307+
return err;
4308+
}
4309+
4310+
command = sara_r5_calloc_char(strlen(SARA_R5_FILE_SYSTEM_READ_FILE) + filename.length() + 8);
4311+
if (command == NULL)
4312+
return SARA_R5_ERROR_OUT_OF_MEMORY;
4313+
sprintf(command, "%s=\"%s\"", SARA_R5_FILE_SYSTEM_READ_FILE, filename.c_str());
4314+
4315+
response = sara_r5_calloc_char(fileSize + minimumResponseAllocation);
4316+
if (response == NULL)
4317+
{
4318+
if (_printDebug == true)
4319+
{
4320+
_debugPort->print(F("getFileContents: response alloc failed: "));
4321+
_debugPort->println(fileSize + minimumResponseAllocation);
4322+
}
4323+
free(command);
4324+
return SARA_R5_ERROR_OUT_OF_MEMORY;
4325+
}
4326+
4327+
// A large file will completely fill the backlog buffer - but it will be pruned afterwards
4328+
// Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early...
4329+
// To try and avoid this, look for \"\r\nOK\r\n
4330+
const char fileReadTerm[] = "\"\r\nOK\r\n";
4331+
err = sendCommandWithResponse(command, fileReadTerm,
4332+
response, (5 * SARA_R5_STANDARD_RESPONSE_TIMEOUT),
4333+
(fileSize + minimumResponseAllocation));
4334+
4335+
if (err != SARA_R5_ERROR_SUCCESS)
4336+
{
4337+
if (_printDebug == true)
4338+
{
4339+
_debugPort->print(F("getFileContents: sendCommandWithResponse returned err "));
4340+
_debugPort->println(err);
4341+
}
4342+
free(command);
4343+
free(response);
4344+
return err;
4345+
}
4346+
4347+
// Response format: \r\n+URDFILE: "filename",36,"these bytes are the data of the file"\r\n\r\nOK\r\n
4348+
int scanned = 0;
4349+
int readFileSize = 0;
4350+
char *searchPtr = strstr(response, "+URDFILE: ");
4351+
if (searchPtr != NULL)
4352+
{
4353+
searchPtr = strchr(searchPtr, '\"'); // Find the first quote
4354+
searchPtr = strchr(++searchPtr, '\"'); // Find the second quote
4355+
4356+
scanned = sscanf(searchPtr, "\",%d,", &readFileSize); // Get the file size (again)
4357+
if (scanned == 1)
4358+
{
4359+
searchPtr = strchr(++searchPtr, '\"'); // Find the third quote
4360+
4361+
if (searchPtr == NULL)
4362+
{
4363+
if (_printDebug == true)
4364+
{
4365+
_debugPort->println(F("getFileContents: third quote not found!"));
4366+
}
4367+
free(command);
4368+
free(response);
4369+
return SARA_R5_ERROR_UNEXPECTED_RESPONSE;
4370+
}
4371+
4372+
int bytesRead = 0;
4373+
4374+
while (bytesRead < readFileSize)
4375+
{
4376+
searchPtr++; // Increment searchPtr then copy file char into contents
4377+
contents[bytesRead] = *searchPtr; // Append file char to contents
4378+
bytesRead++;
4379+
}
4380+
if (_printDebug == true)
4381+
{
4382+
_debugPort->print(F("getFileContents: total bytes read: "));
4383+
_debugPort->println(bytesRead);
4384+
}
4385+
err = SARA_R5_ERROR_SUCCESS;
4386+
}
4387+
else
4388+
{
4389+
if (_printDebug == true)
4390+
{
4391+
_debugPort->print(F("getFileContents: sscanf failed! scanned is "));
4392+
_debugPort->println(scanned);
4393+
}
4394+
err = SARA_R5_ERROR_UNEXPECTED_RESPONSE;
4395+
}
4396+
}
4397+
else
4398+
{
4399+
if (_printDebug == true)
4400+
_debugPort->println(F("getFileContents: strstr failed!"));
4401+
err = SARA_R5_ERROR_UNEXPECTED_RESPONSE;
4402+
}
4403+
4404+
free(command);
4405+
free(response);
4406+
return err;
4407+
}
42864408
SARA_R5_error_t SARA_R5::getFileSize(String filename, int *size)
42874409
{
42884410
SARA_R5_error_t err;
@@ -4920,7 +5042,11 @@ SARA_R5_error_t SARA_R5::parseSocketReadIndication(int socket, int length)
49205042
if (_socketReadCallback != NULL)
49215043
{
49225044
String dataAsString = ""; // Create an empty string
4923-
for (int i = 0; i < bytesRead; i++) // Copy the data from readDest into the String in a binary-compatible way
5045+
// Copy the data from readDest into the String in a binary-compatible way
5046+
// Important Note: some implementations of concat, like the one on ESP32, are binary-compatible.
5047+
// But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's.
5048+
// The only true binary-compatible solution is to use socketReadCallbackPlus...
5049+
for (int i = 0; i < bytesRead; i++)
49245050
dataAsString.concat(readDest[i]);
49255051
_socketReadCallback(socket, dataAsString);
49265052
}
@@ -4969,6 +5095,9 @@ SARA_R5_error_t SARA_R5::parseSocketReadIndicationUDP(int socket, int length)
49695095
if (_socketReadCallback != NULL)
49705096
{
49715097
String dataAsString = ""; // Create an empty string
5098+
// Important Note: some implementations of concat, like the one on ESP32, are binary-compatible.
5099+
// But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's.
5100+
// The only true binary-compatible solution is to use socketReadCallbackPlus...
49725101
for (int i = 0; i < bytesRead; i++) // Copy the data from readDest into the String in a binary-compatible way
49735102
dataAsString.concat(readDest[i]);
49745103
_socketReadCallback(socket, dataAsString);

‎src/SparkFun_u-blox_SARA-R5_Arduino_Library.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,8 @@ class SARA_R5 : public Print
796796

797797
// File system
798798
// TO DO: add full support for file tags. Default tag to USER
799-
SARA_R5_error_t getFileContents(String filename, String *contents);
799+
SARA_R5_error_t getFileContents(String filename, String *contents); // OK for text files. But will fail with binary files (containing \0) on some platforms.
800+
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.
800801
SARA_R5_error_t getFileSize(String filename, int *size);
801802
SARA_R5_error_t deleteFile(String filename);
802803

0 commit comments

Comments
 (0)
Please sign in to comment.