zoukankan      html  css  js  c++  java
  • WiFi-ESP8266入门http(2-1)文件系统-复杂结构的网页

    https://blog.csdn.net/solar_Lan/article/details/74231360

    用到的网页文件:链接:https://pan.baidu.com/s/1vk6xmsYZuJe8CMFzJNKdJw 密码:oiz2

    注:对于ESP8266开源技术感兴趣的可以加群,我们一起探索交流学习,群号:579932824。群名:ESP8266开源技术交流群。

    在第一篇教程中,由ESP8266返回的网页都是通过直接发送String来完成响应,这个方法是挺快的,但是在复杂结构的网页下就显得格外麻烦,调整的时候需要一个个找,而且还是在html结构打乱的情况下找,把css和js写入到同一个页面内无疑也是增加了调试的成本,

    所以官方引入了一个SPIFFS的文件系统(SPIFFS的github地址:https://github.com/pellepl/spiffs),

    这个文件系统是通过共用板载的Flash芯片来完成

    (官方说明文档:https://github.com/esp8266/Arduino/blob/master/doc/filesystem.md),

    之前在配置环境的时候相比应该还记得有个选择Flash Size的选项吧,这个就是分配程序和SPIFFS空间的选项。一般市面上的12E型都已经搭载了4M的Flash,所以大家在选择的时候就选择使用4M的,剩下是1M还是3M的SPIFFS就看实际需要,一般推荐使用1M,因为烧写SPIFFS的时候不像烧写程序那样只是根据程序大小烧写部分区块,而是整个区块完整烧写的,3M烧写一次的时间差不多有4-5分钟,烧写1M的则会很快。

    这次教程的代码:

    #include <ESP8266WiFi.h>  
    
    #include <ESP8266WebServer.h>  
    
    #include <FS.h>  
    
    ESP8266WebServer server ( 80 );  
    
    String ssid = "...."; // 需要连接的wifi热点名称  
    
    String password = "........"; // 需要连接的wifi热点密码  
    
    /** 
    
     * 根据文件后缀获取html协议的返回内容类型 
    
     */  
    
    String getContentType(String filename){  
    
      if(server.hasArg("download")) return "application/octet-stream";  
    
      else if(filename.endsWith(".htm")) return "text/html";  
    
      else if(filename.endsWith(".html")) return "text/html";  
    
      else if(filename.endsWith(".css")) return "text/css";  
    
      else if(filename.endsWith(".js")) return "application/javascript";  
    
      else if(filename.endsWith(".png")) return "image/png";  
    
      else if(filename.endsWith(".gif")) return "image/gif";  
    
      else if(filename.endsWith(".jpg")) return "image/jpeg";  
    
      else if(filename.endsWith(".ico")) return "image/x-icon";  
    
      else if(filename.endsWith(".xml")) return "text/xml";  
    
      else if(filename.endsWith(".pdf")) return "application/x-pdf";  
    
      else if(filename.endsWith(".zip")) return "application/x-zip";  
    
      else if(filename.endsWith(".gz")) return "application/x-gzip";  
    
      return "text/plain";  
    
    }  
    
    /* NotFound处理 
    
     * 用于处理没有注册的请求地址 
    
     * 一般是处理一些页面请求 
    
     */  
    
    void handleNotFound() {  
    
      String path = server.uri();  
    
      Serial.print("load url:");  
    
      Serial.println(path);  
    
      String contentType = getContentType(path);  
    
      String pathWithGz = path + ".gz";  
    
      if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){  
    
        if(SPIFFS.exists(pathWithGz))  
    
          path += ".gz";  
    
        File file = SPIFFS.open(path, "r");  
    
        size_t sent = server.streamFile(file, contentType);  
    
        file.close();  
    
        return;  
    
      }  
    
      String message = "File Not Found
    
    ";  
    
      message += "URI: ";  
    
      message += server.uri();  
    
      message += "
    Method: ";  
    
      message += ( server.method() == HTTP_GET ) ? "GET" : "POST";  
    
      message += "
    Arguments: ";  
    
      message += server.args();  
    
      message += "
    ";  
    
      for ( uint8_t i = 0; i < server.args(); i++ ) {  
    
        message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "
    ";  
    
      }  
    
      server.send ( 404, "text/plain", message );  
    
    }  
    
    void handleMain() {  
    
      /* 返回信息给浏览器(状态码,Content-type, 内容) 
    
       * 这里是访问当前设备ip直接返回一个String 
    
       */  
    
      Serial.print("handleMain");  
    
      File file = SPIFFS.open("/index.html", "r");  
    
      size_t sent = server.streamFile(file, "text/html");  
    
      file.close();  
    
      return;  
    
    }  
    
    /* 引脚更改处理 
    
     * 访问地址为htp://192.162.xxx.xxx/pin?a=XXX的时候根据a的值来进行对应的处理 
    
     */  
    
    void handlePin() {  
    
      if(server.hasArg("a")) { // 请求中是否包含有a的参数  
    
        String action = server.arg("a"); // 获得a参数的值  
    
        if(action == "on") { // a=on  
    
          digitalWrite(2, LOW); // 点亮8266上的蓝色led,led是低电平驱动,需要拉低才能亮  
    
          server.send ( 200, "text/html", "Pin 2 has turn on"); return; // 返回数据  
    
        } else if(action == "off") { // a=off  
    
          digitalWrite(2, HIGH); // 熄灭板载led  
    
          server.send ( 200, "text/html", "Pin 2 has turn off"); return;  
    
        }  
    
        server.send ( 200, "text/html", "unknown action"); return;  
    
      }  
    
      server.send ( 200, "text/html", "action no found");  
    
    }  
    
    void setup() {   
    
      // 日常初始化网络  
    
      pinMode(2, OUTPUT);  
    
      Serial.begin ( 115200 );  
    
      SPIFFS.begin();  
    
      int connectCount = 0;  
    
      WiFi.begin ( ssid.c_str(), password.c_str() );  
    
      while ( WiFi.status() != WL_CONNECTED ) {  
    
        delay ( 1000 );  
    
        Serial.print ( "." );  
    
        if(connectCount > 30) {  
    
          Serial.println( "Connect fail!" );  
    
          break;  
    
        }  
    
        connectCount += 1;  
    
      }  
    
      if(WiFi.status() == WL_CONNECTED) {  
    
        Serial.println ( "" );  
    
        Serial.print ( "Connected to " );  
    
        Serial.println ( ssid );  
    
        Serial.print ( "IP address: " );  
    
        Serial.println ( WiFi.localIP() );  
    
        connectCount = 0;  
    
      }  
    
      server.on ("/", handleMain); // 绑定‘/’地址到handleMain方法处理  
    
      server.on ("/pin", HTTP_GET, handlePin); // 绑定‘/pin’地址到handlePin方法处理  
    
      server.onNotFound ( handleNotFound ); // NotFound处理  
    
      server.begin();  
    
      Serial.println ( "HTTP server started" );  
    
    }  
    
       
    
    void loop() {  
    
      /* 循环处理,因为ESP8266的自带的中断已经被系统占用, 
    
       * 只能用过循环的方式来处理网络请求 
    
       */  
    
      server.handleClient();  
    
    }  
    

      

    代码修改自之前路由系统,毕竟web页面配合路由的请求会很方便。

    主要是增加了getContentType方法和修改了handleMain、handleNotFound。修改handleMain引导访问根目录到index.html文件上,修改handleNotFound加入文件检查,有则直接返回,没有则404。

    需要用到的css和js文件(度盘连接),这里的文件是压缩成gz格式,在浏览器中是支持这种格式的压缩文件的,压缩成gz的目的是减少数据量,节约传输的带宽,8266虽然说是54M的制式,但是从Flash读取出数据再传输到客户端上的数据流量大约只有6-9kb/s,一个jquery min没压缩前大约94kb,最快的情况传输需要10秒钟,而压缩成gz格式之后只有32kb,传输也就只需要3秒钟,中间的等待时间就少了很多。在handleNotFound里边做了判断,如果找到同名文件带有gz格式的文件优先返回gz文件。

    接下来就是将文件上传到Flash上了,在这里需要下载一个Arduino IDE的插件(github地址:https://github.com/esp8266/arduino-esp8266fs-plugin/releases/download/0.3.0/ESP8266FS-0.3.0.zip,度盘:)。下载完成之后解压到IDE的tools文件夹中,解压之后完整的路径应该是“Arduino IDE的文件夹/tools/ESP8266FS/tool/esp8266fs.jar”,然后重启Arduino IDE,打开项目,在对应的项目文件夹下创建名称为data的文件夹,这个data文件夹就是上传数据用的文件夹,上传之后这个目录就是8266的根目录,将需要上传的文件复制到这个文件夹中,让8266进入烧写状态并关闭IDE的串口管理器,最后选择Tools(工具)->ESP8266 Sketch Data Upload选项,将文件上传到给8266的板载Flash。进入烧写状态之后就慢慢等着文件上传完成了,完成之后8266会重启,但是保险起见,建议手动重启一次。

    之后待8266连接上wifi之后访问它在串口管理器打印的IP,就可以看到上传到8266上的页面了。

  • 相关阅读:
    Docker 容器默认root账号运行,很不安全!
    Prometheus阅读目录
    linux修改SSH远程登录端口 服务器安全篇
    linux 部署出现Fatal error: Class 'DOMDocument' not found。
    mysql开启远程访问权限
    linux 重置mysql 密码
    推送(极光推送)
    linux 搭建SVN
    C语言词频统计设计
    读《构建之法》有感
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/9595924.html
Copyright © 2011-2022 走看看