/* * USERS OF ARDUINO 0023 AND EARLIER: use the 'SDWebBrowse.pde' sketch... * 'SDWebBrowse.ino' can be ignored. * USERS OF ARDUINO 1.0 AND LATER: **DELETE** the 'SDWebBrowse.pde' sketch * and use ONLY the 'SDWebBrowse.ino' file. By default, BOTH files will * load when using the Sketchbook menu, and the .pde version will cause * compiler errors in 1.0. Delete the .pde, then load the sketch. * * I can't explain WHY this is necessary, but something among the various * libraries here appears to be wreaking inexplicable havoc with the * 'ARDUINO' definition, making the usual version test unusable (BOTH * cases evaluate as true). FML. */ /* * This sketch uses the microSD card slot on the Arduino 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 http://www.ladyada.net/learn/arduino/ethfiles.html * Pull requests should go to http://github.com/adafruit/SDWebBrowse */ //--------------- // // Water_Meter // nico // may 2012 // //--------------- #include #include #include #include #define BLUE_LED 5 /************ REALTIME STUFF ***********/ #include #include "RTClib.h" RTC_DS1307 RTC; /************ ETHERNET STUFF ************/ byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte ip[] = { 192, 168, 1, 77 }; // default address, can be overriden by SD card. Server server(80); /************ SDCARD STUFF ************/ Sd2Card card; SdVolume volume; SdFile root; SdFile file; SdFile myFile; /************ INTERRUPT STUFF *********/ #include "TimerOne.h" int pinInt = 0; // pin 2 volatile int count; void callback() { count++; } // store error strings in flash to save RAM #define error(s) error_P(PSTR(s)) void error_P(const char* str) { PgmPrint("error: "); SerialPrintln_P(str); if (card.errorCode()) { PgmPrint("SD error: "); Serial.print(card.errorCode(), HEX); Serial.print(','); Serial.println(card.errorData(), HEX); } while(1); } //------------------------------------------------------------ //------------------------------------------------------------ void setup() { /************ REALTIME STUFF ***********/ Wire.begin(); RTC.begin(); if (! RTC.isrunning()) Serial.println("RTC is NOT running!"); /************ INTERRUPT STUFF *********/ attachInterrupt(pinInt, callback, RISING); // attaches callback() as a timer overflow interrupt count = 0; pinMode(BLUE_LED, OUTPUT); // blue led digitalWrite(BLUE_LED, LOW); // off pinMode(3, OUTPUT); // blue led digitalWrite(3, HIGH); // off Serial.begin(9600); PgmPrint("Free RAM: "); Serial.println(FreeRam()); // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with // breadboards. use SPI_FULL_SPEED for better performance. pinMode(10, OUTPUT); // set the SS pin as an output (necessary!) digitalWrite(10, HIGH); // but turn off the W5100 chip! if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!"); // initialize a FAT volume if (!volume.init(&card)) error("vol.init failed!"); PgmPrint("Volume is FAT"); Serial.println(volume.fatType(),DEC); Serial.println(); if (!root.openRoot(&volume)) error("openRoot failed"); // list file in root with date and size PgmPrintln("Files found in root:"); root.ls(LS_DATE | LS_SIZE); Serial.println(); // Recursive list of all directories PgmPrintln("Files found in all dirs:"); root.ls(LS_R); Serial.println(); PgmPrintln("Done"); // ethernet config from card //--------------------------- if (file.open(&root, "config.txt", O_READ)) { digitalWrite(BLUE_LED, HIGH); Serial.println("read config.txt:"); char num[10]; int index = 0, indexip = 0; int16_t c; while ((c = file.read()) > 0) { Serial.print((char)c); num[index++]=c; if (c=='.' || c=='\n') { num[index]='\0'; ip[indexip++]=atoi(num); index=0; } } Serial.println(); Serial.println("done reading."); file.close(); digitalWrite(BLUE_LED, LOW); } else { Serial.print("could not open 'config.txt'"); } //-------------------- if (!myFile.open(&root, "test.txt", O_RDWR | O_CREAT | O_AT_END)) { Serial.print("could not open 'test.txt'"); } // if the file opened okay, write to it: Serial.print("Writing to test.txt..."); myFile.println("testing 1, 2, 3."); // close the file: myFile.close(); Serial.println("done."); //-------------------- char sbuf[50]; sprintf(sbuf, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); Serial.println(sbuf); // Debugging complete, we start the server! Ethernet.begin(mac, ip); server.begin(); } //------------------------------------------------------------ //------------------------------------------------------------ void ListFiles(Client client, uint8_t flags) { // This code is just copied from SdFile.cpp in the SDFat library // and tweaked to print to the client output in html! dir_t p; root.rewind(); client.println(RTC.now().unixtime()); client.print("count: "); client.println(count); client.println(""); } //------------------------------------------------------------ //------------------------------------------------------------ // How big our line buffer should be. 100 is plenty! #define BUFSIZ 100 void loop() { char clientline[BUFSIZ]; int index = 0; // todo: make this atomic w/r interrupt int save_count = count; count = 0; // end atomic if (save_count) { // open stream for append char* waterlog = "waterlog.txt"; if (!myFile.open(&root, waterlog, O_RDWR | O_CREAT | O_AT_END)) { Serial.print("could not open "); Serial.println(waterlog); } else { digitalWrite(BLUE_LED, HIGH); Serial.print("Writing to "); Serial.print(waterlog); Serial.println("..."); myFile.print(save_count); myFile.print(" liters @ "); myFile.print(RTC.now().unixtime()); myFile.println(); myFile.close(); Serial.println("done."); digitalWrite(BLUE_LED, LOW); } } Client 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 root file if (strstr(clientline, "GET / ") != 0) { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); // print all the files, use a helper to keep it clean client.println("

Files:

"); ListFiles(client, LS_SIZE); } else 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; // print the file we want Serial.println(filename); if (! file.open(&root, filename, O_READ)) { client.println("HTTP/1.1 404 Not Found"); client.println("Content-Type: text/html"); client.println(); client.println("

File Not Found!

"); break; } Serial.println("Opened!"); client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/plain"); client.println(); int16_t c; while ((c = file.read()) > 0) { // uncomment the serial to debug (slow!) //Serial.print((char)c); client.print((char)c); } 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("

File Not Found!

"); } break; } } // give the web browser time to receive the data delay(1); client.stop(); } } //------------------------------------------------------------ //------------------------------------------------------------