ESP8266 Arduino开发 搭建web服务器与客户端开发

news2024/11/17 21:49:29

一、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); //这样调用即可
void sendHeader(const String& name, const String& value, bool first = false);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/164038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

位运算相关

1.与运算 &#xff08;点我&#xff09; 这个题的大概意思&#xff1a;给222个数nnn和xxx&#xff0c;其中满足n&(n1)&(n2)&(n3)...&mxn\&(n1)\&(n2)\&(n3)...\&mxn&(n1)&(n2)&(n3)...&mx,求最小的mmm&#xff0c;只要满足m&g…

【异常】java11提示: Cannot find any provider supporting RSA/ECB/PKCS1Padding的问题

一、背景 项目中需要对敏感字段进行加密&#xff0c;但是加密方法中涉及到比较复杂的加密算法&#xff0c;这些算法都需要一个Provider&#xff0c;主要是用于初始化算法的。 以下是遇到的具体问题 二、报错截图 java.security.NoSuchAlgorithmException: Cannot find any pr…

【软件测试】软件测试模型

1. V模型 需求分析—计划—设计—编码—测试 ● 概要设计&#xff1a;设计整体架构&#xff0c;框架 ● 详细设计&#xff1a;模块和模块之间的详细设计 ● 集成测试&#xff0c;单元测试&#xff1a;通常由开发人员进行 特点&#xff1a; 明确标注了测试的多类型明确标注了测…

Introduction to Multi-Armed Bandits——01 Scope and Motivation

Introduction to Multi-Armed Bandits——01 Scope and Motivation 参考资料 Slivkins A. Introduction to multi-armed bandits[J]. Foundations and Trends in Machine Learning, 2019, 12(1-2): 1-286.项目地址 https://github.com/yijunquan-afk/bandit-learning Bandit…

LeetCode622.设计循环队列

设计循环队列1.题目描述2.思路3.代码实现以及分析3.1 创建结构体3.2创建一个具体的循环队列3.3判断是否为空 和 判断是否为满4. 进队列 和 出队列5.取队首和队尾元素6.释放空间7.总结1.题目描述 设计循环队列 2.思路 环形队列的抽象图 我们这里使用数组模拟实现循环队列&…

TransactionTemplate自动注入,只看这一篇文章就够了

标准的springboot接入mybatis步骤 1.引入了对应的依赖包 2.应用的properties下增加相应配置 3.根据配置进行自动装配 一般我们会配置这些信息&#xff0c;主要包括三类 1.数据库的连接信息 2.指定的数据源类型 3.mybatis的配置信息 配完以后&#xff0c;当你启动SpringBoot的主…

你是真的“C”——详解C语言数组模块知识

详解C语言数组模块知识&#x1f60e;前言&#x1f64c;一维数组的创建和初始化&#x1f64c;1.1 数组的创建&#x1f49e;1.2 数组的初始化&#x1f49e;1.3 一维数组的使用&#x1f49e;1.4 一维数组在内存中的存储&#x1f49e;二维数组的创建和初始化&#x1f64c;1.1 二维数…

【Python百日进阶-数据分析】Day225 - plotly的Ohlc图go.Ohlc()

文章目录一、语法二、参数三、返回值四、实例4.1 简单的OHLC图4.2 隐藏滑块的OHLC图4.3 添加自定义文本和注释4.4 自定义OHLC颜色4.5 带日期时间对象的简单的OHLC图4.6 自定义悬浮文本4.7 Dash中的应用一、语法 ohlc&#xff08;Open-High-Low-Close 的缩写&#xff09;是一种…

【C++逆向】虚表(Virtual table)逆向 | 安卓so虚函数逆向

什么是多态 定义一个虚基类ISpeaker class ISpeaker{ protected:size_t b; public:ISpeaker( size_t _v ): b(_v) {}virtual void speak() 0; };有两个子类&#xff0c;都实现了虚函数speak()&#xff1a; class Dog : public ISpeaker { public:Dog(): ISpeaker(0){}//vir…

1581_AURIX_TC275_SMU故障处理梳理

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 前面为了缓解自己的学习压力&#xff0c;一次学习笔记大概也就是看10页文档整理一下。这一次其实是看了几十页&#xff0c;但是里面过掉了一些信息&#xff0c;而且这部分内容不是很好拆分…

hive在IDEA中debug

一、hive在IDEA中debug 安装hadoop环境&#xff08;1和2替换顺序也可以&#xff09; 注&#xff1a;hadoop环境不需要从源码编译 https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/SingleCluster.html 按照官网教程编译源码 https://cwiki.apach…

软件工程专业课实验报告

一、结构化分析方法1.1需求描述教务管理子系统的需求描述&#xff1a;教务管理是一项需求周密计划、严谨安排的工作&#xff0c;要依据教师、学生信息进行合理安排。开学阶段&#xff0c;需要教师提交开课申请进行开课&#xff0c;学生根据老师的开课信息&#xff0c;选择课程&…

uview 使用遇到的问题。

uviewuniappvue&#xff0c;uView是uni-app生态专用的UI框架。 1. 注意uview版本&#xff0c;uview 2.0与uview1.0 官方提示&#xff1a;uView2.0是继1.0以来的一次重大更新&#xff0c;2.0已全面兼容nvue。 因此在接手项目的时候首先得看清楚&#xff0c;之前开发的是uview…

【自学Python】Python获取字符串长度

Python获取字符串长度 Python获取字符串长度教程 在 Python 中要想获取 字符串 长度可以使用 len() 函数。 Python len()函数详解 定义 我们将要获取的字符串的长度&#xff0c;传进 len() 函数&#xff0c;即可实现获取字符串的长度。 语法 len(string)参数 参数描述s…

【7】K8s_Ingress | Service的统一网关入口

目录 1、Ingress简介 2、安装ingress 【1】制作ingress.yaml文件并执行 【2】测试&#xff0c;创建一个test.yaml文件并执行 【3】设置域名访问&#xff0c;用yaml文件 【4】路径重写 【5】流量限制 1、Ingress简介 Ingress: Service的统一网关入口是k8s中的一个api对象&…

时序数据库TDengine基本概念和建模思路

目录 一 、 时序数据库基本概念 采集量 标签 数据采集点 表 超级表 子表 库 二、 TDengine数据库建模策略 建表模式建表情形 行列数据库存储的区别&#xff1a; 接触的传统业务的数据模式都是行存储&#xff0c;我们会把不同类型的对象创建不同的表进行存储他们各自的属…

机器学习公式推导与代码实现-无监督学习模型

聚类分析与k均值聚类算法 督学习算法。在给定样本的情况下,聚类分析通过度量特征相似度或者距离,将样本自动划分为若干类别。 距离度量和相似度度量方式 距离度量和相似度度量是聚类分析的核心概念,大多数聚类算法建立在距离度量之上。常用的距离度量方式包括闵氏距离和马…

linux系统中使用QT来实现数据库的调用方法

大家好&#xff0c;今天主要和大家分享一下&#xff0c;如何使用QT中数据库的使用方法。 目录 第一&#xff1a;数据库基本简介 第二&#xff1a;数据库表格基本操作 第三&#xff1a;数据库最终效果 第一&#xff1a;数据库基本简介 数据库是按照数据结构来组织&#xff0c;…

视频目标检测与轨迹跟踪代码案例

前言通过阅读相关文献及测试&#xff0c;找到了一种基于多模板匹配的改进方法&#xff0c;可以对遥感视频卫星中的移动目标进行探测&#xff0c;并绘制其轨迹。根据实验结果发现&#xff0c;可以比较有效的对运动目标进行跟踪。一、原理核心思想比较简单。即通过不同旋转角度的…

AQS之ReentrantLock详解

非公平锁加锁过程一般我们在使用ReentrantLock的时候&#xff0c;代码如下&#xff1a;Test public void test(){ReentrantLock lock new ReentrantLock();lock.lock();try{//编写业务逻辑}catch (Exception e){lock.unlock();} }当我们在用ReentrantLock独占锁的时候&#xf…