-
-
Save Jerware/cfc10296de1a85424800 to your computer and use it in GitHub Desktop.
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
#pragma SPARK_NO_PREPROCESSOR | |
#include "SdFat.h" | |
#define WEBDUINO_SERIAL_DEBUGGING 1 | |
#include "WebServer.h" | |
void statusLedFlicker(); | |
void helloCmd(WebServer &server, WebServer::ConnectionType type, char *, bool); | |
void uploadCmd(WebServer & server, WebServer::ConnectionType type, char * url_tail, bool tail_complete); | |
void LEDCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete); | |
void deleteCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete); | |
void processWebServer(); | |
void WebServerLaunch(); | |
void listFiles(uint8_t flags, uint8_t indent); | |
/*************************************************** | |
Upload Test | |
****************************************************/ | |
// Pick an SPI configuration. | |
// See SPI configuration section below (comments are for photon). | |
#define SPI_CONFIGURATION 0 | |
//------------------------------------------------------------------------------ | |
// Setup SPI configuration. | |
#if SPI_CONFIGURATION == 0 | |
// Primary SPI with DMA | |
// SCK => A3, MISO => A4, MOSI => A5, SS => A2 (default) | |
SdFat sd; | |
const uint8_t SD_CS = SS; | |
#elif SPI_CONFIGURATION == 1 | |
// Secondary SPI with DMA | |
// SCK => D4, MISO => D3, MOSI => D2, SS => D1 | |
SdFat sd(1); | |
const uint8_t SD_CS = D1; | |
#elif SPI_CONFIGURATION == 2 | |
// Primary SPI with Arduino SPI library style byte I/O. | |
// SCK => A3, MISO => A4, MOSI => A5, SS => A2 (default) | |
SdFatLibSpi sd; | |
const uint8_t SD_CS = SS; | |
#elif SPI_CONFIGURATION == 3 | |
// Software SPI. Use any digital pins. | |
// MISO => D5, MOSI => D6, SCK => D7, SS => D0 | |
SdFatSoftSpi<D5, D6, D7> sd; | |
const uint8_t SD_CS = D0; | |
#endif // SPI_CONFIGURATION | |
//------------------------------------------------------------------------------ | |
SdFile myFile; // set filesystem | |
/* This creates an instance of the webserver. By specifying a prefix | |
* of "", all pages will be at the root of the server. */ | |
#define PREFIX "" | |
WebServer webserver(PREFIX, 80); | |
#define STATUS_LED D7 | |
boolean statusLedState; | |
void setup(void) { | |
Serial.begin(57600); | |
Serial.println("Hello there!"); | |
// SD Init | |
Serial.print("Init SD: "); | |
if (!sd.begin(SD_CS, SPI_FULL_SPEED)) { | |
Serial.println("fail"); | |
return; | |
} | |
Serial.println("OK!"); | |
// web server setup | |
WebServerLaunch(); | |
// debug LED setup | |
pinMode(STATUS_LED, OUTPUT); | |
digitalWrite(STATUS_LED, HIGH); | |
} | |
void loop() { | |
processWebServer(); | |
} | |
void statusLedFlicker() | |
{ | |
if (statusLedState == false) | |
{ | |
digitalWrite(STATUS_LED, LOW); | |
} | |
else | |
{ | |
digitalWrite(STATUS_LED, HIGH); | |
} | |
statusLedState = !statusLedState; | |
} | |
// WebServer | |
void WebServerLaunch() | |
{ | |
/* setup our default command that will be run when the user accesses | |
* the root page on the server */ | |
webserver.setDefaultCommand(&helloCmd); | |
/* run the same command if you try to load /index.html, a common | |
* default page name */ | |
webserver.addCommand("index.html", &helloCmd); | |
webserver.addCommand("led", &LEDCmd); | |
webserver.addCommand("delete", &deleteCmd); | |
webserver.addCommand("upload", &uploadCmd); | |
/* start the webserver */ | |
webserver.begin(); | |
} | |
void processWebServer() | |
{ | |
char buff[64]; | |
int len = 64; | |
/* process incoming connections one at a time forever */ | |
webserver.processConnection(buff, &len); | |
} | |
// Modified LS function from SDFAT lib to print to webserver | |
void listFiles(WebServer &server, uint8_t flags, uint8_t indent) { | |
// make sure we're looking at root | |
char currentDirectory[13]; | |
sd.vwd()->getName(currentDirectory, 13); | |
sd.chdir("/"); | |
myFile.rewind(); | |
server.println("<p>SD CONTENTS:<br>"); | |
while (myFile.openNext(sd.vwd(), O_READ)) { | |
if (!myFile.isHidden() || (flags & LS_A)) { | |
// get folder name | |
char foundfile[13]; | |
myFile.getName(foundfile, 13); | |
// add requested indents | |
for (uint8_t i = 0; i < indent; i++) { | |
server.print(" "); | |
} | |
// print slash if folder | |
if (myFile.isDir()) { | |
server.print('/'); | |
} | |
server.print(foundfile); | |
server.println("<br>"); | |
} | |
myFile.close(); | |
} | |
sd.chdir(currentDirectory); | |
} | |
void LEDCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete) | |
{ | |
statusLedFlicker(); | |
} | |
void deleteCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete) | |
{ | |
// delete all files in root, leaving directories | |
// make sure we're looking at root | |
char currentDirectory[13]; | |
sd.vwd()->getName(currentDirectory, 13); | |
sd.chdir("/"); | |
myFile.rewind(); | |
while (myFile.openNext(sd.vwd(), O_READ)) | |
{ | |
myFile.printName(&Serial); | |
char fileNameString[13]; | |
myFile.getName(fileNameString, 13); | |
if (!myFile.isDir()) | |
{ | |
myFile.close(); | |
sd.remove(fileNameString); | |
} | |
else myFile.close(); | |
} | |
sd.chdir(currentDirectory); | |
} | |
void helloCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete) | |
{ | |
/* this line sends the standard "we're all OK" headers back to the | |
browser */ | |
server.httpSuccess(); | |
/* if we're handling a GET or POST, we can output our data here. | |
For a HEAD request, we just stop after outputting headers. */ | |
if (type == WebServer::HEAD) | |
return; | |
/* this defines some HTML text in read-only memory aka PROGMEM. | |
* This is needed to avoid having the string copied to our limited | |
* amount of RAM. */ | |
P(Page_start) = "<html><head>\n<title>Upload Test</title>\n"; | |
server.printP(Page_start); | |
server.println("<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>\n"); | |
server.println("</head><body>\n"); | |
server.println("<script>"); | |
server.print("function funky(cmd){ $.ajax('http://"); | |
server.print(WiFi.localIP()); | |
server.println("/' + cmd); }"); | |
server.println("</script>\n"); | |
server.printP("<H2><p>Upload Test</p></H2>\n"); | |
server.println("<table><tr>"); | |
server.println("<td><form><input type='button' value='LED TOGGLE' onclick='funky(\"led\")'></form></td>\n"); | |
server.println("<td><form><input type='button' value='DELETE ROOT FILES' onclick='funky(\"delete\")'></form></td>\n"); | |
server.println("</tr></table>"); | |
server.println("<p>Upload Here</p>"); | |
server.println("<p><form method='post' enctype='multipart/form-data' id='uploader' action='/upload' method='POST'>"); | |
server.println("<input type='file' name='my_file[]' multiple>"); | |
server.println("<input type='submit' value='Upload'>"); | |
server.println("</form>"); | |
server.println("<p>"); | |
server.println("SSID: "); | |
server.println(WiFi.SSID()); | |
server.println("<br>"); | |
server.println("Local IP: "); | |
server.println(WiFi.localIP()); | |
server.println("<br>"); | |
server.println("Subnet Mask: "); | |
server.println(WiFi.subnetMask()); | |
server.println("<br>"); | |
server.println("Gateway IP: "); | |
server.println(WiFi.gatewayIP()); | |
server.println("<br>"); | |
server.println("---"); | |
server.println("<br>"); | |
server.println("deviceID: "); | |
String myID = System.deviceID(); | |
server.println(myID); | |
server.println("<br>"); | |
server.printlnf("System version: %s", System.version().c_str()); | |
server.println("<br>"); | |
server.print("free memory: "); | |
uint32_t freemem = System.freeMemory(); | |
server.println(freemem); | |
server.println(""); | |
// readHTML(server, "/00system/wifi/index.htm"); | |
listFiles(server, 0, 1); | |
} | |
void uploadCmd(WebServer & server, WebServer::ConnectionType type, char * url_tail, bool tail_complete) | |
{ | |
// make sure we upload to the root | |
char currentDirectory[13]; | |
sd.vwd()->getName(currentDirectory, 13); | |
sd.chdir("/"); | |
sd.vwd()->rewind(); | |
Serial.println("uploadCmd Called..."); | |
int numUploads = 0; | |
long nbytes; | |
boolean success = false; | |
if (type == WebServer::POSTMULTI) // this is what is expected: a multipart form | |
{ | |
Serial.println("POSTMULTI detected..."); | |
bool repeat; | |
int act = -1; | |
char ch; | |
while ((act = server.readNextFormPart(act)) != -4) | |
{ // if readnextformpart returns -4, either an error occurred or end of forms was reached. | |
numUploads++; | |
Serial.print(numUploads); | |
Serial.print(" : "); | |
Serial.print("m_filename: "); | |
Serial.println(server.m_filename); | |
if (strlen(server.m_filename) > 0) | |
{ // filename is not empty: a file has been submitted. filename is read in readnextformpart. | |
int buffer[5]; // a simple FIFO buffer is used to make sure the last two bytes are not written to file. A better way could(should) be used. for now, this works | |
int b_read = 0; | |
int b_write = 0; | |
int diff = 0; // buffer read/write indexes, and the number of bytes the read buffer is behind | |
SdFile filetoload; | |
filetoload.clearWriteError(); | |
if (filetoload.open(server.m_filename, O_CREAT | O_WRITE | O_TRUNC)) | |
{ // returns true if file was opened succesfully | |
nbytes = 0; // number of bytes read | |
success = true; | |
while ((act = server.readNextFormPart(-3)) >= 0) | |
{ // as long as a valid byte is read. (-3) as input means it is returning reading bytes and exiting if a boundary was found. | |
nbytes++; | |
buffer[b_write] = act; // put data in buffer | |
b_write = (b_write + 1) % 5; //updat buffer index | |
diff++; | |
if (diff > 2) | |
{ // start writing after a 2-byte delay | |
nbytes++; | |
ch = buffer[b_read]; | |
filetoload.write(buffer[b_read]); //write data to files | |
if (filetoload.getWriteError()) | |
{ | |
break; | |
} | |
b_read = (b_read + 1) % 5; | |
diff--; | |
} | |
} | |
// free(buffer); | |
// this previous section needs some cleaning up. writing to a much larger buffer and writing the buffer in a single step to the file would probably be much faster. | |
if (filetoload.getWriteError()) | |
{ | |
success = false; | |
Serial.println("write error!!"); | |
} | |
Serial.println("Finished writing!"); | |
filetoload.close(); | |
} | |
else | |
{ | |
Serial.println("Failed to open file!!"); | |
} | |
} | |
} | |
} // end if POSTMULTI | |
server.httpSuccess(); | |
if (success) | |
{ | |
server.print("<html><body><h1>"); | |
server.print(numUploads); | |
server.println("file(s) uploaded.</h1><p>"); | |
server.print("Bytes: "); | |
server.println(nbytes); | |
server.print("<p>SD Contents:"); | |
listFiles(server, 0, 1); | |
server.println("</p></body></html>"); | |
} | |
else | |
{ | |
server.println("<html><body><h1>Problems occurred. File may not have uploaded correctly</h1></body></html>"); | |
} | |
sd.chdir(currentDirectory); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment