|
|
|
// ArduinoJson - https://arduinojson.org
|
|
|
|
// Copyright © 2014-2024, Benoit BLANCHON
|
|
|
|
// MIT License
|
|
|
|
//
|
|
|
|
// This example shows how to store your project configuration in a file.
|
|
|
|
// It uses the SD library but can be easily modified for any other file-system.
|
|
|
|
//
|
|
|
|
// The file contains a JSON document with the following content:
|
|
|
|
// {
|
|
|
|
// "hostname": "examples.com",
|
|
|
|
// "port": 2731
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// To run this program, you need an SD card connected to the SPI bus as follows:
|
|
|
|
// * MOSI <-> pin 11
|
|
|
|
// * MISO <-> pin 12
|
|
|
|
// * CLK <-> pin 13
|
|
|
|
// * CS <-> pin 4
|
|
|
|
//
|
|
|
|
// https://arduinojson.org/v7/example/config/
|
|
|
|
|
|
|
|
#include <ArduinoJson.h>
|
|
|
|
#include <SD.h>
|
|
|
|
#include <SPI.h>
|
|
|
|
|
|
|
|
// Our configuration structure.
|
|
|
|
struct Config {
|
|
|
|
char hostname[64];
|
|
|
|
int port;
|
|
|
|
};
|
|
|
|
|
|
|
|
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
|
|
|
|
JsonDocument 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
|
|
|
|
config.port = doc["port"] | 2731;
|
|
|
|
strlcpy(config.hostname, // <- destination
|
|
|
|
doc["hostname"] | "example.com", // <- source
|
|
|
|
sizeof(config.hostname)); // <- destination's capacity
|
|
|
|
|
|
|
|
// 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
|
|
|
|
JsonDocument doc;
|
|
|
|
|
|
|
|
// Set the values in the document
|
|
|
|
doc["hostname"] = config.hostname;
|
|
|
|
doc["port"] = config.port;
|
|
|
|
|
|
|
|
// 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
|
|
|
|
const int chipSelect = 4;
|
|
|
|
while (!SD.begin(chipSelect)) {
|
|
|
|
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() {
|
|
|
|
// not used in this example
|
|
|
|
}
|
|
|
|
|
|
|
|
// Performance issue?
|
|
|
|
// ------------------
|
|
|
|
//
|
|
|
|
// File is an unbuffered stream, which is not optimal for ArduinoJson.
|
|
|
|
// See: https://arduinojson.org/v7/how-to/improve-speed/
|
|
|
|
|
|
|
|
// See also
|
|
|
|
// --------
|
|
|
|
//
|
|
|
|
// https://arduinojson.org/ contains the documentation for all the functions
|
|
|
|
// used above. It also includes an FAQ that will help you solve any
|
|
|
|
// serialization or deserialization problem.
|
|
|
|
//
|
|
|
|
// The book "Mastering ArduinoJson" contains a case study of a project that has
|
|
|
|
// a complex configuration with nested members.
|
|
|
|
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
|
|
|
|
// Learn more at https://arduinojson.org/book/
|
|
|
|
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|