初始化提交
This commit is contained in:
@@ -0,0 +1,860 @@
|
||||
/****************************************************************************************************************************
|
||||
ESP_FSWebServer - Example WebServer with SPIFFS backend for esp8266
|
||||
For ESP8266 boards
|
||||
|
||||
ESP_WiFiManager is a library for the ESP8266/ESP32 platform (https://github.com/esp8266/Arduino) to enable easy
|
||||
configuration and reconfiguration of WiFi credentials using a Captive Portal.
|
||||
|
||||
Modified from Tzapu https://github.com/tzapu/WiFiManager
|
||||
and from Ken Taylor https://github.com/kentaylor
|
||||
|
||||
Built by Khoi Hoang https://github.com/khoih-prog/ESP_WiFiManager
|
||||
Licensed under MIT license
|
||||
|
||||
Example modified from https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino
|
||||
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the ESP8266WebServer library for Arduino environment.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Version: 1.2.0
|
||||
|
||||
Version Modified By Date Comments
|
||||
------- ----------- ---------- -----------
|
||||
1.0.0 K Hoang 07/10/2019 Initial coding
|
||||
1.0.1 K Hoang 13/12/2019 Fix bug. Add features. Add support for ESP32
|
||||
1.0.2 K Hoang 19/12/2019 Fix bug thatkeeps ConfigPortal in endless loop if Portal/Router SSID or Password is NULL.
|
||||
1.0.3 K Hoang 05/01/2020 Option not displaying AvailablePages in Info page. Enhance README.md. Modify examples
|
||||
1.0.4 K Hoang 07/01/2020 Add RFC952 setHostname feature.
|
||||
1.0.5 K Hoang 15/01/2020 Add configurable DNS feature. Thanks to @Amorphous of https://community.blynk.cc
|
||||
1.0.6 K Hoang 03/02/2020 Add support for ArduinoJson version 6.0.0+ ( tested with v6.14.1 )
|
||||
1.0.7 K Hoang 13/04/2020 Reduce start time, fix SPIFFS bug in examples, update README.md
|
||||
1.0.8 K Hoang 10/06/2020 Fix STAstaticIP issue. Restructure code. Add LittleFS support for ESP8266 core 2.7.1+
|
||||
1.0.9 K Hoang 29/07/2020 Fix ESP32 STAstaticIP bug. Permit changing from DHCP <-> static IP using Config Portal.
|
||||
Add, enhance examples (fix MDNS for ESP32)
|
||||
1.0.10 K Hoang 08/08/2020 Add more features to Config Portal. Use random WiFi AP channel to avoid conflict.
|
||||
1.0.11 K Hoang 17/08/2020 Add CORS feature. Fix bug in softAP, autoConnect, resetSettings.
|
||||
1.1.0 K Hoang 28/08/2020 Add MultiWiFi feature to autoconnect to best WiFi at runtime
|
||||
1.1.1 K Hoang 30/08/2020 Add setCORSHeader function to allow flexible CORS. Fix typo and minor improvement.
|
||||
1.1.2 K Hoang 17/08/2020 Fix bug. Add example.
|
||||
1.2.0 K Hoang 09/10/2020 Restore cpp code besides Impl.h code to use if linker error. Fix bug.
|
||||
*****************************************************************************************************************************/
|
||||
/*****************************************************************************************************************************
|
||||
How To Use:
|
||||
1) Upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
|
||||
2) or you can upload the contents of a folder if you CD in that folder and run the following command:
|
||||
for file in `\ls -A1`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
|
||||
3) access the sample web page at http://esp8266fs.local
|
||||
4) edit the page by going to http://esp8266fs.local/edit
|
||||
*****************************************************************************************************************************/
|
||||
#if !defined(ESP8266)
|
||||
#error This code is intended to run on the ESP8266 platform! Please check your Tools->Board setting.
|
||||
#endif
|
||||
|
||||
// Use from 0 to 4. Higher number, more debugging messages and memory usage.
|
||||
#define _WIFIMGR_LOGLEVEL_ 3
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <DNSServer.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
|
||||
// From v1.1.0
|
||||
#include <ESP8266WiFiMulti.h>
|
||||
ESP8266WiFiMulti wifiMulti;
|
||||
//////
|
||||
|
||||
#include <FS.h>
|
||||
|
||||
#define USE_LITTLEFS true
|
||||
|
||||
#if USE_LITTLEFS
|
||||
#include <LittleFS.h>
|
||||
FS* filesystem = &LittleFS;
|
||||
#define FileFS LittleFS
|
||||
#define FS_Name "LittleFS"
|
||||
#else
|
||||
FS* filesystem = &SPIFFS;
|
||||
#define FileFS SPIFFS
|
||||
#define FS_Name "SPIFFS"
|
||||
#endif
|
||||
|
||||
#define DBG_OUTPUT_PORT Serial
|
||||
|
||||
#define ESP_getChipId() (ESP.getChipId())
|
||||
|
||||
// SSID and PW for Config Portal
|
||||
String ssid = "ESP_" + String(ESP_getChipId(), HEX);
|
||||
const char* password = "your_password";
|
||||
|
||||
// SSID and PW for your Router
|
||||
String Router_SSID;
|
||||
String Router_Pass;
|
||||
|
||||
// From v1.1.0
|
||||
#define MIN_AP_PASSWORD_SIZE 8
|
||||
|
||||
#define SSID_MAX_LEN 32
|
||||
//From v1.0.10, WPA2 passwords can be up to 63 characters long.
|
||||
#define PASS_MAX_LEN 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char wifi_ssid[SSID_MAX_LEN];
|
||||
char wifi_pw [PASS_MAX_LEN];
|
||||
} WiFi_Credentials;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
String wifi_ssid;
|
||||
String wifi_pw;
|
||||
} WiFi_Credentials_String;
|
||||
|
||||
#define NUM_WIFI_CREDENTIALS 2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS];
|
||||
} WM_Config;
|
||||
|
||||
WM_Config WM_config;
|
||||
|
||||
#define CONFIG_FILENAME F("/wifi_cred.dat")
|
||||
//////
|
||||
|
||||
// Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected
|
||||
bool initialConfig = false;
|
||||
|
||||
// Use false if you don't like to display Available Pages in Information Page of Config Portal
|
||||
// Comment out or use true to display Available Pages in Information Page of Config Portal
|
||||
// Must be placed before #include <ESP_WiFiManager.h>
|
||||
#define USE_AVAILABLE_PAGES false
|
||||
|
||||
// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
|
||||
// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
|
||||
// You have to explicitly specify false to disable the feature.
|
||||
//#define USE_STATIC_IP_CONFIG_IN_CP false
|
||||
|
||||
// Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal.
|
||||
// See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23)
|
||||
#define USE_ESP_WIFIMANAGER_NTP false
|
||||
|
||||
// Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare
|
||||
// See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21)
|
||||
#define USE_CLOUDFLARE_NTP false
|
||||
|
||||
// New in v1.0.11
|
||||
#define USING_CORS_FEATURE true
|
||||
//////
|
||||
|
||||
// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
|
||||
#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
|
||||
// Force DHCP to be true
|
||||
#if defined(USE_DHCP_IP)
|
||||
#undef USE_DHCP_IP
|
||||
#endif
|
||||
#define USE_DHCP_IP true
|
||||
#else
|
||||
// You can select DHCP or Static IP here
|
||||
//#define USE_DHCP_IP true
|
||||
#define USE_DHCP_IP false
|
||||
#endif
|
||||
|
||||
// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
|
||||
#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
|
||||
// Force DHCP to be true
|
||||
#if defined(USE_DHCP_IP)
|
||||
#undef USE_DHCP_IP
|
||||
#endif
|
||||
#define USE_DHCP_IP true
|
||||
#else
|
||||
// You can select DHCP or Static IP here
|
||||
//#define USE_DHCP_IP true
|
||||
#define USE_DHCP_IP false
|
||||
#endif
|
||||
|
||||
#if ( USE_DHCP_IP || ( defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP ) )
|
||||
// Use DHCP
|
||||
#warning Using DHCP IP
|
||||
IPAddress stationIP = IPAddress(0, 0, 0, 0);
|
||||
IPAddress gatewayIP = IPAddress(192, 168, 2, 1);
|
||||
IPAddress netMask = IPAddress(255, 255, 255, 0);
|
||||
#else
|
||||
// Use static IP
|
||||
#warning Using static IP
|
||||
#ifdef ESP32
|
||||
IPAddress stationIP = IPAddress(192, 168, 2, 232);
|
||||
#else
|
||||
IPAddress stationIP = IPAddress(192, 168, 2, 186);
|
||||
#endif
|
||||
|
||||
IPAddress gatewayIP = IPAddress(192, 168, 2, 1);
|
||||
IPAddress netMask = IPAddress(255, 255, 255, 0);
|
||||
#endif
|
||||
|
||||
#define USE_CONFIGURABLE_DNS true
|
||||
|
||||
IPAddress dns1IP = gatewayIP;
|
||||
IPAddress dns2IP = IPAddress(8, 8, 8, 8);
|
||||
|
||||
#include <ESP_WiFiManager.h> //https://github.com/khoih-prog/ESP_WiFiManager
|
||||
|
||||
const char* host = "esp8266fs";
|
||||
|
||||
ESP8266WebServer server(80);
|
||||
|
||||
//holds the current upload
|
||||
File fsUploadFile;
|
||||
|
||||
// Function Prototypes
|
||||
uint8_t connectMultiWiFi(void);
|
||||
|
||||
void heartBeatPrint(void)
|
||||
{
|
||||
static int num = 1;
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED)
|
||||
Serial.print("H"); // H means connected to WiFi
|
||||
else
|
||||
Serial.print("F"); // F means not connected to WiFi
|
||||
|
||||
if (num == 80)
|
||||
{
|
||||
Serial.println();
|
||||
num = 1;
|
||||
}
|
||||
else if (num++ % 10 == 0)
|
||||
{
|
||||
Serial.print(" ");
|
||||
}
|
||||
}
|
||||
|
||||
void check_WiFi(void)
|
||||
{
|
||||
if ( (WiFi.status() != WL_CONNECTED) )
|
||||
{
|
||||
Serial.println("\nWiFi lost. Call connectMultiWiFi in loop");
|
||||
connectMultiWiFi();
|
||||
}
|
||||
}
|
||||
|
||||
void check_status(void)
|
||||
{
|
||||
static ulong checkstatus_timeout = 0;
|
||||
static ulong checkwifi_timeout = 0;
|
||||
|
||||
static ulong current_millis;
|
||||
|
||||
#define WIFICHECK_INTERVAL 1000L
|
||||
#define HEARTBEAT_INTERVAL 10000L
|
||||
|
||||
current_millis = millis();
|
||||
|
||||
// Check WiFi every WIFICHECK_INTERVAL (1) seconds.
|
||||
if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0))
|
||||
{
|
||||
check_WiFi();
|
||||
checkwifi_timeout = current_millis + WIFICHECK_INTERVAL;
|
||||
}
|
||||
|
||||
// Print hearbeat every HEARTBEAT_INTERVAL (10) seconds.
|
||||
if ((current_millis > checkstatus_timeout) || (checkstatus_timeout == 0))
|
||||
{
|
||||
heartBeatPrint();
|
||||
checkstatus_timeout = current_millis + HEARTBEAT_INTERVAL;
|
||||
}
|
||||
}
|
||||
|
||||
//format bytes
|
||||
String formatBytes(size_t bytes)
|
||||
{
|
||||
if (bytes < 1024)
|
||||
{
|
||||
return String(bytes) + "B";
|
||||
}
|
||||
else if (bytes < (1024 * 1024))
|
||||
{
|
||||
return String(bytes / 1024.0) + "KB";
|
||||
}
|
||||
else if (bytes < (1024 * 1024 * 1024))
|
||||
{
|
||||
return String(bytes / 1024.0 / 1024.0) + "MB";
|
||||
}
|
||||
else
|
||||
{
|
||||
return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
|
||||
}
|
||||
}
|
||||
|
||||
String getContentType(String filename)
|
||||
{
|
||||
if (server.hasArg("download"))
|
||||
{
|
||||
return "application/octet-stream";
|
||||
}
|
||||
else 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";
|
||||
}
|
||||
|
||||
bool handleFileRead(String path)
|
||||
{
|
||||
DBG_OUTPUT_PORT.println("handleFileRead: " + path);
|
||||
if (path.endsWith("/"))
|
||||
{
|
||||
path += "index.htm";
|
||||
}
|
||||
|
||||
String contentType = getContentType(path);
|
||||
String pathWithGz = path + ".gz";
|
||||
|
||||
if (filesystem->exists(pathWithGz) || filesystem->exists(path))
|
||||
{
|
||||
if (filesystem->exists(pathWithGz))
|
||||
{
|
||||
path += ".gz";
|
||||
}
|
||||
|
||||
File file = filesystem->open(path, "r");
|
||||
server.streamFile(file, contentType);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void handleFileUpload()
|
||||
{
|
||||
if (server.uri() != "/edit")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HTTPUpload& upload = server.upload();
|
||||
|
||||
if (upload.status == UPLOAD_FILE_START)
|
||||
{
|
||||
String filename = upload.filename;
|
||||
|
||||
if (!filename.startsWith("/"))
|
||||
{
|
||||
filename = "/" + filename;
|
||||
}
|
||||
|
||||
DBG_OUTPUT_PORT.print("handleFileUpload Name: "); DBG_OUTPUT_PORT.println(filename);
|
||||
fsUploadFile = filesystem->open(filename, "w");
|
||||
filename.clear();
|
||||
}
|
||||
else if (upload.status == UPLOAD_FILE_WRITE)
|
||||
{
|
||||
//DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize);
|
||||
|
||||
if (fsUploadFile)
|
||||
{
|
||||
fsUploadFile.write(upload.buf, upload.currentSize);
|
||||
}
|
||||
}
|
||||
else if (upload.status == UPLOAD_FILE_END)
|
||||
{
|
||||
if (fsUploadFile)
|
||||
{
|
||||
fsUploadFile.close();
|
||||
}
|
||||
|
||||
DBG_OUTPUT_PORT.print("handleFileUpload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
|
||||
}
|
||||
}
|
||||
|
||||
void handleFileDelete()
|
||||
{
|
||||
if (server.args() == 0)
|
||||
{
|
||||
return server.send(500, "text/plain", "BAD ARGS");
|
||||
}
|
||||
String path = server.arg(0);
|
||||
DBG_OUTPUT_PORT.println("handleFileDelete: " + path);
|
||||
|
||||
if (path == "/")
|
||||
{
|
||||
return server.send(500, "text/plain", "BAD PATH");
|
||||
}
|
||||
|
||||
if (!filesystem->exists(path))
|
||||
{
|
||||
return server.send(404, "text/plain", "FileNotFound");
|
||||
}
|
||||
|
||||
filesystem->remove(path);
|
||||
server.send(200, "text/plain", "");
|
||||
path.clear();
|
||||
}
|
||||
|
||||
void handleFileCreate()
|
||||
{
|
||||
if (server.args() == 0)
|
||||
{
|
||||
return server.send(500, "text/plain", "BAD ARGS");
|
||||
}
|
||||
|
||||
String path = server.arg(0);
|
||||
DBG_OUTPUT_PORT.println("handleFileCreate: " + path);
|
||||
|
||||
if (path == "/")
|
||||
{
|
||||
return server.send(500, "text/plain", "BAD PATH");
|
||||
}
|
||||
|
||||
if (filesystem->exists(path))
|
||||
{
|
||||
return server.send(500, "text/plain", "FILE EXISTS");
|
||||
}
|
||||
|
||||
File file = filesystem->open(path, "w");
|
||||
|
||||
if (file)
|
||||
{
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
return server.send(500, "text/plain", "CREATE FAILED");
|
||||
}
|
||||
|
||||
server.send(200, "text/plain", "");
|
||||
path.clear();
|
||||
}
|
||||
|
||||
void handleFileList()
|
||||
{
|
||||
if (!server.hasArg("dir"))
|
||||
{
|
||||
server.send(500, "text/plain", "BAD ARGS");
|
||||
return;
|
||||
}
|
||||
|
||||
String path = server.arg("dir");
|
||||
DBG_OUTPUT_PORT.println("handleFileList: " + path);
|
||||
Dir dir = filesystem->openDir(path);
|
||||
path.clear();
|
||||
|
||||
String output = "[";
|
||||
|
||||
while (dir.next())
|
||||
{
|
||||
File entry = dir.openFile("r");
|
||||
|
||||
if (output != "[")
|
||||
{
|
||||
output += ',';
|
||||
}
|
||||
|
||||
bool isDir = false;
|
||||
output += "{\"type\":\"";
|
||||
output += (isDir) ? "dir" : "file";
|
||||
output += "\",\"name\":\"";
|
||||
|
||||
if (entry.name()[0] == '/')
|
||||
{
|
||||
output += &(entry.name()[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
output += entry.name();
|
||||
}
|
||||
|
||||
output += "\"}";
|
||||
entry.close();
|
||||
}
|
||||
|
||||
output += "]";
|
||||
server.send(200, "text/json", output);
|
||||
}
|
||||
|
||||
void loadConfigData(void)
|
||||
{
|
||||
File file = FileFS.open(CONFIG_FILENAME, "r");
|
||||
LOGERROR(F("LoadWiFiCfgFile "));
|
||||
|
||||
if (file)
|
||||
{
|
||||
file.readBytes((char *) &WM_config, sizeof(WM_config));
|
||||
file.close();
|
||||
LOGERROR(F("OK"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR(F("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
void saveConfigData(void)
|
||||
{
|
||||
File file = FileFS.open(CONFIG_FILENAME, "w");
|
||||
LOGERROR(F("SaveWiFiCfgFile "));
|
||||
|
||||
if (file)
|
||||
{
|
||||
file.write((uint8_t*) &WM_config, sizeof(WM_config));
|
||||
file.close();
|
||||
LOGERROR(F("OK"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR(F("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t connectMultiWiFi(void)
|
||||
{
|
||||
#if ESP32
|
||||
// For ESP32, this better be 0 to shorten the connect time
|
||||
#define WIFI_MULTI_1ST_CONNECT_WAITING_MS 0
|
||||
#else
|
||||
// For ESP8266, this better be 2200 to enable connect the 1st time
|
||||
#define WIFI_MULTI_1ST_CONNECT_WAITING_MS 2200L
|
||||
#endif
|
||||
|
||||
#define WIFI_MULTI_CONNECT_WAITING_MS 100L
|
||||
|
||||
uint8_t status;
|
||||
|
||||
LOGERROR(F("ConnectMultiWiFi with :"));
|
||||
|
||||
if ( (Router_SSID != "") && (Router_Pass != "") )
|
||||
{
|
||||
LOGERROR3(F("* Flash-stored Router_SSID = "), Router_SSID, F(", Router_Pass = "), Router_Pass );
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
|
||||
{
|
||||
// Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
|
||||
if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
|
||||
{
|
||||
LOGERROR3(F("* Additional SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
|
||||
}
|
||||
}
|
||||
|
||||
LOGERROR(F("Connecting MultiWifi..."));
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
|
||||
#if !USE_DHCP_IP
|
||||
#if USE_CONFIGURABLE_DNS
|
||||
// Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
|
||||
WiFi.config(stationIP, gatewayIP, netMask, dns1IP, dns2IP);
|
||||
#else
|
||||
// Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2.
|
||||
WiFi.config(stationIP, gatewayIP, netMask);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int i = 0;
|
||||
status = wifiMulti.run();
|
||||
delay(WIFI_MULTI_1ST_CONNECT_WAITING_MS);
|
||||
|
||||
while ( ( i++ < 10 ) && ( status != WL_CONNECTED ) )
|
||||
{
|
||||
status = wifiMulti.run();
|
||||
|
||||
if ( status == WL_CONNECTED )
|
||||
break;
|
||||
else
|
||||
delay(WIFI_MULTI_CONNECT_WAITING_MS);
|
||||
}
|
||||
|
||||
if ( status == WL_CONNECTED )
|
||||
{
|
||||
LOGERROR1(F("WiFi connected after time: "), i);
|
||||
LOGERROR3(F("SSID:"), WiFi.SSID(), F(",RSSI="), WiFi.RSSI());
|
||||
LOGERROR3(F("Channel:"), WiFi.channel(), F(",IP address:"), WiFi.localIP() );
|
||||
}
|
||||
else
|
||||
LOGERROR(F("WiFi not connected"));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
DBG_OUTPUT_PORT.begin(115200);
|
||||
while (!DBG_OUTPUT_PORT);
|
||||
|
||||
DBG_OUTPUT_PORT.print("\nStarting ESP_FSWebServer using " + String(FS_Name));
|
||||
DBG_OUTPUT_PORT.println(" on " + String(ARDUINO_BOARD));
|
||||
|
||||
DBG_OUTPUT_PORT.setDebugOutput(false);
|
||||
|
||||
if (!filesystem->begin())
|
||||
{
|
||||
DBG_OUTPUT_PORT.print(FS_Name);
|
||||
DBG_OUTPUT_PORT.println(F(" failed! AutoFormatting."));
|
||||
|
||||
filesystem->format();
|
||||
}
|
||||
|
||||
// Uncomment to format FS. Remember to uncomment after done
|
||||
//filesystem->format();
|
||||
Dir dir = filesystem->openDir("/");
|
||||
DBG_OUTPUT_PORT.println("Opening / directory");
|
||||
|
||||
while (dir.next())
|
||||
{
|
||||
String fileName = dir.fileName();
|
||||
size_t fileSize = dir.fileSize();
|
||||
DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
|
||||
}
|
||||
|
||||
DBG_OUTPUT_PORT.println();
|
||||
|
||||
unsigned long startedAt = millis();
|
||||
|
||||
//Local intialization. Once its business is done, there is no need to keep it around
|
||||
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
|
||||
//ESP_WiFiManager ESP_wifiManager;
|
||||
// Use this to personalize DHCP hostname (RFC952 conformed)
|
||||
ESP_WiFiManager ESP_wifiManager("ESP-FSWebServer");
|
||||
|
||||
//set custom ip for portal
|
||||
ESP_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 186, 1), IPAddress(192, 168, 186, 1), IPAddress(255, 255, 255, 0));
|
||||
|
||||
ESP_wifiManager.setMinimumSignalQuality(-1);
|
||||
|
||||
// From v1.0.10 only
|
||||
// Set config portal channel, default = 1. Use 0 => random channel from 1-13
|
||||
ESP_wifiManager.setConfigPortalChannel(0);
|
||||
//////
|
||||
|
||||
#if !USE_DHCP_IP
|
||||
#if USE_CONFIGURABLE_DNS
|
||||
// Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
|
||||
ESP_wifiManager.setSTAStaticIPConfig(stationIP, gatewayIP, netMask, dns1IP, dns2IP);
|
||||
#else
|
||||
// Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2.
|
||||
ESP_wifiManager.setSTAStaticIPConfig(stationIP, gatewayIP, netMask);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// New from v1.1.1
|
||||
#if USING_CORS_FEATURE
|
||||
ESP_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin");
|
||||
#endif
|
||||
|
||||
// We can't use WiFi.SSID() in ESP32 as it's only valid after connected.
|
||||
// SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot
|
||||
// Have to create a new function to store in EEPROM/SPIFFS for this purpose
|
||||
Router_SSID = ESP_wifiManager.WiFi_SSID();
|
||||
Router_Pass = ESP_wifiManager.WiFi_Pass();
|
||||
|
||||
//Remove this line if you do not want to see WiFi password printed
|
||||
DBG_OUTPUT_PORT.println("Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass);
|
||||
|
||||
// SSID to uppercase
|
||||
ssid.toUpperCase();
|
||||
|
||||
// From v1.1.0, Don't permit NULL password
|
||||
if ( (Router_SSID == "") || (Router_Pass == "") )
|
||||
{
|
||||
DBG_OUTPUT_PORT.println("We haven't got any access point credentials, so get them now");
|
||||
|
||||
initialConfig = true;
|
||||
|
||||
// Starts an access point
|
||||
if (!ESP_wifiManager.startConfigPortal((const char *) ssid.c_str(), password))
|
||||
DBG_OUTPUT_PORT.println("Not connected to WiFi but continuing anyway.");
|
||||
else
|
||||
DBG_OUTPUT_PORT.println("WiFi connected...yeey :)");
|
||||
|
||||
// Stored for later usage, from v1.1.0, but clear first
|
||||
memset(&WM_config, 0, sizeof(WM_config));
|
||||
|
||||
for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
|
||||
{
|
||||
String tempSSID = ESP_wifiManager.getSSID(i);
|
||||
String tempPW = ESP_wifiManager.getPW(i);
|
||||
|
||||
if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1)
|
||||
strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str());
|
||||
else
|
||||
strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1);
|
||||
|
||||
if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1)
|
||||
strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str());
|
||||
else
|
||||
strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1);
|
||||
|
||||
// Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
|
||||
if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
|
||||
{
|
||||
LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
|
||||
wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
|
||||
}
|
||||
}
|
||||
|
||||
saveConfigData();
|
||||
}
|
||||
else
|
||||
{
|
||||
wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
|
||||
}
|
||||
|
||||
startedAt = millis();
|
||||
|
||||
if (!initialConfig)
|
||||
{
|
||||
// Load stored data, the addAP ready for MultiWiFi reconnection
|
||||
loadConfigData();
|
||||
|
||||
for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
|
||||
{
|
||||
// Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
|
||||
if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
|
||||
{
|
||||
LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
|
||||
wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
|
||||
}
|
||||
}
|
||||
|
||||
if ( WiFi.status() != WL_CONNECTED )
|
||||
{
|
||||
DBG_OUTPUT_PORT.println("ConnectMultiWiFi in setup");
|
||||
|
||||
connectMultiWiFi();
|
||||
}
|
||||
}
|
||||
|
||||
DBG_OUTPUT_PORT.print("After waiting ");
|
||||
DBG_OUTPUT_PORT.print((float) (millis() - startedAt) / 1000L);
|
||||
DBG_OUTPUT_PORT.print(" secs more in setup(), connection result is ");
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED)
|
||||
{
|
||||
DBG_OUTPUT_PORT.print("connected. Local IP: ");
|
||||
DBG_OUTPUT_PORT.println(WiFi.localIP());
|
||||
}
|
||||
else
|
||||
DBG_OUTPUT_PORT.println(ESP_wifiManager.getStatus(WiFi.status()));
|
||||
|
||||
//SERVER INIT
|
||||
//list directory
|
||||
server.on("/list", HTTP_GET, handleFileList);
|
||||
|
||||
//load editor
|
||||
server.on("/edit", HTTP_GET, []()
|
||||
{
|
||||
if (!handleFileRead("/edit.htm"))
|
||||
{
|
||||
server.send(404, "text/plain", "FileNotFound");
|
||||
}
|
||||
});
|
||||
|
||||
//create file
|
||||
server.on("/edit", HTTP_PUT, handleFileCreate);
|
||||
|
||||
//delete file
|
||||
server.on("/edit", HTTP_DELETE, handleFileDelete);
|
||||
|
||||
//first callback is called after the request has ended with all parsed arguments
|
||||
//second callback handles file uploads at that location
|
||||
server.on("/edit", HTTP_POST, []()
|
||||
{
|
||||
server.send(200, "text/plain", "");
|
||||
}, handleFileUpload);
|
||||
|
||||
//called when the url is not defined here
|
||||
//use it to load content from SPIFFS
|
||||
server.onNotFound([]()
|
||||
{
|
||||
if (!handleFileRead(server.uri()))
|
||||
{
|
||||
server.send(404, "text/plain", "FileNotFound");
|
||||
}
|
||||
});
|
||||
|
||||
//get heap status, analog input value and all GPIO statuses in one json call
|
||||
server.on("/all", HTTP_GET, []()
|
||||
{
|
||||
String json('{');
|
||||
json += "\"heap\":" + String(ESP.getFreeHeap());
|
||||
json += ", \"analog\":" + String(analogRead(A0));
|
||||
json += ", \"gpio\":" + String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
|
||||
json += "}";
|
||||
server.send(200, "text/json", json);
|
||||
json.clear();
|
||||
});
|
||||
|
||||
server.begin();
|
||||
|
||||
DBG_OUTPUT_PORT.print("HTTP server started @ ");
|
||||
DBG_OUTPUT_PORT.println(WiFi.localIP());
|
||||
|
||||
MDNS.begin(host);
|
||||
DBG_OUTPUT_PORT.print("Open http://");
|
||||
DBG_OUTPUT_PORT.print(host);
|
||||
DBG_OUTPUT_PORT.println(".local/edit to see the file browser");
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
// this is just for checking if we are alive and connected to WiFi
|
||||
check_status();
|
||||
|
||||
server.handleClient();
|
||||
MDNS.update();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
# ESP_FSWebServer Example
|
||||
|
||||
## First, how Config Portal works?
|
||||
In `Configuration Portal Mode`, it starts an access point called `ESP_xxxxxx`. Connect to it using the configurable password you can define in the code. For example, `your_password` (see examples):
|
||||
|
||||
```cpp
|
||||
// SSID and PW for Config Portal
|
||||
String ssid = "ESP_" + String(ESP_getChipId(), HEX);
|
||||
const char* password = "your_password";
|
||||
```
|
||||
After you connected, please, go to http://192.168.4.1, you'll see this `Main` page:
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/khoih-prog/ESP_WiFiManager/blob/master/Images/Main.png">
|
||||
</p>
|
||||
|
||||
Select `Information` to enter the Info page where the board info will be shown (long page)
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/khoih-prog/ESP_WiFiManager/blob/master/Images/Info.png">
|
||||
</p>
|
||||
|
||||
or short page (default)
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/khoih-prog/ESP_WiFiManager/blob/master/Images/Info_Short.png">
|
||||
</p>
|
||||
|
||||
Select `Configuration` to enter this page where you can select an AP and specify its WiFi Credentials
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/khoih-prog/ESP_WiFiManager/blob/master/Images/Configuration.png">
|
||||
</p>
|
||||
|
||||
Enter your credentials, then click `Save`. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP.
|
||||
|
||||
If you're already connected to a listed WiFi AP and don't want to change anything, just select `Exit Portal` from the `Main` page to reboot the board and connect to the previously-stored AP. The WiFi Credentials are still intact.
|
||||
|
||||
|
||||
## How to use this ESP_FSWebServer example?
|
||||
|
||||
This shows you how to use this example in Ubuntu (but you can use similar commands in other OSes)
|
||||
|
||||
1. For example, you already downloaded from (https://github.com/khoih-prog/ESP_WiFiManager/tree/master/examples/ESP_FSWebServer/data) to a local folder, e.g.,
|
||||
|
||||
~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
|
||||
|
||||
1. Upload the contents of that `data folder` with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
|
||||
2. or upload the contents of a folder by running the following commands:
|
||||
- Ubuntu$ cd ~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
|
||||
- Ubuntu$ for file in \`\ls -A1\`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
|
||||
3. Access the sample web page at http://esp8266fs.local
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/khoih-prog/ESP_WiFiManager/blob/master/examples/ESP_FSWebServer/pics/esp8266fs.local.png">
|
||||
</p>
|
||||
|
||||
4. Edit / Delete / Download any file in the the folder by going to http://esp8266fs.local/edit
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/khoih-prog/ESP_WiFiManager/blob/master/examples/ESP_FSWebServer/pics/esp8266fs.local_edit.png">
|
||||
</p>
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
@@ -0,0 +1,97 @@
|
||||
<!--
|
||||
FSWebServer - Example Index Page
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the ESP8266WebServer library for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<title>ESP Monitor</title>
|
||||
<script type="text/javascript" src="graphs.js"></script>
|
||||
<script type="text/javascript">
|
||||
var heap,temp,digi;
|
||||
var reloadPeriod = 1000;
|
||||
var running = false;
|
||||
|
||||
function loadValues(){
|
||||
if(!running) return;
|
||||
var xh = new XMLHttpRequest();
|
||||
xh.onreadystatechange = function(){
|
||||
if (xh.readyState == 4){
|
||||
if(xh.status == 200) {
|
||||
var res = JSON.parse(xh.responseText);
|
||||
heap.add(res.heap);
|
||||
temp.add(res.analog);
|
||||
digi.add(res.gpio);
|
||||
if(running) setTimeout(loadValues, reloadPeriod);
|
||||
} else running = false;
|
||||
}
|
||||
};
|
||||
xh.open("GET", "/all", true);
|
||||
xh.send(null);
|
||||
};
|
||||
|
||||
function run(){
|
||||
if(!running){
|
||||
running = true;
|
||||
loadValues();
|
||||
}
|
||||
}
|
||||
|
||||
function onBodyLoad(){
|
||||
var refreshInput = document.getElementById("refresh-rate");
|
||||
refreshInput.value = reloadPeriod;
|
||||
refreshInput.onchange = function(e){
|
||||
var value = parseInt(e.target.value);
|
||||
reloadPeriod = (value > 0)?value:0;
|
||||
e.target.value = reloadPeriod;
|
||||
}
|
||||
var stopButton = document.getElementById("stop-button");
|
||||
stopButton.onclick = function(e){
|
||||
running = false;
|
||||
}
|
||||
var startButton = document.getElementById("start-button");
|
||||
startButton.onclick = function(e){
|
||||
run();
|
||||
}
|
||||
|
||||
// Example with 10K thermistor
|
||||
//function calcThermistor(v) {
|
||||
// var t = Math.log(((10230000 / v) - 10000));
|
||||
// t = (1/(0.001129148+(0.000234125*t)+(0.0000000876741*t*t*t)))-273.15;
|
||||
// return (t>120)?0:Math.round(t*10)/10;
|
||||
//}
|
||||
//temp = createGraph(document.getElementById("analog"), "Temperature", 100, 128, 10, 40, false, "cyan", calcThermistor);
|
||||
|
||||
temp = createGraph(document.getElementById("analog"), "Analog Input", 100, 128, 0, 1023, false, "cyan");
|
||||
heap = createGraph(document.getElementById("heap"), "Current Heap", 100, 125, 0, 30000, true, "orange");
|
||||
digi = createDigiGraph(document.getElementById("digital"), "GPIO", 100, 146, [0, 4, 5, 16], "gold");
|
||||
run();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body id="index" style="margin:0; padding:0;" onload="onBodyLoad()">
|
||||
<div id="controls" style="display: block; border: 1px solid rgb(68, 68, 68); padding: 5px; margin: 5px; width: 362px; background-color: rgb(238, 238, 238);">
|
||||
<label>Period (ms):</label>
|
||||
<input type="number" id="refresh-rate"/>
|
||||
<input type="button" id="start-button" value="Start"/>
|
||||
<input type="button" id="stop-button" value="Stop"/>
|
||||
</div>
|
||||
<div id="heap"></div>
|
||||
<div id="analog"></div>
|
||||
<div id="digital"></div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
Reference in New Issue
Block a user