赞
踩
https://github.com/me-no-dev/ESPAsyncWebServer 里面有参考实例和源文件
该库还支持WebSocket、EventSource
头文件:
- #include <Arduino.h>
- #ifdef ESP32
- #include <WiFi.h>
- #include <AsyncTCP.h>
- #elif defined(ESP8266)
- #include <ESP8266WiFi.h>
- #include <ESPAsyncTCP.h>
- #endif
- #include <ESPAsyncWebSrv.h>
- #include <ESPAsyncWebServer.h> //引入相应库
-
- AsyncWebServer server(80); //声明WebServer对象
-
- void handleRoot(AsyncWebServerRequest *request) //回调函数
- {
- Serial.println("User requested.");
- request->send(200, "html", "<div>Hello World!</div>"); //向客户端发送响应和内容
- }
-
- void setup()
- {
- server.on("/", HTTP_GET, handleRoot); //注册链接"/"与对应回调函数
- server.on("/change", HTTP_GET, [] (AsyncWebServerRequest *request) {
- String name;
- if (request->hasParam("name")) {
- name = request->getParam("name")->value();
- val = atof(String(request->getParam("val")->value()).c_str());
- if(name == "Z"){
- Z = val;
- int pwmVal = map((int)val,0,100,1023,0); // 用户请求数值为0-100,转为0-1023
- ledcWrite(0, pwmVal);//指定通道输出一定占空比波形
- }else if(name == "A"){
- A = val;
- }else if(name == "B"){
- B = val;
- }
- } else {
- name = "No message sent";
- }
- request->send(200, "text/plain", "Hello, GET: " + name);
- });
- server.begin(); //启动服务器
- }
-
- void loop(){}
ESPAsyncWebServer中对于请求的调取实在回调函数中进行的,回调函数传入一个 AsyncWebServerRequest
对象
- request->version(); // uint8_t: 0 = HTTP/1.0, 1 = HTTP/1.1
- request->method(); // enum: HTTP_GET, HTTP_POST, HTTP_DELETE, HTTP_PUT, HTTP_PATCH, HTTP_HEAD, HTTP_OPTIONS
- // HTTP_GET = 0b00000001, HTTP_POST = 0b00000010, HTTP_DELETE = 0b00000100, HTTP_PU = 0b00001000, HTTP_PATCH = 0b00010000, HTTP_HEAD = 0b00100000, HTTP_OPTIONS = 0b01000000, HTTP_ANY = 0b01111111
- request->url(); // String: URL of the request (not including host, port or GET parameters)
- request->host(); // String: The requested host (can be used for virtual hosting)
- request->contentType(); // String: ContentType of the request (not avaiable in Handler::canHandle)
- request->contentLength(); // size_t: ContentLength of the request (not avaiable in Handler::canHandle)
- request->multipart(); // bool: True if the request has content type "multipart"
- request->headers(); // int 返回头参数长度
- request->params(); // int 返回get post 参数长度
- int headers = request->headers();
- // 遍历请求头
- int i;
- for(i=0;i<headers;i++){
- AsyncWebHeader* h = request->getHeader(i);
- Serial.printf("HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
- // 下面行功能同上面两行
- //Serial.printf("HEADER[%s]: %s\n", request->headerName(i).c_str(), request->header(i).c_str());
- }
- /******************************************************************************/
- // 指定参数名称
- if(request->hasHeader("MyHeader")){ // 获取请求头参数
- AsyncWebHeader* h = request->getHeader("MyHeader");
- Serial.printf("MyHeader: %s\n", h->value().c_str());
- // 下面行功能同上面两行
- // Serial.printf("MyHeader: %s\n", request->header("MyHeader").c_str());
- }
-
(post请求时,用getParam('name')指定参数名,得不到post参数,需要用下面的方法遍历,用不知道为什么。有明白的麻烦留个言,谢谢!)
- int params = request->params();
- for(int i=0;i<params;i++){
- AsyncWebParameter* p = request->getParam(i);
- if(p->isFile()){ //p->isPost() is also true
- Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
- } else if(p->isPost()){
- Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
- } else { //GET
- Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
- }
- }
- // 下面语句功能同上面
- //int args = request->args();
- //for(int i=0;i<args;i++){
- // Serial.printf("ARG[%s]: %s\n", request->argName(i).c_str(), request->arg(i).c_str());
- //}
- /*********************************************************************************/
- // 指定参数
- if(request->hasParam("download")) //Check if GET parameter exists
- AsyncWebParameter* p = request->getParam("download");
-
- if(request->hasParam("download", true)) //Check if POST (but not File) parameter exists
- AsyncWebParameter* p = request->getParam("download", true);
-
- if(request->hasParam("download", true, true)) //Check if FILE was uploaded
- AsyncWebParameter* p = request->getParam("download", true, true);
-
- // 下面语句功能同上面
- //if(request->hasArg("download"))
- // String arg = request->arg("download");
- request->send(200, "text/plain", "Hello World!");
- // 发送 PROGMEM 字符串
- const char index_html[] PROGMEM = "..."; // large char array, tested with 14k
- request->send_P(200, "text/html", index_html);
- #include <ESPAsyncWebServer.h> //引入相应库
-
- AsyncWebServer server(80); //声明WebServer对象
- AsyncWebSocket ws("/"); // WebSocket对象,url为/
-
- void handleRoot(AsyncWebServerRequest *request) //回调函数
- {
- Serial.println("User requested.");
- request->send(200, "html", "<p>Hello World!</p>"); //向客户端发送响应和内容
- }
- // WebSocket事件回调函数
- void onEventHandle(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
- {
- if (type == WS_EVT_CONNECT) // 有客户端建立连接
- {
- Serial.printf("ws[%s][%u] connect\n", server->url(), client->id());
- client->printf("Hello Client %u !", client->id()); // 向客户端发送数据
- client->ping(); // 向客户端发送ping
- }
- else if (type == WS_EVT_DISCONNECT) // 有客户端断开连接
- {
- Serial.printf("ws[%s][%u] disconnect: %u\n", server->url(), client->id());
- }
- else if (type == WS_EVT_ERROR) // 发生错误
- {
- Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t *)arg), (char *)data);
- }
- else if (type == WS_EVT_PONG) // 收到客户端对服务器发出的ping进行应答(pong消息)
- {
- Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len) ? (char *)data : "");
- }
- else if (type == WS_EVT_DATA) // 收到来自客户端的数据
- {
- AwsFrameInfo *info = (AwsFrameInfo *)arg;
- Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT) ? "text" : "binary", info->index, info->index + len);
- data[len] = 0;
- Serial.printf("%s\n", (char *)data);
- }
- }
-
- void setup()
- {
- ws.onEvent(onEventHandle); // 绑定回调函数
- server.addHandler(&ws); // 将WebSocket添加到服务器中
- server.on("/", HTTP_GET, handleRoot); //注册链接"/"与对应回调函数
- server.on("/led", HTTP_GET, [](AsyncWebServerRequest *request) { //注册链接"/led"与对应回调函数(匿名函数形式声明)
- request->send(200, "text/plain", "hello"); //向客户端发送响应和内容
- });
- server.begin(); //启动服务器
- delay(1000);
- ws.textAll("{\"r\":" + String(str_r) + ",\"T\":" + String(str_T) + "}"); // 向所有建立连接的客户端发送数据
- }
-
- void loop(){
- ws.cleanupClients(); // 关闭过多的WebSocket连接以节省资源
- }
void text(const char * message, size_t len);
void text(const char * message);
void text(uint8_t * message, size_t len);
void text(char * message);
void text(const String &message);
void text(const __FlashStringHelper *data);
void text(AsyncWebSocketMessageBuffer *buffer);
void text(uint32_t id, const char * message, size_t len);
一般发送json数据:
- char destBuf[80] = { 0 }; // 初始化为 0 字符
- sprintf(destBuf, "{\"time\": \"20%02d-%02d-%02d 星期%d %02d:%02d:%02d\",\"wifi_st\":%d,\"ssid\":\"%s\",\"counter\":%d}",userData.Y,userData.M,userData.D,userData.w,userData.h ,userData.m,userData.s,WiFi.status(),WiFi.SSID(),pulseCount); // .1f 表示仅输出小数点后 1 位
- ws.textAll(destBuf);
附 html js部分:
- <html lang='en'>
- <head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'><title>控制台</title></head>
- <body>
- <form action='/change' method='POST'>
- <div><label>当前转速(r) </label><input id='r' class="v" type="text" name="r" value="47" readonly> r/s <label> | LED周期(T) </label><input class="v" type="text" name="T" id='T' value="20.5" readonly> ms</div>
- <br>
- <!-- <div><label>调节电机转速: </label><button style= "width: 30px;" id='down' type = 'button' onclick="d()">-</button><button style= "width: 30px;" id='' type = 'button' onclick="u()">+</button></div> -->
- <div><label>调节电机转速: </label>
- <input style="width:60%;" name = "Z" type="range" min="0" max="100" value="100" oninput="rangeValue.innerText = this.value" onchange="s('Z',this.value)"><span id="rangeValue"></span>
- </div>
- <div><label>LED固定转角(A) </label><input class="v" type="text" name="A" value="15" onblur="s('A',this.value)">度</div>
- <div><label>LED超前角度(B) </label><input class="v" type="text" name="B" value="2" onblur="s('B',this.value)">度</div>
- <br>
- <label>备注: T= (1+ 1/r x (B/360)) / (rx(360/A)) :一个分解动作的时间 除以 分度</label>
- <br><br>
- </form>
- <div onclick="sd()">点击向服务器发送数据</div><div id="info"></div>
- </body>
- <script>
- var ws;
- var json;
- window.onload = function () {
- if ("WebSocket" in window) {
- ws = new WebSocket("ws://" + window.location.host + "/");
- ws.onopen = function () {
- document.getElementById("info").innerHTML += "WebSocket连接成功!" + "<br>";
- ws.send("connect ok!");
- };
- ws.onmessage = function (evt) {
- console.log(evt.data);
- try{
- json = JSON.parse(evt.data);
- console.log("is JSON");
- if(typeof(json.time) != "undefined"){
- document.getElementById('time').innerHTML = json.time;
- }
- if(typeof(json.alert) != "undefined"){
- alert(json.alert);
- }
- }catch{
- document.getElementById("info").innerHTML += evt.data + "<br>";
- }
-
-
- };
- ws.onerror = function () {
- document.getElementById("info").innerHTML += "通讯发送错误!" + "<br>";
- };
- ws.onclose = function () {
- document.getElementById("info").innerHTML += "WebSocketTest连接已关闭!" + "<br>";
- };
- } else {
- document.getElementById("info").innerHTML = "浏览器不支持 WebSocket!";
- }
- };
- function sd() {
- console.log('send "hahaha~~~"');
- ws.send("hahaha~~~");
- }
- var val;
- var vname;
- function s(vname,val){
- console.log(vname,val);
- var xhr=new XMLHttpRequest();
- xhr.open("GET","/change?name=" + vname + "&val=" + val,true);
- xhr.send();
- xhr.onreadystatechange=function(){
- if(xhr.readyState==4 && xhr.status==200){
- console.log(xhr.response);
- }
- }
- }
- </script>
- </html>
笔记引用自:
《Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:快速入门》
《Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:请求与响应》
《Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:WebSocket和EventSource》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。