From a9495f693742fb0c837f6870d715fca498142396 Mon Sep 17 00:00:00 2001 From: chsw Date: Wed, 30 Mar 2022 21:16:45 +0200 Subject: [PATCH 1/2] First version of updated web-ui --- grbl_controller_esp32/browser.cpp | 378 +++++++++++++++++++++++++----- grbl_controller_esp32/browser.h | 3 + 2 files changed, 318 insertions(+), 63 deletions(-) diff --git a/grbl_controller_esp32/browser.cpp b/grbl_controller_esp32/browser.cpp index 97495ee..d66d9c4 100644 --- a/grbl_controller_esp32/browser.cpp +++ b/grbl_controller_esp32/browser.cpp @@ -14,6 +14,7 @@ #include "browser.h" #include #include "draw.h" +#include "actions.h" #include "setupTxt.h" String webpage = ""; WebServer server(80); @@ -31,9 +32,17 @@ String gatewayStr = ""; // used to store the IP address values in string (for SD String subnetStr = ""; // used to store the IP address values in string (for SD, preferences, config) String grbl_Telnet_IPStr = ""; // used to store the GRBL IP address values in string (for SD, preferences, config) extern Preferences preferences ; // used to save the WIFi parameters +extern volatile uint8_t statusPrinting ; + + +extern float runningPercent ; +extern uint32_t sdFileSize ; +extern uint32_t sdNumberOfCharSent ; File32 root ; // used for Directory +String onetimeMessage = ""; + void initWifi() { uint32_t startMillis = millis(); uint8_t yText = 140 ; @@ -94,13 +103,15 @@ void initWifi() { ///////////////////////////// Server Commands server.on("/", HomePage); server.on("/download", File_Download); - server.on("/upload", File_Upload); + //server.on("/upload", File_Upload); server.on("/fupload", HTTP_POST,[](){ server.send(200);}, handleFileUpload); //server.on("/stream", File_Stream); server.on("/delete", File_Delete); - server.on("/dir", sd_dir); + server.on("/browse", sd_dir); server.on("/confirmDelete", confirmDelete); - server.on("/confirmDownload", confirmDownload); + server.on("/status", serverStatus); + server.on("/execute", serverExecuteFile); + server.on("/createDir", serverCreateDir); ///////////////////////////// End of Request commands server.begin(); //Serial.println("HTTP server started"); @@ -192,7 +203,8 @@ boolean checkWifiOnSD(void){ char subnetChar[50] = {0} ; char grbl_Telnet_IPChar[50] = {0}; if ( ! sd.begin(SD_CHIPSELECT_PIN , SD_SCK_MHZ(5)) ) { - //Serial.println( __CARD_MOUNT_FAILED ) ; + Serial.println( __CARD_MOUNT_FAILED ) ; + Serial.println(sd.card()->errorCode()); return false; } //if ( ! SD.exists( "/" ) ) { // check if root exist @@ -297,6 +309,9 @@ boolean getWifiIp( char * ipBuf ) { // return true if wifi status = con //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void HomePage(){ SendHTML_Header(); + webpage += F("
"); + webpage += F("
"); + // webpage += F(""); // webpage += F(""); // webpage += F(""); @@ -306,7 +321,12 @@ void HomePage(){ SendHTML_Content(); SendHTML_Stop(); // Stop is needed because no content length was sent } - +String getParent(String path) +{ + if(path.length()<1) + return "/"; + return path.substring(0, path.lastIndexOf("/", path.length()-(path.charAt(path.length()-1)=='/'?2:1))); +} //-------------------------------------------------------------------------- boolean checkSd() { if ( ! sd.begin(SD_CHIPSELECT_PIN , SD_SCK_MHZ(5)) ) { @@ -326,18 +346,11 @@ void confirmDelete(){ if (server.hasArg("fileName")) SelectInput("Confirm filename to delete","delete","delete" , server.arg(0)); } } - -void confirmDownload(){ - if (server.args() > 0 ) { // check that arguments were received - if (server.hasArg("fileName")) SelectInput("Confirm filename to download","download","download" , server.arg(0)); - } -} - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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")) DownloadFile(server.arg(0)); + if (server.hasArg("file")) + DownloadFile(server.arg("file")); } else SelectInput("Enter filename to download","download","download",""); } @@ -369,7 +382,7 @@ void DownloadFile(String filename){ } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -void File_Upload(){ +/*void File_Upload(){ append_page_header(); webpage += F("

Select File to Upload

"); webpage += F("
"); @@ -378,6 +391,47 @@ void File_Upload(){ webpage += F("[Back]

"); append_page_footer(); server.send(200, "text/html",webpage); +}*/ + +void serverCreateDir(){ + if (!server.hasArg("directoryName")) + { +// SelectInput("Name of directory to create","/createDir","def" , server.arg(0)); + SendHTML_Header(); + webpage += F("

Name of directory to create

"); + webpage += F(""); + webpage += F(""); + webpage += F(""); + webpage += F("
"); + // webpage += F("[Back]

"); + append_page_footer(); + SendHTML_Content(); + SendHTML_Stop(); + + } + else + { + Serial.print("create dir: "); + Serial.print(server.arg("parentDir")); + Serial.print(", "); + Serial.println(server.arg("directoryName")); + + if ( ! sd.begin(SD_CHIPSELECT_PIN , SD_SCK_MHZ(5)) ) { + reportError("Fail to mount SD card - SD card present?" ); + } else { + String path = String(server.arg("parentDir"))+"/"+String(server.arg("directoryName")); + if(sd.mkdir(path)) + { + onetimeMessage = F("

Directory sucessfully created

"); + } + else + { + onetimeMessage = F("Failed to create directory"); + } + webpage = ""; + server.send(200, "text/html", webpage); + } + } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ File32 UploadFile; @@ -389,7 +443,26 @@ void handleFileUpload(){ // upload a new file to the Filing system // 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) { errorWhileUploading = false ; + Serial.print(F("filename ")); + Serial.println(uploadfile.filename.c_str()); + Serial.print(F("server.args() ")); + Serial.println(server.args()); + Serial.print(F("server.hasArg(dir) ")); + Serial.println(server.hasArg("dir")); + Serial.print(F("server.arg(dir) ")); + Serial.println(server.arg("dir1")); + + String filename = uploadfile.filename; +// for(int i=0; i0 && server.hasArg(F("dir"))) + { + filename = server.arg("dir")+"/"+filename; + } + Serial.print(F("File upload to ")); + Serial.println(filename.c_str()); sd.remove(filename.c_str()); // Remove a previous version, otherwise data is appended the file again UploadFile.close() ; //UploadFile = sd.open(filename.c_str() , 0X11); // Open the file for writing in SPIFFS (create it, if doesn't exist) @@ -431,16 +504,36 @@ void handleFileUpload(){ // upload a new file to the Filing system //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void sd_dir(){ if (checkSd() ) { + String dir = ""; + if (server.args() > 0 && server.hasArg("dir")) + { + dir = server.arg("dir"); + } + if(dir.length()<1) + dir = "/"; + root.close() ; - root = sd.open("/"); + root = sd.open(dir.c_str()); if (root) { root.rewind(); SendHTML_Header(); //webpage += F("

SD Card Contents


"); - webpage += F("


"); + webpage += "

"+dir+"


"; + if (onetimeMessage.length() > 0) + { + webpage += "

" + onetimeMessage + "

"; + onetimeMessage = ""; + } + webpage += F("
"); + webpage += F(""); + webpage += ""; + webpage += F(""); + webpage += F("
"); + webpage += ""; + webpage += F("
"); webpage += F(""); webpage += F(""); - printDirectory("/",0); + printDirectory(dir.c_str(),0); webpage += F("
Name/TypeType File/DirFile SizeDeleteDownload
"); SendHTML_Content(); } else { @@ -457,7 +550,10 @@ void sd_dir(){ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void printDirectory(const char * dirname, uint8_t levels){ File32 root1 = sd.open(dirname); - char fileName[23] ; + String directory = String(dirname); + if(!directory.endsWith("/")) + directory = directory+"/"; + char fileName[33] ; //String fileNameS ; if(!root1){ root1.close() ; @@ -467,21 +563,47 @@ void printDirectory(const char * dirname, uint8_t levels){ root1.close() ; return; } + File32 file1 ; + + if(directory.length()>1) + { + String parentDir = getParent(directory); +// String parentDir = directory.substring(0, directory.lastIndexOf("/", directory.length()-2)); + if(parentDir.length()==0) + parentDir = "/"; + webpage += "..Dir"; + //printDirectory(fileName, levels-1); + } root1.rewind(); //P("print Directory: dirname is a directory") ; - File32 file1 ; while(file1.openNext(&root1)){ if (webpage.length() > 1000) { SendHTML_Content(); } - file1.getName(fileName , 22); - //fileNameS = fileName ; - //P(fileName); - //if ( file1.isDir()) P("is dir") ; - if(file1.isDir()){ - webpage += "" +String(fileName)+ "Dir"; - //printDirectory(fileName, levels-1); - } else { + file1.getName(fileName , 32); + if(file1.isDir()) + { + if(strcmp(fileName, "System Volume Information")==0) + { + // Skip this directory + } + else + { + webpage += "" +String(fileName)+ "Dir"; + webpage += "
" ; + webpage += "" ; + webpage += ""; + } + } + file1.close(); + } + root1.rewind(); + while(file1.openNext(&root1)){ + if (webpage.length() > 1000) { + SendHTML_Content(); + } + file1.getName(fileName , 32); + if(!file1.isDir()){ int bytes = file1.size(); String fsize = ""; if (bytes < 1024) fsize = String(bytes)+" B"; @@ -490,12 +612,13 @@ void printDirectory(const char * dirname, uint8_t levels){ else fsize = String(bytes/1024.0/1024.0/1024.0,3)+" GB"; webpage += "" + String(fileName) + "File" + fsize + ""; //"; // Cell content goes here - webpage += "
" ; - webpage += "
" ; + webpage += "
" ; + webpage += "
" ; webpage += ""; } file1.close(); } + file1.close(); } @@ -509,34 +632,50 @@ void File_Delete(){ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void SD_file_delete(String filename) { // Delete the file if (checkSd() ) { - SendHTML_Header(); File32 dataFile = sd.open( filename.c_str() ); // if (dataFile) { - if (sd.remove( filename.c_str() )) { - //Serial.println(F("File deleted successfully")); - webpage += "

File '" +filename+ "' has been erased

"; + if(dataFile.isDir()) + { + if(sd.rmdir(filename.c_str())) + onetimeMessage = "

Directory '" +filename+ "' has been erased

"; + else + onetimeMessage = "

Directory '" +filename+ "' could not be erased! Non empty?

"; + } + else if (sd.remove( filename.c_str() )) { + onetimeMessage = "

File '" +filename+ "' has been erased

"; } else { - webpage += "

File '" +filename+ "' could not be erased !!!!!

"; + onetimeMessage = "

File '" +filename+ "' could not be erased !!!!!

"; } } else { - webpage += "

File '" +filename+ "' does not exist !!!!!

"; + onetimeMessage = "

File '" +filename+ "' does not exist !!!!!

"; } - append_page_footer(); - SendHTML_Content(); - SendHTML_Stop(); + //webpage = ""; + + webpage = ""; + server.send(200, "text/html", webpage); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void SendNoCacheHeaders() +{ + server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); +} void SendHTML_Header(){ - server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); - server.sendHeader("Pragma", "no-cache"); - server.sendHeader("Expires", "-1"); + SendNoCacheHeaders(); 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 SendJson_Header(){ + SendNoCacheHeaders(); + server.setContentLength(CONTENT_LENGTH_UNKNOWN); + server.send(200, "application/json", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. + webpage = ""; +} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void SendHTML_Content(){ server.sendContent(webpage); @@ -586,7 +725,41 @@ String file_size(int bytes){ else fsize = String(bytes/1024.0/1024.0/1024.0,3)+" GB"; return fsize; } +float calculateSdPercent() +{ + if(sdFileSize > 0) + return sdFileSize > 0 ? (float)sdNumberOfCharSent / sdFileSize : 100.0; +} +String getCurrentStatus() +{ + String status = ""; + switch (statusPrinting) + { + case PRINTING_STOPPED: + status = "Idle"; break; + case PRINTING_FROM_SD: + status = String("Running program (") + (int)(calculateSdPercent()*100) + "%)"; break; + case PRINTING_FROM_GRBL: + status = String("Running program (") + runningPercent + "%)"; break; + case PRINTING_ERROR: + status = "Error on program"; break; + case PRINTING_PAUSED: + case PRINTING_FROM_GRBL_PAUSED: + status = "Running program (paused)"; break; + case PRINTING_FROM_USB: + status = "Running (USB)"; break; + case PRINTING_CMD: + status = "Running command"; break; + case PRINTING_FROM_TELNET: + status = "Running (telnet)"; break; + case PRINTING_STRING: + status = "Running string"; break; + default: + status = "Unknown state"; + } + return status; +} void append_page_header() { webpage = F(""); webpage += F(""); @@ -617,30 +790,109 @@ void append_page_header() { // 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("a{font-size:75%;}"); webpage += F("p{font-size:75%;}"); - webpage += F("

File Server

"); -// webpage += F("
"); - webpage += F(""); - //webpage += F(""); - webpage += F(""); -// webpage += F(""); - //webpage += F(""); - + webpage += F("

⌂RS-CNC32 "); + webpage += F("Current status: "); + webpage += getCurrentStatus(); + webpage += F("

"); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void append_page_footer(){ // Saves repeating many lines of code for HTML page footers - - //webpage += "
" ; - // webpage += "
©"+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))+"
"; webpage += F(""); } + +void addJsonAttribute(String name, String value, boolean first) +{ + if(!first) + webpage +=", "; + webpage += name + ": \""+value+"\""; +} +void addJsonAttribute(String name, long value, boolean first) +{ + if(!first) + webpage +=", "; + webpage += name + ": "+value; +} +void addJsonAttribute(String name, float value, boolean first) +{ + if(!first) + webpage +=", "; + webpage += name + ": "+value; +} +void serverExecuteFile() +{ + if (server.args() > 0 ) { // Arguments were received + if (server.hasArg("filename")) + { + if (checkSd() ) { + //SendHTML_Header(); + File32 dataFile = sd.open( server.arg(0).c_str() ); // + if (dataFile) { + webpage = "ok"; +// dataFile + } else { + webpage = "not found: "+server.arg(0); + } + } else { + webpage = "Specify filename!"; + } + } + + } + else SelectInput("Select a File to execute","execute","execute",""); + + SendJson_Header(); + SendHTML_Content(); + SendHTML_Stop(); // Stop is needed because no content length was sent + +// webpage = "ok"; + fSdFilePrint(1); +} + +void serverStatus(){ + SendJson_Header(); + + webpage = "{"; + String status; + switch(statusPrinting) + { + case PRINTING_STOPPED: + status = "PRINTING_STOPPED"; break; + case PRINTING_FROM_SD: + status = "PRINTING_FROM_SD"; break; + case PRINTING_ERROR: + status = "PRINTING_ERROR"; break; + case PRINTING_PAUSED: + status = "PRINTING_PAUSED"; break; + case PRINTING_FROM_USB: + status = "PRINTING_FROM_USB"; break; + case PRINTING_CMD: + status = "PRINTING_CMD"; break; + case PRINTING_FROM_TELNET: + status = "PRINTING_FROM_TELNET"; break; + case PRINTING_STRING: + status = "PRINTING_STRING"; break; + case PRINTING_FROM_GRBL: + status = "PRINTING_FROM_GRBL"; break; + case PRINTING_FROM_GRBL_PAUSED: + status = "PRINTING_FROM_GRBL_PAUSED"; break; + default: + status = "UNKNOWN"; + } + addJsonAttribute("status", status, true); + if(statusPrinting == PRINTING_FROM_SD && sdFileSize>0) + { + addJsonAttribute("progress", calculateSdPercent(), false); + addJsonAttribute("fileSize", (long)sdFileSize, false); + addJsonAttribute("bytesSent", (long)sdNumberOfCharSent, false); + } + if(statusPrinting == PRINTING_FROM_GRBL && sdFileSize>0) + { + addJsonAttribute("progress", runningPercent, false); + } + webpage +="}"; + SendHTML_Content(); + SendHTML_Stop(); // Stop is needed because no content length was sent +} + diff --git a/grbl_controller_esp32/browser.h b/grbl_controller_esp32/browser.h index 9a19be8..fb0782d 100644 --- a/grbl_controller_esp32/browser.h +++ b/grbl_controller_esp32/browser.h @@ -25,6 +25,9 @@ void append_page_footer(); boolean getWifiIp( char * ipBuf ) ; void confirmDelete(); void confirmDownload() ; +void serverStatus(); +void serverExecuteFile(); +void serverCreateDir(); void retrieveWifiParam(void) ; boolean checkWifiOnSD(void) ; #endif From e744dfd610bc61458a1742aa6717ef4a65e47b24 Mon Sep 17 00:00:00 2001 From: chsw Date: Tue, 10 May 2022 22:00:13 +0200 Subject: [PATCH 2/2] Upload with progressbar --- grbl_controller_esp32/browser.cpp | 172 ++++++++++++++++++------------ grbl_controller_esp32/browser.h | 3 + 2 files changed, 108 insertions(+), 67 deletions(-) diff --git a/grbl_controller_esp32/browser.cpp b/grbl_controller_esp32/browser.cpp index d66d9c4..7a534d5 100644 --- a/grbl_controller_esp32/browser.cpp +++ b/grbl_controller_esp32/browser.cpp @@ -103,15 +103,15 @@ void initWifi() { ///////////////////////////// Server Commands server.on("/", HomePage); server.on("/download", File_Download); - //server.on("/upload", File_Upload); - server.on("/fupload", HTTP_POST,[](){ server.send(200);}, handleFileUpload); - //server.on("/stream", File_Stream); + server.on("/fupload", HTTP_POST,[](){ server.send(200,"text/plain","");}, handleFileUpload); server.on("/delete", File_Delete); server.on("/browse", sd_dir); server.on("/confirmDelete", confirmDelete); server.on("/status", serverStatus); server.on("/execute", serverExecuteFile); server.on("/createDir", serverCreateDir); + server.on("/fileupload.js", file_fileupload_js); + server.on("/style.css", file_style_css); ///////////////////////////// End of Request commands server.begin(); //Serial.println("HTTP server started"); @@ -382,16 +382,6 @@ void DownloadFile(String filename){ } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/*void File_Upload(){ - append_page_header(); - webpage += F("

Select File to Upload

"); - webpage += F("
"); - webpage += F("
"); - webpage += F("

"); - webpage += F("[Back]

"); - append_page_footer(); - server.send(200, "text/html",webpage); -}*/ void serverCreateDir(){ if (!server.hasArg("directoryName")) @@ -445,19 +435,12 @@ void handleFileUpload(){ // upload a new file to the Filing system errorWhileUploading = false ; Serial.print(F("filename ")); Serial.println(uploadfile.filename.c_str()); - Serial.print(F("server.args() ")); - Serial.println(server.args()); Serial.print(F("server.hasArg(dir) ")); - Serial.println(server.hasArg("dir")); - Serial.print(F("server.arg(dir) ")); - Serial.println(server.arg("dir1")); - + Serial.println(server.hasArg("dir")); String filename = uploadfile.filename; -// for(int i=0; i0 && server.hasArg(F("dir"))) + if(server.hasArg(F("dir"))) { filename = server.arg("dir")+"/"+filename; } @@ -467,39 +450,45 @@ void handleFileUpload(){ // upload a new file to the Filing system UploadFile.close() ; //UploadFile = sd.open(filename.c_str() , 0X11); // Open the file for writing in SPIFFS (create it, if doesn't exist) //UploadFile = sd.open(filename.c_str() , O_WRITE | O_CREAT); // Open the file for writing (create it, if doesn't exist) - if ( ! sd.begin(SD_CHIPSELECT_PIN , SD_SCK_MHZ(5)) ) { - reportError("Fail to mount SD card - SD card present?" ); + if ( ! sd.begin(SD_CHIPSELECT_PIN , SD_SCK_MHZ(5)) ) { + sendHtmlMessage(409, "Fail to mount SD card - SD card present?"); errorWhileUploading = true ; } else { + Serial.print("Creating file ok: "); UploadFile = sd.open(filename.c_str() , O_WRITE | O_CREAT); // Open the file for writing (create it, if doesn't exist) if ( ! UploadFile ) errorWhileUploading = true ; + Serial.println(!errorWhileUploading); } } else if (uploadfile.status == UPLOAD_FILE_WRITE) { + Serial.print("Uploading file ok. chunk: "); if(UploadFile) { int32_t bytesWritten = UploadFile.write(uploadfile.buf, uploadfile.currentSize); // Write the received bytes to the file if ( bytesWritten == -1) errorWhileUploading = true ; } else { errorWhileUploading = true ; } + Serial.print(uploadfile.currentSize); + Serial.print(" bytes. status: "); + Serial.println(!errorWhileUploading); } else if (uploadfile.status == UPLOAD_FILE_END) { if(UploadFile && ( errorWhileUploading == false) ) // If the file was successfully created { UploadFile.close(); // Close the file at the end - webpage = ""; - append_page_header(); - webpage += F("

File was successfully uploaded

"); - webpage += F("

Uploaded File Name: "); webpage += uploadfile.filename+"

"; - webpage += F("

File Size: "); webpage += file_size(uploadfile.totalSize) + "


"; - append_page_footer(); - server.send(200,"text/html",webpage); + onetimeMessage="File was successfully uploaded. Fileame: "+uploadfile.filename+", size: "+file_size(uploadfile.totalSize); + sendHtmlMessage(200, onetimeMessage); + Serial.println("File closed"); } else { UploadFile.close(); // close for safety ; not sure it is really needed - reportError("

Could Not Create Uploaded File (write-protected?)

"); + sendHtmlMessage(409, "Could Not Create Uploaded File (write-protected?)"); } } - //} + else if (uploadfile.status == UPLOAD_FILE_ABORTED) + { + Serial.println("File upload aborted!"); + onetimeMessage = "File upload was aborted!"; + } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void sd_dir(){ @@ -525,10 +514,15 @@ void sd_dir(){ onetimeMessage = ""; } webpage += F("
"); - webpage += F(""); - webpage += ""; + webpage += F(""); + webpage += ""; webpage += F(""); - webpage += F("
"); + webpage += F("
"); + webpage += F(""); + webpage += F("

"); + webpage += F("

"); + + webpage += F(""); webpage += ""; webpage += F("
"); webpage += F(""); @@ -656,6 +650,10 @@ void SD_file_delete(String filename) { // Delete the file } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void SendCacheHeaders() +{ + server.sendHeader("Cache-Control", "max-age=3600"); +} void SendNoCacheHeaders() { server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); @@ -707,6 +705,11 @@ void reportError(String textError){ SendHTML_Content(); SendHTML_Stop(); } +void sendHtmlMessage(int statuscode, String text) +{ + server.send(statuscode, "text/html","

"+text+"

"); + server.client().stop(); +} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void ReportFileNotPresent(String target){ SendHTML_Header(); @@ -765,34 +768,9 @@ void append_page_header() { webpage += F(""); webpage += F("File Server"); // NOTE: 1em = 16px webpage += F(""); - webpage += F("

⌂RS-CNC32 "); + webpage += F(""); + webpage += F(""); + webpage += F("

⌂RS-CNC32 "); webpage += F("Current status: "); webpage += getCurrentStatus(); webpage += F("

"); @@ -806,19 +784,19 @@ void addJsonAttribute(String name, String value, boolean first) { if(!first) webpage +=", "; - webpage += name + ": \""+value+"\""; + webpage += "\""+name + "\": \""+value+"\""; } void addJsonAttribute(String name, long value, boolean first) { if(!first) webpage +=", "; - webpage += name + ": "+value; + webpage += "\""+name + "\": \""+value+"\""; } void addJsonAttribute(String name, float value, boolean first) { if(!first) webpage +=", "; - webpage += name + ": "+value; + webpage += "\"" + name + "\": \""+value+"\""; } void serverExecuteFile() { @@ -895,4 +873,64 @@ void serverStatus(){ SendHTML_Content(); SendHTML_Stop(); // Stop is needed because no content length was sent } +void file_fileupload_js() +{ + webpage = ""; + webpage += F("function _(el) {return document.getElementById(el);}"); + webpage += F("function uploadFile() {"); + webpage += F("var formdata = new FormData(_('upload'));"); + webpage += F("var ajax = new XMLHttpRequest();"); + webpage += F("ajax.upload.addEventListener(\"progress\", progressHandler, false);"); + webpage += F("ajax.addEventListener(\"loadend\", completeHandler, false);"); + webpage += F("ajax.open('POST', '/fupload',true);"); + webpage += F("ajax.send(formdata);"); + webpage += F("}"); + + webpage += F("function progressHandler(event) {"); + webpage += F("_(\"loaded_n_total\").innerHTML = \"Uploaded \" + event.loaded + \" bytes of \" + event.total;"); + webpage += F("var percent = (event.total > 0) ? ((event.loaded / event.total) * 100):0;"); + webpage += F("_(\"progressBar\").value = Math.round(percent); _(\"status\").innerHTML = Math.round(percent) + \"% uploaded... please wait\";}"); + + webpage += F("function completeHandler(event) {_(\"status\").innerHTML = \"complete\"; _(\"progressBar\").value = 0;location.reload();}"); + + //server.setContentLength(CONTENT_LENGTH_UNKNOWN); + SendCacheHeaders(); + server.send(200, "text/javascript", webpage); // Empty content inhibits Content-length header so we have to close the socket ourselves. + webpage=""; +} + +void file_style_css() +{ + 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("button:disabled{color:gray;background-color:lightgray;}"); + 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%;}"); + + SendCacheHeaders(); + server.send(200, "text/css", webpage); // Empty content inhibits Content-length header so we have to close the socket ourselves. + webpage=""; +} diff --git a/grbl_controller_esp32/browser.h b/grbl_controller_esp32/browser.h index fb0782d..85e0144 100644 --- a/grbl_controller_esp32/browser.h +++ b/grbl_controller_esp32/browser.h @@ -28,6 +28,9 @@ void confirmDownload() ; void serverStatus(); void serverExecuteFile(); void serverCreateDir(); +void file_fileupload_js(); +void file_style_css(); +void sendHtmlMessage(int statuscode, String text); void retrieveWifiParam(void) ; boolean checkWifiOnSD(void) ; #endif