本帖最后由 M5Stack 于 2019-8-26 11:03 编辑
M5Stack内置了TF卡槽,因此可以方便的读写文件,本节将利用M5Stack做一个Markdown的网络服务器。Markdown是一种轻量级的标记语言,支持HTML、富文本、文本文件等,下面就一起来做一个Markdown的网络服务器。 简要提醒: 当设备开启时会先检测SD卡,因为我们的内容是存放在TF卡中。因此在TF卡中先存入下列文件: •已知的Wi-Fi网络文件(Wi-Fi.ini); •样式文件(style.css); •支持Markdown的JS库(markdown.js); •要显示的Markdown(*.md)放到SD卡根目录
插入存储卡后,必须重新启动设备。 启动时,设备将从存储卡下载Wi-Fi设置,并尝试连接到第一个可用网络。屏幕上将会显示IP地址。 要查看网页,必须使用支持JS和CSS的浏览器。
接下来正式开始本节教程
1.绘制图标 使用画图工具或其他软件绘制图标
同样的,还要绘制其他几个图标:“插入存储卡”,“视图”,“失败”,“计时器”。 接下来,我们将使用工具转换像素数组,访问这个网址并上传你的图片就可以快速进行Xbitmap转换 https://www.online-utility.org/image/convert/to/XBM 我们只需要将*.C文件放入TF卡内。
接下来在我们的程序中建立数组
- extern unsigned char timer_logo[];
- extern unsigned char insertsd_logo[];
- extern unsigned char error_logo[];
- extern unsigned char wifi_logo[];
- extern unsigned char views_logo[];
复制代码
2.建立WiFi客户端 开启client模式
- WiFi.begin(char* ssid, char* password);
复制代码
3.显示TF卡内容 初始化SD类的实例,同时检查存储卡是否安装在插槽中。如果未插入TF卡,屏幕进行提示
- if (!SD.begin())
- {
- M5.Lcd.fillRoundRect(0, 0, 320, 240, 7, 0xffff);
- M5.Lcd.drawBitmap(50, 70, 62, 115, (uint16_t *)insertsd_logo);
- M5.Lcd.setCursor(130, 70);
- M5.Lcd.print("INSERT");
- M5.Lcd.setCursor(130, 90);
- M5.Lcd.print("THE TF-CARD");
- M5.Lcd.setCursor(130, 110);
- M5.Lcd.print("AND TAP");
- M5.Lcd.setCursor(130, 130);
- M5.Lcd.setTextColor(0xe8e4);
- M5.Lcd.print("POWER");
- M5.Lcd.setTextColor(0x7bef);
- M5.Lcd.print(" BUTTON");
- while(true);
- }
复制代码
4.TF卡文件读取 为了从TF卡读取数据,有必要调用SD类的open方法,将其作为带有文件地址的char *参数传递。代码中自定义了一个函数用来方便传入路径参数
- String TFReadFile(String path) {
- File file = SD.open(strToChar(path));
- String buf = "";
- if (file)
- {
- while (file.available())
- {
- buf += (char)file.read();
- }
- file.close();
- }
- return buf;
- }
复制代码
下面编写一个简单的函数来转换String到char *:
-
- char* strToChar(String str) {
- int len = str.length() + 1;
- char* buf = new char[len];
- strcpy(buf, str.c_str());
- return buf;
- }
复制代码
TFReadFile()将文件的地址作为String参数,尝试读取它,并将文件内容作为String返回,如果读取的文件不起作用,该函数将返回一个空字符串。 5.写文件到TF卡中 为了写入文件,需要通过FILE_WRITE参数,这里通过变量res来判断是否有新内容写入,如果file.print(str)>0,则可以使用File类的print方法覆盖数据。
- bool TFWriteFile(String path, String str) {
- File file = SD.open(strToChar(path), FILE_WRITE);
- bool res = false;
- if (file)
- {
- if (file.print(str)) res = true;
- }
- file.close();
- return false;
- }
复制代码
6.使用WIFI.ini进行WI-FI设置 如果在已知Wi-Fi网络中读取配置文件并且该设备能够连接到第一个可用的网络,连接网络会很便捷。
接下来通过读取.ini文件完成网络配置,设置连接10秒钟超时,在此之前需要先定义两个函数,第一个函数通过分割字符 char separator 分离字符串
- String parseString(int idSeparator, char separator, String str) {
- String output = "";
- int separatorCout = 0;
- for (int i = 0; i < str.length(); i++)
- {
- if ((char)str == separator)
- {
- separatorCout++;
- }
- else
- {
- if (separatorCout == idSeparator)
- {
- output += (char)str;
- }
- else if (separatorCout > idSeparator)
- {
- break;
- }
- }
- }
- return output;
- }
复制代码
第二个函数记录分隔符出现的次数
- int cntChrs(String str, char chr) {
- int cnt = 0;
- for (int i = 0; i < str.length(); i++){
- if (str == chr) cnt++;
- }
- return cnt;
- }
复制代码
下面就通过定义的函数来获取配置信息
- bool configWifi() {
- /* Get WiFi SSID & password from wifi.ini from TF-card */
- String file = TFReadFile("/system/wifi.ini");
- if (file != ""){
- for (int i = 0; i < cntChrs(file, 'n'); i++){
- String wifi = parseString(i, 'n', file);
- wifi = wifi.substring(0, (wifi.length() - 1)); // remove last char 'r'
- String ssid = parseString(0, ' ', wifi);
- String pswd = parseString(1, ' ', wifi);
- char* ssid_ = strToChar(ssid);
- char* pswd_ = strToChar(pswd);
- if (WiFi.begin(ssid_, pswd_)){
- delay(10);
- unsigned long timeout = 10000;
- unsigned long previousMillis = millis();
- while (true){
- unsigned long currentMillis = millis();
- if (currentMillis - previousMillis > timeout) break;
- if (WiFi.status() == WL_CONNECTED) return true;
- delay(100);
- }
- }
- }
- }
- return false;
- }
复制代码
7.记录查看次数 每次打开任何页面时,客户端都会将查看次数增加一次。 要存储计数器,我们将自动在系统文件夹中创建一个view文件
- int getViews() {
- String file = TFReadFile("/system/views");
- if (file != "") return file.toInt();
- return -1;
- }
-
- bool increaseViews() {
- int total = getViews();
- if (total != -1)
- {
- total++;
- if (TFWriteFile("/system/views", (String)(total))) return true;
- }
- else
- {
- if (TFWriteFile("/system/views", (String)(1))) return true;
- }
- return false;
- }
复制代码
8.接受访问请求
- String openPage(String page) {
- page += ".md";
- String content = TFReadFile(page);
- if (content != "")
- {
- increaseViews();
- drawViews();
- return content;
- }
- return "# 404 NOT FOUND #n### MARKDOWN WEB SERVER ON M5STACK ###"; // if not found 404
- }
-
- void loop() {
- String currentString = "";
- bool readyResponse = false;
- WiFiClient client = server.available();
- while (client.connected())
- {
- if (client.available())
- {
- char c = client.read();
- if ((c != 'r') && (c != 'n'))
- currentString += c;
- else
- readyResponse = true;
-
- if (readyResponse){
- String GET = parseGET(currentString);
- String mrkdwnContent = openPage(GET);
- client.flush();
- client.println("HTTP/1.1 200 OK");
- client.println("Content-type:text/html");
- client.println();
- client.println("");
- client.println("");
- client.println("");
- client.println("Markdown page | M5STACK");
- client.println("");
- client.println("");
- client.println("");
- client.println("");
- client.println("");
- client.println("");
- client.println("");
- client.println("");
- client.print("");
- client.println();
- client.println();
- readyResponse = false;
- currentString = "";
- client.stop();
- }
- }
- }
- }
复制代码
完整程序如下
0
|
|
|
|