Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
326 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
void append_page_header() { | ||
webpage = F("<!DOCTYPE html><html>"); | ||
webpage += F("<head>"); | ||
webpage += F("<title>File Server</title>"); // NOTE: 1em = 16px | ||
webpage += F("<meta name='viewport' content='user-scalable=yes,initial-scale=1.0,width=device-width'>"); | ||
webpage += F("<style>"); | ||
webpage += F("body{max-width:65%;margin:0 auto;font-family:arial;font-size:105%;text-align:center;color:blue;background-color:#F7F2Fd;}"); | ||
webpage += F("ul{list-style-type:none;margin:0.1em;padding:0;border-radius:0.375em;overflow:hidden;background-color:#dcade6;font-size:1em;}"); | ||
webpage += F("li{float:left;border-radius:0.375em;border-right:0.06em solid #bbb;}last-child {border-right:none;font-size:85%}"); | ||
webpage += F("li a{display: block;border-radius:0.375em;padding:0.44em 0.44em;text-decoration:none;font-size:85%}"); | ||
webpage += F("li a:hover{background-color:#EAE3EA;border-radius:0.375em;font-size:85%}"); | ||
webpage += F("section {font-size:0.88em;}"); | ||
webpage += F("h1{color:white;border-radius:0.5em;font-size:1em;padding:0.2em 0.2em;background:#558ED5;}"); | ||
webpage += F("h2{color:orange;font-size:1.0em;}"); | ||
webpage += F("h3{font-size:0.8em;}"); | ||
webpage += F("table{font-family:arial,sans-serif;font-size:0.9em;border-collapse:collapse;width:85%;}"); | ||
webpage += F("th,td {border:0.06em solid #dddddd;text-align:left;padding:0.3em;border-bottom:0.06em solid #dddddd;}"); | ||
webpage += F("tr:nth-child(odd) {background-color:#eeeeee;}"); | ||
webpage += F(".rcorners_n {border-radius:0.5em;background:#558ED5;padding:0.3em 0.3em;width:20%;color:white;font-size:75%;}"); | ||
webpage += F(".rcorners_m {border-radius:0.5em;background:#558ED5;padding:0.3em 0.3em;width:50%;color:white;font-size:75%;}"); | ||
webpage += F(".rcorners_w {border-radius:0.5em;background:#558ED5;padding:0.3em 0.3em;width:70%;color:white;font-size:75%;}"); | ||
webpage += F(".column{float:left;width:50%;height:45%;}"); | ||
webpage += F(".row:after{content:'';display:table;clear:both;}"); | ||
webpage += F("*{box-sizing:border-box;}"); | ||
webpage += F("footer{background-color:#eedfff; text-align:center;padding:0.3em 0.3em;border-radius:0.375em;font-size:60%;}"); | ||
webpage += F("button{border-radius:0.5em;background:#558ED5;padding:0.3em 0.3em;width:20%;color:white;font-size:130%;}"); | ||
webpage += F(".buttons {border-radius:0.5em;background:#558ED5;padding:0.3em 0.3em;width:15%;color:white;font-size:80%;}"); | ||
webpage += F(".buttonsm{border-radius:0.5em;background:#558ED5;padding:0.3em 0.3em;width:9%; color:white;font-size:70%;}"); | ||
webpage += F(".buttonm {border-radius:0.5em;background:#558ED5;padding:0.3em 0.3em;width:15%;color:white;font-size:70%;}"); | ||
webpage += F(".buttonw {border-radius:0.5em;background:#558ED5;padding:0.3em 0.3em;width:40%;color:white;font-size:70%;}"); | ||
webpage += F("a{font-size:75%;}"); | ||
webpage += F("p{font-size:75%;}"); | ||
webpage += F("</style></head><body><h1>File Server "); webpage += String(ServerVersion) + "</h1>"; | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void append_page_footer(){ // Saves repeating many lines of code for HTML page footers | ||
webpage += F("<ul>"); | ||
webpage += F("<li><a href='/'>Home</a></li>"); // Lower Menu bar command entries | ||
webpage += F("<li><a href='/download'>Download</a></li>"); | ||
webpage += F("<li><a href='/upload'>Upload</a></li>"); | ||
webpage += F("</ul>"); | ||
webpage += "<footer>©"+String(char(byte(0x40>>1)))+String(char(byte(0x88>>1)))+String(char(byte(0x5c>>1)))+String(char(byte(0x98>>1)))+String(char(byte(0x5c>>1))); | ||
webpage += String(char((0x84>>1)))+String(char(byte(0xd2>>1)))+String(char(0xe4>>1))+String(char(0xc8>>1))+String(char(byte(0x40>>1))); | ||
webpage += String(char(byte(0x64/2)))+String(char(byte(0x60>>1)))+String(char(byte(0x62>>1)))+String(char(0x70>>1))+"</footer>"; | ||
webpage += F("</body></html>"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
/* Version 1 | ||
* | ||
* ESP32/ESP8266 example of downloading and uploading a file from or to the ESP device's Filing System | ||
* | ||
This software, the ideas and concepts is Copyright (c) David Bird 2018. All rights to this software are reserved. | ||
Any redistribution or reproduction of any part or all of the contents in any form is prohibited other than the following: | ||
1. You may print or download to a local hard disk extracts for your personal and non-commercial use only. | ||
2. You may copy the content to individual third parties for their personal use, but only if you acknowledge the author David Bird as the source of the material. | ||
3. You may not, except with my express written permission, distribute or commercially exploit the content. | ||
4. You may not transmit it or store it in any other website or other form of electronic retrieval system for commercial purposes. | ||
The above copyright ('as annotated') notice and this permission notice shall be included in all copies or substantial portions of the Software and where the | ||
software use is visible to an end-user. | ||
THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT. FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY | ||
OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
See more at http://www.dsbird.org.uk | ||
* | ||
*/ | ||
#ifdef ESP8266 | ||
#include <ESP8266WiFi.h> // Built-in | ||
#include <ESP8266WiFiMulti.h> // Built-in | ||
#include <ESP8266WebServer.h> // Built-in | ||
#include <ESP8266mDNS.h> | ||
#else | ||
#include <WiFi.h> // Built-in | ||
#include <WiFiMulti.h> // Built-in | ||
#include <ESP32WebServer.h> // https://github.com/Pedroalbuquerque/ESP32WebServer download and place in your Libraries folder | ||
#include <ESPmDNS.h> | ||
#include "FS.h" | ||
#endif | ||
|
||
#include "Network.h" | ||
#include "Sys_Variables.h" | ||
#include "CSS.h" | ||
#include <SD.h> | ||
#include <SPI.h> | ||
|
||
#ifdef ESP8266 | ||
ESP8266WiFiMulti wifiMulti; | ||
ESP8266WebServer server(80); | ||
#else | ||
WiFiMulti wifiMulti; | ||
ESP32WebServer server(80); | ||
#endif | ||
|
||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void setup(void){ | ||
Serial.begin(115200); | ||
if (!WiFi.config(local_IP, gateway, subnet, dns)) { //WiFi.config(ip, gateway, subnet, dns1, dns2); | ||
Serial.println("WiFi STATION Failed to configure Correctly"); | ||
} | ||
wifiMulti.addAP(ssid_1, password_1); // add Wi-Fi networks you want to connect to, it connects strongest to weakest | ||
wifiMulti.addAP(ssid_2, password_2); // Adjust the values in the Network tab | ||
wifiMulti.addAP(ssid_3, password_3); | ||
wifiMulti.addAP(ssid_4, password_4); // You don't need 4 entries, this is for example! | ||
|
||
Serial.println("Connecting ..."); | ||
while (wifiMulti.run() != WL_CONNECTED) { // Wait for the Wi-Fi to connect: scan for Wi-Fi networks, and connect to the strongest of the networks above | ||
delay(250); Serial.print('.'); | ||
} | ||
Serial.println("\nConnected to "+WiFi.SSID()+" Use IP address: "+WiFi.localIP().toString()); // Report which SSID and IP is in use | ||
// The logical name http://fileserver.local will also access the device if you have 'Bonjour' running or your system supports multicast dns | ||
if (!MDNS.begin(servername)) { // Set your preferred server name, if you use "myserver" the address would be http://myserver.local/ | ||
Serial.println(F("Error setting up MDNS responder!")); | ||
ESP.restart(); | ||
} | ||
#ifdef ESP32 | ||
// Note: SD_Card readers on the ESP32 will NOT work unless there is a pull-up on MISO, either do this or wire one on (1K to 4K7) | ||
Serial.println(MISO); | ||
pinMode(19,INPUT_PULLUP); | ||
#endif | ||
Serial.print(F("Initializing SD card...")); | ||
if (!SD.begin(SD_CS_pin)) { // see if the card is present and can be initialised. Wemos SD-Card CS uses D8 | ||
Serial.println(F("Card failed or not present, no SD Card data logging possible...")); | ||
SD_present = false; | ||
} | ||
else | ||
{ | ||
Serial.println(F("Card initialised... file access enabled...")); | ||
SD_present = true; | ||
} | ||
// Note: Using the ESP32 and SD_Card readers requires a 1K to 4K7 pull-up to 3v3 on the MISO line, otherwise they do-not function. | ||
//---------------------------------------------------------------------- | ||
///////////////////////////// Server Commands | ||
server.on("/", HomePage); | ||
server.on("/download", File_Download); | ||
server.on("/upload", File_Upload); | ||
server.on("/fupload", HTTP_POST,[](){ server.send(200);}, handleFileUpload); | ||
///////////////////////////// End of Request commands | ||
server.begin(); | ||
Serial.println("HTTP server started"); | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void loop(void){ | ||
server.handleClient(); // Listen for client connections | ||
} | ||
|
||
// All supporting functions from here... | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void HomePage(){ | ||
SendHTML_Header(); | ||
webpage += F("<a href='/download'><button>Download</button></a>"); | ||
webpage += F("<a href='/upload'><button>Upload</button></a>"); | ||
append_page_footer(); | ||
SendHTML_Content(); | ||
SendHTML_Stop(); // Stop is needed because no content length was sent | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void File_Download(){ // This gets called twice, the first pass selects the input, the second pass then processes the command line arguments | ||
if (server.args() > 0 ) { // Arguments were received | ||
if (server.hasArg("download")) SD_file_download(server.arg(0)); | ||
} | ||
else SelectInput("Enter filename to download","download","download"); | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void SD_file_download(String filename){ | ||
if (SD_present) { | ||
File download = SD.open("/"+filename); | ||
if (download) { | ||
server.sendHeader("Content-Type", "text/text"); | ||
server.sendHeader("Content-Disposition", "attachment; filename="+filename); | ||
server.sendHeader("Connection", "close"); | ||
server.streamFile(download, "application/octet-stream"); | ||
download.close(); | ||
} else ReportFileNotPresent("download"); | ||
} else ReportSDNotPresent(); | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void File_Upload(){ | ||
append_page_header(); | ||
webpage += F("<h3>Select File to Upload</h3>"); | ||
webpage += F("<FORM action='/fupload' method='post' enctype='multipart/form-data'>"); | ||
webpage += F("<input class='buttons' style='width:40%' type='file' name='fupload' id = 'fupload' value=''><br>"); | ||
webpage += F("<br><button class='buttons' style='width:10%' type='submit'>Upload File</button><br>"); | ||
webpage += F("<a href='/'>[Back]</a><br><br>"); | ||
append_page_footer(); | ||
server.send(200, "text/html",webpage); | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
File UploadFile; | ||
void handleFileUpload(){ // upload a new file to the Filing system | ||
HTTPUpload& uploadfile = server.upload(); // See https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer/srcv | ||
// For further information on 'status' structure, there are other reasons such as a failed transfer that could be used | ||
if(uploadfile.status == UPLOAD_FILE_START) | ||
{ | ||
String filename = uploadfile.filename; | ||
if(!filename.startsWith("/")) filename = "/"+filename; | ||
Serial.print("Upload File Name: "); Serial.println(filename); | ||
SD.remove(filename); // Remove a previous version, otherwise data is appended the file again | ||
UploadFile = SD.open(filename, FILE_WRITE); // Open the file for writing in SPIFFS (create it, if doesn't exist) | ||
filename = String(); | ||
} | ||
else if (uploadfile.status == UPLOAD_FILE_WRITE) | ||
{ | ||
if(UploadFile) UploadFile.write(uploadfile.buf, uploadfile.currentSize); // Write the received bytes to the file | ||
} | ||
else if (uploadfile.status == UPLOAD_FILE_END) | ||
{ | ||
if(UploadFile) // If the file was successfully created | ||
{ | ||
UploadFile.close(); // Close the file again | ||
Serial.print("Upload Size: "); Serial.println(uploadfile.totalSize); | ||
webpage = ""; | ||
append_page_header(); | ||
webpage += F("<h3>File was successfully uploaded</h3>"); | ||
webpage += F("<h2>Uploaded File Name: "); webpage += uploadfile.filename+"</h2>"; | ||
webpage += F("<h2>File Size: "); webpage += file_size(uploadfile.totalSize) + "</h2><br>"; | ||
append_page_footer(); | ||
server.send(200,"text/html",webpage); | ||
} | ||
else | ||
{ | ||
ReportCouldNotCreateFile("upload"); | ||
} | ||
} | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void SendHTML_Header(){ | ||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); | ||
server.sendHeader("Pragma", "no-cache"); | ||
server.sendHeader("Expires", "-1"); | ||
server.setContentLength(CONTENT_LENGTH_UNKNOWN); | ||
server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. | ||
append_page_header(); | ||
server.sendContent(webpage); | ||
webpage = ""; | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void SendHTML_Content(){ | ||
server.sendContent(webpage); | ||
webpage = ""; | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void SendHTML_Stop(){ | ||
server.sendContent(""); | ||
server.client().stop(); // Stop is needed because no content length was sent | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void SelectInput(String heading1, String command, String arg_calling_name){ | ||
SendHTML_Header(); | ||
webpage += F("<h3>"); webpage += heading1 + "</h3>"; | ||
webpage += F("<FORM action='/"); webpage += command + "' method='post'>"; // Must match the calling argument e.g. '/chart' calls '/chart' after selection but with arguments! | ||
webpage += F("<input type='text' name='"); webpage += arg_calling_name; webpage += F("' value=''><br>"); | ||
webpage += F("<type='submit' name='"); webpage += arg_calling_name; webpage += F("' value=''><br>"); | ||
webpage += F("<a href='/'>[Back]</a>"); | ||
append_page_footer(); | ||
SendHTML_Content(); | ||
SendHTML_Stop(); | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void ReportSDNotPresent(){ | ||
SendHTML_Header(); | ||
webpage += F("<h3>No SD Card present</h3>"); | ||
webpage += F("<a href='/'>[Back]</a><br><br>"); | ||
append_page_footer(); | ||
SendHTML_Content(); | ||
SendHTML_Stop(); | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void ReportFileNotPresent(String target){ | ||
SendHTML_Header(); | ||
webpage += F("<h3>File does not exist</h3>"); | ||
webpage += F("<a href='/"); webpage += target + "'>[Back]</a><br><br>"; | ||
append_page_footer(); | ||
SendHTML_Content(); | ||
SendHTML_Stop(); | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
void ReportCouldNotCreateFile(String target){ | ||
SendHTML_Header(); | ||
webpage += F("<h3>Could Not Create Uploaded File (write-protected?)</h3>"); | ||
webpage += F("<a href='/"); webpage += target + "'>[Back]</a><br><br>"; | ||
append_page_footer(); | ||
SendHTML_Content(); | ||
SendHTML_Stop(); | ||
} | ||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
String file_size(int bytes){ | ||
String fsize = ""; | ||
if (bytes < 1024) fsize = String(bytes)+" B"; | ||
else if(bytes < (1024*1024)) fsize = String(bytes/1024.0,3)+" KB"; | ||
else if(bytes < (1024*1024*1024)) fsize = String(bytes/1024.0/1024.0,3)+" MB"; | ||
else fsize = String(bytes/1024.0/1024.0/1024.0,3)+" GB"; | ||
return fsize; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Adjust the following values to match your needs | ||
// ----------------------------------------------- | ||
#define servername "sensorserver2" // Set your server's logical name here e.g. if 'myserver' then address is http://myserver.local/ | ||
IPAddress local_IP(192, 168, 0, 150); // Set your server's fixed IP address here | ||
IPAddress gateway(192, 168, 0, 1); // Set your network Gateway usually your Router base address | ||
IPAddress subnet(255, 255, 255, 0); // Set your network sub-network mask here | ||
IPAddress dns(192,168,0,1); // Set your network DNS usually your Router base address | ||
const char ssid_1[] = "your_SSID1"; | ||
const char password_1[] = "your_PASSWORD_for SSID1"; | ||
|
||
const char ssid_2[] = "your_SSID2"; | ||
const char password_2[] = "your_PASSWORD_for SSID2"; | ||
|
||
const char ssid_3[] = "your_SSID3"; | ||
const char password_3[] = "your_PASSWORD_for SSID3"; | ||
|
||
const char ssid_4[] = "your_SSID4"; | ||
const char password_4[] = "your_PASSWORD_for SSID4"; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#define ServerVersion "1.0" | ||
String webpage = ""; | ||
bool SD_present = false; | ||
|
||
#ifdef ESP8266 | ||
#define SD_CS_pin D8 // The pin on Wemos D1 Mini for SD Card Chip-Select | ||
#else | ||
#define SD_CS_pin 5 // Use pin 5 on MH-T Live ESP32 version of Wemos D1 Mini for SD Card Chip-Select | ||
#endif // Use pin 13 on Wemos ESP32 Pro | ||
|
||
|