先编写html网页,由于不会美工,都没用CCS。
<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>
<!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文件就好
工具及网页Html打包上传
细心的朋友应该发现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);
}
}
.整 个流程结整。
例程项目
|