Lab_interaccio/2020/SDWebBrowse/SDWebBrowse.ino

272 lines
7.9 KiB
Arduino
Raw Normal View History

2025-02-25 21:29:42 +01:00
/*
* SDWebBrowse.ino
*
* This sketch uses the microSD card slot on the a WIZ5500 Ethernet shield
* to serve up files over a very minimal browsing interface
*
* Some code is from Bill Greiman's SdFatLib examples, some is from the
* Arduino Ethernet WebServer example and the rest is from Limor Fried
* (Adafruit) so its probably under GPL
*
* Tutorial is at https://learn.adafruit.com/arduino-ethernet-sd-card/serving-files-over-ethernet
*
*/
#include <SPI.h>
#include <SD.h>
#include <Ethernet2.h>
/************ ETHERNET STUFF ************/
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // change if necessary
byte ip[] = { 192, 168, 1, 177 }; // change if necessary
EthernetServer server(80);
/************ SDCARD STUFF ************/
#define SDCARD_CS 4
File root;
#if defined(ESP8266)
// default for ESPressif
#define WIZ_CS 15
#elif defined(ESP32)
#define WIZ_CS 33
#elif defined(ARDUINO_STM32_FEATHER)
// default for WICED
#define WIZ_CS PB4
#elif defined(TEENSYDUINO)
#define WIZ_CS 10
#elif defined(ARDUINO_FEATHER52)
#define WIZ_CS 11
#else // default for 328p, 32u4 and m0
#define WIZ_CS 10
#endif
// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))
void error_P(const char* str) {
Serial.print(F("error: "));
Serial.println(str);
while(1);
}
void setup() {
Serial.begin(115200);
while (!Serial); // For 32u4 based microcontrollers like 32u4 Adalogger Feather
//Serial.print(F("Free RAM: ")); Serial.println(FreeRam());
if (!SD.begin(SDCARD_CS)) {
error("card.init failed!");
}
root = SD.open("/");
printDirectory(root, 0);
// Recursive list of all directories
Serial.println(F("Files found in all dirs:"));
printDirectory(root, 0);
Serial.println();
Serial.println(F("Done"));
// Debugging complete, we start the server!
Serial.println(F("Initializing WizNet"));
Ethernet.init(WIZ_CS);
// give the ethernet module time to boot up
delay(1000);
// start the Ethernet connection
// Use the fixed IP specified. If you want to use DHCP first
// then switch the Ethernet.begin statements
Ethernet.begin(mac, ip);
// try to congifure using DHCP address instead of IP:
// Ethernet.begin(mac);
// print the Ethernet board/shield's IP address to Serial monitor
Serial.print(F("My IP address: "));
Serial.println(Ethernet.localIP());
server.begin();
}
void ListFiles(EthernetClient client, uint8_t flags, File dir) {
client.println("<ul>");
while (true) {
File entry = dir.openNextFile();
// done if past last used entry
if (! entry) {
// no more files
break;
}
// print any indent spaces
client.print("<li><a href=\"");
client.print(entry.name());
if (entry.isDirectory()) {
client.println("/");
}
client.print("\">");
// print file name with possible blank fill
client.print(entry.name());
if (entry.isDirectory()) {
client.println("/");
}
client.print("</a>");
/*
// print modify date/time if requested
if (flags & LS_DATE) {
dir.printFatDate(p.lastWriteDate);
client.print(' ');
dir.printFatTime(p.lastWriteTime);
}
// print size if requested
if (!DIR_IS_SUBDIR(&p) && (flags & LS_SIZE)) {
client.print(' ');
client.print(p.fileSize);
}
*/
client.println("</li>");
entry.close();
}
client.println("</ul>");
}
// How big our line buffer should be. 100 is plenty!
#define BUFSIZ 100
void loop()
{
char clientline[BUFSIZ];
char name[17];
int index = 0;
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
boolean current_line_is_blank = true;
// reset the input buffer
index = 0;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// If it isn't a new line, add the character to the buffer
if (c != '\n' && c != '\r') {
clientline[index] = c;
index++;
// are we too big for the buffer? start tossing out data
if (index >= BUFSIZ)
index = BUFSIZ -1;
// continue to read more data!
continue;
}
// got a \n or \r new line, which means the string is done
clientline[index] = 0;
// Print it out for debugging
Serial.println(clientline);
// Look for substring such as a request to get the file
if (strstr(clientline, "GET /") != 0) {
// this time no space after the /, so a sub-file!
char *filename;
filename = clientline + 5; // look after the "GET /" (5 chars) *******
// a little trick, look for the " HTTP/1.1" string and
// turn the first character of the substring into a 0 to clear it out.
(strstr(clientline, " HTTP"))[0] = 0;
if(filename[strlen(filename)-1] == '/') { // Trim a directory filename
filename[strlen(filename)-1] = 0; // as Open throws error with trailing /
}
Serial.print(F("Web request for: ")); Serial.println(filename); // print the file we want
File file = SD.open(filename, O_READ);
if ( file == 0 ) { // Opening the file with return code of 0 is an error in SDFile.open
client.println("HTTP/1.1 404 Not Found");
client.println("Content-Type: text/html");
client.println();
client.println("<h2>File Not Found!</h2>");
client.println("<br><h3>Couldn't open the File!</h3>");
break;
}
Serial.println("File Opened!");
client.println("HTTP/1.1 200 OK");
if (file.isDirectory()) {
Serial.println("is a directory");
//file.close();
client.println("Content-Type: text/html");
client.println();
client.print("<h2>Files in /");
client.print(filename);
client.println(":</h2>");
ListFiles(client,LS_SIZE,file);
file.close();
} else { // Any non-directory clicked, server will send file to client for download
client.println("Content-Type: application/octet-stream");
client.println();
char file_buffer[16];
int avail;
while (avail = file.available()) {
int to_read = min(avail, 16);
if (to_read != file.read(file_buffer, to_read)) {
break;
}
// uncomment the serial to debug (slow!)
//Serial.write((char)c);
client.write(file_buffer, to_read);
}
file.close();
}
} else {
// everything else is a 404
client.println("HTTP/1.1 404 Not Found");
client.println("Content-Type: text/html");
client.println();
client.println("<h2>File Not Found!</h2>");
}
break;
}
}
// give the web browser time to receive the data
delay(1);
client.stop();
}
}
void printDirectory(File dir, int numTabs) {
while(true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
break;
}
for (uint8_t i=0; i<numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}