Hi
i am looking to be able to store project configurations on the flash on a RP2040
I have been attempting to use the following examples as the base for a test before integrating to my project using the latest ArduinoJSON V7 software
examples:
JsonConfigFile
littleFS_Test
The ArduinoJSON JsonConfigFile example uses an SD Card and Streams the JSON to the SD Card - I do not have an SD Card available but it does compile.
The LittleFS example sketch writes to a file and I have successfully compiled and run this code and it works on the Nano
When I try to create the new required function to write to the Flash using the LittleFS Sample it will not compile with the following error(below)
From my limited understanding i believe that the definition of File that I am using is wrong as it is not a stream (and it should be for ArduinJson ) and my definitions are wrong (on top of issues with not correctly using pointer to the file ).
ToDo
change strcpy to strlcopy to avoid buffer overrun issues occurring
properly handle Null values in the config file properly
other errors in my code as well but I am not able to get past this point.
I have been searching various forums and cannot see to find a any direction.
I am not asking for to correct my code but if you would be able to direct me as to what I am doing wrong and where I should look (or read up) i would appreciate it.
the error is in saveConfigFile function
The compile error
/Users/brett/Documents/Arduino/libraries/ArduinoJson/src/ArduinoJson/Serialization/Writer.hpp:18:19: error: request for member 'write' in '*((ArduinoJson::V704PB2::detail::Writer<__sFILE*, void>*)this)->ArduinoJson::V704PB2::detail::Writer<__sFILE*, void>::dest_', which is of pointer type '__sFILE*' (maybe you meant to use '->' ?)
return dest_->write(c);
~~~~~~~^~~~~
Using library LittleFS_Mbed_RP2040 at version 1.1.0 in folder: /Users/brett/Documents/Arduino/libraries/LittleFS_Mbed_RP2040
Using library ArduinoJson at version 7.0.4 in folder: /Users/brett/Documents/Arduino/libraries/ArduinoJson
exit status 1
Compilation error: exit status 1
the function i am getting the error in is here
void saveConfigFile(const char *filename, const configData &config) {
// this was from the original JsonConfigFile example sketch
// File file = SD.open(filename);
FILE *file = fopen(filename, "w"); // this is the error code
JsonDocument doc;
doc.set(config);
serializeJson(doc, file);
}
the full code is below
/****************************************************************************************************************************
LittleFS_Test.ino - Filesystem wrapper for LittleFS on the Mbed RP2040
For MBED RP2040-based boards such as Nano_RP2040_Connect, RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040.
Written by Khoi Hoang
Built by Khoi Hoang https://github.com/khoih-prog/LittleFS_Mbed_RP2040
Licensed under MIT license
*****************************************************************************************************************************/
#define LFS_MBED_RP2040_VERSION_MIN_TARGET "LittleFS_Mbed_RP2040 v1.1.0"
#define LFS_MBED_RP2040_VERSION_MIN 1001000
#define _LFS_LOGLEVEL_ 1
#define RP2040_FS_SIZE_KB 64
#define FORCE_REFORMAT false
#include <LittleFS_Mbed_RP2040.h>
#include <ArduinoJson.h>
LittleFS_MBED *myFS;
//#include <SD.h>
//#include <SPI.h>
struct configData {
//WiFi
char ssid[30]; // your network SSID (name)
char pass[30];
//Touch Screen Calibration
float xCalM;
float xCalC;
float yCalM;
float yCalC;
//MQTT
char mqttBroker[15];
int mqttPort;
//API forecast
char forecastApiKey[20];
char latitude[10];
char longitude[10];
char declination[3];
char azimuth[4];
char kwpInvertor[5];
char dampingM[5];
char dampingE[5];
};
configData config;
// Following in the function for XXX Server these will not change
char forecastServer[] = "api.xxx.solar";
int forecastServerPort = 443;
//File name for Config File
char configFile[] = MBED_LITTLEFS_FILE_PREFIX "/config.txt";
void readCharsFromFile(const char *path) {
Serial.print("readCharsFromFile: ");
Serial.print(path);
FILE *file = fopen(path, "r");
if (file) {
Serial.println(" => Open OK");
} else {
Serial.println(" => Open Failed");
return;
}
char c;
while (true) {
c = fgetc(file);
if (feof(file)) {
break;
} else
Serial.print(c);
}
fclose(file);
}
void readFile(const char *path) {
Serial.print("Reading file: ");
Serial.print(path);
FILE *file = fopen(path, "r");
if (file) {
Serial.println(" => Open OK");
} else {
Serial.println(" => Open Failed");
return;
}
char c;
uint32_t numRead = 1;
while (numRead) {
numRead = fread((uint8_t *)&c, sizeof(c), 1, file);
if (numRead)
Serial.print(c);
}
fclose(file);
}
void saveConfigFile(const char *filename, const configData &config) {
// this was from the original JsonConfigFile example sketch
// File file = SD.open(filename);
FILE *file = fopen(filename, "w"); // this is the error code
JsonDocument doc;
doc.set(config);
serializeJson(doc, file);
}
void writeFile(const char *path, const char *message, size_t messageSize) {
Serial.print("Writing file: ");
Serial.print(path);
FILE *file = fopen(path, "w");
if (file) {
Serial.println(" => Open OK");
} else {
Serial.println(" => Open Failed");
return;
}
if (fwrite((uint8_t *)message, 1, messageSize, file)) {
Serial.println("* Writing OK");
} else {
Serial.println("* Writing failed");
}
fclose(file);
}
void appendFile(const char *path, const char *message, size_t messageSize) {
Serial.print("Appending file: ");
Serial.print(path);
FILE *file = fopen(path, "a");
if (file) {
Serial.println(" => Open OK");
} else {
Serial.println(" => Open Failed");
return;
}
if (fwrite((uint8_t *)message, 1, messageSize, file)) {
Serial.println("* Appending OK");
} else {
Serial.println("* Appending failed");
}
fclose(file);
}
void deleteFile(const char *path) {
Serial.print("Deleting file: ");
Serial.print(path);
if (remove(path) == 0) {
Serial.println(" => OK");
} else {
Serial.println(" => Failed");
return;
}
}
void renameFile(const char *path1, const char *path2) {
Serial.print("Renaming file: ");
Serial.print(path1);
Serial.print(" to: ");
Serial.print(path2);
if (rename(path1, path2) == 0) {
Serial.println(" => OK");
} else {
Serial.println(" => Failed");
return;
}
}
void testFileIO(const char *path) {
Serial.print("Testing file I/O with: ");
Serial.print(path);
#define BUFF_SIZE 512
static uint8_t buf[BUFF_SIZE];
FILE *file = fopen(path, "w");
if (file) {
Serial.println(" => Open OK");
} else {
Serial.println(" => Open Failed");
return;
}
size_t i;
Serial.println("- writing");
uint32_t start = millis();
size_t result = 0;
// Write a file only 1/4 of RP2040_FS_SIZE_KB
for (i = 0; i < RP2040_FS_SIZE_KB / 2; i++) {
result = fwrite(buf, BUFF_SIZE, 1, file);
if (result != 1) {
Serial.print("Write result = ");
Serial.println(result);
Serial.print("Write error, i = ");
Serial.println(i);
break;
}
}
Serial.println("");
uint32_t end = millis() - start;
Serial.print(i / 2);
Serial.print(" Kbytes written in (ms) ");
Serial.println(end);
fclose(file);
printLine();
file = fopen(path, "r");
start = millis();
end = start;
i = 0;
if (file) {
start = millis();
Serial.println("- reading");
result = 0;
fseek(file, 0, SEEK_SET);
// Read file only 1/4 of RP2040_FS_SIZE_KB
for (i = 0; i < RP2040_FS_SIZE_KB / 2; i++) {
result = fread(buf, BUFF_SIZE, 1, file);
if (result != 1) {
Serial.print("Read result = ");
Serial.println(result);
Serial.print("Read error, i = ");
Serial.println(i);
break;
}
}
Serial.println("");
end = millis() - start;
Serial.print((i * BUFF_SIZE) / 1024);
Serial.print(" Kbytes read in (ms) ");
Serial.println(end);
fclose(file);
} else {
Serial.println("- failed to open file for reading");
}
}
void printLine() {
Serial.println("====================================================");
}
void setup() {
/*
Set these up for First Time use
*/
//WiFi
strcpy(config.ssid, "xxxxxx");
strcpy(config.pass, "xxxxxx");
//TouchScreen Calibration
config.xCalM = -0.09;
config.xCalC = 350.53;
config.yCalM = -0.07;
config.yCalC = 261.67;
//MQTT
strcpy(config.mqttBroker, "192.168.2.12");
config.mqttPort = 1883;
//Solar Forecast API
strcpy(config.forecastApiKey, "notAvailable");
strcpy(config.latitude, "36.9074");
strcpy(config.longitude, "-4.1324");
strcpy(config.dampingM, "0.5");
strcpy(config.dampingE, "0");
strcpy(config.kwpInvertor, "7");
strcpy(config.declination, "44");
strcpy(config.azimuth, "4");
// This is the end of initial variable setup
Serial.begin(115200);
while (!Serial)
delay(1000);
Serial.print("\nStart LittleFS_Test on ");
Serial.println(BOARD_NAME);
Serial.println(LFS_MBED_RP2040_VERSION);
#if defined(LFS_MBED_RP2040_VERSION_MIN)
if (LFS_MBED_RP2040_VERSION_INT < LFS_MBED_RP2040_VERSION_MIN) {
Serial.print("Warning. Must use this example on Version equal or later than : ");
Serial.println(LFS_MBED_RP2040_VERSION_MIN_TARGET);
}
#endif
myFS = new LittleFS_MBED();
if (!myFS->init()) {
Serial.println("LITTLEFS Mount Failed");
return;
}
//char fileName2[] = MBED_LITTLEFS_FILE_PREFIX "/hello2.txt";
//not this message
//char message[] = "Hello from " BOARD_NAME "\n";
/*
JsonDocument dailyFilter;
dailyFilter["daily"]["data"][0]["day"] = true;
dailyFilter["daily"]["data"][0]["day"]["all_day"]["temperature"] = true;
dailyFilter["daily"]["data"][0]["day"]["all_day"]["cloud_cover"]["total"] = true;
dailyFilter["daily"]["data"][0]["day"]["all_day"]["precipitation"]["total"] = true;
*/
Serial.println("\nTest complete");
} // End of Setup
/*
void saveConfigFile(const char *filename, const configData &config) {
if (checkFile(filename)) {
deleteFile(filename);
}
myFS = new LittleFS_MBED();
FILE *file = fopen(filename, "w");
if (file)
{
Serial.println(" => Open OK");
}
else
{
Serial.println(" => Open Failed");
return;
}
JsonDocument doc;
doc.set(config);
serializeJson(doc, file);
}
void loadConfigFile(const char *filename) {
myFS = new LittleFS_MBED();
//File file = LittleFS_MBED.open(filename, "r");
FILE *file = fopen(filename, "r");
JsonDocument doc;
deserializeJson(doc, file);
//here we need to copy the json config the the global variables
convertFromJson(doc)
//return doc.as<configData>();
}
*/
void convertToJson(const configData &src, JsonVariant dst) {
dst["ssid"] = src.ssid;
dst["pass"] = src.pass;
//TouchScreen Calibration
dst["xCalM"] = src.xCalM;
dst["xCalC"] = src.xCalC;
dst["yCalM"] = src.yCalM;
dst["yCalC"] = src.yCalC;
//MQTT
dst["mqttBroker"] = src.mqttBroker;
dst["mqttPort"] = src.mqttPort;
//Solar Forecast API
dst["forecastApiKey"] = src.forecastApiKey;
dst["latitude"] = src.latitude;
dst["longitude"] = src.longitude;
dst["dampingM"] = src.dampingM;
dst["dampingE"] = src.dampingE;
dst["kwpInvertor"] = src.kwpInvertor;
dst["declination"] = src.declination;
dst["azimuth"] = src.azimuth;
}
void convertFromJson(JsonVariantConst src, configData &dst) {
strlcpy(dst.ssid, src["ssid"] | "xx", sizeof(dst.ssid));
strlcpy(dst.pass, src["pass"] | "xx", sizeof(dst.pass));
//TouchScreen Calibration
dst.xCalM = src["xCalM"];
dst.xCalC = src["xCalC"];
dst.yCalM = src["yCalM"];
dst.yCalC = src["yCalC"];
//MQTT
strlcpy(dst.mqttBroker, src["mqttBroker"] | "xx", sizeof(dst.mqttBroker));
strlcpy(dst.pass, src["mqttPort"] | "xx", sizeof(dst.mqttPort));
//Solar Forecast API
strlcpy(dst.forecastApiKey, src["forecastApiKey"] | "xx", sizeof(dst.forecastApiKey));
strlcpy(dst.latitude, src["latitude"] | "xx", sizeof(dst.latitude));
strlcpy(dst.longitude, src["longitude"] | "xx", sizeof(dst.longitude));
strlcpy(dst.dampingM, src["dampingM"] | "xx", sizeof(dst.dampingM));
strlcpy(dst.dampingE, src["dampingE"] | "xx", sizeof(dst.dampingE));
strlcpy(dst.kwpInvertor, src["kwpInvertor"] | "xx", sizeof(dst.kwpInvertor));
strlcpy(dst.declination, src["declination"] | "xx", sizeof(dst.declination));
strlcpy(dst.azimuth, src["azimuth"] | "xx", sizeof(dst.azimuth));
}
void loop() {
}