发帖
0 0 0

忙里偷闲发个AI-WB2的Http server例程

小何
论坛元老

7

主题

21

回帖

3519

积分

论坛元老

积分
3519
Ai-WB2系列 15 0 昨天 21:22
先编写html网页,由于不会美工,都没用CCS。
无标题1.jpg
    <h2 align="center" id="SSE_ID"></h2>

    <h5 align="center">
        <input type="time" class="spin_button"  id="utc_8" style="border:none;font-size:32px;font-weight:bold;display:none" disabled>
    </h5>

    <!--
    <hr color="red"/>
    -->
    <!-- chrome ID=Pairing_ID-->
    <!-- 火狐 type=number-->
    <!--
    <style type="text/css">
        input[ID=Pairing_ID]::-webkit-outer-spin-button, input[ID=Pairing_ID]::-webkit-inner-spin-button {
            -webkit-appearance: none!important;margin:0;
        };
        
        input[type=number]{
                -moz-appearance:textfield;
            };
    </style>

    <label for="Pairing">Pincode:</label>
    <label for="Pairing" id="Pincode"></label>
    <br>
    <label for="Pairing">Pairing_On_Network:Node_ID:</label>
    <input type="number" id="Pairing_ID" name="node_id" placeholder="Node_ID" value='' step="1" required>
    <input type="button" id="Pairing" value="确认">
    <br>
    亮度调整:<input type="text" id="num" value="128" style="width:22px" disabled>
    <input type="range" id="luminance" min="10" max="254" step="1" value="128">
    -->

    <!-- 标题标签 -->
    <h3>Firmware Update Page</h3>

    <!-- 标题标签 id选择器 -->
    <h4 id="latest_firmware"></h4>

    <!-- input标签 输入类型:文件 id选择器 文件类型 jquery控件不显示 事件会在域的内容改变时发生;事件也可用于单选框与复选框改变后触发的事件。 -->
    <!-- none = 隐藏; inline = 显示 -->
    <input type="file" id="selectedFile" accept=".bin" style="display: none;" >
   
    <input type="button" value="Browse..." >

    <h4 id="file_info"></h4>
    <input type='submit' id="upload_button" value='Update Firmware'>

    <div class="wifi_ap">
        <hr color="red"/>
        <h3>WiFi configuration page</h3>
        <label for="ssid_text">SSID</label>
        <input type="text" name="ssid_text" id="ssid_text" required>
        <label for="pass_text">Password</label>
        <input type="text" name="pass_text" id="pass_text" minlength="8" required>
        <input type="button" id="set_config" value="SET">
    </div>

    <hr color="red"/>
    <input type="button" id="restart" value="重启" style="margin-left:150px;">
    <input type="button" id="reset" value="重置" style="margin-left:180px;">
   
    <hr color="red"/>
   
    <script type="text/javascript">
        var seconds = 10;
        var theTimer;
        var updateFirmwarecolor = 0;

        var set_config_color = 0;

        var SysStatus;
        var es = new EventSource("/McuToHtml");
        
        var downfilename;

        //当连接上之后就会立即触发;
        /*es.addEventListener('open',function(){
            test++;
            console.log("open" + test);
        },false);
        */
        //服务器向客户端发送数据的默认事件,通过e.data可以获取到数据;
        es.addEventListener('message',function(e){
            console.log("id:" + e.lastEventId + ";message:" + e.data);
            if(e.lastEventId == 0){
                console.log("UTC_8:" + e.data);
                if((e.data & 0x04000000) != 0){
                    let hourdate = parseInt((e.data & 0x1ffff) / 3600);
                        if(hourdate < 10){
                            hourdate = "0" + hourdate;
                        }
                    let Min1 = (e.data & 0x1ffff) % 3600;
                    let Mindate = parseInt(Min1 / 60);
                        if(Mindate < 10){
                            Mindate = "0" + Mindate;
                        }
                    let Sec1 = (e.data & 0x1ffff)  % 3600;
                    let Secdate = Sec1 % 60;
                        if(Secdate < 10){
                            Secdate = "0" + Secdate;
                        }
                    utc_8.style.display="";
                    utc_8.value = hourdate + ":" + Mindate + ":" + Secdate;
                    console.log("UTC-8:" + hourdate + ":" + Mindate + ":" + Secdate);
                }
                else{
                    utc_8.style.display="none";
                }
               
            }
            else{

            }
            document.getElementById("SSE_ID").innerHTML = "参数设定(SSE_ID:" + e.lastEventId + ")";
            test_function.style.background="";
        },false);

        //自定义事件(SSE支持自定义事件);
        es.addEventListener('foo',function(e){
            console.log("foo:" + e.data);
        },false);

        //当链接发生错误时触发。
        /*es.addEventListener('error',function(){
        console.info('error');
        },false);*/

        function myFunction() {
            var x = document.getElementById("selectedFile");
            var file = x.files[0];
            date = new Date(file.lastModified);  //
            Y = date.getFullYear() + '-';
            M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
            D = date.getDate();
            h = date.getHours() + ':';
            m = (date.getMinutes()  < 10 ?  '0'+(date.getMinutes()) : date.getMinutes()) + ':';
            s = (date.getSeconds() < 10 ? '0'+(date.getSeconds()) : date.getSeconds());
            document.getElementById("file_info").innerHTML = "File: " + file.name + "<br>" + "Size: " + file.size + "bytes" + "<br>" + "Latest Modified Date:" + Y + M + D + " " + h + m + s;
            console.log(file.name.includes(downfilename))
            if(!file.name.includes(downfilename))
            {
                confirm("升级文件不相同");
                document.getElementById("file_info").style.color = "red";
            }
        }

        function updateFirmware() {
            // Form Data
            var formData = new FormData();
            var fileSelect = document.getElementById("selectedFile");
            if (fileSelect.files && fileSelect.files.length == 1) {
                var file = fileSelect.files[0];
                formData.set("file", file, file.name);
                // Http Request
                var xhr = new XMLHttpRequest();
                //Upload progress
                xhr.upload.addEventListener("progress", function(evt) {
                    if (evt.lengthComputable) {
                        var percentComplete = (evt.loaded / evt.total) * 100;
                        var x = Math.floor(percentComplete);
                        //Do something with upload progress
                        //console.log(x);
                        document.getElementById("latest_firmware").innerHTML = "Progress:" + x + "%.";
                        // After we send it all, lets ask the board if it went well.
                        if (x == 100) {
                            // Lets ask the board for the upload resilt
                            getstatus();
                        }
                        if(updateFirmwarecolor == 1){
                            //document.getElementById("upload_button").style.background="blue";
                            upload_button.style.background="blue";
                            updateFirmwarecolor = 0;
                        }
                        else{
                            //document.getElementById("upload_button").style.background="red";
                            upload_button.style.background="red";
                            updateFirmwarecolor = 1;
                        }
                    } else {
                        window.alert('total size is unknown')
                    }
                }, false);
                xhr.open('POST', "/update");
                xhr.responseType = "blob";
                xhr.send(formData);
            }
            else {
                window.alert('Select A File First')
            }
        }
        

        // https://developer.mozilla.org/en ... XMLHttpRequest/send
        function getstatus() {
            var xhr = new XMLHttpRequest();
            var requestURL = "/status";
            xhr.open('POST', requestURL, true);
            //xhr.responseType = "blob";
            //Send the proper header information along with the request
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");//设置为表单方式提交
            xhr.onreadystatechange = function() { // Call a function when the state changes.在状态更改时调用函数。//绑定响应状态事件监听函数
                if ((this.readyState == XMLHttpRequest.DONE) && (this.status == 200)) //监听readyState状态,监听HTTP状态码
                {
                    /* readyState属性值
                        返回值 说明
                        0          未初始化。表示对象已经建立,但是尚未初始化,尚未调用 open() 方法
                        1          初始化。表示对象已经建立,尚未调用 send() 方法
                        2          发送数据。表示 send() 方法已经调用,但是当前的状态及 HTTP 头未知
                        3          数据传送中。已经接收部分数据,因为响应及 HTTP 头不安全,这时通过 responseBody 和 responseText 获取部分数据会出现错误
                        4          完成。= XMLHttpRequest.DONE 数据接收完毕,此时可以通过 responseBody 和 responseText 获取完整的响应数据  
                        
                        readyState        存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
                                    0: 请求未初始化
                                    1: 服务器连接已建立
                                    2: 请求已接收
                                    3: 请求处理中
                                    4: 请求已完成,且响应已就绪
                        
                        status        200: "OK"
                                404: 未找到页面
                    */
                    var response = JSON.parse(xhr.responseText);
                    console.log(xhr.responseText);
                    console.log(response);
                    downfilename = response.compile_name;
                    if (response.Page_feed == 1)
                    {
                        location.replace("index");  
                    }
                    else if(response.Page_feed == 3){
                        location.replace("time");
                    }
                    else{
                        SysStatus = response.SysStatus;
                        if((SysStatus & 0x20000000) == 0){
                            SSE_ID.style.background='';
                        }
                        else{
                            SSE_ID.style.background="green";
                        }
                        document.getElementById("latest_firmware").innerHTML = "Latest Firmware:  " + response.compile_name + " : " + response.compile_date + " - " + response.compile_time;
                        console.log(response.compile_name);
                        console.log(response.compile_date);
                        console.log(response.compile_time);
                        // If flashing was complete it will return a 1, else -1
                        // A return of 0 is just for information on the Latest Firmware request
                        if (response.status == 1) {
                            // Start the countdown timer
                            console.log("Status Request Returned ok");
                            // Set the delay time in seconds
                            seconds = 10;
                            // Start the countdown timer
                            console.log("starting the timer");
                            // Since ESP32 reported ok, lets set a tier to reload this web page
                            // Lets give it 10 seconds to reboot and re-connect to the router.
                            theTimer = setInterval(function() {
                                startMyTimer();
                            }, 1000);
                        }
                        else if (response.status == -1) {
                            document.getElementById("latest_firmware").innerHTML = "!!! Upload Error !!!";
                        }
                        ssid_text.value = response.ssid_text;
                        pass_text.value = response.pass_text;
                        
                    }
                }
            }
            console.log("Requestiing Upgrade Status");
            xhr.send('status');
        
        }

        function startMyTimer() {
            console.log("timer" + seconds);
            if (--seconds == 0) {
                clearInterval(theTimer);
                location.reload();
            }
            else {
                document.getElementById("latest_firmware").innerHTML = "Upgrade Complete, Rebooting in " + seconds + " Seconds.";
            }
        }

        function download(value) {
            var upload_path = "/download/" + value;
            let xhr=new XMLHttpRequest();
            xhr.open('POST' ,upload_path,true);
            xhr.responseType='blob';
            xhr.onload=()=>{
                if(xhr.status==200){
                    var blob = new Blob([xhr.response], {type: 'text/plain;charset=utf-8'});
                    blob.responseType='blob';
                    let url=window.URL || window.webkitURL || window.moxURL;
                    let downloadHref = window.URL.createObjectURL(blob);
                    let downloadLink = document.createElement('a');
                    downloadLink.href = downloadHref;
                    downloadLink.download = value;
                    downloadLink.click();
                    url.revokeObjectURL(downloadHref);
                }
            }
            xhr.send();
        }
        
        function HtmlToMcu(data) {
                var xhr = new XMLHttpRequest();
                var requestURL = "/HtmlToMcu";
                xhr.open('POST', requestURL, true);
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");//设置为表单方式提交
                xhr.responseType = "text";
                xhr.send(data);
            }

        function McuToHtmlData(id_value){
            var requestURL = "/McuToHtmlData/" + id_value;
            var xhr = new XMLHttpRequest();
            xhr.open('POST', requestURL, true);
           // xhr.responseType = "blob";
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");//设置为表单方式提交
            xhr.onreadystatechange = function() { // Call a function when the state changes.在状态更改时调用函数。//绑定响应状态事件监听函数
                if ((this.readyState == XMLHttpRequest.DONE) && (this.status == 200)) //监听readyState状态,监听HTTP状态码
                {
                    /* readyState属性值
                        返回值 说明
                        0          未初始化。表示对象已经建立,但是尚未初始化,尚未调用 open() 方法
                        1          初始化。表示对象已经建立,尚未调用 send() 方法
                        2          发送数据。表示 send() 方法已经调用,但是当前的状态及 HTTP 头未知
                        3          数据传送中。已经接收部分数据,因为响应及 HTTP 头不安全,这时通过 responseBody 和 responseText 获取部分数据会出现错误
                        4          完成。= XMLHttpRequest.DONE 数据接收完毕,此时可以通过 responseBody 和 responseText 获取完整的响应数据  
                        
                        readyState        存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
                                    0: 请求未初始化
                                    1: 服务器连接已建立
                                    2: 请求已接收
                                    3: 请求处理中
                                    4: 请求已完成,且响应已就绪
                        
                        status        200: "OK"
                                404: 未找到页面
                    */
                    var response = JSON.parse(xhr.responseText);
                    console.log("Status Request Returned ok" + xhr.responseText);
                    console.log(response.status + esponse.ompile_nane + response.compile_time + response.compile_date);
                    // Status Request Returned ok{"status":0,"compile_time":"16:39:37","compile_date":"Dec 31 2022"}
                    //                          "{\"status\":0,\"compile_time\":\"%s\",\"compile_date\":\"%s\"}"
                    //Status Request Returned ok{"status":0,"compile_time":"18:03:21","compile_date":"Dec 31 2022"}
                }
            }
            xhr.send();
        }



        $(document).ready(function() {

            $("#set_config").click(function() {
                if(ssid_text.value != '')
                {
                    if(pass_text.value.length > 7){
                        HtmlToMcu("ssid:" + ssid_text.value + "pass:" + pass_text.value);
                    }
                    else{
                        alert('SSID空或Password少于8位\n');
                    }
                    console.log("ssid:" + ssid_text.value + "pass:" + pass_text.value);
                    if(set_config_color == 1){
                        //document.getElementById("set_config").style.background="blue";
                        set_config.style.background="blue";
                        set_config_color = 0;
                    }
                    else{
                        //document.getElementById("set_config").style.background="red";
                        set_config.style.background="red";
                        set_config_color = 1;
                    }
                    location.replace("index");
                }
                else
                {
                    let errorText = ''
                    if(ssid_text.value == '') {
                        errorText = 'Missing SSID\n';
                    }
                    alert(errorText);
                }
            });  

            $("#Page_feed").click(function() {
                HtmlToMcu("page_feed:" + 65537);
                console.log("page_feed:" + 65537);
                location.replace("index");
            });

            $("#time_id").click(function() {
                HtmlToMcu("page_feed:" + 196611);
                console.log("page_feed:" + 196611);
                location.replace("time");
            });

            $("#restart").click(function() {
                let r = confirm("确认重起")
                if(r == true){
                    HtmlToMcu("restart:" + 170);
                    console.log("restart:" + 170);
                    location.replace("index");
                }
                else{

                }
               
            });

            $("#reset").click(function() {
                let r = confirm("确认重置")
                if(r == true){
                    HtmlToMcu("reset:" + 170);
                    console.log("reset:" + 170);
                    location.replace("index");
                }
                else{

                }
            });

            $("#test_function").click(function() {
                test_function.style.background="green";
                HtmlToMcu("test_set:" + 170);
                console.log("test_set:" + 170);
            });

        });//(document).ready(function()

    </script>


无标题2.jpg
<!DOCTYPE html><html lang="en"><head><title>Page Not Found</title></head><body>Page Not Found.</body></html>


使用LWIP官方的makefsdata工具生成数据文件fsdata_custom.c,在windows下运bat文件就好
无标题.jpg
工具及网页Html打包上传
上传的附件: WebsiteFiles.rar (169.71 KB, 下载次数: 0)



细心的朋友应该发现html文件不全,因为有的需要,写在了
const char Debug_parameters_http_index_hml[] =
                                            "<!DOCTYPE html>\n"
                                            "<html lang='zh-cmn-Hans'>\n"
                                            "<head>\n"
                                            "<meta charset='UTF-8'>\n"
                                            "<title>ESP 调试参数</title>\n"
                                            "<meta name='viewport' content='width=device-width, initial-scale=1'>\n"
                                            "<meta http-equiv='refresh' content='300'>\n"
                                            "<script src='jquery-3.4.1.min.js'></script>\n"
                                            "</head>\n"
                                            "<body onload='getstatus();'>\n";
数段里。
完整 的 http_server.c
/**
* @file http_server.c
* @brief
*
* Copyright (c) 2022 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.  The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/

#include "stdbool.h"
#include "lwip/api.h"
#include "lwip/arch.h"
#include "lwip/opt.h"
// #include "lwip/inet.h"
// #include "lwip/netif.h"
#include "lwip/tcpbase.h"
#include "lwip/tcp.h"
#include "lwip/apps/fs.h"
#include "lwip/apps/httpd.h"

#include "FreeRTOS.h"
#include "task.h"

#include "http_server_fs_open.h"
#include "app_inclued.h"

const HtmlServerRouter_TypeDef httpRouter[] = {
    //{ "/", "/index.html" },
    { "/", "/Debug_parameters.html","/upload_script.html"},
    { "/favicon.ico", "/asset/favicon.ico" },
    { "/js/main.js", "/js/main.js" },
    { "/css/style.css", "/css/style.css" },
    { "/css/asset/off.png", "/asset/off.png" },
    { "/asset/off.png", "/asset/off.png" },
    { "/css/asset/on.png", "/asset/on.png" },
    { "/asset/on.png", "/asset/on.png" },
    { "/asset/ok.json", "/asset/ok.json" },
    { "*", "/404.html" }

};

SemaphoreHandle_t console_lock = NULL;
sys_sem_t s_x_btn_semaphore = NULL;
char button_clicked_flag = false;

static struct netconn *http_active_conn = NULL;
static StackType_t http_server_stack[512];
static StaticTask_t http_server_handle;

void send_file(const char *path)
{
    struct fs_file file;
    err_t error = ERR_OK;

    OS_MSG("file path Date:%s.\r\n",path);

    error = fs_open(&file, path);

    if (error == ERR_OK) {
        netconn_write(http_active_conn, (const unsigned char *)(file.data), (size_t)file.len, NETCONN_NOCOPY);
        OS_MSG("file.Date:%s;file.len:%d;index Date:%d;\r\n",file.data,file.len,file.index);
    } else {
        OS_MSG("[ERROR] send file read failed, path: %s, error code: %d\r\n", path, error);
    }

    fs_close(&file);
}
/*
err_t try_send_file(const char *path)
{
    struct fs_file file;
    err_t error = ERR_OK;

    error = fs_open(&file, path);

    if (error == ERR_OK) {
        netconn_write(http_active_conn, (const unsigned char *)(file.data), (size_t)file.len, NETCONN_NOCOPY);
    } else {
        OS_MSG("[ERROR] try send file read failed, path: %s, error code: %d\r\n", path, error);
    }

    fs_close(&file);

    return error;
}
*/
void serch_send_file(const char *url)
{
    static uint16_t router_length = sizeof(httpRouter) / sizeof(HtmlRequestMethod_TypeDef);
    uint16_t i = 0;

    for (i = 0; i < router_length; i++) {
        if (!strcmp(url, httpRouter.url)) {
            send_file(httpRouter.path);
            if(httpRouter.second_path != NULL){
                send_file(httpRouter.second_path);
            }
            break;
        }
    }

    /* send 404 */
    if (i >= router_length) {
        OS_MSG("[WARNING] Not found path %s, sended 404 page.\r\n", url);
        send_file(httpRouter[router_length - 1].path);
    }
}

void http_post_btn_process(const char *url, const char *body)
{
    OS_MSG("post Date:%s.\r\n",body);
    if (strstr(body, "true") == NULL) {
        button_clicked_flag = false;
    } else {
        button_clicked_flag = true;
    }

    xSemaphoreGive(s_x_btn_semaphore);
}

void process_http_get(const char *url, const char *body)//
{
    serch_send_file(url);
}

void process_http_post(const char *url, const char *body)
{
    if (!strcmp(url, "/button_clicked")) {
        http_post_btn_process(url, body);
        serch_send_file("/asset/ok.json");
    }
}


#if 1
const char Debug_parameters_http_index_hml[] =
                                            "<!DOCTYPE html>\n"
                                            "<html lang='zh-cmn-Hans'>\n"
                                            "<head>\n"
                                            "<meta charset='UTF-8'>\n"
                                            "<title>ESP 调试参数</title>\n"
                                            "<meta name='viewport' content='width=device-width, initial-scale=1'>\n"
                                            "<meta http-equiv='refresh' content='300'>\n"
                                            "<script src='jquery-3.4.1.min.js'></script>\n"
                                            "</head>\n"
                                            "<body onload='getstatus();'>\n";

static void send_file_Debug_parameters_http_index_hml(const char *index_hml,size_t index_hml_size,const char *url)//sizeof(index_hml_size)
{
    netconn_write(http_active_conn, index_hml, index_hml_size, NETCONN_NOCOPY);
    serch_send_file(url);
    netconn_write(http_active_conn, "</body>\n</html>\n", sizeof("</body>\n</html>\n"), NETCONN_NOCOPY);
}
#endif

void process_http_request(const char *requset, uint16_t length)
{
    char *mem = NULL;
    char *str = NULL;
    char *body = NULL;
    char *url = NULL;

    mem = malloc(length);
    memset(mem, 0, length);

    str = mem;
    body = mem;

    memcpy(str, requset, sizeof(char) * length);

    OS_MSG("requset Date:%s.\r\n",requset);
   
    HtmlRequestMethod_TypeDef method = HTTP_UNKNOWN;

    /* get http request method */
    if (str != NULL) {
        str = strtok(str, " ");
        if (!strcmp(str, "GET")) {
            method = HTTP_GET;
            OS_MSG("[LOG] Methon: GET\r\n");
        } else if (!strcmp(str, "POST")) {
            method = HTTP_POST;
            OS_MSG("[LOG] Methon: POST\r\n");
        } else {
            method = HTTP_UNKNOWN;
            OS_MSG("[LOG] Methon: UNKNOWN\r\n");
        }
    }

    /* get url */
    if (str != NULL) {
        str = strtok(NULL, " ");
        if (str != NULL) {
            url = malloc(strlen(str) + 1);
            memset(url, 0, strlen(str) + 1);
            strcpy(url, str);
            OS_MSG("[LOG] URL: %s\r\n", url);
        }
    }

    memcpy(body, requset, sizeof(char) * length);

    OS_MSG("body Date:%s.\r\n",body);

    /* process http requset */
    switch (method) {
        case HTTP_GET:
            if(strcmp(url,"/")){
                send_file_Debug_parameters_http_index_hml(Debug_parameters_http_index_hml,sizeof(Debug_parameters_http_index_hml),url);
            }
            else{
            process_http_get(url, body);//
            }
            break;
        case HTTP_POST:
            process_http_post(url, body);
            break;
        default:
            break;
    }

    free(url);
    free(mem);
}

void http_server_process(struct netconn *conn)
{
    struct netbuf *inbuf;
    char *buf;
    uint16_t buflen;
    OS_MSG("http_server_process\r\n");
    if (netconn_recv(conn, &inbuf) == ERR_OK) {
        if (netconn_err(conn) == ERR_OK) {
            netbuf_data(inbuf, (void **)&buf, &buflen);
            process_http_request(buf, buflen);
        }
        netconn_close(conn);
        netbuf_delete(inbuf);
    }
}

void http_server_thread(void *arg)
{
    // httpd_init();
    struct netconn *conn, *newconn;

    xEventGroupWaitBits(APP_event_group,APP_event_WIFI_AP_CONNECTED_BIT | APP_event_WIFI_STA_CONNECTED_BIT,pdFALSE,pdFALSE,portMAX_DELAY);
    vTaskDelay(1000);

    vSemaphoreCreateBinary(console_lock);

    LWIP_UNUSED_ARG(arg);
   
    /* create a new tcp connection handle */
    conn = netconn_new(NETCONN_TCP);

    if (conn != NULL) {
        /* bind to port 80 HTTP whit default IP addr */
        if (netconn_bind(conn, IP4_ADDR_ANY, HTTP_SERVER_PORT) == ERR_OK) {
            
            /* start listening port */
            netconn_listen(conn);
            OS_MSG("http server listen :%d\r\n", HTTP_SERVER_PORT);

            while (1) {
                if (netconn_accept(conn, &newconn) == ERR_OK) {
                    if (newconn == NULL) {
                        OS_MSG("[ERROR]\r\n");
                    }
                    http_active_conn = newconn;
                    http_server_process(newconn);
                    http_active_conn = NULL;
                    netconn_delete(newconn);
                }
                else
                {
                    netconn_close(conn);
                    netconn_delete(conn);
                    break;
                }
                vTaskDelay(100);
            }
        }
    }
}
创建一个线程
void http_server_thread(void *arg)
{
// httpd_init();
struct netconn *conn, *newconn;

xEventGroupWaitBits(APP_event_group,APP_event_WIFI_AP_CONNECTED_BIT | APP_event_WIFI_STA_CONNECTED_BIT,pdFALSE,pdFALSE,portMAX_DELAY);//等待WIFI或有AP联上
vTaskDelay(1000);

vSemaphoreCreateBinary(console_lock);

LWIP_UNUSED_ARG(arg);

/* create a new tcp connection handle */
conn = netconn_new(NETCONN_TCP);

if (conn != NULL) {
/* bind to port 80 HTTP whit default IP addr */
if (netconn_bind(conn, IP4_ADDR_ANY, HTTP_SERVER_PORT) == ERR_OK) {

/* start listening port */
netconn_listen(conn);
OS_MSG("http server listen :%d\r\n", HTTP_SERVER_PORT);

while (1) {
if (netconn_accept(conn, &newconn) == ERR_OK) {
if (newconn == NULL) {
OS_MSG("[ERROR]\r\n");
}
http_active_conn = newconn;
http_server_process(newconn);
http_active_conn = NULL;
netconn_delete(newconn);
}
else
{
netconn_close(conn);
netconn_delete(conn);
break;
}
vTaskDelay(100);
}
}
}
}


绑定端口80和    listening port
if (conn != NULL) {
        /* bind to port 80 HTTP whit default IP addr */
        if (netconn_bind(conn, IP4_ADDR_ANY, HTTP_SERVER_PORT) == ERR_OK) {
            
            /* start listening port */
            netconn_listen(conn);
            OS_MSG("http server listen :%d\r\n", HTTP_SERVER_PORT);

处理http_server_process(newconn);收的数据并响应

void http_server_process(struct netconn *conn)
{
    struct netbuf *inbuf;
    char *buf;
    uint16_t buflen;
    OS_MSG("http_server_process\r\n");
    if (netconn_recv(conn, &inbuf) == ERR_OK) {
        if (netconn_err(conn) == ERR_OK) {
            netbuf_data(inbuf, (void **)&buf, &buflen);
            process_http_request(buf, buflen);
        }
        netconn_close(conn);
        netbuf_delete(inbuf);
    }
}


判断是get模式还是POst模式

void process_http_request(const char *requset, uint16_t length)
{
    char *mem = NULL;
    char *str = NULL;
    char *body = NULL;
    char *url = NULL;

    mem = malloc(length);
    memset(mem, 0, length);

    str = mem;
    body = mem;

    memcpy(str, requset, sizeof(char) * length);

    OS_MSG("requset Date:%s.\r\n",requset);
   
    HtmlRequestMethod_TypeDef method = HTTP_UNKNOWN;

    /* get http request method */
    if (str != NULL) {
        str = strtok(str, " ");
        if (!strcmp(str, "GET")) {
            method = HTTP_GET;
            OS_MSG("[LOG] Methon: GET\r\n");
        } else if (!strcmp(str, "POST")) {
            method = HTTP_POST;
            OS_MSG("[LOG] Methon: POST\r\n");
        } else {
            method = HTTP_UNKNOWN;
            OS_MSG("[LOG] Methon: UNKNOWN\r\n");
        }
    }

    /* get url */
    if (str != NULL) {
        str = strtok(NULL, " ");
        if (str != NULL) {
            url = malloc(strlen(str) + 1);
            memset(url, 0, strlen(str) + 1);
            strcpy(url, str);
            OS_MSG("[LOG] URL: %s\r\n", url);
        }
    }

    memcpy(body, requset, sizeof(char) * length);

    OS_MSG("body Date:%s.\r\n",body);

    /* process http requset */
    switch (method) {
        case HTTP_GET:
            if(strcmp(url,"/")){
                send_file_Debug_parameters_http_index_hml(Debug_parameters_http_index_hml,sizeof(Debug_parameters_http_index_hml),url);
            }
            else{
            process_http_get(url, body);//
            }
            break;
        case HTTP_POST:
            process_http_post(url, body);
            break;
        default:
            break;
    }

    free(url);
    free(mem);
}

向客户端响应HTML数据

const char Debug_parameters_http_index_hml[] =
                                            "<!DOCTYPE html>\n"
                                            "<html lang='zh-cmn-Hans'>\n"
                                            "<head>\n"
                                            "<meta charset='UTF-8'>\n"
                                            "<title>ESP 调试参数</title>\n"
                                            "<meta name='viewport' content='width=device-width, initial-scale=1'>\n"
                                            "<meta http-equiv='refresh' content='300'>\n"
                                            "<script src='jquery-3.4.1.min.js'></script>\n"
                                            "</head>\n"
                                            "<body onload='getstatus();'>\n";



static void send_file_Debug_parameters_http_index_hml(const char *index_hml,size_t index_hml_size,const char *url)//sizeof(index_hml_size)
{
    netconn_write(http_active_conn, index_hml, index_hml_size, NETCONN_NOCOPY);
    serch_send_file(url);
    netconn_write(http_active_conn, "</body>\n</html>\n", sizeof("</body>\n</html>\n"), NETCONN_NOCOPY);
}
#endif

发送makefsdata生成的数据文件serch_send_file(url);


void send_file(const char *path)
{
    struct fs_file file;
    err_t error = ERR_OK;

    OS_MSG("file path Date:%s.\r\n",path);

    error = fs_open(&file, path);

    if (error == ERR_OK) {
        netconn_write(http_active_conn, (const unsigned char *)(file.data), (size_t)file.len, NETCONN_NOCOPY);
        OS_MSG("file.Date:%s;file.len:%d;index Date:%d;\r\n",file.data,file.len,file.index);
    } else {
        OS_MSG("[ERROR] send file read failed, path: %s, error code: %d\r\n", path, error);
    }

    fs_close(&file);
}
void serch_send_file(const char *url)
{
    static uint16_t router_length = sizeof(httpRouter) / sizeof(HtmlRequestMethod_TypeDef);
    uint16_t i = 0;

    for (i = 0; i < router_length; i++) {
        if (!strcmp(url, httpRouter.url)) {
            send_file(httpRouter.path);
            if(httpRouter.second_path != NULL){
                send_file(httpRouter.second_path);
            }
            break;
        }
    }

    /* send 404 */
    if (i >= router_length) {
        OS_MSG("[WARNING] Not found path %s, sended 404 page.\r\n", url);
        send_file(httpRouter[router_length - 1].path);
    }
}

.整 个流程结整。
例程项目
上传的附件: 新建文件夹.rar (528.67 KB, 下载次数: 0)

──── 0人觉得很赞 ────

使用道具 举报

您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28078 个
  • 话题数: 39675 篇