SD.hを使用してブラウザに表示する参考ソフト先人の方が公開されておりましたが
SD_MMC版のブラウザ表示ソフトはどこにも見当たらなかったので、先人の皆様のソフトを参考に作成しました。
最初に、Wi-Fiの設定プログラムです。
//Wi-Fiの設定は、ESP-Touchから行うこと
#include "WiFi.h"
WiFiServer server(80);//portの指定
//Wi-FIの初期設定
void WiFiInit(){
// 前回接続時情報で接続する
Serial.println("WiFi begin");
WiFi.begin();
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
// 10秒以上接続できなかったら抜ける
if ( 10000 < millis() ) {
break;
}
}
Serial.println("");
// 未接続の場合にはSmartConfig待受
if ( WiFi.status() != WL_CONNECTED ) {
WiFi.mode(WIFI_STA);
WiFi.beginSmartConfig();
Serial.println("Waiting for SmartConfig");
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print("#");
// 30秒以上接続できなかったら抜ける
if ( 30000 < millis() ) {
Serial.println("");
Serial.println("Reset");
ESP.restart();
}
}
// Wi-fi接続
Serial.println("");
Serial.println("Waiting for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
// 60秒以上接続できなかったら抜ける
if ( 60000 < millis() ) {
Serial.println("");
Serial.println("Reset");
ESP.restart();
}
}
Serial.println("");
Serial.println("WiFi Connected.");
}
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
次はSDカードの初期化プログラムです。
//--------------SD定義
#include "sd_read_write.h"
#include "SD_MMC.h"
//ESP32 WRover-eの場合のピンアサインです。
#define SD_MMC_CMD 15 //Please do not modify it.
#define SD_MMC_CLK 14 //Please do not modify it.
#define SD_MMC_D0 2 //Please do not modify it.
//ESP32S3 WROOMなら
#define SD_MMC_CMD 38 //Please do not modify it.
#define SD_MMC_CLK 39 //Please do not modify it.
#define SD_MMC_D0 40 //Please do not modify it.
//----------------
void SDInit(){
SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD_MMC card attached");
return;
}
Serial.print("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("SD_MMC Card Size: %lluMB\n", cardSize);
}
以下Libです。そのままコピペしてファイルを作ってください。
SDカードの初期化のためのライブラリ
#ifndef __SD_READ_WRITE_H
#define __SD_READ_WRITE_H
#include "Arduino.h"
#include "FS.h"
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
void createDir(fs::FS &fs, const char * path);
void removeDir(fs::FS &fs, const char * path);
void readFile(fs::FS &fs, const char * path);
void writeFile(fs::FS &fs, const char * path, const char * message);
void appendFile(fs::FS &fs, const char * path, const char * message);
void renameFile(fs::FS &fs, const char * path1, const char * path2);
void deleteFile(fs::FS &fs, const char * path);
void testFileIO(fs::FS &fs, const char * path);
#endif
#include "sd_read_write.h"
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : ");
Serial.println(file.name());
if(levels){
listDir(fs, file.path(), levels -1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
void createDir(fs::FS &fs, const char * path){
Serial.printf("Creating Dir: %s\n", path);
if(fs.mkdir(path)){
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
void removeDir(fs::FS &fs, const char * path){
Serial.printf("Removing Dir: %s\n", path);
if(fs.rmdir(path)){
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
Serial.write(file.read());
}
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
}
void appendFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
}
void renameFile(fs::FS &fs, const char * path1, const char * path2){
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\n", path);
if(fs.remove(path)){
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
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\r\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();
}
HTML表示用のライブラリ
#ifndef CHECHANDRESPONSE_H
#define CHECHANDRESPONSE_H
//you could chose readwrite\readonly
#define readrite
//you could chose UseWiFi/UseEthernet
#define UseWiFi
//Enable/Disable Rename
#define EnableRename
#ifdef UseWiFi
#include <WiFi.h>
#define WiFiEthernet WiFi
#define WiFiEthernetClient WiFiClient
#else
#include <Ethernet.h>
#define WiFiEthernet Ethernet
#define WiFiEthernetClient EthernetClient
#endif
//ヘッダーの追加
#include "SD_MMC.h"
//もともとあったSD,SPIは使用しないので削除
//#include <SD.h>
//#include <SPI.h>
bool CheckAndResponse(WiFiEthernetClient &client);
void process_request(WiFiEthernetClient& client, String request);
void sendHTTP(WiFiEthernetClient& client, const String& request);
/*
bool checkfilename(String checkstr);
String kmgt(unsigned long bytes);
String getType(const String& extension);
String getFilename(const String& filename);
String getExtension(const String& filename);
String ipToString(uint32_t ip);
String processReequest(char c);
String urlEncode(String str);
String urlDecode(String str);
*/
#endif
//元々のソースではSD.hを使用していたが、今回はSDMMC.hでのSDカードの参照なので、SDの部分を全て
//SD_MMCに書き換えた
#include "CheckAndResponse.h"
// decode %URL
String urlDecode(String str) {
String decoded = "";
char temp[] = "0x00";
int str_len = str.length();
for (int i = 0; i < str_len; i++) {
if (str[i] == '%') {
if (i + 2 < str_len) {
temp[2] = str[i + 1];
temp[3] = str[i + 2];
decoded += (char)strtol(temp, NULL, 16);
i += 2;
}
} else if (str[i] == '+') {
decoded += ' ';
} else {
decoded += str[i];
}
}
return decoded;
}
// ecode %URL
String urlEncode(String str) {
String encoded = "";
char temp[] = "0x00";
for (int i = 0; i < str.length(); i++) {
char c = str[i];
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~' || c == '/') {
encoded += c;
//} else if (c == ' ') {
// encoded += '+';
} else {
sprintf(temp, "%02X", c);
encoded += '%' + String(temp);
}
}
return encoded;
}
//defines for client
#define BUFFLEN 256 //length of the receive buffer
char buff[BUFFLEN]; //buffer
int count = 0; //counter for the buffer
bool isBlankLine = false; //if the last line is empty, the end of request
String path;
bool POSTflag = false;
#ifndef readonly
String cmdfilename;
String newfilename;
int ContentLength;
String errormessage;
bool Uploadflag = false;
String boundary;
bool Header = true; //when it is false, countdown ContentLength
#endif
#ifndef readonly
//put received char in buffer and check the GET command and empty line
String processReequest(char c) {
if (c == '\r') {
isBlankLine = false;
return ""; //if the code is CR, ignore it
} else if (c == '\n') { //if the code is NL, read the GET request
buff[count] = '\0'; //put null character at the end
String request = buff; //convert to String
if (!POSTflag && !Uploadflag) { //nomarl Header
isBlankLine = (count == 0); //and check if the line is empty
} else if (Uploadflag && Header) {
Header = !(count == 0);
} else if (!Header) {
ContentLength -= count; //count down ContenLength
}
//else if(!POSTflag && Uploadflag && count == 0){ //end header when fileupload
// isBlankLine = (count == 0);
//}
count = 0;
return request;
} else { //if the code is not control code, record it
isBlankLine = false;
if (count >= (BUFFLEN - 1)) count = 0; //if almost overflow, reset the counter
buff[count++] = c; //add char at the end of buffer
if (count == ContentLength && POSTflag) { //POST Payload finished
buff[count] = '\0'; //put null character at the end
String request = buff; //convert to String
if (request.startsWith("cmdfilename")) { //finish post payload
Serial.println("POST is finished");
isBlankLine = true;
count = 0;
return request;
}
}
return "";
}
}
#else
String processReequest(char c) {
if(c == '\r'){ //if the code is CR, ignore it
isBlankLine = false;
return "";
}
else if(c == '\n') { //if the code is NL, read the GET request
buff[count]='\0'; //put null character at the end
String request = buff; //convert to String
isBlankLine = (count == 0); //and check if the line is empty
count=0;
return request;
}
else { //if the code is not control code, record it
isBlankLine = false;
if(count >= (BUFFLEN - 1) ) count=0; //if almost overflow, reset the counter
buff[count++]=c; //add char at the end of buffer
return "";
}
}
#endif
// https://qiita.com/dojyorin/items/ac56a1c2c620782d90a6
String ipToString(uint32_t ip) {
String result = "";
result += String((ip & 0xFF), 10);
result += ".";
result += String((ip & 0xFF00) >> 8, 10);
result += ".";
result += String((ip & 0xFF0000) >> 16, 10);
result += ".";
result += String((ip & 0xFF000000) >> 24, 10);
return result;
}
String getExtension(const String& filename) {
int dotIndex = filename.lastIndexOf('.');
if (dotIndex == -1 || dotIndex == filename.length() - 1) {
return "";
}
return filename.substring(dotIndex + 1);
}
String getFilename(const String& filename) {
int dotIndex = filename.lastIndexOf('/');
if (dotIndex == -1 || dotIndex == filename.length() - 1) {
return "";
}
return filename.substring(dotIndex + 1);
}
//decide header by extension
String getType(const String& extension) {
if (extension.equalsIgnoreCase("txt")) {
return "text/plain";
} else if (extension.equalsIgnoreCase("csv")) {
return "text/csv";
} else if (extension.equalsIgnoreCase("html") || extension.equalsIgnoreCase("htm")) {
return "text/html";
} else if (extension.equalsIgnoreCase("css")) {
return "text/css";
} else if (extension.equalsIgnoreCase("js")) {
return "text/javascript";
} else if (extension.equalsIgnoreCase("json")) {
return "application/json";
} else if (extension.equalsIgnoreCase("pdf")) {
return "application/pdf";
} else if (extension.equalsIgnoreCase("jpg") || extension.equalsIgnoreCase("jpeg")) {
return "image/jpeg";
} else if (extension.equalsIgnoreCase("png")) {
return "image/png";
} else if (extension.equalsIgnoreCase("gif")) {
return "image/gif";
} else if (extension.equalsIgnoreCase("svg")) {
return "image/svg+xml";
} else if (extension.equalsIgnoreCase("zip")) {
return "application/zip";
} else if (extension.equalsIgnoreCase("mpeg") || extension.equalsIgnoreCase("mpg")) {
return "video/mpeg";
} else {
return "other";
}
}
String kmgt(unsigned long bytes) {
if (bytes < 1000) {
return String(bytes) + "B";
} else if (1000 <= bytes && bytes < 1000000) {
return String(int(bytes / 1000)) + "KB";
} else if (1000000 <= bytes && bytes < 1000000000) {
return String(int(bytes / 1000000)) + "MB";
} else{
return String(int(bytes / 1000000000)) + "GB";
}
}
#ifndef readonly
//check not use Forbidden characters
bool checkfilename(String checkstr) { //OK > true, invalid > false
if (checkstr.indexOf("/") == checkstr.length() - 1 || checkstr.indexOf("/") == -1) { //If "/" is used as the last character
return checkstr.indexOf("\\") == -1 && checkstr.indexOf(":") == -1 && checkstr.indexOf("*") == -1 && checkstr.indexOf("?") == -1 && checkstr.indexOf("\"") == -1 && checkstr.indexOf("<") == -1 && checkstr.indexOf(">") == -1 && checkstr.indexOf("|") == -1;
}
return false;
}
#endif
bool CheckAndResponse(WiFiEthernetClient &client){
if (client) {
Serial.println("new client");
while (client.connected()) {
if (client.available()) {
char c = client.read();
//Serial.write(c); //Output Request from client
String request = processReequest(c);
if (!request.equals("")) {
process_request(client, request);
}
//if the line is blank, the request has ended.
if (isBlankLine) {
sendHTTP(client, request); //send HTTP response
break;
}
}
}
return true;
}
return false;
}
#ifndef readonly
void process_request(WiFiEthernetClient& client, String request) {
if (request.startsWith("GET")) {
//String path = request.substring(4).toInt();
path = request;
path.replace("GET ", "");
path.replace(" HTTP/1.1", "");
path = urlDecode(path); //decode%
POSTflag = false;
Uploadflag = false;
} else if (request.startsWith("POST")) {
Serial.print("post:");
Serial.println(request);
path = request;
path.replace("POST ", "");
path.replace(" HTTP/1.1", "");
path = urlDecode(path); //decode%
POSTflag = true;
Uploadflag = false;
} else if (request.startsWith("Content-Length") && POSTflag) {
//Serial.print("Content-Length:");
//Serial.println(request);
request.replace("Content-Length: ", "");
ContentLength = request.toInt();
//Serial.print("ContentLength=");
//Serial.println(ContentLength);
} else if (request.startsWith("cmdfilename") && POSTflag) {
//Serial.print("cmd:");
//Serial.println(request);
cmdfilename = request.substring(0, request.indexOf("&"));
cmdfilename.replace("cmdfilename=", "");
String secondIndex = request.substring(request.indexOf("&") + 1, request.lastIndexOf("&"));
String thirdIndex = request.substring(request.lastIndexOf("&") + 1, request.length());
if (secondIndex.startsWith("newfilename")) {
newfilename = secondIndex;
} else {
newfilename = thirdIndex;
}
newfilename.replace("newfilename=", "");
cmdfilename = urlDecode(cmdfilename); //decode
newfilename = urlDecode(newfilename); //decode
if (!checkfilename(cmdfilename) || !checkfilename(newfilename)) { //OK > true, invalid > false
POSTflag = false;
errormessage = "Invalid characters are used.";
} else if (cmdfilename.equals("")) {
POSTflag = false;
errormessage = "Prease enter file name to operate.";
}
//Serial.print("cmdfilename:");
//Serial.println(cmdfilename);
//Serial.print("newfilename:");
//Serial.println(newfilename);
} else if (request.startsWith("Content-Type") && POSTflag) {
if (!Uploadflag) { //serch boundary
//serch "boundary="
while (!request.startsWith("boundary=")) {
request.remove(0, 1); //remove first letter
if (request.length() == 0) {
break;
}
}
if (request.length() != 0) { //if boundary found
request.replace("boundary=", "");
boundary = request;
//Serial.print("boundary=");
//Serial.println(boundary);
Uploadflag = true;
} else { //if boundary didn't find
Uploadflag = false;
}
} else { //upload file
//ContentLength -= (request.length() + 1);
String filename = path + request;
//setting upload file
newfilename = path + newfilename;
File file = SD_MMC.open(newfilename, FILE_WRITE);
while (client.available()) {
char c = client.read();
//Serial.write(c);
ContentLength -= 1;
//Serial.println(ContentLength);
if (c == '\n') {
break;
}
}
//write file
Serial.println("Start writting uploadfile");
//recive file with buffer
const int BufferSize = 1024;
//int finish_count = BufferSize + boundary.length() + 3 + 11; //use client check
int finish_count = boundary.length() + 3 + 11; //use client check
//const int filesize = ContentLength - boundary.length() - 3 - 11; //use file check
const size_t bufferSize = BufferSize; //buffer size
byte buffe[bufferSize]; //buffe
int countb = 0;
const int misslimit = 2048;
int misscount = 0;
while (ContentLength > finish_count && misscount < misslimit) {
while (countb < BufferSize && ContentLength > finish_count) {
if (client.available()) {
buffe[countb] = client.read();
countb += 1;
ContentLength -= 1;
} else {
//Serial.print(".");
misscount += 1;
delay(10);
break;
}
}
//Serial.println(ContentLength);
file.write(buffe, countb);
countb = 0;
}
while (client.available() && misscount < misslimit) { //write last boudary
char c = client.read();
Serial.write(c);
}
file.close();
Uploadflag = false;
POSTflag = false;
Header = true;
if (!(misscount < misslimit)) {
Serial.println("To many packet loss.");
client.println("HTTP/1.1 500 Internal Server Error");
client.println("Connection: close");
errormessage = "File will be broken. Delete & try again.";
isBlankLine = false;
} else {
isBlankLine = true;
}
}
} else if (request.endsWith(boundary) && Uploadflag) { //start payload
//Serial.println("payload start");
Serial.println(request);
//ContentLength -= (boundary.length()+3); //boundary,--,\n
} else if (request.startsWith("Content-Disposition") && Uploadflag) { //get upload filename
//ContentLength -= (request.length() + 1);
//serch filename=
while (!request.startsWith("filename=")) {
request.remove(0, 1); //remove first letter
if (request.length() == 0) {
errormessage = "Not found filename.";
}
}
request.replace("filename=\"", "");
request.replace("\"", "");
newfilename = request;
Serial.print("newfilename:");
Serial.println(newfilename);
}
}
#else
void process_request(WiFiEthernetClient &client,String request){
if(request.startsWith("GET")){
//String path = request.substring(4).toInt();
path = request;
path.replace("GET ","");
path.replace(" HTTP/1.1","");
path = urlDecode(path); //decode%
}
}
#endif
void sendHTTP(WiFiEthernetClient& client, const String& request) {
//Serial.println("");
Serial.print("path:");
Serial.println(path);
if (path.equals("")) {
path = "/";
}
if (path.endsWith("/") && !POSTflag) { //readDirectory
if (!path.equals("/")) {
path.remove(path.length() - 1); //delet last "/"
}
if (SD_MMC.exists(path)) { //check path is exist
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("");
client.println("");
Serial.print("Directroy:");
Serial.println(path);
client.println("<!DOCTYPE html>");
client.println("<html>");
client.println("<head>");
client.println("<title>SD Reader</title>");
client.println("<meta charset=\"UTF-8\">");
client.println("</head>");
client.println("<body>");
//display current path
client.print("<h1>");
client.print(path);
if (!path.equals("/")) { //add "/"
client.print("/");
}
client.println("</h1>");
#ifndef readonly
//command
client.print("<form action=\"");
client.print(urlEncode(path));
if (!path.equals("/")) {
client.print("/");
}
client.println("\" method=\"POST\">");
client.println("Enter File or Folder name to operate.<br>");
client.println("<input type=\"text\" name=\"cmdfilename\">");
client.println("<input type=\"submit\" name=\"mkdir\" value=\"mkdir\">");
client.println("<input type=\"submit\" name=\"delete\" value=\"delete\"><br>");
#ifndef DisableRename
client.println("Enter new name.<br>");
client.println("<input type=\"text\" name=\"newfilename\">");
client.println("<input type=\"submit\" name=\"rename\" value=\"rename\">");
#endif
client.println("</form>");
//file upload
client.print("<form action=\"");
client.print(urlEncode(path));
if (!path.equals("/")) {
client.print("/");
}
client.println("\" method=\"POST\" enctype=\"multipart/form-data\">");
client.println("Upload file. (Recommend < 20MB)<br>");
client.println("<input type=\"file\" name=\"uploadfile\">");
client.println("<input type=\"submit\" value=\"upload\">");
client.println("</form>");
//display Error message
if (!errormessage.equals("")) {
client.print("<p><font color=\"red\">");
client.println(errormessage);
client.print("</font></p>");
errormessage = "";
}
#endif
//Parent Directory
String IPaddr = ipToString(WiFiEthernet.localIP());
if (!path.equals("/")) {
client.print("<p><a href=\"");
client.print("http://");
client.print(IPaddr);
client.print(urlEncode(path.substring(0, path.lastIndexOf("/") + 1))); //Parent Directory path
client.print("\" >");
client.print("Parent Directory");
client.print("</a>");
client.println("</p>");
}
client.print("<hr>");
//list up directory contents
File dir = SD_MMC.open(path);
while (true) {
File entry = dir.openNextFile();
if (!entry) {
break;
}
String filename = entry.name();
if (entry.isDirectory()) {
filename += "/";
}
String fileurl = "http://" + IPaddr + urlEncode(path);
if (path.equals("/")) {
fileurl += urlEncode(filename);
} else {
fileurl += "/" + urlEncode(filename);
}
client.print("<p>");
client.print("<a href=\"");
client.print(fileurl);
client.print("\" >");
client.print(filename);
client.println("</a>");
if (!filename.endsWith("/")) { //display file size
client.print(" ");
client.println(kmgt(entry.size()));
}
client.println("</p>");
entry.close();
}
dir.close();
client.print("<hr>");
client.print("<p>");
client.print("Powered by ");
client.print("<a href=\"https://github.com/UnagiDojyou/ArduinoIDE_SD_FAT32_Fileserver\">ArduinoIDE_SD_FAT32_Fileserver</a>");
client.println("</p>");
client.println("</body>");
client.println("</html>");
} else { //Directory not Found
client.println("HTTP/1.1 404 Not Found");
client.println("Connection: close");
}
} else if (!POSTflag) { //File
if (SD_MMC.exists(path)) {
Serial.print("File:");
Serial.println(path);
String extension = getExtension(getFilename(path));
File file = SD_MMC.open(path);
unsigned long filesize = file.size();
client.println("HTTP/1.1 200 OK");
client.print("Content-Length: ");
client.println(filesize);
if (extension.equals("other")) {
client.print("Content-Disposition");
} else {
client.print("Content-Type: ");
client.println(getType(extension));
}
client.println("Connection: close");
client.println();
//send file to client with 1024 buffer.
const size_t bufferSize = 1024; //buffer size
byte buffe[bufferSize]; //buffe
while (file.available() && client.connected()) {
size_t bytesRead = file.read(buffe, bufferSize);
client.write(buffe, bytesRead);
}
file.close();
} else { //File not Found
client.println("HTTP/1.1 404 Not Found");
client.println("Connection: close");
}
}
#ifndef readonly
else if (POSTflag && request.indexOf("mkdir=mkdir") > -1) { //mkdri
//Serial.println("mkdir");
String newdir = path + cmdfilename;
Serial.print("mkdir:");
Serial.println(newdir);
if (!SD_MMC.mkdir(newdir)) {
errormessage = "Cannot make " + newdir;
}
} else if (POSTflag && request.indexOf("delete=delete") > -1) { //delete
//Serial.println("delete");
String rmpath = path + cmdfilename;
Serial.print("delete:");
Serial.println(rmpath);
if (cmdfilename.endsWith("/")) { //directory
if (!SD_MMC.rmdir(rmpath.substring(0, rmpath.length() - 1))) {
errormessage = "Cannot delete " + rmpath;
}
} else { //file
if (!SD_MMC.remove(rmpath)) {
errormessage = "Cannot delete " + rmpath + "/";
}
}
}
#ifndef DisableRename
else if (POSTflag && request.indexOf("rename=rename") > -1) { //rename
Serial.println("rename");
String Newname = path + newfilename;
String Oldname = path + cmdfilename;
if (Newname.endsWith("/") ^ Oldname.endsWith("/")) {
errormessage = "Either \"/\" is missing or surplus.";
} else if (!SD_MMC.rename(Oldname, Newname)) {
errormessage = "Cannot rename " + Oldname + "to" + "Newname";
}
}
#endif
if (POSTflag) { //send page(must be exexute if(path.endsWith("/") && !POSTflag))
POSTflag = false;
sendHTTP(client, request);
}
#endif
client.println("");
client.stop();
Serial.println("Response finish");
return;
}
以上がライブラリになります。
最後にこれらを組み合わせてプログラムを作成すると以下のようになります。
//2024 0524 ブラウザでSDカードの中身を参照可能なところまで作り込みOK
//URLの指定は、IPアドレス/フォルダ名/ とすること 最後の/を忘れないこと
//Wi-Fiの設定は、ESP-Touchから行うこと
#include <Arduino.h>
#include "WiFi.h"
WiFiServer server(80);
//--------------SD定義
#include "sd_read_write.h"
#include "SD_MMC.h"
#define SD_MMC_CMD 15 //Please do not modify it.
#define SD_MMC_CLK 14 //Please do not modify it.
#define SD_MMC_D0 2 //Please do not modify it.
//----------------
#include <SD.h>
#include <FS.h>
#include "CheckAndResponse.h"//同じディレクトリに置けば認識される
//https://github.com/UnagiDojyou/ArduinoIDE_SD_FAT32_Fileserver/tree/main/ESP32_FAT32_Fileserver_readwrite
//Wi-FIの初期設定
void WiFiInit(){
// 前回接続時情報で接続する
Serial.println("WiFi begin");
WiFi.begin();
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
// 10秒以上接続できなかったら抜ける
if ( 10000 < millis() ) {
break;
}
}
Serial.println("");
// 未接続の場合にはSmartConfig待受
if ( WiFi.status() != WL_CONNECTED ) {
WiFi.mode(WIFI_STA);
WiFi.beginSmartConfig();
Serial.println("Waiting for SmartConfig");
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print("#");
// 30秒以上接続できなかったら抜ける
if ( 30000 < millis() ) {
Serial.println("");
Serial.println("Reset");
ESP.restart();
}
}
// Wi-fi接続
Serial.println("");
Serial.println("Waiting for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
// 60秒以上接続できなかったら抜ける
if ( 60000 < millis() ) {
Serial.println("");
Serial.println("Reset");
ESP.restart();
}
}
Serial.println("");
Serial.println("WiFi Connected.");
}
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
void SDInit(){
SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD_MMC card attached");
return;
}
Serial.print("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("SD_MMC Card Size: %lluMB\n", cardSize);
}
void setup() {
// シリアル初期化
Serial.begin(115200);
WiFiInit();
SDInit();
server.begin(); //start the server
Serial.print("\nHTTP server started at: ");
Serial.println(WiFi.localIP());
listDir(SD_MMC, "/", 0);
}
void loop() {
WiFiClient client = server.available();
CheckAndResponse(client);
}
SDカードの中身にmainというフォルダがあれば
http://192.168.24.15/main/ といったように指定します。
するとブラウザに表示されるはずです。
コメント