当ESP8266使用无线终端模式,作为一台微型服务器,如果想向用户展示网站信息,图片信息时,就需要使用到ESP8266的闪存文件系统(4M),可以将文件上传到开发板上,供用户访问
1 设置闪存文件系统
Arduino:工具>>Flash Size>>选择对应的闪存文件大小
2 通过代码使用闪存文件系统
2 .1 向闪存文件系统写入信息
#include <FS.h> // 引入FS(Flash Size)库
String file_name = "/text/notes.txt"; // 文件位置和名称(根目录/text下的notes.txt)
void setup() {
Serial.begin(9600);
Serial.println("SPIFFS format start");
SPIFFS.format(); // 格式化SPIFFS(清除闪存文件系统)
Serial.println("SPIFFS format finish");
if(SPIFFS.begin()){ // 启动SPIFFS(启动后才能进行操作)
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
File dataFile = SPIFFS.open(file_name, "w");// 建立File对象,w表示写入,r表示读取
dataFile.println("Hello IOT World."); // File.println()写入
dataFile.close(); // 完成文件写入后关闭文件
Serial.println("Finished Writing data to SPIFFS");
}
void loop() {
}
2.2 读取闪存文件系统
#include <FS.h>
String file_name = "/text/notes.txt";
void setup() {
Serial.begin(9600);
if(SPIFFS.begin()){
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
if (SPIFFS.exists(file_name)){ // 判断闪存文件file_name是否存在
Serial.print(file_name);
Serial.println(" FOUND.");
} else {
Serial.print(file_name);
Serial.print(" NOT FOUND.");
}
File dataFile = SPIFFS.open(file_name, "r");
for(int i=0; i<dataFile.size(); i++){
Serial.print((char)dataFile.read()); // File.read()读取,每次只能读取一个字符
}
dataFile.close();
}
void loop() {
}
3 通过ArduinoIDE插件使用闪存文件系统
3.1 下载Arduino-ESP8266闪存文件插件程序
(插件仅支持arduino1.0版本,不支持2.0以上版本)
方式一:官网GitHub下载>>选择"ESP8266FS-0.5.0.zip"
方式二:太极创客官网下载
查看ArduinoIDE"项目文件夹地址":文件>>首选项项目文件夹地址
在该地址下建立一个tools文件夹,将下载好的插件解压缩,得到的ESP8266FS文件夹移入tools下
重启ArduinoIDE,在工具下看到"ESP8266 Sketch Data Upload"表示插件安装成功
3.2 插件使用
点击"ESP8266 Sketch Data Upload",会向开发板上传与当前程序所在位置同目录的data文件夹
3.2.1 向闪存文件系统存入网页信息
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <FS.h>
ESP8266WiFiMulti wifiMulti;
ESP8266WebServer esp8266_server(80);
void setup() {
Serial.begin(9600);
wifiMulti.addAP("WIFI1", "12345678");
wifiMulti.addAP("WIFI2", "12345678");
wifiMulti.addAP("WIFI3", "12345678");
Serial.println("Connecting ...");
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) {
delay(1000);
Serial.print(i++); Serial.print(' ');
}
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID());
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
if(SPIFFS.begin()){ // 启动闪存文件系统
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
esp8266_server.onNotFound(handleUserRequet);
esp8266_server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
esp8266_server.handleClient();
}
void handleUserRequet() {
String webAddress = esp8266_server.uri(); // 获取用户请求网址信息
bool fileReadOK = handleFileRead(webAddress);
if (!fileReadOK){
esp8266_server.send(404, "text/plain", "404 Not Found");
}
}
bool handleFileRead(String path) {
if (path.endsWith("/")) { // 如果访问地址以"/"为结尾,则改为默认访问 /index.html
path = "/index.html";
}
String contentType = getContentType(path); // 获取文件类型
if (SPIFFS.exists(path)) { // 如果访问的文件可以在SPIFFS中找到
File file = SPIFFS.open(path, "r"); // 则尝试打开该文件
esp8266_server.streamFile(file, contentType);// esp8266_server.streamFile()将该文件返回给浏览器
file.close(); // 并且关闭文件
return true; // 返回true
}
return false; // 如果文件未找到,则返回false
}
// 获取文件类型
String getContentType(String filename){
if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
直接访问保存在开发板上的网页信息:
3.2.2 通过PWM控制LED灯亮度
通过模拟信号控制LED的点亮程度,不再只是单纯地通过低高电平控制灯的亮灭(0亮1灭)
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <FS.h>
ESP8266WiFiMulti wifiMulti;
ESP8266WebServer esp8266_server(80);
void setup(void){
Serial.begin(9600);
Serial.println("");
pinMode(LED_BUILTIN, OUTPUT);
wifiMulti.addAP("WIFI1", "12345678");
wifiMulti.addAP("WIFI2", "12345678");
wifiMulti.addAP("WIFI3", "12345678");
Serial.println("Connecting ...");
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) {
delay(1000);
Serial.print(i++); Serial.print(' ');
}
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID());
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
if(SPIFFS.begin()){
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
esp8266_server.on("/LED-Control", handleLEDControl);
esp8266_server.onNotFound(handleUserRequest);
esp8266_server.begin();
Serial.println("HTTP server started");
}
void loop(void){
esp8266_server.handleClient(); //处理网络请求
}
void handleLEDControl(){
String ledPwm = esp8266_server.arg("ledPwm"); //esp8266_server.arg("ledPwm"),获取ledPwm对应的值
int ledPwmVal = ledPwm.toInt();
analogWrite(LED_BUILTIN, ledPwmVal); // anologWrite(pin,int)写入模拟信号(0~1023)
String httpBody = "Led PWM: " + ledPwm + "<p><a href=\"/LED.html\"><-LED Page</a></p>";
esp8266_server.send(200, "text/html", httpBody);
}
void handleUserRequest() {
String reqResource = esp8266_server.uri();
Serial.print("reqResource: ");
Serial.println(reqResource);
bool fileReadOK = handleFileRead(reqResource);
if (!fileReadOK){
esp8266_server.send(404, "text/plain", "404 Not Found");
}
}
bool handleFileRead(String resource) {
if (resource.endsWith("/")) {
resource = "/LED.html";
}
String contentType = getContentType(resource);
if (SPIFFS.exists(resource)) {
File file = SPIFFS.open(resource, "r");
esp8266_server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}
String getContentType(String filename){
if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
4 通过网页使用闪存文件系统
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <FS.h>
ESP8266WiFiMulti wifiMulti;
ESP8266WebServer esp8266_server(80);
File fsUploadFile;
void setup() {
Serial.begin(9600);
Serial.println("");
wifiMulti.addAP("WIFI1", "12345678");
wifiMulti.addAP("WIFI1", "12345678");
wifiMulti.addAP("WIFI1", "12345678");
Serial.println("Connecting ...");
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) {
delay(1000);
Serial.print(i++); Serial.print('.');
}
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID());
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
if(SPIFFS.begin()){
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
esp8266_server.on("/upload.html",HTTP_POST,respondOK,handleFileUpload);
esp8266_server.onNotFound(handleUserRequest);
esp8266_server.begin();
Serial.println("HTTP server started");
}
void loop() {
esp8266_server.handleClient();
}
void handleFileUpload(){
HTTPUpload& upload = esp8266_server.upload();
if(upload.status == UPLOAD_FILE_START){
String filename = upload.filename; // 建立字符串变量用于存放上传文件名
if(!filename.startsWith("/")) filename = "/" + filename; // 为上传文件名前加上"/"
Serial.println("File Name: " + filename);
fsUploadFile = SPIFFS.open(filename, "w"); // 在SPIFFS中建立文件用于写入用户上传的文件数据
} else if(upload.status == UPLOAD_FILE_WRITE){
if(fsUploadFile)
fsUploadFile.write(upload.buf, upload.currentSize); // 向SPIFFS文件写入浏览器发来的文件数据
} else if(upload.status == UPLOAD_FILE_END){ // 如果上传状态为UPLOAD_FILE_END
if(fsUploadFile) { // 如果文件成功建立
fsUploadFile.close(); // 将文件关闭
Serial.println(" Size: "+ upload.totalSize); // 通过串口监视器输出文件大小
esp8266_server.sendHeader("Location","/success.html"); // 将浏览器跳转到/success.html(成功上传页面)
esp8266_server.send(303); // 发送相应代码303(重定向到新页面)
} else { // 如果文件未能成功建立
Serial.println("File upload failed"); // 通过串口监视器输出报错信息
esp8266_server.send(500, "text/plain", "500: couldn't create file"); // 向浏览器发送相应代码500(服务器错误)
}
}
}
void respondOK(){
esp8266_server.send(200);
}
// 处理用户浏览器的HTTP访问
void handleUserRequest(){
String webAddress = esp8266_server.uri();
// 通过handleFileRead函数处处理用户访问
bool fileReadOK = handleFileRead(webAddress);
// 如果在SPIFFS无法找到用户访问的资源,则回复404 (Not Found)
if (!fileReadOK){
esp8266_server.send(404, "text/plain", "404 Not Found");
}
}
bool handleFileRead(String path) { //处理浏览器HTTP访问
if (path.endsWith("/")) { // 如果访问地址以"/"为结尾
path = "/index.html"; // 则将访问地址修改为/index.html便于SPIFFS访问
}
String contentType = getContentType(path); // 获取文件类型
if (SPIFFS.exists(path)) { // 如果访问的文件可以在SPIFFS中找到
File file = SPIFFS.open(path, "r"); // 则尝试打开该文件
esp8266_server.streamFile(file, contentType);// 并且将该文件返回给浏览器
file.close(); // 并且关闭文件
return true; // 返回true
}
return false; // 如果文件未找到,则返回false
}
String getContentType(String filename){
if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}