/** * Function starts the SD card service and makes sure that the appropriate directory * structure exists, then creates the file to use for logging data. Data will be logged * to a file called fileNamePrefix_0.csv or fileNamePrefix_0.bin (number will be incremented * for each new log file) * * @param chipSelectPin Arduino pin SD card reader CS pin is attached to * @param fileNamePrefix string to prefix at beginning of data file * @param csvData boolean flag whether we are writing csv data or binary data (used for filename) * * @return true if successful, false if failed */ bool beginDataLog(int chipSelectPin, const char *fileNamePrefix, bool csvData) { bool ret; int i = 0; int max_len; char fileName[19]; char prefix[8]; char rootPath[] = "/data"; if (_output_buffer != NULL) { delete []_output_buffer; } OUTPUT_BUF_SIZE = 512; _output_buffer = vol.cacheAddress()->output_buf; if (freeMemory() < 400) { strcpy_P(_getOutBuf(), sd_card_error); Serial.print(_getOutBuf()); Serial.print(freeMemory()); Serial.println(", need 400)"); ret = false; } else { ret = sd.begin(chipSelectPin, SPI_FULL_SPEED); } //Filenames need to fit the 8.3 filename convention, so truncate down the //given filename if it is too long. memcpy(prefix, fileNamePrefix, 7); prefix[7] = '\0'; if (ret) { if (!sd.exists(rootPath)) ret = sd.mkdir(rootPath); if (ret) { while (true) { if (i < 10) { max_len = 7; } else if (i < 100) { max_len = 6; } else if (i < 1000) { max_len = 5; } else { break; } prefix[max_len - 1] = '\0'; sprintf(fileName, "%s/%s%d.%s", rootPath, prefix, i, csvData ? "csv" : "bin"); if (!sd.exists(fileName)) { file = sd.open(fileName, FILE_WRITE); break; } i++; } } } return file.isOpen(); }
boolean put_handler(AtMegaWebServer& web_server) { const char* length_str = web_server.get_header_value("Content-Length"); long length = atol(length_str); const char *path = web_server.get_path(); SdFile file; if(!file.open(path, O_CREAT | O_WRITE | O_TRUNC)){ // maybe the folder must be created char *c = strrchr(path, '/'); if(c){ *c = 0; if(sdfat.mkdir(path)){ #if DEBUG Serial << "put_handler make DIR: ok " << path <<'\n'; #endif *c = '/'; if(!file.open(path, O_CREAT | O_WRITE | O_TRUNC)){ #if DEBUG Serial << "put_handler open FILE: failed " << path <<'\n'; #endif } } *c = '/'; } } if(file.isOpen()){ EthernetClient client = web_server.get_client(); long size = 0; int read = 0; while(size < length && web_server.waitClientAvailable()){ read = client.read((uint8_t*)buffer, sizeof(buffer)); file.write(buffer, read); size += read; } file.close(); #if DEBUG Serial << "file written: " << size << " of: " << length << '\n'; #endif if(size < length){ web_server.sendHttpResult(404); }else{ web_server.sendHttpResult(200); web_server << path; } }else{ web_server.sendHttpResult(422); // assuming it's a bad filename (non 8.3 name) #if DEBUG Serial << F("put_handler open file failed: send 422 ") << path <<'\n'; #endif } return true; }
//------------------------------------------------------------------------------ void setup() { Serial.begin(9600); // Wait for USB Serial while (!Serial) { SysCall::yield(); } delay(1000); cout << F("Type any character to start\n"); // Wait for input line and discard. cin.readline(); cout << endl; // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with // breadboards. use SPI_FULL_SPEED for better performance. if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) { sd.initErrorHalt(); } if (sd.exists("Folder1") || sd.exists("Folder1/file1.txt") || sd.exists("Folder1/File2.txt")) { error("Please remove existing Folder1, file1.txt, and File2.txt"); } int rootFileCount = 0; sd.vwd()->rewind(); while (file.openNext(sd.vwd(), O_READ)) { if (!file.isHidden()) { rootFileCount++; } file.close(); if (rootFileCount > 10) { error("Too many files in root. Please use an empty SD."); } } if (rootFileCount) { cout << F("\nPlease use an empty SD for best results.\n\n"); delay(1000); } // Create a new folder. if (!sd.mkdir("Folder1")) { error("Create Folder1 failed"); } cout << F("Created Folder1\n"); // Create a file in Folder1 using a path. if (!file.open("Folder1/file1.txt", O_CREAT | O_WRITE)) { error("create Folder1/file1.txt failed"); } file.close(); cout << F("Created Folder1/file1.txt\n"); // Change volume working directory to Folder1. if (!sd.chdir("Folder1")) { error("chdir failed for Folder1.\n"); } cout << F("chdir to Folder1\n"); // Create File2.txt in current directory. if (!file.open("File2.txt", O_CREAT | O_WRITE)) { error("create File2.txt failed"); } file.close(); cout << F("Created File2.txt in current directory\n"); cout << F("\nList of files on the SD.\n"); sd.ls("/", LS_R); // Remove files from current directory. if (!sd.remove("file1.txt") || !sd.remove("File2.txt")) { error("remove failed"); } cout << F("\nfile1.txt and File2.txt removed.\n"); // Change current directory to root. if (!sd.chdir()) { error("chdir to root failed.\n"); } cout << F("\nList of files on the SD.\n"); sd.ls(LS_R); // Remove Folder1. if (!sd.rmdir("Folder1")) { error("rmdir for Folder1 failed\n"); } cout << F("\nFolder1 removed.\n"); cout << F("\nList of files on the SD.\n"); sd.ls(LS_R); cout << F("Done!\n"); }