Uniot Core
0.8.1
Loading...
Searching...
No Matches
Storage.h
Go to the documentation of this file.
1/*
2 * This is a part of the Uniot project.
3 * Copyright (C) 2016-2023 Uniot <contact@uniot.io>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
26
31
32#pragma once
33
34// doc: https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html
35#if UNIOT_USE_NVSFS == 1
36#include <NVSFS.h>
37#define FileFS NVSFS
38#elif UNIOT_USE_LITTLEFS == 1
39#include <LittleFS.h>
40#define FileFS LittleFS
41#else
42#include <FS.h>
43#include <SPIFFS.h>
44#define FileFS SPIFFS
45#endif
46
47#include <Bytes.h>
48#include <Logger.h>
49
50namespace uniot {
51
63class Storage {
64 public:
74 Storage(const String &path) {
75 String normalizedPath = path;
76 if (!normalizedPath.startsWith("/")) {
77 normalizedPath = "/" + normalizedPath;
78 }
79 setPath(normalizedPath);
80
81 sInstancesCount++;
82
83 if (!sMounted) {
84#if defined(ESP8266)
85 sMounted = FileFS.begin();
86#elif defined(ESP32)
87 sMounted = FileFS.begin(true);
88#endif
89 // By default, FileFS will automatically format the filesystem if one is not detected.
90 // This means that you will lose all filesystem data even if other filesystem exists.
91 UNIOT_LOG_WARN_IF(!sMounted, "Failed to mount the file system");
92 }
93 }
94
101 virtual ~Storage() {
102 sInstancesCount--;
103 if (!sInstancesCount) {
104 unmount();
105 }
106 }
107
118 static void unmount() {
119 if (sMounted) {
120 FileFS.end();
121 sMounted = false;
122 }
123 }
124
135 virtual bool store() {
136 auto file = FileFS.open(mPath, "w");
137 if (!file) {
138 UNIOT_LOG_WARN("Failed to open %s", mPath.c_str());
139 return false;
140 }
141 file.write(mData.raw(), mData.size());
142 file.close();
143
144#if defined(ESP8266)
145#if UNIOT_USE_LITTLEFS != 1
146 // using SPIFFS.gc() can avoid or reduce issues where SPIFFS reports
147 // free space but is unable to write additional data to a file
148 UNIOT_LOG_DEBUG_IF(!FileFS.gc(), "SPIFFS gc failed. That's all right. Caller: %s", mPath.c_str());
149#endif
150#endif
151
152 return true;
153 }
154
165 virtual bool restore() {
166 auto file = FileFS.open(mPath, "r");
167 if (!file) {
168 UNIOT_LOG_WARN("Failed to open %s. It is ok on first start", mPath.c_str());
169 return false;
170 }
171#ifdef UNIOT_USE_NVSFS
172 mData = file.getBytes(); // NVSFS provides a convenient way to get bytes directly
173#else
174 mData = _readSmallFile(file); // TODO: cleanup before read?
175#endif
176 file.close();
177 return true;
178 }
179
189 virtual bool clean() {
190 mData.clean();
191 if (!FileFS.remove(mPath)) {
192 UNIOT_LOG_WARN("Failed to remove %s", mPath.c_str());
193 return false;
194 }
195 return true;
196 }
197
198 protected:
206
212 String mPath;
213
219 void setPath(const String &path) {
220 mPath = path;
221 // There is a limit of 32 chars in total for filenames.
222 // One '\0' char is reserved for string termination.
223 UNIOT_LOG_WARN_IF(path.length() > 31, "Path length of '%s' > 31 chars", mPath.c_str());
224 }
225
226 private:
236
237#ifndef UNIOT_USE_NVSFS
238 Bytes _readSmallFile(File &file) {
239 auto toRead = file.size() - file.position();
240 char *buf = (char *)malloc(toRead);
241 auto countRead = file.readBytes(buf, toRead);
242 const Bytes data((uint8_t *)buf, countRead);
243 free(buf);
244 return data;
245 }
246#endif
247
253 static bool sMounted;
254
260 static unsigned int sInstancesCount;
261};
262
263} // namespace uniot
#define FileFS
Definition Storage.h:44
Definition Bytes.h:38
size_t size() const
Gets the size of the byte array.
Definition Bytes.h:303
Storage(const String &path)
Constructs a Storage object for a specific file.
Definition Storage.h:74
String mPath
The file path where data is stored.
Definition Storage.h:212
void setPath(const String &path)
Sets the file path, ensuring it starts with "/".
Definition Storage.h:219
virtual bool clean()
Clears data and removes the file from the file system.
Definition Storage.h:189
Bytes mData
The byte array containing the data to be stored or the loaded data.
Definition Storage.h:205
virtual bool store()
Writes the current data to the file system.
Definition Storage.h:135
virtual bool restore()
Loads data from the file system into memory.
Definition Storage.h:165
virtual ~Storage()
Destructor.
Definition Storage.h:101
static void unmount()
Explicitly unmounts the filesystem.
Definition Storage.h:118
#define UNIOT_LOG_WARN(...)
Log an WARN level message Used for warnings about potentially problematic situations....
Definition Logger.h:247
#define UNIOT_LOG_WARN_IF(log_cond, log...)
Conditionally log an WARN level message Used for warnings about potentially problematic situations....
Definition Logger.h:255
#define UNIOT_LOG_DEBUG_IF(log_cond, log...)
Conditionally log an DEBUG level message Used for general information about system operation....
Definition Logger.h:301
Contains all classes and functions related to the Uniot Core.