Skip to content

Update getFileBlock #39

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

Merged
merged 9 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
18 changes: 18 additions & 0 deletions .github/workflows/add_issue_to_project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Add new issue to our main project

on:
issues:
types:
- opened

jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@main
with:
# You can target a project in a different organization
# to the issue
project-url: https://github.com/orgs/sparkfun/projects/19
github-token: ${{ secrets.DEFECT_ADD_TO_PROJECT }}
106 changes: 76 additions & 30 deletions src/SparkFun_u-blox_SARA-R5_Arduino_Library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5580,10 +5580,14 @@ SARA_R5_error_t SARA_R5::getFileContents(String filename, char *contents)
return err;
}

SARA_R5_error_t SARA_R5::getFileBlock(const String& filename, char* buffer, size_t offset, size_t requested_length, size_t& bytes_read)
SARA_R5_error_t SARA_R5::getFileBlock(const String& filename, char* buffer, size_t offset, size_t requestedLength, size_t& bytesRead)
{
bytes_read = 0;
if (filename.length() < 1 || buffer == nullptr || requested_length < 1)
SARA_R5_error_t err;
char *command;
char *response;

bytesRead = 0;
if (filename.length() < 1 || buffer == nullptr || requestedLength < 1)
{
return SARA_R5_ERROR_UNEXPECTED_PARAM;
}
Expand All @@ -5599,54 +5603,96 @@ SARA_R5_error_t SARA_R5::getFileBlock(const String& filename, char* buffer, size
return SARA_R5_ERROR_INVALID;
}

size_t cmd_len = filename.length() + 32;
char* cmd = sara_r5_calloc_char(cmd_len);
sprintf(cmd, "at+urdblock=\"%s\",%zu,%zu\r\n", filename.c_str(), offset, requested_length);
sendCommand(cmd, false);
command = sara_r5_calloc_char(strlen(SARA_R5_FILE_SYSTEM_READ_BLOCK) + filename.length() + 28);
if (command == nullptr)
{
return SARA_R5_ERROR_OUT_OF_MEMORY;
}
sprintf(command, "%s=\"%s\",%lu,%lu", SARA_R5_FILE_SYSTEM_READ_BLOCK, filename.c_str(), (unsigned long) offset, (unsigned long) requestedLength);

response = sara_r5_calloc_char(minimumResponseAllocation);
if (response == nullptr)
{
if (_printDebug == true)
{
_debugPort->print(F("getFileBlock: response alloc failed: "));
_debugPort->println(minimumResponseAllocation);
}
free(command);
return SARA_R5_ERROR_OUT_OF_MEMORY;
}

// Send command and wait for some response
// Response format: \r\n+URDBLOCK: "filename",64000,"these bytes are the data of the file block"\r\n\r\nOK\r\n
sendCommand(command, true);
err = waitForResponse(SARA_R5_FILE_SYSTEM_READ_BLOCK, SARA_R5_RESPONSE_ERROR, 5 * SARA_R5_STANDARD_RESPONSE_TIMEOUT);
if (err != SARA_R5_ERROR_SUCCESS)
{
if (_printDebug == true)
{
_debugPort->print(F("getFileBlock: waitForResponse returned err "));
_debugPort->println(err);
}
free(command);
free(response);
return err;
}

// Skip the filename in quotes and get the data length index
int ich;
char ch;
int quote_count = 0;
size_t comma_idx = 0;

while (quote_count < 3)
int quoteCount = 0;
size_t lengthIndex = 0;
while (quoteCount < 3 && bytesRead < minimumResponseAllocation)
{
ich = _hardSerial->read();
if (ich < 0)
{
continue;
}
ch = (char)(ich & 0xFF);
cmd[bytes_read++] = ch;
response[bytesRead++] = ch;
if (ch == '"')
{
quote_count++;
quoteCount++;
}
else if (ch == ',' && comma_idx == 0)
else if (ch == ',' && lengthIndex == 0 && quoteCount == 2)
{
comma_idx = bytes_read;
lengthIndex = bytesRead;
}
}
response[bytesRead] = 0; // Make response a null-terminated string
response[bytesRead - 2] = 0; // Terminate response string right after block length
size_t data_length = strtoul(&response[lengthIndex], nullptr, 10);

cmd[bytes_read] = 0;
cmd[bytes_read - 2] = 0;

// Example response:
// +URDBLOCK: "wombat.bin",64000,"<data starts here>... "<cr><lf>
size_t data_length = strtoul(&cmd[comma_idx], nullptr, 10);
free(cmd);

bytes_read = 0;
size_t bytes_remaining = data_length;
while (bytes_read < data_length)
// Read file block data directly into supplied buffer
bytesRead = 0;
size_t bytesRemaining = data_length;
while (bytesRead < data_length)
{
// This method seems more reliable than reading a byte at a time.
size_t rc = _hardSerial->readBytes(&buffer[bytes_read], bytes_remaining);
bytes_read += rc;
bytes_remaining -= rc;
size_t rc = _hardSerial->readBytes(&buffer[bytesRead], bytesRemaining);
bytesRead += rc;
bytesRemaining -= rc;
}

return SARA_R5_ERROR_SUCCESS;
// Read rest of response until \r\nOK\r\n
err = waitForResponse(SARA_R5_RESPONSE_OK, SARA_R5_RESPONSE_ERROR, SARA_R5_STANDARD_RESPONSE_TIMEOUT);
if (err != SARA_R5_ERROR_SUCCESS)
{
if (_printDebug == true)
{
_debugPort->print(F("getFileBlock: waitForResponse returned err "));
_debugPort->println(err);
}
free(command);
free(response);
return err;
}

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

SARA_R5_error_t SARA_R5::getFileSize(String filename, int *size)
Expand Down
2 changes: 1 addition & 1 deletion src/SparkFun_u-blox_SARA-R5_Arduino_Library.h
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@ class SARA_R5 : public Print
// TO DO: add full support for file tags. Default tag to USER
SARA_R5_error_t getFileContents(String filename, String *contents); // OK for text files. But will fail with binary files (containing \0) on some platforms.
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 getFileBlock(const String& filename, char* buffer, size_t offset, size_t requestedLength, size_t& bytesRead); // OK for binary files. Make sure buffer can hold the requested block size.

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