Skip to content

Add helpers for Filesystem operations #74

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 11 commits into from
Jun 24, 2020
42 changes: 42 additions & 0 deletions examples/WiFiStorage/WiFiStorage.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
This example shows how to interact with NiNa internal memory partition
APIs are modeled on SerialFlash library (not on SD) to speedup operations and avoid buffers.
*/

#include <WiFiNINA.h>

void setup() {

Serial.begin(115200);
while (!Serial);

// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}

WiFiStorageFile file = WiFiStorage.open("/fs/testfile");

if (file) {
file.erase();
}

String test = "Cantami o Diva del pelide Achille";
file.write(test.c_str(), test.length());

if (file) {
file.seek(0);
while (file.available()) {
uint8_t buf[128];
int ret = file.read(buf, 128);
Serial.write(buf, ret);
}
}
}

void loop() {
// put your main code here, to run repeatedly:

}
1 change: 1 addition & 0 deletions src/WiFi.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern "C" {
#include "WiFiClient.h"
#include "WiFiSSLClient.h"
#include "WiFiServer.h"
#include "WiFiStorage.h"

class WiFiClass
{
Expand Down
30 changes: 30 additions & 0 deletions src/WiFiStorage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
WiFiStorage.cpp - Library for Arduino boards based on NINA wifi module.
Copyright (c) 2018 Arduino SA. All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "WiFiStorage.h"

WiFiStorageFile WiFiStorageClass::open(const char *filename) {
WiFiStorageFile file(filename);
file.size();
return file;
}

WiFiStorageFile WiFiStorageClass::open(String filename) {
return open(filename.c_str());
}
133 changes: 133 additions & 0 deletions src/WiFiStorage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
WiFiStorage.h - Library for Arduino boards based on NINA wifi module.
Copyright (c) 2018 Arduino SA. All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef wifistorage_h
#define wifistorage_h

#include "utility/wifi_drv.h"

class WiFiStorageFile;

class WiFiStorageClass
{
public:
static bool begin();

static WiFiStorageFile open(const char *filename);
static WiFiStorageFile open(String filename);

static bool exists(const char *filename) {
uint32_t len;
return (WiFiDrv::existsFile(filename, strlen(filename), &len) > 0);
}
static bool exists(const char *filename, uint32_t* len) {
return (WiFiDrv::existsFile(filename, strlen(filename), len) > 0);
}
static bool remove(const char *filename) {
WiFiDrv::deleteFile(filename, strlen(filename));
return true;
}
static bool rename(const char * old_file_name, const char * new_file_name) {
return (WiFiDrv::renameFile(old_file_name, strlen(old_file_name), new_file_name, strlen(new_file_name)) == 0);
}
static bool read(const char *filename, uint32_t offset, uint8_t* buffer, uint32_t buffer_len) {
WiFiDrv::readFile(filename, strlen(filename), offset, buffer, buffer_len);
return true;
}
static bool write(const char *filename, uint32_t offset, uint8_t* buffer, uint32_t buffer_len) {
WiFiDrv::writeFile(filename, strlen(filename), offset, buffer, buffer_len);
return true;
}
static bool download(const char* url, const char *filename) {
WiFiDrv::downloadFile(url, strlen(url), filename, strlen(filename));
return true;
}

static bool remove(String filename) {
return remove(filename.c_str());
}
static bool rename(String old_file_name, String new_file_name) {
return rename(old_file_name.c_str(), new_file_name.c_str());
}
static bool read(String filename, uint32_t offset, uint8_t* buffer, uint32_t buffer_len) {
return read(filename.c_str(), offset, buffer, buffer_len);
}
static bool write(String filename, uint32_t offset, uint8_t* buffer, uint32_t buffer_len) {
return write(filename.c_str(), offset, buffer, buffer_len);
}
static bool download(String url, String filename) {
return download(url.c_str(), filename.c_str());
}
};

extern WiFiStorageClass WiFiStorage;


class WiFiStorageFile
{
public:
constexpr WiFiStorageFile(const char* _filename) : filename(_filename) { }

operator bool() {
return WiFiStorage.exists(filename, &length);
}
uint32_t read(void *buf, uint32_t rdlen) {
if (offset + rdlen > length) {
if (offset >= length) return 0;
rdlen = length - offset;
}
WiFiStorage.read(filename, offset, (uint8_t*)buf, rdlen);
offset += rdlen;
return rdlen;
}
uint32_t write(const void *buf, uint32_t wrlen) {
WiFiStorage.write(filename, offset, (uint8_t*)buf, wrlen);
offset += wrlen;
return wrlen;
}
void seek(uint32_t n) {
offset = n;
}
uint32_t position() {
return offset;
}
uint32_t size() {
WiFiStorage.exists(filename, &length);
return length;
}
uint32_t available() {
WiFiStorage.exists(filename, &length);
return length - offset;
}
void erase() {
offset = 0;
WiFiStorage.remove(filename);
}
void flush();
void close() {
offset = 0;
}
protected:
friend class WiFiStorageClass;
uint32_t offset = 0;
uint32_t length = 0;
const char* filename;
};

#endif
16 changes: 16 additions & 0 deletions src/utility/spi_drv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,22 @@ int SpiDrv::waitResponse(uint8_t cmd, uint8_t* numParamRead, uint8_t** params, u
return 1;
}

void SpiDrv::sendParamNoLen(uint8_t* param, size_t param_len, uint8_t lastParam)
{
int i = 0;
// Send Spi paramLen
sendParamLen8(0);

// Send Spi param data
for (i=0; i<param_len; ++i)
{
spiTransfer(param[i]);
}

// if lastParam==1 Send Spi END CMD
if (lastParam == 1)
spiTransfer(END_CMD);
}

void SpiDrv::sendParam(uint8_t* param, uint8_t param_len, uint8_t lastParam)
{
Expand Down
2 changes: 2 additions & 0 deletions src/utility/spi_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class SpiDrv

static void sendParam(uint8_t* param, uint8_t param_len, uint8_t lastParam = NO_LAST_PARAM);

static void sendParamNoLen(uint8_t* param, size_t param_len, uint8_t lastParam = NO_LAST_PARAM);

static void sendParamLen8(uint8_t param_len);

static void sendParamLen16(uint16_t param_len);
Expand Down
114 changes: 114 additions & 0 deletions src/utility/wifi_drv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1078,4 +1078,118 @@ void WiFiDrv::analogWrite(uint8_t pin, uint8_t value)
SpiDrv::spiSlaveDeselect();
}

int8_t WiFiDrv::downloadFile(const char* url, uint8_t url_len, const char *filename, uint8_t filename_len)
{
WAIT_FOR_SLAVE_SELECT();
// Send Command
SpiDrv::sendCmd(DOWNLOAD_FILE, PARAM_NUMS_2);
SpiDrv::sendParam((uint8_t*)url, url_len, NO_LAST_PARAM);
SpiDrv::sendParam((uint8_t*)filename, filename_len, LAST_PARAM);

// pad to multiple of 4
int commandSize = 6 + url_len + filename_len;
while (commandSize % 4) {
SpiDrv::readChar();
commandSize++;
}

SpiDrv::spiSlaveDeselect();
//Wait the reply elaboration
SpiDrv::waitForSlaveReady();
SpiDrv::spiSlaveSelect();

// Wait for reply
uint8_t _data = 0;
uint8_t _dataLen = 0;
if (!SpiDrv::waitResponseCmd(DOWNLOAD_FILE, PARAM_NUMS_1, &_data, &_dataLen))
{
WARN("error waitResponse");
_data = WL_FAILURE;
}
SpiDrv::spiSlaveDeselect();
return _data;
}

int8_t WiFiDrv::renameFile(const char * old_file_name, uint8_t const old_file_name_len, const char * new_file_name, uint8_t const new_file_name_len)
{
WAIT_FOR_SLAVE_SELECT();
/* Send Command */
SpiDrv::sendCmd(RENAME_FILE, PARAM_NUMS_2);
SpiDrv::sendParam((uint8_t*)old_file_name, old_file_name_len, NO_LAST_PARAM);
SpiDrv::sendParam((uint8_t*)new_file_name, new_file_name_len, LAST_PARAM);

/* pad to multiple of 4 */
int commandSize = 6 + old_file_name_len + new_file_name_len;
while (commandSize % 4) {
SpiDrv::readChar();
commandSize++;
}

SpiDrv::spiSlaveDeselect();
/* Wait the reply elaboration */
SpiDrv::waitForSlaveReady();
SpiDrv::spiSlaveSelect();

/* Wait for reply */
uint8_t data = 0;
uint8_t dataLen = 0;
if (!SpiDrv::waitResponseCmd(RENAME_FILE, PARAM_NUMS_1, &data, &dataLen))
{
WARN("error waitResponse");
data = WL_FAILURE;
}
SpiDrv::spiSlaveDeselect();
return data;
}

int8_t WiFiDrv::fileOperation(uint8_t operation, const char *filename, uint8_t filename_len, uint32_t offset, uint8_t* buffer, uint32_t len)
{
WAIT_FOR_SLAVE_SELECT();
// Send Command
uint8_t numParams = PARAM_NUMS_3;
if (operation == WRITE_FILE) {
numParams = PARAM_NUMS_4;
}

SpiDrv::sendCmd(operation, numParams);
SpiDrv::sendParam((uint8_t*)&offset, sizeof(offset), NO_LAST_PARAM);
SpiDrv::sendParam((uint8_t*)&len, sizeof(len), NO_LAST_PARAM);
SpiDrv::sendParam((uint8_t*)filename, filename_len, (operation == WRITE_FILE) ? NO_LAST_PARAM : LAST_PARAM);
if (operation == WRITE_FILE) {
SpiDrv::sendParamNoLen((uint8_t*)buffer, len, LAST_PARAM);
}

// pad to multiple of 4
int commandSize = 4 + numParams + sizeof(offset) + sizeof(len) + filename_len;
while (commandSize % 4) {
SpiDrv::readChar();
commandSize++;
}

SpiDrv::spiSlaveDeselect();
//Wait the reply elaboration
SpiDrv::waitForSlaveReady();
SpiDrv::spiSlaveSelect();

// Wait for reply
uint8_t _data = 0;
uint8_t _dataLen = 0;
SpiDrv::waitResponseCmd(operation, PARAM_NUMS_1, (operation == WRITE_FILE) ? &_data : buffer, &_dataLen);

SpiDrv::spiSlaveDeselect();
return _dataLen;
}

void WiFiDrv::applyOTA() {
WAIT_FOR_SLAVE_SELECT();

// Send Command
SpiDrv::sendCmd(APPLY_OTA_COMMAND, PARAM_NUMS_0);

SpiDrv::spiSlaveDeselect();

// don't wait for return; OTA operation should be fire and forget :)
}


WiFiDrv wiFiDrv;
23 changes: 23 additions & 0 deletions src/utility/wifi_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,29 @@ class WiFiDrv
static void digitalWrite(uint8_t pin, uint8_t value);
static void analogWrite(uint8_t pin, uint8_t value);

static int8_t downloadFile(const char* url, uint8_t url_len, const char *filename, uint8_t filename_len);
static int8_t renameFile(const char * old_file_name, uint8_t const old_file_name_len, const char * new_file_name, uint8_t const new_file_name_len);

static int8_t fileOperation(uint8_t operation, const char *filename, uint8_t filename_len, uint32_t offset, uint8_t* buffer, uint32_t len);

static int8_t readFile(const char *filename, uint8_t filename_len, uint32_t offset, uint8_t* buffer, uint32_t buffer_len) {
return fileOperation(READ_FILE, filename, filename_len, offset, buffer, buffer_len);
};
static int8_t writeFile(const char *filename, uint8_t filename_len, uint32_t offset, uint8_t* buffer, uint32_t buffer_len) {
return fileOperation(WRITE_FILE, filename, filename_len, offset, buffer, buffer_len);
};
static int8_t deleteFile(const char *filename, uint8_t filename_len) {
return fileOperation(DELETE_FILE, filename, filename_len, 0, NULL, 0);
};
static int8_t existsFile(const char *filename, uint8_t filename_len, uint32_t* len) {
int32_t length = 0;
fileOperation(EXISTS_FILE, filename, filename_len, 0, (uint8_t*)&length, sizeof(length));
*len = length;
return length >= 0;
};

static void applyOTA();

friend class WiFiUDP;
friend class WiFiClient;
};
Expand Down
Loading