Save configuration data in the file system of ESP8266
ESP8266 is an interesting module to build on for multiple reasons. For me, the main advantage was that I can buy the NodeMCU version on ESP8266 and I can build my projects using Arduino IDE which I’m used to. No additional programmer needed, no issues with configuration – simple start for small handyman stuff.
The other thing I found is the fact that I can use the file system on the board itself. No need to use external memory cards. Depending on the module type, you can have between 512kB and 4MB Flash from which between 64kB till 3MB can be used as the filesystem.
In my projects, I use this area to store the larger pieces of the configuration (URLs, keys) but you can also use it to store and serve assets files for your HTML pages (JS, CSS) or pages themselves. Handy!
The toolbox
In order to make my work as easy as possible, I created two functions – one to handle file writes and one to handle file reads. I don’t need the detailed information on my files. I simply need to store values and retrieve them afterward. So, there is no fancy error handling, but feel free to add one 🙂 Here are the functions:
String load_from_file(String file_name) { String result = ""; File this_file = LittleFS.open(file_name, "r"); if (!this_file) { // failed to open the file, retrn empty result return result; } while (this_file.available()) { result += (char)this_file.read(); } this_file.close(); return result; } bool write_to_file(String file_name, String contents) { File this_file = LittleFS.open(file_name, "w"); if (!this_file) { // failed to open the file, return false return false; } int bytesWritten = this_file.print(contents); if (bytesWritten == 0) { // write failed return false; } this_file.close(); return true; }
The “load from file” function is doing its best to load the data from the file. If there is no file or error occurred, an empty string is returned. I can handle it in the way I want. As per the “write to file” function, it is trying to write to the file. If there is an error – false is returned, otherwise – true. In both cases, I assume that the values to store and values retrieved are strings. If you want to save some space, you can use numeric values as well.
The usage
Take a look at these code samples:
String saved_data = load_from_file("my_file.txt"); write_to_file("my_file.txt", "data to save" );
It is simple as that. In order to read the data, you are using the “load from file” and the name of the file you want to read. For the “write to file” the file name is followed by the data you want to save. Please note that the “write to file” function is overwriting the values previously stored in the file. This one is not appending to it.
I created a simple script to show how this works in action. In the beginning, I included the “LittleFS.h” in order to use filesystem-related functions. In the setup function, I started the LittleFS filesystem by using “LittleFS.begin()”. Also in the setup, I read from the file to check if there is any data to display. Later, in the loop, I simply save the “millis” value in the file. So, this gives me the information about the module uptime on the previous run.
#include "LittleFS.h" void setup() { Serial.begin(115200); Serial.println("Booting"); delay(2000); LittleFS.begin(); String saved_millis = load_from_file("last_millis.txt"); if (saved_millis == "") { Serial.println("The file was empty or not present"); } else { Serial.println("The last value saved in file is: " + saved_millis); } } void loop() { write_to_file("last_millis.txt", String( millis() ) ); delay(100); } String load_from_file(String file_name) { // contents of this function are described above } bool write_to_file(String file_name, String contents) { // contents of this function are described above }
So, how the output looks like? On the first execution, when tere is no file in the Flash memory, I see the following:
Booting The file was empty or not present
The script notifies me that there was nothing to read. For me it doesn’t matter if the file was present and empty or if there was no file – I know that my “configuration variable” should be initialized with a default value. When the code runs, the current “millis” is written to the file, so after the module reboot I see the following information:
Booting The last value saved in file is: 35568
The file read operation was successful, and I can use the retrieved value as my “configuration variable”.