最近有做一个小项目,一些系统设定需要保存,开机后依旧是上次设置的值,之前使用eeprom来储存,但有些esp8266在写值会重启,能力有限,至今没有找到原因在哪里,所以当时改了储存设定的方式,改用文件系统来做,以下为记录
1、文件也就两种方式要么读要么写,故有以下两个函数,分别实现读参与写参,如有需要可以直接移植取用,
2、需要调用的一些函数如下,可另放一个.ino
/***********************************************************************************
函数:/WIFIConfig.conf文件中读取设置数据并连接WIFI
***********************************************************************************/
void read_setting()
{
DBG_433("读取config设定");
String str = str_read_or_show("/json/setConfig.json", true); // 读取文件内容
String on_hour = analysis_json(str, "on_hour"); // 解析on_hour
String on_minute = analysis_json(str, "on_minute"); // 解析on_minute
String off_hour = analysis_json(str, "off_hour"); // 解析on_hour
String off_minute = analysis_json(str, "off_minute"); // 解析on_minute
String first_open = analysis_json(str, "first_open"); // 解析first_open
String dingshikaiguan = analysis_json(str, "dingshikaiguan"); // 解析dingshikaiguan
String chixugongqi_change = analysis_json(str, "chixugongqi_change"); // 解析chixugongqi_change
String oled_fx = analysis_json(str, "oled_fx"); // 解析oled_fx
set_time.on_hour = strtoul(on_hour.c_str(), NULL, 10);
set_time.on_minute = strtoul(on_minute.c_str(), NULL, 10);
set_time.off_hour = strtoul(off_hour.c_str(), NULL, 10);
set_time.off_minute = strtoul(off_minute.c_str(), NULL, 10);
set_time.first_open = strtoul(first_open.c_str(), NULL, 10);
set_time.dingshikaiguan = strtoul(dingshikaiguan.c_str(), NULL, 10);
set_time.chixugongqi_change = strtoul(chixugongqi_change.c_str(), NULL, 10);
set_time.oled_fx = strtoul(oled_fx.c_str(), NULL, 10);
Serial.printf("是否第一次开机:%d 开机时间 %d:%d /关机时间 %d:%d 定时开关:%d 供气模式: %d 屏幕方向 %d\n", set_time.first_open, set_time.os_hour, set_time.os_minute, set_time.on_hour, set_time.on_minute, set_time.off_hour, set_time.off_minute, set_time.dingshikaiguan, set_time.chixugongqi_change, set_time.oled_fx);
}
/**********************************************************************************
函数:
*********************************************************************************/
void write_setting()
{
DBG_433("更新设定");
String rec_on_hour = String("") + set_time.on_hour;
String rec_on_minute = String("") + set_time.on_minute;
String rec_off_hour = String("") + set_time.off_hour;
String rec_off_minute = String("") + set_time.off_minute;
String rec_first_open = String("") + set_time.first_open;
String rec_dingshikaiguan = String("") + set_time.dingshikaiguan;
String rec_chixugongqi_change = String("") + set_time.chixugongqi_change;
String rec_oled_fx = String("") + set_time.oled_fx;
StaticJsonDocument<200> set_json; // 创建一个JSON对象,wifi_json
set_json["on_hour"] = rec_on_hour; // 写入一个建和值
set_json["on_minute"] = rec_on_minute; // 写入一个键和值
set_json["off_hour"] = rec_off_hour; // 写入一个建和值
set_json["off_minute"] = rec_off_minute; // 写入一个键和值
set_json["first_open"] = rec_first_open; // 写入一个建和值
set_json["dingshikaiguan"] = rec_dingshikaiguan; // 写入一个键和值
set_json["chixugongqi_change"] = rec_chixugongqi_change; // 写入一个建和值
set_json["oled_fx"] = rec_oled_fx; // 写入一个键和值
String set_json_str; // 定义一个字符串变量
serializeJson(set_json, set_json_str); // 生成JOSN的字符串
str_write("/json/setConfig.json", set_json_str); // 字符串写入
}
#include <ArduinoJson.h>
#include "FS.h"
String file_name0 = "/json/config.json"; // 被读取的文件位置和名称
String file_name1 = "/json/mn88xxxconfig.json"; // 被读取的文件位置和名称
String file_name2 = "/json/mn88xxxconfigcal.json"; // 被读取的文件位置和名称
String file_name3 = "/json/mn78xxxconfigcal.json"; // 被读取的文件位置和名称
File fsUploadFile; // 建立文件对象用于闪存文件上传
/**************************************************************************************
函数:字符串写入文件,文件如果存在,将被清零并新建,文件不存在,将新建该文件
path: 文件的绝对路径
str: 要写入的字符串
*************************************************************************************/
void str_write(String path, String str)
{
Serial.println("写入文件");
File wf = SPIFFS.open(path, "w"); // 以写入模式打开文件
if (!wf)
{ // 如果无法打开文件
Serial.println("打开文件写入时错误"); // 显示错误信息
return; // 无法打开文件直接返回
}
wf.print(str); // 字符串写入文件
wf.close(); // 关闭文件
File rf = SPIFFS.open(path, "r"); // 以读取模式打开文件
Serial.print("FILE:");
Serial.println(rf.readString()); // 读取文件
rf.close(); // 关闭文件
}
/**********************************************************************************
函数:从文件path中读取字符串
path: 文件的绝对路径
return: 返回读取的字符串
*********************************************************************************/
String str_read_or_show(String path, bool read_or_show)
{
String str;
Serial.println('\n');
Serial.print("读取文件:");
Serial.println(path);
// 确认闪存中是否有file_name文件
if (SPIFFS.exists(path))
{
Serial.print(path);
Serial.println(" FOUND.");
}
else
{
Serial.print(path);
Serial.print(" NOT FOUND.");
return "false";
}
File configFile = SPIFFS.open(path, "r");
if (!configFile)
{
Serial.println("Failed to open config file");
return "";
}
if (read_or_show)
{
/*********************************************************************************/
Serial.println("read from file:");
str = configFile.readString();
/*********************************************************************************/
}
else
{
while (configFile.available())
{
Serial.write(configFile.read());
} // 这部分放str前边会导致出错
// 读取文件内容并且通过串口监视器输出文件信息
return "";
/*********************************************************************************/
}
configFile.close();
return str;
}
/***************************************************************************************
函数:解析JSON字符串,从JSON字符串名称得到该值
str: JSON字符串
Name: JSON集合的名称
return: 返回值的字符串
***************************************************************************************/
String analysis_json(String str, String Name)
{
DynamicJsonDocument doc(str.length() * 2); // 定义一个JSON对象
deserializeJson(doc, str); // 反序列数据
String value = doc[Name].as<String>(); // 从Name中读取对应的值
return value;
}
/***********************************************************************************
函数:/WIFIConfig.conf文件中读取设置数据并连接WIFI
***********************************************************************************/
void wifi_connect()
{
Serial.println();
Serial.println("在conf文件中读取数据并连接WIFI");
String str = str_read_or_show("/json/WIFIConfig.json", true); // 读取文件内容
String wifiname = analysis_json(str, "wifiname"); // 解析WIFI名称
String wifipassword = analysis_json(str, "wifipassword"); // 解析WIFI密码
Serial.print("WiFi 名称: "); // 显示wifi
Serial.println(wifiname); //
Serial.print("WiFi 密码: "); //
Serial.println(wifipassword); //
}
/**********************************************************************************
函数:响应网站/setwifi目录的POST请求,收到请求后,运行get_WIFI_set_CALLback回调函数
获取并格式化收到的POST数据
*********************************************************************************/
void get_WIFI_set_CALLback()
{
Serial.println("收到设置WIFI按钮");
String rec_wifiname = "Xiaomi";
String rec_wifipassword = "wifipassword";
// 把SSID和password写成一个JSON格式
StaticJsonDocument<200> wifi_json; // 创建一个JSON对象,wifi_json
wifi_json["wifiname"] = rec_wifiname; // 写入一个建和值
wifi_json["wifipassword"] = rec_wifipassword; // 写入一个键和值
String wifi_json_str; // 定义一个字符串变量
serializeJson(wifi_json, wifi_json_str); // 生成JOSN的字符串
str_write("/json/WIFIConfig.json", wifi_json_str); // 字符串写入
}
void seting_config_setup()
{
Serial.println("Mounting FS...");
spiffs_begin();
read_sise();
list_sp();
}
// 处理/LED-Control请求
void del_config()
{
String file_cal = "/json/setConfig.json";
// 从闪存中删除file_name文件
if (SPIFFS.remove(file_cal))
{
Serial.print(file_cal);
Serial.println(" remove sucess");
}
else
{
Serial.print(file_cal);
Serial.println(" remove fail");
}
}
/***********************************************************************************
函数:
***********************************************************************************/
void spiffs_begin()
{
if (SPIFFS.begin())
{ // 启动SPIFFS
Serial.println("SPIFFS Started.");
}
else
{
Serial.println("SPIFFS Failed to Start.");
}
}
void list_sp()
{
Serial.println();
String folder_all = "/"; // 被读取的文件夹
spiffs_begin();
// 显示目录中文件内容以及文件大小
Dir dir = SPIFFS.openDir(folder_all); // 建立“目录”对象
while (dir.next())
{ // dir.next()用于检查目录中是否还有“下一个文件”
Serial.println(dir.fileName()); // 输出文件名
}
}
void read_data()
{
str_read_or_show(file_name0, false);
str_read_or_show(file_name1, false);
str_read_or_show(file_name2, false);
str_read_or_show(file_name3, false);
}
void read_sise()
{
uint32_t realSize = ESP.getFlashChipRealSize();
uint32_t ideSize = ESP.getFlashChipSize();
FlashMode_t ideMode = ESP.getFlashChipMode();
Serial.printf("Flash real id: %08X\n", ESP.getFlashChipId());
Serial.printf("Flash real size: %u\n\n", realSize);
Serial.printf("Flash ide size: %u\n", ideSize);
Serial.printf("Flash ide speed: %u\n", ESP.getFlashChipSpeed());
Serial.printf("Flash ide mode: %s\n", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT"
: ideMode == FM_DIO ? "DIO"
: ideMode == FM_DOUT ? "DOUT"
: "UNKNOWN"));
if (ideSize != realSize)
{
Serial.println("Flash Chip configuration wrong!\n");
}
else
{
Serial.println("Flash Chip configuration ok.\n");
}
}