123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- #include <WiFi.h>
- #include <WiFiMulti.h>
- #include <WebServer.h>
- #include <FS.h>
- #include <SD_MMC.h>
- WiFiMulti WiFiMulti;
- WebServer server(80); //Starting a server on port 80
- //Home Dynamic IoT Communication Protocol Headers and Information
- const String uuid = "d9ed122a-b359-4564-8bf1-6cd27ec517b2"; //Please change this UUIDv4 if you have more than one identical setup in the same subnet
- const String driver="3dprcu.ext.hd.imuslab";
- const String devName="3D Printer Remote Control Unit";
- //WebServer settings
- const String webroot = "/web";
- //System Settings
- bool forceCORS = true; //Some versions of WebServer.h do not include Access Control Allow Origin * by default. Set this to true to send it out manually
- void setup(){
- Serial.begin(115200);
- delay(10);
- Serial.println("");
- Serial.println("[info] ESP32 3D Printer Remote Controller Unit");
- Serial.println("[info] Open source prototype for the aCloud 3D Printer Control System.");
- // Add more WiFi AP for backups
- WiFiMulti.addAP("Toby Room Automation", "homedynamicsystem");
- //WiFiMulti.addAP("Backup-SSID", "password");
- if (initSDcard() == false){
- //Init SD card failed. Terminate the startup process.
- return;
- }
-
- Serial.print("[info] Waiting for WiFi... ");
- while(WiFiMulti.run() != WL_CONNECTED) {
- Serial.print(".");
- delay(500);
- }
- Serial.println("");
- Serial.println("[OK] WiFi connected");
- Serial.print("[info] IP address: ");
- Serial.println(WiFi.localIP());
- delay(500);
- //Define handler for index
- server.on("/", handle_OnConnect);
- //Define Web Server handler for Home Dynamic Protocol
- server.on("/uuid", handle_uuid);
- server.on("/info", handle_info);
- server.on("/status", handle_status);
- //Define handler for file operations
- server.on("/list", HTTP_GET, printDirectory); //Usage: /list?dir=/{dirname}
- server.on("/upload", HTTP_POST, []() {
- sendCORS();
- server.send(200, "text/plain", "");
- }, handleFileUpload);
- //Define handler for NOT FOUND exception
- server.onNotFound(handle_NotFound);
- server.begin();
- Serial.println("[info] RESTFUL API server started");
- Serial.println("[OK] System Ready!");
- }
- void loop()
- {
- server.handleClient();
- }
- //Home Dynamic Communication Protocol related response handler
- void handle_uuid(){
- if (forceCORS){
- server.sendHeader("Access-Control-Allow-Origin", "*");
- }
- server.send(200, "text/plain", uuid);
- }
- void handle_info(){
- if (forceCORS){
- server.sendHeader("Access-Control-Allow-Origin", "*");
- }
- server.send(200, "text/plain", devName + "_" + driver);
- }
- void handle_status(){
- //Report printing progress here. Work in progress
- }
- void handle_OnConnect(){
- server.sendHeader("Location", "/web/index.html",true);
- server.send(302, "text/plane","");
- }
- File uploadFile;
- void handleFileUpload() {
- if (server.uri() != "/upload") {
- return;
- }
- HTTPUpload& upload = server.upload();
- if (upload.status == UPLOAD_FILE_START) {
- if (SD_MMC.exists((char *)upload.filename.c_str())) {
- SD_MMC.remove((char *)upload.filename.c_str());
- }
- uploadFile = SD_MMC.open(upload.filename.c_str(), FILE_WRITE);
- Serial.print("[info] Upload: START, filename: "); Serial.println(upload.filename);
- } else if (upload.status == UPLOAD_FILE_WRITE) {
- if (uploadFile) {
- uploadFile.write(upload.buf, upload.currentSize);
- }
- Serial.print("[info] Upload: WRITE, Bytes: "); Serial.println(upload.currentSize);
- } else if (upload.status == UPLOAD_FILE_END) {
- if (uploadFile) {
- uploadFile.close();
- }
- Serial.print("[info] Upload: END, Size: "); Serial.println(upload.totalSize);
- }
- }
- void handleHTMLDelivery(String path){
- if (!loadFromSdCard(path)){
- //This file do not exists or it is empty. Deliver 404 page instead.
- sendCORS();
- server.send(404, "text/plain", "Page not found");
- }
- }
- void handle_NotFound(){
- String path = server.uri();
- int index = path.indexOf("/web");
- int deleteIndicator = path.indexOf("/delete");
- if (index >= 0 && deleteIndicator == -1) {
- handleHTMLDelivery(path);
- }else if (deleteIndicator >= 0 ){
- handleDeleteRequest(path);
- }else{
- sendCORS();
- server.send(404, "text/plain", "Page not found");
- }
- }
- bool initSDcard(){
- Serial.println("[info] Trying to initiate SD card file system.");
- if(!SD_MMC.begin()){
- Serial.println("[error] Card Mount Failed");
- return false;
- }
- uint8_t cardType = SD_MMC.cardType();
- if(cardType == CARD_NONE){
- Serial.println("[error] No SD_MMC card attached");
- return false;
- }
- Serial.print("[info] SD_MMC Card Type: ");
- if(cardType == CARD_MMC){
- Serial.println("MMC");
- } else if(cardType == CARD_SD){
- Serial.println("SDSC");
- } else if(cardType == CARD_SDHC){
- Serial.println("SDHC");
- } else {
- Serial.println("UNKNOWN");
- }
- uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
- Serial.printf("[OK] SD_MMC Card Size: %lluMB\n", cardSize);
- return true;
- }
- void printDirectory() {
- if (!server.hasArg("dir")) {
- server.send(500, "text/plain", "Not directory.");
- return;
- }
- String path = server.arg("dir");
- if (path != "/" && !SD_MMC.exists((char *)path.c_str())) {
- server.send(500, "text/plain", "Bad path");
- return;
- }
- File dir = SD_MMC.open((char *)path.c_str());
- path = String();
- if (!dir.isDirectory()) {
- dir.close();
- server.send(500, "text/plain", "Not directory");
- return;
- }
- dir.rewindDirectory();
- if (forceCORS){
- server.sendHeader("Access-Control-Allow-Origin", "*");
- }
- server.setContentLength(CONTENT_LENGTH_UNKNOWN);
- server.send(200, "application/json", "");
- WiFiClient client = server.client();
- server.sendContent("[");
- for (int cnt = 0; true; ++cnt) {
- File entry = dir.openNextFile();
- if (!entry) {
- break;
- }
- String output;
- if (cnt > 0) {
- output = ',';
- }
- output += "{\"type\":\"";
- output += (entry.isDirectory()) ? "dir" : "file";
- output += "\",\"name\":\"";
- output += entry.name();
- output += "\"";
- output += "}";
- server.sendContent(output);
- entry.close();
- }
- server.sendContent("]");
- dir.close();
- }
- //Test read and write speed using test.txt file
- void testFileIO(fs::FS &fs, const char * path){
- File file = fs.open(path);
- static uint8_t buf[512];
- size_t len = 0;
- uint32_t start = millis();
- uint32_t end = start;
- if(file){
- len = file.size();
- size_t flen = len;
- start = millis();
- while(len){
- size_t toRead = len;
- if(toRead > 512){
- toRead = 512;
- }
- file.read(buf, toRead);
- len -= toRead;
- }
- end = millis() - start;
- Serial.printf("%u bytes read for %u ms\n", flen, end);
- file.close();
- } else {
- Serial.println("Failed to open file for reading");
- }
- file = fs.open(path, FILE_WRITE);
- if(!file){
- Serial.println("Failed to open file for writing");
- return;
- }
- size_t i;
- start = millis();
- for(i=0; i<2048; i++){
- file.write(buf, 512);
- }
- end = millis() - start;
- Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
- file.close();
- }
- bool loadFromSdCard(String path){
- String dataType = "text/plain";
- if(path.endsWith("/")) path += "index.htm";
- if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf("."));
- else if(path.endsWith(".htm")) dataType = "text/html";
- else if(path.endsWith(".html")) dataType = "text/html";
- else if(path.endsWith(".css")) dataType = "text/css";
- else if(path.endsWith(".js")) dataType = "application/javascript";
- else if(path.endsWith(".png")) dataType = "image/png";
- else if(path.endsWith(".gif")) dataType = "image/gif";
- else if(path.endsWith(".jpg")) dataType = "image/jpeg";
- else if(path.endsWith(".ico")) dataType = "image/x-icon";
- else if(path.endsWith(".svg")) dataType = "image/svg+xml";
- else if(path.endsWith(".xml")) dataType = "text/xml";
- else if(path.endsWith(".pdf")) dataType = "application/pdf";
- else if(path.endsWith(".zip")) dataType = "application/zip";
- else if(path.endsWith(".mp3")) dataType = "audio/mpeg";
- else if(path.endsWith(".mp4")) dataType = "video/mp4";
- else if(path.endsWith(".otf")) dataType = "font/otf";
- else if(path.endsWith(".ttf")) dataType = "font/ttf";
- File dataFile = SD_MMC.open(path.c_str());
- if(dataFile.isDirectory()){
- path += "/index.html";
- dataType = "text/html";
- dataFile = SD_MMC.open(path.c_str());
- }
- if (!dataFile)
- return false;
- if (server.hasArg("download")) dataType = "application/octet-stream";
- if (server.streamFile(dataFile, dataType) != dataFile.size()) {
- Serial.println("[error] Sent less data than expected!");
- }
- dataFile.close();
- return true;
- }
- void deleteRecursive(String path) {
- File file = SD_MMC.open((char *)path.c_str());
- if (!file.isDirectory()) {
- file.close();
- SD_MMC.remove((char *)path.c_str());
- return;
- }
- file.rewindDirectory();
- while (true) {
- File entry = file.openNextFile();
- if (!entry) {
- break;
- }
- String entryPath = path + "/" + entry.name();
- if (entry.isDirectory()) {
- entry.close();
- deleteRecursive(entryPath);
- } else {
- entry.close();
- SD_MMC.remove((char *)entryPath.c_str());
- }
- yield();
- }
- SD_MMC.rmdir((char *)path.c_str());
- file.close();
- }
- void handleDeleteRequest(String fullPath) {
- int index = fullPath.indexOf(",");
- String path = fullPath.substring(index + 1, fullPath.length());
- Serial.println("[info] Request delete path: " + path);
- if (path == "/" || !SD_MMC.exists((char *)path.c_str())) {
- sendCORS();
- server.send(500, "text/plain", "Bad path");
- return;
- }
- deleteRecursive(path);
- sendCORS();
- server.send(200, "text/plain", "DONE");
- }
- void sendCORS(){
- if (forceCORS){
- server.sendHeader("Access-Control-Allow-Origin", "*");
- server.sendHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
- server.sendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
- }
- }
|