CanGrow/include/CanGrow_LittleFS.h

855 lines
29 KiB
C

/*
*
* include/CanGrow_LittleFS.h - LittleFS handling header file
*
*
*
*/
// LittleFS auto format
#define FORMAT_LITTLEFS_IF_FAILED true
void LFS_Init() {
const static char LogLoc[] PROGMEM = "[LittleFS:Init]";
Log.notice(F("%s" CR), LogLoc);
// ESP8266 crashes with first argument set
#ifdef ESP8266
if(!LittleFS.begin()) {
#endif
// ESP32 works, do autoformat if mount fails
#ifdef ESP32
if(!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)) {
#endif
Log.notice(F("%s FAILED initializing. You have to format LittleFS manually. Will now restart." CR), LogLoc);
Restart();
}
}
void LFS_Format() {
const static char LogLoc[] PROGMEM = "[LittleFS:Format]";
Log.notice(F("%s formatting ..." CR), LogLoc);
// ESP32 LittleFS needs begin() first, otherwise it would crash
// ESP8266 does not need it, so we leave it
#ifdef ESP32
LittleFS.begin();
#endif
if(LittleFS.format()) {
Log.notice(F("%s done!" CR), LogLoc);
} else {
Log.error(F("%s FAILED" CR), LogLoc);
}
}
bool existFile(const char *path) {
const static char LogLoc[] PROGMEM = "[LittleFS]";
#ifdef ESP8266
File file = LittleFS.open(path, "r");
#endif
#ifdef ESP32
fs::FS &fs = LittleFS;
File file = fs.open(path);
#endif
if (!file) {
Log.notice(F("%s file exists: %s" CR), LogLoc, path);
file.close();
return false;
} else {
Log.warning(F("%s file does not exist: %s" CR), LogLoc, path);
file.close();
return true;
}
}
String readFile(const char *path) {
const static char LogLoc[] PROGMEM = "[LittleFS]";
String fileContent;
#ifdef ESP8266
File file = LittleFS.open(path, "r");
#endif
#ifdef ESP32
fs::FS &fs = LittleFS;
File file = fs.open(path);
#endif
if (!file) {
Log.error(F("%s FAILED to open file for reading: %s" CR), LogLoc, path);
return String(F("ERROR CANNOT OPEN"));
}
Log.notice(F("%s file content: %s" CR), LogLoc, path);
Log.notice(F("%s ----------" CR), LogLoc);
while (file.available()) { Serial.write(file.read()); }
Log.notice(F("%s ----------" CR), LogLoc);
fileContent = file.readString();
file.close();
return fileContent;
}
void writeFile(const char *path, const char *message) {
const static char LogLoc[] PROGMEM = "[LittleFS]";
#ifdef ESP8266
File file = LittleFS.open(path, "w");
#endif
#ifdef ESP32
fs::FS &fs = LittleFS;
File file = fs.open(path, FILE_WRITE);
#endif
if (!file) {
Log.error(F("%s FAILED to open file for reading: %s" CR), LogLoc, path);
return;
}
if (file.print(message)) {
Log.notice(F("%s file written: %s" CR), LogLoc, path);
} else {
Log.error(F("%s writing file FAILED: %s" CR), LogLoc, path);
}
//delay(2000); // Make sure the CREATE and LASTWRITE times are different
file.close();
}
void deleteFile(const char *path) {
const static char LogLoc[] PROGMEM = "[LittleFS]";
#ifdef ESP32
fs::FS &fs = LittleFS;
File file = fs.open(path, FILE_WRITE);
#endif
Log.notice(F("%s deleting file: %s" CR), LogLoc, path);
#ifdef ESP8266
if (LittleFS.remove(path)) {
#endif
#ifdef ESP32
if (fs.remove(path)) {
#endif
Log.notice(F("%s deleted file: %s" CR), LogLoc, path);
} else {
Log.error(F("%s deleting file FAILED: %s" CR), LogLoc, path);
}
}
// https://arduinojson.org/v7/example/config/
// https://arduinojson.org/v7/assistant/
bool LoadConfig() {
const static char LogLoc[] PROGMEM = "[LittleFS:LoadConfig]";
#ifdef ESP8266
File file = LittleFS.open(CANGROW_CFG, "r");
#endif
#ifdef ESP32
fs::FS &fs = LittleFS;
File file = fs.open(CANGROW_CFG);
#endif
Log.notice(F("%s loading config from: %s" CR), LogLoc, CANGROW_CFG);
JsonDocument doc;
// Deserialize the JSON document
DeserializationError error = deserializeJson(doc, file);
if(error) {
Log.error(F("%s FAILED to load config: %s" CR), LogLoc, CANGROW_CFG);
if (existFile(CANGROW_CFG)) {
readFile(CANGROW_CFG);
}
return false;
}
/*
* put json values into config structs
*/
// Copy strings from the JsonDocument to the Config struct as char
strlcpy(config.test, doc["test"], sizeof(config.test));
/* WiFi */
JsonObject objWifi = doc["wifi"][0];
if(objWifi.containsKey("ssid"))
strlcpy(config.wifi.ssid, objWifi["ssid"], sizeof(config.wifi.ssid));
if(objWifi.containsKey("password"))
strlcpy(config.wifi.password, objWifi["password"], sizeof(config.wifi.password));
// Copy bool / int directly into struct
if(objWifi.containsKey("dhcp"))
config.wifi.dhcp = objWifi["dhcp"];
// load the ip addresses as array
if(objWifi.containsKey("ip")) {
for(byte i=0; i < 4 ; i++) {
config.wifi.ip[i] = objWifi["ip"][i];
config.wifi.netmask[i] = objWifi["netmask"][i];
config.wifi.gateway[i] = objWifi["gateway"][i];
config.wifi.dns[i] = objWifi["dns"][i];
}
}
/* System */
JsonObject objSystem = doc["system"][0];
if(objSystem.containsKey("ntpOffset"))
config.system.ntpOffset = objSystem["ntpOffset"];
if(objSystem.containsKey("maintenanceDuration"))
config.system.maintenanceDuration = objSystem["maintenanceDuration"];
if(objSystem.containsKey("esp32cam"))
strlcpy(config.system.esp32cam, objSystem["esp32cam"], sizeof(config.system.esp32cam));
if(objSystem.containsKey("httpUser"))
strlcpy(config.system.httpUser, objSystem["httpUser"], sizeof(config.system.httpUser));
if(objSystem.containsKey("httpPass"))
strlcpy(config.system.httpPass, objSystem["httpPass"], sizeof(config.system.httpPass));
if(objSystem.containsKey("httpLogSerial"))
config.system.httpLogSerial = objSystem["httpLogSerial"];
if(objSystem.containsKey("schedulerInterval"))
config.system.schedulerInterval = objSystem["schedulerInterval"];
if(objSystem.containsKey("ntp"))
config.system.ntp = objSystem["ntp"];
if(objSystem.containsKey("rtc"))
config.system.rtc = objSystem["rtc"];
if(objSystem.containsKey("time2fs"))
config.system.time2fs = objSystem["time2fs"];
if(objSystem.containsKey("pwmFreq"))
config.system.pwmFreq = objSystem["pwmFreq"];
/* System Outputs */
JsonObject objSystemOutput = objSystem["output"][0];
for(byte i=0; i < Max_Outputs; i++) {
if(objSystemOutput["type"][i] > 0) {
if(objSystemOutput.containsKey("type"))
config.system.output.type[i] = objSystemOutput["type"][i];
if(objSystemOutput.containsKey("device"))
config.system.output.device[i] = objSystemOutput["device"][i];
if(objSystemOutput.containsKey("name"))
strlcpy(config.system.output.name[i], objSystemOutput["name"][i], sizeof(config.system.output.name[i]));
if(objSystemOutput.containsKey("enabled"))
config.system.output.enabled[i] = objSystemOutput["enabled"][i];
// gpio
if(objSystemOutput.containsKey("gpio"))
config.system.output.gpio[i] = objSystemOutput["gpio"][i];
if(objSystemOutput.containsKey("invert"))
config.system.output.invert[i] = objSystemOutput["invert"][i];
if(objSystemOutput.containsKey("gpio_pwm"))
config.system.output.gpio_pwm[i] = objSystemOutput["gpio_pwm"][i];
// i2c type
if(objSystemOutput.containsKey("i2c_type"))
config.system.output.i2c_type[i] = objSystemOutput["i2c_type"][i];
// i2c addr
if(objSystemOutput.containsKey("i2c_addr"))
config.system.output.i2c_addr[i] = objSystemOutput["i2c_addr"][i];
// i2c port
if(objSystemOutput.containsKey("i2c_port"))
config.system.output.i2c_port[i] = objSystemOutput["i2c_port"][i];
// web
if(objSystemOutput.containsKey("webcall_host"))
strlcpy(config.system.output.webcall_host[i], objSystemOutput["webcall_host"][i], sizeof(config.system.output.webcall_host[i]));
if(objSystemOutput.containsKey("webcall_path_on"))
strlcpy(config.system.output.webcall_path_on[i], objSystemOutput["webcall_path_on"][i], sizeof(config.system.output.webcall_path_on[i]));
if(objSystemOutput.containsKey("webcall_path_off"))
strlcpy(config.system.output.webcall_path_off[i], objSystemOutput["webcall_path_off"][i], sizeof(config.system.output.webcall_path_off[i]));
}
}
/* System Sensors */
JsonObject objSystemSensor = objSystem["sensor"][0];
for(byte i=0; i < Max_Sensors; i++) {
if(objSystemSensor["type"][i] > 0) {
if(objSystemSensor.containsKey("type"))
config.system.sensor.type[i] = objSystemSensor["type"][i];
if(objSystemSensor.containsKey("name"))
strlcpy(config.system.sensor.name[i], objSystemSensor["name"][i], sizeof(config.system.sensor.name[i]));
if(objSystemSensor.containsKey("i2c_addr"))
//strlcpy(config.system.sensor.i2c_addr[i], objSystemSensor["i2c_addr"][i], sizeof(config.system.sensor.i2c_addr[i]));
config.system.sensor.i2c_addr[i] = objSystemSensor["i2c_addr"][i];
// gpio
if(objSystemSensor.containsKey("gpio")) {
for(byte j = 0; j < Max_Sensors_GPIO; j++) {
config.system.sensor.gpio[i][j] = objSystemSensor["gpio"][i][j];
}
}
// offset
if(objSystemSensor.containsKey("offset")) {
for(byte j = 0; j < Max_Sensors_Read; j++) {
config.system.sensor.offset[i][j] = objSystemSensor["offset"][i][j];
}
}
// low
if(objSystemSensor.containsKey("low")) {
for(byte j = 0; j < Max_Sensors_Read; j++) {
config.system.sensor.low[i][j] = objSystemSensor["low"][i][j];
}
}
// high
if(objSystemSensor.containsKey("high")) {
for(byte j = 0; j < Max_Sensors_Read; j++) {
config.system.sensor.high[i][j] = objSystemSensor["high"][i][j];
}
}
// rawConvert
if(objSystemSensor.containsKey("rawConvert")) {
for(byte j = 0; j < Max_Sensors_Read; j++) {
config.system.sensor.rawConvert[i][j] = objSystemSensor["rawConvert"][i][j];
}
}
}
}
/* Grow */
JsonObject objGrow = doc["grow"][0];
if(objGrow.containsKey("name"))
strlcpy(config.grow.name, objGrow["name"], sizeof(config.grow.name));
if(objGrow.containsKey("start"))
config.grow.start = objGrow["start"];
if(objGrow.containsKey("daysVeg"))
config.grow.daysVeg = objGrow["daysVeg"];
if(objGrow.containsKey("daysBloom"))
config.grow.daysBloom = objGrow["daysBloom"];
/* Grow Light */
JsonObject objLight = objGrow["light"][0];
for(byte i = 0; i < Max_Outputs; i++) {
/* get light.configured */
if(objLight.containsKey("configured"))
config.grow.light.configured[i] = objLight["configured"][i];
/* check if light is configured */
if(config.grow.light.configured[i] == true) {
/* get the rest of the config */
if(objLight.containsKey("output"))
config.grow.light.output[i] = objLight["output"][i];
if(objLight.containsKey("sunriseHourVeg"))
config.grow.light.sunriseHourVeg[i] = objLight["sunriseHourVeg"][i];
if(objLight.containsKey("sunriseMinuteVeg"))
config.grow.light.sunriseMinuteVeg[i] = objLight["sunriseMinuteVeg"][i];
if(objLight.containsKey("sunsetHourVeg"))
config.grow.light.sunsetHourVeg[i] = objLight["sunsetHourVeg"][i];
if(objLight.containsKey("sunsetMinuteVeg"))
config.grow.light.sunsetMinuteVeg[i] = objLight["sunsetMinuteVeg"][i];
if(objLight.containsKey("sunriseHourBloom"))
config.grow.light.sunriseHourBloom[i] = objLight["sunriseHourBloom"][i];
if(objLight.containsKey("sunriseMinuteBloom"))
config.grow.light.sunriseMinuteBloom[i] = objLight["sunriseMinuteBloom"][i];
if(objLight.containsKey("sunsetHourBloom"))
config.grow.light.sunsetHourBloom[i] = objLight["sunsetHourBloom"][i];
if(objLight.containsKey("sunsetMinuteBloom"))
config.grow.light.sunsetMinuteBloom[i] = objLight["sunsetMinuteBloom"][i];
if(objLight.containsKey("power"))
config.grow.light.power[i] = objLight["power"][i];
if(objLight.containsKey("fade"))
config.grow.light.fade[i] = objLight["fade"][i];
if(objLight.containsKey("fadeDuration"))
config.grow.light.fadeDuration[i] = objLight["fadeDuration"][i];
}
}
/* Grow Air */
JsonObject objAir = objGrow["air"][0];
for(byte i = 0; i < Max_Outputs; i++) {
/* get air.configured */
if(objAir.containsKey("configured"))
config.grow.air.configured[i] = objAir["configured"][i];
/* check if air is configured */
if(config.grow.air.configured[i] == true) {
/* get the rest of the config */
if(objAir.containsKey("output"))
config.grow.air.output[i] = objAir["output"][i];
if(objAir.containsKey("power"))
config.grow.air.power[i] = objAir["power"][i];
if(objAir.containsKey("controlSensor"))
config.grow.air.controlSensor[i] = objAir["controlSensor"][i];
if(objAir.containsKey("controlRead"))
config.grow.air.controlRead[i] = objAir["controlRead"][i];
if(objAir.containsKey("controlMode"))
config.grow.air.controlMode[i] = objAir["controlMode"][i];
if(objAir.containsKey("min"))
config.grow.air.min[i] = objAir["min"][i];
if(objAir.containsKey("max"))
config.grow.air.max[i] = objAir["max"][i];
}
}
/* Grow Water */
JsonObject objWater = objGrow["water"][0];
for(byte i = 0; i < Max_Outputs; i++) {
/* get air.configured */
if(objWater.containsKey("configured"))
config.grow.water.configured[i] = objWater["configured"][i];
/* check if air is configured */
if(config.grow.water.configured[i] == true) {
/* get the rest of the config */
if(objWater.containsKey("output"))
config.grow.water.output[i] = objWater["output"][i];
if(objWater.containsKey("onTime"))
config.grow.water.onTime[i] = objWater["onTime"][i];
if(objWater.containsKey("controlSensor"))
config.grow.water.controlSensor[i] = objWater["controlSensor"][i];
if(objWater.containsKey("controlRead"))
config.grow.water.controlRead[i] = objWater["controlRead"][i];
if(objWater.containsKey("controlMode"))
config.grow.water.controlMode[i] = objWater["controlMode"][i];
if(objWater.containsKey("min"))
config.grow.water.min[i] = objWater["min"][i];
if(objWater.containsKey("max"))
config.grow.water.max[i] = objWater["max"][i];
if(objWater.containsKey("interval"))
config.grow.water.interval[i] = objWater["interval"][i];
if(objWater.containsKey("intervalUnit"))
config.grow.water.intervalUnit[i] = objWater["intervalUnit"][i];
}
}
// Close the file (Curiously, File's destructor doesn't close the file)
file.close();
Log.notice(F("%s config successfully loaded" CR), LogLoc);
#ifdef DEBUG
Log.verbose(F("%s --- runtime config ---" CR), LogLoc);
serializeJsonPretty(doc, Serial);
// Json output does not end with NewLine
Serial.println("");
Log.verbose(F("%s ----------------------" CR), LogLoc);
#endif
return true;
}
bool SaveConfig(bool writeToSerial = false) {
const static char LogLoc[] PROGMEM = "[LittleFS:SaveConfig]";
/*
* Building config.json here
*/
JsonDocument doc;
/* Root */
doc["test"] = config.test;
/* WiFi */
JsonObject objWifi = doc["wifi"].add<JsonObject>();
objWifi["ssid"] = config.wifi.ssid;
objWifi["password"] = config.wifi.password;
// save the ip addressess as array
int i;
for(i=0; i <4 ; i++) {
objWifi["ip"][i] = config.wifi.ip[i];
objWifi["netmask"][i] = config.wifi.netmask[i];
objWifi["gateway"][i] = config.wifi.gateway[i];
objWifi["dns"][i] = config.wifi.dns[i];
}
objWifi["dhcp"] = config.wifi.dhcp;
/* System */
JsonObject objSystem = doc["system"].add<JsonObject>();
objSystem["ntpOffset"] = config.system.ntpOffset;
objSystem["maintenanceDuration"] = config.system.maintenanceDuration;
objSystem["esp32cam"] = config.system.esp32cam;
objSystem["httpUser"] = config.system.httpUser;
objSystem["httpPass"] = config.system.httpPass;
objSystem["httpLogSerial"] = config.system.httpLogSerial;
objSystem["schedulerInterval"] = config.system.schedulerInterval;
objSystem["ntp"] = config.system.ntp;
objSystem["rtc"] = config.system.rtc;
objSystem["time2fs"] = config.system.time2fs;
objSystem["pwmFreq"] = config.system.pwmFreq;
/* System Outputs */
JsonObject objSystemOutput = objSystem["output"].add<JsonObject>();
for(byte i=0; i < Max_Outputs; i++) {
if(config.system.output.type[i] > 0) {
objSystemOutput["type"][i] = config.system.output.type[i];
objSystemOutput["device"][i] = config.system.output.device[i];
objSystemOutput["name"][i] = config.system.output.name[i];
objSystemOutput["enabled"][i] = config.system.output.enabled[i];
// gpio
objSystemOutput["gpio"][i] = config.system.output.gpio[i];
objSystemOutput["invert"][i] = config.system.output.invert[i];
objSystemOutput["gpio_pwm"][i] = config.system.output.gpio_pwm[i];
// i2c type
objSystemOutput["i2c_type"][i] = config.system.output.i2c_type[i];
objSystemOutput["i2c_addr"][i] = config.system.output.i2c_addr[i];
objSystemOutput["i2c_port"][i] = config.system.output.i2c_port[i];
// web
objSystemOutput["webcall_host"][i] = config.system.output.webcall_host[i];
objSystemOutput["webcall_path_on"][i] = config.system.output.webcall_path_on[i];
objSystemOutput["webcall_path_off"][i] = config.system.output.webcall_path_off[i];
}
}
/* System Sensors */
JsonObject objSystemSensor = objSystem["sensor"].add<JsonObject>();
for(byte i=0; i < Max_Sensors; i++) {
if(config.system.sensor.type[i] > 0) {
objSystemSensor["type"][i] = config.system.sensor.type[i];
objSystemSensor["name"][i] = config.system.sensor.name[i];
objSystemSensor["i2c_addr"][i] = config.system.sensor.i2c_addr[i];
for(byte j = 0; j < Max_Sensors_GPIO; j++) {
objSystemSensor["gpio"][i][j] = config.system.sensor.gpio[i][j];
}
/* offset reading */
for(byte j = 0; j < Max_Sensors_Read; j++) {
objSystemSensor["offset"][i][j] = config.system.sensor.offset[i][j];
}
/* low reading */
for(byte j = 0; j < Max_Sensors_Read; j++) {
objSystemSensor["low"][i][j] = config.system.sensor.low[i][j];
}
/* high reading */
for(byte j = 0; j < Max_Sensors_Read; j++) {
objSystemSensor["high"][i][j] = config.system.sensor.high[i][j];
}
/* rawConvert reading */
for(byte j = 0; j < Max_Sensors_Read; j++) {
objSystemSensor["rawConvert"][i][j] = config.system.sensor.rawConvert[i][j];
}
}
}
/* Grow */
JsonObject objGrow = doc["grow"].add<JsonObject>();
objGrow["name"] = config.grow.name;
objGrow["start"] = config.grow.start;
objGrow["daysVeg"] = config.grow.daysVeg;
objGrow["daysBloom"] = config.grow.daysBloom;
/* Grow Light */
JsonObject objLight = objGrow["light"].add<JsonObject>();
for(byte i = 0; i < Max_Outputs; i++) {
#ifdef DEBUG
Log.verbose(F("%s LightId %d, Max_Outputs %d, light.configured %T" CR), LogLoc, i, Max_Outputs, config.grow.light.configured[i]);
#endif
if(config.grow.light.configured[i] == true) {
objLight["configured"][i] = config.grow.light.configured[i];
objLight["output"][i] = config.grow.light.output[i];
objLight["sunriseHourVeg"][i] = config.grow.light.sunriseHourVeg[i];
objLight["sunriseMinuteVeg"][i] = config.grow.light.sunriseMinuteVeg[i];
objLight["sunsetHourVeg"][i] = config.grow.light.sunsetHourVeg[i];
objLight["sunsetMinuteVeg"][i] = config.grow.light.sunsetMinuteVeg[i];
objLight["sunriseHourBloom"][i] = config.grow.light.sunriseHourBloom[i];
objLight["sunriseMinuteBloom"][i] = config.grow.light.sunriseMinuteBloom[i];
objLight["sunsetHourBloom"][i] = config.grow.light.sunsetHourBloom[i];
objLight["sunsetMinuteBloom"][i] = config.grow.light.sunsetMinuteBloom[i];
objLight["power"][i] = config.grow.light.power[i];
objLight["fade"][i] = config.grow.light.fade[i];
objLight["fadeDuration"][i] = config.grow.light.fadeDuration[i];
}
}
/* Grow Air */
JsonObject objAir = objGrow["air"].add<JsonObject>();
for(byte i = 0; i < Max_Outputs; i++) {
//Log.verbose(F("%s LightId %d, Max_Outputs %d, light.configured %T" CR), LogLoc, i, Max_Outputs, config.grow.light.configured[i]);
if(config.grow.air.configured[i] == true) {
objAir["configured"][i] = config.grow.air.configured[i];
objAir["output"][i] = config.grow.air.output[i];
objAir["power"][i] = config.grow.air.power[i];
objAir["controlSensor"][i] = config.grow.air.controlSensor[i];
objAir["controlRead"][i] = config.grow.air.controlRead[i];
objAir["controlMode"][i] = config.grow.air.controlMode[i];
objAir["min"][i] = config.grow.air.min[i];
objAir["max"][i] = config.grow.air.max[i];
}
}
/* Grow Water */
JsonObject objWater = objGrow["water"].add<JsonObject>();
for(byte i = 0; i < Max_Outputs; i++) {
//Log.verbose(F("%s LightId %d, Max_Outputs %d, light.configured %T" CR), LogLoc, i, Max_Outputs, config.grow.light.configured[i]);
if(config.grow.water.configured[i] == true) {
objWater["configured"][i] = config.grow.water.configured[i];
objWater["output"][i] = config.grow.water.output[i];
objWater["onTime"][i] = config.grow.water.onTime[i];
objWater["controlSensor"][i] = config.grow.water.controlSensor[i];
objWater["controlRead"][i] = config.grow.water.controlRead[i];
objWater["controlMode"][i] = config.grow.water.controlMode[i];
objWater["min"][i] = config.grow.water.min[i];
objWater["max"][i] = config.grow.water.max[i];
objWater["interval"][i] = config.grow.water.interval[i];
objWater["intervalUnit"][i] = config.grow.water.intervalUnit[i];
}
}
/*
* END Building config.json here
*/
// if writeToSerial is true, output json to serial, but do not write to LittleFS
if(writeToSerial == false) {
#ifdef ESP8266
File file = LittleFS.open(CANGROW_CFG, "w");
#endif
#ifdef ESP32
fs::FS &fs = LittleFS;
File file = fs.open(CANGROW_CFG, FILE_WRITE);
#endif
if (!file) {
//Log.notice(F("%s loading config from: %s" CR), LogLoc, CANGROW_CFG);
Log.error(F("%s FAILED to open configfile for writing: %s" CR), LogLoc, CANGROW_CFG);
return false;
} else {
Log.notice(F("%s opened for writing %s" CR), LogLoc, CANGROW_CFG);
}
// Serialize JSON to file
if (serializeJson(doc, file) == 0) {
Log.error(F("%s FAILED to write configfile: %s" CR), LogLoc, CANGROW_CFG);
} else {
Log.notice(F("%s successfully written %s" CR), LogLoc, CANGROW_CFG);
}
file.close();
} else {
Log.notice(F("%s --- %s ---" CR), LogLoc, CANGROW_CFG);
serializeJsonPretty(doc, Serial);
Serial.println("");
Log.notice(F("%s ----------------------" CR), LogLoc, CANGROW_CFG);
}
/* every time config get saved, we save the actual time too
* so when ntp is not available, we hopefully do not lack behind too much
* (better then nothing) */
Time2FS_Save();
return true;
}
///*
//* ESP8266 functions
//*/
///*functions from https://github.com/esp8266/Arduino/blob/master/libraries/LittleFS/examples/LittleFS_Timestamp/LittleFS_Timestamp.ino*/
//#ifdef ESP8266
//void listDir(const char *dirname) {
//Serial.printf("Listing directory: %s\n", dirname);
//Dir root = LittleFS.openDir(dirname);
//while (root.next()) {
//File file = root.openFile("r");
//Serial.print(" FILE: ");
//Serial.print(root.fileName());
//Serial.print(" SIZE: ");
//Serial.print(file.size());
//time_t cr = file.getCreationTime();
//time_t lw = file.getLastWrite();
//file.close();
//struct tm *tmstruct = localtime(&cr);
//Serial.printf(" CREATION: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
//tmstruct = localtime(&lw);
//Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
//}
//}
//void readFile(const char *path) {
//Serial.printf("Reading file: %s\n", path);
//File file = LittleFS.open(path, "r");
//if (!file) {
//Serial.println("Failed to open file for reading");
//return;
//}
//Serial.print("Read from file: ");
//while (file.available()) { Serial.write(file.read()); }
//file.close();
//}
//void writeFile(const char *path, const char *message) {
//Serial.printf("Writing file: %s\n", path);
//File file = LittleFS.open(path, "w");
//if (!file) {
//Serial.println("Failed to open file for writing");
//return;
//}
//if (file.print(message)) {
//Serial.println("File written");
//} else {
//Serial.println("Write failed");
//}
//delay(2000); // Make sure the CREATE and LASTWRITE times are different
//file.close();
//}
//void appendFile(const char *path, const char *message) {
//Serial.printf("Appending to file: %s\n", path);
//File file = LittleFS.open(path, "a");
//if (!file) {
//Serial.println("Failed to open file for appending");
//return;
//}
//if (file.print(message)) {
//Serial.println("Message appended");
//} else {
//Serial.println("Append failed");
//}
//file.close();
//}
//void renameFile(const char *path1, const char *path2) {
//Serial.printf("Renaming file %s to %s\n", path1, path2);
//if (LittleFS.rename(path1, path2)) {
//Serial.println("File renamed");
//} else {
//Serial.println("Rename failed");
//}
//}
//void deleteFile(const char *path) {
//Serial.printf("Deleting file: %s\n", path);
//if (LittleFS.remove(path)) {
//Serial.println("File deleted");
//} else {
//Serial.println("Delete failed");
//}
//}
//#endif
///*
//* ESP32 functions
//*/
///*functions from https://github.com/espressif/arduino-esp32/blob/master/libraries/LittleFS/examples/LITTLEFS_time/LITTLEFS_time.ino*/
//#ifdef ESP32
//void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
//Serial.printf("Listing directory: %s\n", dirname);
//File root = fs.open(dirname);
//if (!root) {
//Serial.println("Failed to open directory");
//return;
//}
//if (!root.isDirectory()) {
//Serial.println("Not a directory");
//return;
//}
//File file = root.openNextFile();
//while (file) {
//if (file.isDirectory()) {
//Serial.print(" DIR : ");
//Serial.print(file.name());
//time_t t = file.getLastWrite();
//struct tm *tmstruct = localtime(&t);
//Serial.printf(
//" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour,
//tmstruct->tm_min, tmstruct->tm_sec
//);
//if (levels) {
//listDir(fs, file.path(), levels - 1);
//}
//} else {
//Serial.print(" FILE: ");
//Serial.print(file.name());
//Serial.print(" SIZE: ");
//Serial.print(file.size());
//time_t t = file.getLastWrite();
//struct tm *tmstruct = localtime(&t);
//Serial.printf(
//" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour,
//tmstruct->tm_min, tmstruct->tm_sec
//);
//}
//file = root.openNextFile();
//}
//}
//void removeDir(fs::FS &fs, const char *path) {
//Serial.printf("Removing Dir: %s\n", path);
//if (fs.rmdir(path)) {
//Serial.println("Dir removed");
//} else {
//Serial.println("rmdir failed");
//}
//}
//void readFile(fs::FS &fs, const char *path) {
//Serial.printf("Reading file: %s\n", path);
//File file = fs.open(path);
//if (!file) {
//Serial.println("Failed to open file for reading");
//return;
//}
//Serial.print("Read from file: ");
//while (file.available()) {
//Serial.write(file.read());
//}
//file.close();
//}
//void writeFile(fs::FS &fs, const char *path, const char *message) {
//Serial.printf("Writing file: %s\n", path);
//File file = fs.open(path, FILE_WRITE);
//if (!file) {
//Serial.println("Failed to open file for writing");
//return;
//}
//if (file.print(message)) {
//Serial.println("File written");
//} else {
//Serial.println("Write failed");
//}
//file.close();
//}
//void appendFile(fs::FS &fs, const char *path, const char *message) {
//Serial.printf("Appending to file: %s\n", path);
//File file = fs.open(path, FILE_APPEND);
//if (!file) {
//Serial.println("Failed to open file for appending");
//return;
//}
//if (file.print(message)) {
//Serial.println("Message appended");
//} else {
//Serial.println("Append failed");
//}
//file.close();
//}
//void renameFile(fs::FS &fs, const char *path1, const char *path2) {
//Serial.printf("Renaming file %s to %s\n", path1, path2);
//if (fs.rename(path1, path2)) {
//Serial.println("File renamed");
//} else {
//Serial.println("Rename failed");
//}
//}
//void deleteFile(fs::FS &fs, const char *path) {
//Serial.printf("Deleting file: %s\n", path);
//if (fs.remove(path)) {
//Serial.println("File deleted");
//} else {
//Serial.println("Delete failed");
//}
//}
//#endif