陆续更新
演示视频:
视频链接:http://v.youku.com/v_show/id_XMzEzMTYwNDUyOA==.html?spm=a2hzp.8244740.0.0
项目说明:
其实用arduino做类似的web server是不合适的,web server搭建更推荐使用linux开发板,本项目仅供学习研究。
使用到的硬件:
Arduino UNO、Wiznet W5500扩展板、TF卡一张、网线
因为我只有5500,5500的ethernet库需要使用https://github.com/Wiznet/WIZ_Ethernet_Library
使用5100也是可以的,IDE自带的ethernet库即可。
可实现的功能:
通过浏览器查看、删除TF卡中的文件。
(暂时没有在线编写文件的功能,实际上很多应用中文件都是Arduino采集传感器数据自动生成的)
参考了以下项目:
https://github.com/greiman/SdFat
https://github.com/adafruit/SDWebBrowse
实现思路:
1.仿照REST,通过get实现指定路径的访问、文件查看、文件删除操作
2.在loop中获取请求,并分析判断是哪种操作,并执行相应的操作
因此loop中基本结构框架如下:
[mw_shl_code=arduino,true]void loop()
{
int index = 0;
client = server.available();
if (client)
{
boolean current_line_is_blank = true;
index = 0;
while (client.connected())
{
if (client.available())
{
//SdFile root;
char c = client.read();
if (c != '\n' && c != '\r')
{
clientline[index] = c;
index++;
if (index >= BUFSIZE)
index = BUFSIZE - 1;
continue;
}
clientline[index] = 0;
Serial.println(clientline);
//访问根目录
if (strstr(clientline, "GET / ") != 0)
{
}
//删除文件
else if (strstr(clientline, "/del/") != 0)
{
}
//打开子目录
else if ((strstr(clientline, "GET /") != 0) && (strstr(clientline, "/ HTTP") != 0))
{
}
//打开文件
else if (strstr(clientline, "GET /") != 0)
{
}
//没有找到文件
else
{
}
break;
}
}
delay(1);
client.stop();
}
}[/mw_shl_code]
各功能实现代码:
打开文件夹
[mw_shl_code=arduino,true]void OpenDir(char *dirname)
{
file.open(&root, dirname, O_READ);
ListFiles(file);
file.close();
}
[/mw_shl_code]
输出文件名
[mw_shl_code=arduino,true]void PrintFileName()
{
for (uint8_t i = 0; i < 11; i++) {
if (p.name == ' ') continue;
if (i == 8) {
client.print('.');
}
client.print((char)p.name);
}
if (DIR_IS_SUBDIR(&p)) {
client.print('/');
}
}[/mw_shl_code]
输出文件列表
[mw_shl_code=arduino,true]void ListFiles(SdFile dir)
{
while (dir.readDir(p) > 0)
{
if (p.name[0] == DIR_NAME_FREE) break;
if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') continue;
if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
client.print("<p><a href=\"");
PrintFileName();
client.print("\">");
PrintFileName();
client.print("</a>");
// 大小信息
client.print(" ");
client.print(p.fileSize);
client.print(" ");
client.print("<a href=\"del/");
PrintFileName();
client.print("\">");
client.print("del");
client.print("</a>");
client.println("</p>");
}
}[/mw_shl_code]
打开文件
[mw_shl_code=arduino,true]void OpenFile(char *filename)
{
Serial.println("send file data");
Serial.println(filename);
char *path=strtok(filename, "/");
filename=strtok(NULL, "/");
Serial.println(path);
Serial.println(filename);
file.open(&root, path, O_READ);
SdFile file2;
file2.open(&file, filename, O_READ);
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/plain");
client.println();
int16_t c;
while ((c = file2.read()) > 0) {
client.print((char)c);
}
file2.close();
file.close();
}[/mw_shl_code]
删除文件
[mw_shl_code=arduino,true]void DelFile(char *filename)
{
file.remove(&root,filename);
}[/mw_shl_code]
完整程序如下:
[mw_shl_code=cpp,true]#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
Sd2Card card;
SdVolume volume;
SdFile root;
// SdFile file;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 177);
EthernetServer server(80);
EthernetClient client;
dir_t p;
String readString;
String filelist[20];
#define BUFSIZE 100
char clientline[BUFSIZE];
void initSD()
{
card.init(SPI_HALF_SPEED, 4);
volume.init(&card);
root.openRoot(&volume);
}
void setup()
{
Serial.begin(9600);
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
initSD();
Ethernet.begin(mac, ip);
server.begin();
Serial.print("Server is at ");
Serial.println(Ethernet.localIP());
}
void loop()
{
int index = 0;
client = server.available();
if (client)
{
boolean current_line_is_blank = true;
index = 0;
while (client.connected())
{
if (client.available())
{
//SdFile root;
char c = client.read();
if (c != '\n' && c != '\r')
{
clientline[index] = c;
index++;
if (index >= BUFSIZE)
index = BUFSIZE - 1;
continue;
}
clientline[index] = 0;
Serial.println(clientline);
//访问根目录
if (strstr(clientline, "GET / ") != 0)
{
Sendheader(200);
client.println("<h2>File List:</h2>");
root.rewind();
ListFiles(root);
}
//删除文件
else if (strstr(clientline, "/del/") != 0)
{
char *filename;
filename = clientline + 5;
(strstr(clientline, "/del/ HTTP"))[0] = 0;
Serial.println(filename);
DelFile(filename);
}
//打开子目录
else if ((strstr(clientline, "GET /") != 0) && (strstr(clientline, "/ HTTP") != 0))
{
Serial.println("open dir");
Sendheader(200);
char *dirname;
dirname = clientline + 5;
(strstr(clientline, " HTTP"))[0] = 0;
client.print("<h2>");
client.print(dirname);
client.println(" List:</h2>");
OpenDir(dirname);
}
//打开文件
else if (strstr(clientline, "GET /") != 0)
{
char *filename;
filename = clientline + 5;
(strstr(clientline, " HTTP"))[0] = 0;
OpenFile(filename);
}
//没有找到文件
else
{
Sendheader(404);
client.println("<h2>File Not Found!</h2>");
}
break;
}
}
delay(1);
client.stop();
}
}
void PrintFileName()
{
for (uint8_t i = 0; i < 11; i++) {
if (p.name == ' ') continue;
if (i == 8) {
client.print('.');
}
client.print((char)p.name);
}
if (DIR_IS_SUBDIR(&p)) {
client.print('/');
}
}
void ListFiles(SdFile dir)
{
while (dir.readDir(p) > 0)
{
if (p.name[0] == DIR_NAME_FREE) break;
if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') continue;
if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
client.print("<p><a href=\"");
PrintFileName();
client.print("\">");
PrintFileName();
client.print("</a>");
if (!(DIR_IS_SUBDIR(&p)))
{
client.print(" ");
client.print(p.fileSize);
client.print(" ");
client.print("<a href=\"");
PrintFileName();
client.print("/del/\">");
client.print("del");
client.print("</a>");
}
client.println("</p>");
}
}
void Sendheader(int x)
{
if (x == 200)
{
client.println("HTTP/1.1 200 OK");
}
if (x == 404)
{
client.println("HTTP/1.1 404 Not Found");
return;
}
client.println("Content-Type: text/html");
client.println();
}
void OpenDir(char *dirname)
{
//dirname: DATA/2016/05/
SdFile file, file2, file3;
char *path1 = strtok(dirname, "/"); //DATA
char *path2 = strtok(NULL, "/"); //201X
char *path3 = strtok(NULL, "/"); //XX
if (path2 == NULL)
{
file.open(&root, path1, O_READ);
ListFiles(file);
file.close();
}
else if (path3 == NULL)
{
file.open(&root, path1, O_READ);
file2.open(&file, path2, O_READ);
ListFiles(file2);
file2.close();
file.close();
}
else
{
file.open(&root, path1, O_READ);
file2.open(&file, path2, O_READ);
file3.open(&file2, path3, O_READ);
ListFiles(file3);
file3.close();
file2.close();
file.close();
}
}
void OpenFile(char *filename)
{
//DATA/01/XXX.TXT
char *path1 = strtok(filename, "/"); //DATA
char *path2 = strtok(NULL, "/"); //201X
char *path3 = strtok(NULL, "/"); //XX
filename = strtok(NULL, "/"); //XXX.TXT
SdFile file;
file.open(&root, path1, O_READ);
SdFile file2;
file2.open(&file, path2, O_READ);
SdFile file3;
file3.open(&file2, path3, O_READ);
SdFile file4;
file4.open(&file3, filename, O_READ);
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/plain");
client.println();
int16_t c;
while ((c = file4.read()) > 0) {
client.print((char)c);
}
file4.close();
file3.close();
file2.close();
file.close();
}
void DelFile(char *filename)
{
char *path1 = strtok(filename, "/"); //DATA
char *path2 = strtok(NULL, "/"); //201X
char *path3 = strtok(NULL, "/"); //XX
filename = strtok(NULL, "/"); //XXX.TXT
SdFile file;
file.open(&root, path1, O_READ);
SdFile file2;
file2.open(&file, path2, O_READ);
SdFile file3;
file3.open(&file2, path3, O_READ);
SdFile file4;
file4.remove(&file3, filename);
file4.close();
file3.close();
file2.close();
file.close();
Sendheader(200);
client.print("Delete ");
client.print(filename);
client.println(" success");
}[/mw_shl_code]
|