diff --git a/grbl_controller_esp32/browser.cpp b/grbl_controller_esp32/browser.cpp index 97495ee..7a534d5 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("/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("/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); + 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"); @@ -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,15 +382,46 @@ 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]

"); + +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(); - server.send(200, "text/html",webpage); + 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,58 +433,101 @@ 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.hasArg(dir) ")); + Serial.println(server.hasArg("dir")); + String filename = uploadfile.filename; + + if(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) //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(){ 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 += F(""); + webpage += F("

"); + 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 +544,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 +557,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 +606,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 +626,54 @@ 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 SendCacheHeaders() +{ + server.sendHeader("Cache-Control", "max-age=3600"); +} +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); @@ -568,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(); @@ -586,13 +728,179 @@ 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(""); webpage += F("File Server"); // NOTE: 1em = 16px webpage += F(""); - webpage += F("

File Server

"); -// webpage += F("
"); - webpage += F(""); - //webpage += F(""); - webpage += F(""); -// webpage += F(""); - //webpage += F(""); - -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -void append_page_footer(){ // Saves repeating many lines of code for HTML page footers - - //webpage += "" ; - // webpage += ""; - webpage += F(""); + + 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 9a19be8..85e0144 100644 --- a/grbl_controller_esp32/browser.h +++ b/grbl_controller_esp32/browser.h @@ -25,6 +25,12 @@ void append_page_footer(); boolean getWifiIp( char * ipBuf ) ; void confirmDelete(); 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