#include <ArduinoJson.h>
#include <SD.h>
#include <SPI.h>
// Our configuration structure.
//
// Never use a JsonDocument to store the configuration!
// A JsonDocument is *not* a permanent storage; it's only a temporary storage
// used during the serialization phase. See:
// https://arduinojson.org/v6/faq/why-must-i-create-a-separate-config-object/
struct Config {
char version[6];
unsigned int chrono[3];
unsigned int distance;
float maxSpeed;
unsigned int circumference;
float limitSpeed[3];
unsigned int lapNumber;
bool startLap;
bool averageSpeed;
};
const char *filename = "/config.txt"; // <- SD library uses 8.3 filenames
Config config; // <- global configuration object
// Loads the configuration from a file
void loadConfiguration(const char *filename, Config &config) {
// Open file for reading
File file = SD.open(filename);
// Allocate a temporary JsonDocument
// Don't forget to change the capacity to match your requirements.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<512> doc;
// Deserialize the JSON document
DeserializationError error = deserializeJson(doc, file);
if (error)
Serial.println(F("Failed to read file, using default configuration"));
// Copy values from the JsonDocument to the Config
strlcpy(config.version, // <- destination
doc["version"] | "1.0.0", // <- source
sizeof(config.version)); // <- destination's capacity
JsonArray chrono = doc["chrono"];
config.chrono[0] = chrono[0];
config.chrono[1] = chrono[1];
config.chrono[2] = chrono[2];
config.distance = doc["distance"];
config.maxSpeed = doc["maxSpeed"];
config.circumference = doc["circumference"];
JsonArray limitSpeed = doc["limitSpeed"];
config.limitSpeed[0] = limitSpeed[0];
config.limitSpeed[1] = limitSpeed[1];
config.limitSpeed[2] = limitSpeed[2];
config.lapNumber = doc["lapNumber"];
config.startLap = doc["startLap"];
config.averageSpeed = doc["averageSpeed"];
// Close the file (Curiously, File's destructor doesn't close the file)
file.close();
}
// Saves the configuration to a file
void saveConfiguration(const char *filename, const Config &config) {
// Delete existing file, otherwise the configuration is appended to the file
SD.remove(filename);
// Open file for writing
File file = SD.open(filename, FILE_WRITE);
if (!file) {
Serial.println(F("Failed to create file"));
return;
}
// Allocate a temporary JsonDocument
// Don't forget to change the capacity to match your requirements.
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonDocument<256> doc;
// Set the values in the document
doc["version"] = config.version;
doc["chrono"][0] = config.chrono[0];
doc["chrono"][1] = config.chrono[1];
doc["chrono"][2] = config.chrono[2];
doc["distance"] = config.distance;
doc["maxSpeed"] = config.maxSpeed;
doc["circumference"] = config.circumference;
doc["limitSpeed"][0] = config.limitSpeed[0];
doc["limitSpeed"][1] = config.limitSpeed[1];
doc["limitSpeed"][2] = config.limitSpeed[2];
doc["lapNumber"] = config.lapNumber;
doc["startLap"] = config.startLap;
doc["averageSpeed"] = config.averageSpeed;
// Serialize JSON to file
if (serializeJson(doc, file) == 0) {
Serial.println(F("Failed to write to file"));
}
// Close the file
file.close();
}
// Prints the content of a file to the Serial
void printFile(const char *filename) {
// Open file for reading
File file = SD.open(filename);
if (!file) {
Serial.println(F("Failed to read file"));
return;
}
// Extract each characters by one by one
while (file.available()) {
Serial.print((char)file.read());
}
Serial.println();
// Close the file
file.close();
}
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial) continue;
// Initialize SD library
while (!SD.begin(4)) {
Serial.println(F("Failed to initialize SD library"));
delay(1000);
}
// Should load default config if run for the first time
Serial.println(F("Loading configuration..."));
loadConfiguration(filename, config);
// Create configuration file
Serial.println(F("Saving configuration..."));
saveConfiguration(filename, config);
// Dump config file
Serial.println(F("Print config file..."));
printFile(filename);
}
void loop() {
// put your main code here, to run repeatedly:
}