ESP8266 ArduinoIDE 搭建web服务器与客户端开发
一、wifi 相关配置
1.1 无线终端 wifi 模式
此模式中,esp8266 会连接到指定 wifi 进行工作。
#include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi库
const char* ssid = "home"; // 连接WiFi名(此处使用home为示例)
const char* password = "12345678"; // 连接WiFi密码(此处使用12345678为示例)
void setup() {
Serial.begin(9600); // 启动串口通讯
WiFi.begin(ssid, password); // 启动网络连接
Serial.print("Connecting to "); // 串口监视器输出网络连接信息
Serial.print(ssid); Serial.println(" ..."); // 告知用户NodeMCU正在尝试WiFi连接
int i = 0; // 这一段程序语句用于检查WiFi是否连接成功
while (WiFi.status() != WL_CONNECTED) { // WiFi.status()函数的返回值是由NodeMCU的WiFi连接状态所决定的。
delay(1000); // 如果WiFi连接成功则返回值为WL_CONNECTED
Serial.print(i++); Serial.print(' '); // 此处通过While循环让NodeMCU每隔一秒钟检查一次WiFi.status()函数返回值
} // 同时NodeMCU将通过串口监视器输出连接时长读秒。
// 这个读秒是通过变量i每隔一秒自加1来实现的。
Serial.println(""); // WiFi连接成功后
Serial.println("Connection established!"); // NodeMCU将通过串口监视器输出"连接成功"信息。
Serial.print("IP address: "); // 同时还将输出NodeMCU的IP地址。这一功能是通过调用
Serial.println(WiFi.localIP()); // WiFi.localIP()函数来实现的。该函数的返回值即NodeMCU的IP地址。
}
void loop() {
}
wifi 连接成功,esp8266 通过串口返回当前局域网 IP
1.2 接入点模式(热点模式 AP)
此模式中,esp8266 会开启一个指定名称和密码的热点进行工作。
#include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi库
const char *ssid = "taichi-maker"; // 这里定义将要建立的WiFi名称。此处以"taichi-maker"为示例
const char *password = "12345678"; // 这里定义将要建立的WiFi密码。此处以12345678为示例
void setup() {
Serial.begin(9600); // 启动串口通讯
WiFi.softAP(ssid, password); // 此语句是重点。WiFi.softAP用于启动NodeMCU的AP模式。
Serial.print("Access Point: "); // 通过串口监视器输出信息
Serial.println(ssid); // 告知用户NodeMCU所建立的WiFi名
Serial.print("IP address: "); // 以及NodeMCU的IP地址
Serial.println(WiFi.softAPIP()); // 通过调用WiFi.softAPIP()可以得到NodeMCU的IP地址
}
void loop() {
}
二、搭建HTTP网络服务器
2.1 hello world 程序
#include <ESP8266WiFi.h> // 本程序使用 ESP8266WiFi库
#include <ESP8266WebServer.h> // ESP8266WebServer库
ESP8266WebServer esp8266_server(80); // 建立ESP8266WebServer对象,对象名称为esp8266_server
const char* ssid = "home"; // 连接WiFi名(此处使用home为示例)
const char* password = "123456"; // 连接WiFi密码(此处使用12345678为示例)
void setup(void){
Serial.begin(9600); // 启动串口通讯
WiFi.begin(ssid, password); // 启动网络连接
int i = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(i++); Serial.print(' ');
}
// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println('\n'); // WiFi连接成功后
Serial.print("Connected to "); // NodeMCU将通过串口监视器输出。
Serial.println(WiFi.SSID()); // 连接的WiFI名称
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址
esp8266_server.begin(); // 开启web服务器
esp8266_server.on("/", handleRoot); // 访问根路由即调用 handlerRoot 函数处理
esp8266_server.onNotFound(handleNotFound);
Serial.println("HTTP esp8266_server started"); // 告知用户ESP8266网络服务功能已经启动
}
void loop(void){
esp8266_server.handleClient(); // 处理http服务器访问
}
void handleRoot() { //处理网站根目录“/”的访问请求
esp8266_server.send(200, "text/plain", "Hello from ESP8266"); // 状态码 头报文 正文
}
// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){ // 当浏览器请求的网络资源无法在服务器找到时,
esp8266_server.send(404, "text/plain", "404: Not found"); // NodeMCU将调用此函数。
}
2.2 web LED 点灯案例
#include <ESP8266WiFi.h> // 本程序使用 ESP8266WiFi库
#include <ESP8266WebServer.h> // ESP8266WebServer库
ESP8266WebServer esp8266_server(80); // 建立ESP8266WebServer对象,对象名称为esp8266_server
const char* ssid = "home"; // 连接WiFi名(此处使用home为示例)
const char* password = "123456"; // 连接WiFi密码(此处使用12345678为示例)
void setup(void){
Serial.begin(9600); // 启动串口通讯
pinMode(LED_BUILTIN, OUTPUT); //设置内置LED引脚为输出模式以便控制LED
digitalWrite(LED_BUILTIN,1);// 改变LED的点亮或者熄灭状态
WiFi.begin(ssid, password); // 启动网络连接
int i = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(i++); Serial.print(' ');
}
// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println('\n'); // WiFi连接成功后
Serial.print("Connected to "); // NodeMCU将通过串口监视器输出。
Serial.println(WiFi.SSID()); // 连接的WiFI名称
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址
esp8266_server.begin(); // 开启web服务器
esp8266_server.on("/", handleRoot); // 访问根路由即调用 handlerRoot 函数处理
esp8266_server.on("/LED", HTTP_POST, handleLED); // 设置处理LED控制请求的函数'handleLED'
esp8266_server.onNotFound(handleNotFound);
Serial.println("HTTP esp8266_server started"); // 告知用户ESP8266网络服务功能已经启动
}
void loop(void){
esp8266_server.handleClient(); // 处理http服务器访问
}
void handleLED(){
digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
esp8266_server.sendHeader("Location","/");
esp8266_server.send(303);
}
void handleRoot() { //处理网站根目录“/”的访问请求
esp8266_server.send(200, "text/html", "<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"Toggle LED\"></form>");
}
// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){ // 当浏览器请求的网络资源无法在服务器找到时,
esp8266_server.send(404, "text/plain", "404: Not found"); // NodeMCU将调用此函数。
}
在这里改写了根目录,他会向客户端发送一个按钮的页面,点击即向 "/LED" 路由下发送 POST 请求。
void handleRoot() { //处理网站根目录“/”的访问请求
esp8266_server.send(200, "text/html", "<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"Toggle LED\"></form>");
}
由于我们之前绑定了这个相应,即会触发:
void handleLED(){
digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
esp8266_server.sendHeader("Location","/");
esp8266_server.send(303);
}
他在给 LED 取反后又重定向到根目录,即可实现我们的效果。
三、ESP8266WebServer 库
在之前我们基本使用了 ESP8266WebServer 库的功能,下面我们来配合案例详细了解这个库的 API。
3.1 创建并启动 Web Server
#include <ESP8266WebServer.h> // ESP8266WebServer库
ESP8266WebServer esp8266_server(80); // 建立ESP8266WebServer对象,对象名称为esp8266_server
此时实例化了一个名为 esp8266_server 的webServer 的对象。当实例化完成后即自动启动这个服务。当然,此时我们的 8266 需要已经配置好 wifi 才能被外部访问。
3.2 配置路由处理
esp8266_server.on("/LED", handleLED); // 无论GET 或POST请求都会触发
esp8266_server.on("/LED", HTTP_POST, handleLED); // 无论GET 或POST请求都会触发
void onNotFound(THandlerFunction fn); //配置无效的路由 用于404
void onFileUpload(THandlerFunction fn); //配置处理文件上传的handler
3.3 获取请求类型与参数案例
先用一个案例来演示:
#include <ESP8266WiFi.h> // 本程序使用 ESP8266WiFi库
#include <ESP8266WebServer.h> // ESP8266WebServer库
ESP8266WebServer esp8266_server(80); // 建立ESP8266WebServer对象,对象名称为esp8266_server
const char* ssid = "home"; // 连接WiFi名(此处使用home为示例)
const char* password = "123456"; // 连接WiFi密码(此处使用12345678为示例)
void setup(void){
Serial.begin(9600); // 启动串口通讯
pinMode(LED_BUILTIN, OUTPUT); //设置内置LED引脚为输出模式以便控制LED
digitalWrite(LED_BUILTIN,1);// 改变LED的点亮或者熄灭状态
WiFi.begin(ssid, password); // 启动网络连接
int i = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(i++); Serial.print(' ');
}
// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println('\n'); // WiFi连接成功后
Serial.print("Connected to "); // NodeMCU将通过串口监视器输出。
Serial.println(WiFi.SSID()); // 连接的WiFI名称
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址
esp8266_server.begin(); // 开启web服务器
esp8266_server.onNotFound(handleNotFound);
Serial.println("HTTP esp8266_server started"); // 告知用户ESP8266网络服务功能已经启动
Serial.println("---------------------------------------");
}
void loop(void){
esp8266_server.handleClient(); // 处理http服务器访问
}
// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){
Serial.print("url:");
Serial.println(esp8266_server.uri());
Serial.print("method:");
Serial.println(esp8266_server.method());
Serial.print("arg count:");
Serial.println(esp8266_server.args());
Serial.print("request host:");
Serial.println(esp8266_server.hostHeader());
Serial.print("auth:");
Serial.println(esp8266_server.authenticate("123", "456"));
Serial.println("---------------------------------------");
esp8266_server.send(404, "text/plain", "404: Not found"); // NodeMCU将调用此函数。
}
使用 postman 工具发送消息
192.168.0.105/123、POST 请求、无参数、填入 authorization 账号:123 密码:456
串口即收到信息。对于这个库来说,POST 请求枚举类型是 3,所以返回了method:3,auth 也验证通过。
如果用浏览器访问 192.168.0.105 也会给出相应的返回值。
3.4 获取请求类型方法和参数合集
以下函数均是 ESP8266WebServer 的实例方法
ESP8266WebServer esp8266_server(80);
esp8266_server.url(); //这样调用即可
String url(); //获取请求的url
HTTPMethod method(); //获取请求方法
String arg(String name); //获取请求参数的值 name:根据关键字name获取请求参数的值
String arg(int i); //i:获取第i个请求参数的值
int args(); //获取参数个数
bool hasArg(String name); //是否存在某个参数
//设置需要收集的请求头 headerkeys[]:请求头的名字 headerkeysCount:请求头的个数
void collectHeaders(const char* headerKeys[], const size_t headerKeysCount);
String header(String name); //获取请求头参数 name:请求头名称
String header(int i); //i:获取第i个请求头参数
String headerName(int i); //获取请求头名字 i:获取第i个请求头名字
int headers(); //获取请求头个数
bool hasHeader(String name); //判断是否存在某个请求头
String hostHeader(); //获取请求头Host的值
bool authenticate(const char * username, const char * password); //认证校验
四、响应客户端请求
4.1 响应案例
在 2.2 的点灯案例中,我们编写了 handleLED 函数。在这里我们使用了 sendHeader 和 send 两个客户端响应类函数。
其功能是设置响应头,并且设置为 303 状态码提示浏览器进行刷新。
void handleLED(){
digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
esp8266_server.sendHeader("Location","/");
esp8266_server.send(303);
}
4.2 响应客户端方法和参数合集
以下函数均是 ESP8266WebServer 的实例方法
ESP8266WebServer esp8266_server(80);
esp8266_server.esp8266_server.send(200); //这样调用即可
//设置响应头
//name: 响应头名
//value: 响应头值
//first: 是否需要放在第一行
void sendHeader(const String& name, const String& value, bool first = false);
//设置响应体长度
void setContentLength(const size_t contentLength);
//发送响应内容
void sendContent(const String& content);
//发送响应数据
void send(int code, const char* content_type = NULL, const String& content = String(""));
void send(int code, char* content_type, const String& content);
void send(int code, const String& content_type, const String& content);