开启辅助访问 天气与日历

登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 961|回复: 0

连接wifi自动打开网页

[复制链接]

70

主题

73

帖子

775

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
775

活跃会员热心会员推广达人宣传达人灌水之王突出贡献优秀版主荣誉管理论坛元老

发表于 2021-10-6 21:10:04 | 显示全部楼层 |阅读模式 来自 中国陕西西安
前言
1.Web配网概述

在应用到esp8266的场景,往往与wifi是离不开的,但用户的wifi账号密码又无从知晓,于是乎有了配网。
目前,市面上的配网方式多种多样,但其中博主觉得成功率最高,最方便的方式其实还是Web配网(个人看法),因为Web配网从根本来说就是esp8266开启一个web服务器,在此基础上进行信息交互(POST,GET),所以信息的传输较为稳定,配网成功率高。


2.强制门户概述
强制门户:连接上wifi以后,手机会自动打开一个网页,这就是强制门户。
相信大家遇见过很多拥有免费wifi的地方,连接上wifi以后,就会自动弹出认证界面,在Web配网的基础上,我们加上强制门户,就可以实现连接wifi以后自动打开配网界面,方便用户操作。

Web配网详解
想要实现Web配网,就需要让esp8266开启一个WebServer服务器,需要用到以下函数。
  1. ESP8266WebServer();//创建WebServer
  2. begin();//启动WebServer
  3. on();//请求响应回调
  4. onNotFound();//无法响应的请求的回调函数
  5. send();//发送响应数据
  6. hasArg();//是否存在某个参数
  7. args();//获取参数个数
复制代码
具体WebServer实现代码
  1. const char* AP_NAME = "配网WIFI";//wifi名字
  2. //html网页源码
  3. const char* page_html = "\
  4. <!DOCTYPE html>\r\n\
  5. <html lang='en'>\r\n\
  6. <head>\r\n\
  7.   <meta charset='UTF-8'>\r\n\
  8.   <meta name='viewport' content='width=device-width, initial-scale=1.0'>\r\n\
  9.   <title>Document</title>\r\n\
  10. </head>\r\n\
  11. <body>\r\n\
  12.   <form name='input' action='/' method='POST'>\r\n\
  13.         wifi名称: <br>\r\n\
  14.         <input type='text' name='ssid'><br>\r\n\
  15.         wifi密码:<br>\r\n\
  16.         <input type='text' name='password'><br>\r\n\
  17.         <input type='submit' value='保存'>\r\n\
  18.     </form>\r\n\
  19. </body>\r\n\
  20. </html>\r\n\
  21. ";

  22. IPAddress apIP(192, 168, 4, 1);//esp8266-AP-IP地址
  23. ESP8266WebServer server(80);//创建WebServer

  24. void initBasic(void){//初始化基础
  25.   Serial.begin(115200);
  26.   WiFi.hostname("Smart-ESP8266");//设置ESP8266设备名
  27. }

  28. void initSoftAP(void){//初始化AP模式
  29.   WiFi.mode(WIFI_AP);
  30.   WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
  31.   if(WiFi.softAP(AP_NAME)){
  32.     Serial.println("ESP8266 SoftAP is right");
  33.   }
  34. }

  35. void handleRoot() {//访问主页回调函数
  36.   server.send(200, "text/html", page_html);
  37. }

  38. void handleRootPost() {//Post回调函数
  39.   Serial.println("handleRootPost");
  40.   if (server.hasArg("ssid")) {//判断是否有账号参数
  41.     Serial.print("got ssid:");
  42.     strcpy(sta_ssid, server.arg("ssid").c_str());//将账号参数拷贝到sta_ssid中
  43.     Serial.println(sta_ssid);
  44.   } else {//没有参数
  45.     Serial.println("error, not found ssid");
  46.     server.send(200, "text/html", "<meta charset='UTF-8'>error, not found ssid");//返回错误页面
  47.     return;
  48.   }
  49.   //密码与账号同理
  50.   if (server.hasArg("password")) {
  51.     Serial.print("got password:");
  52.     strcpy(sta_password, server.arg("password").c_str());
  53.     Serial.println(sta_password);
  54.   } else {
  55.     Serial.println("error, not found password");
  56.     server.send(200, "text/html", "<meta charset='UTF-8'>error, not found password");
  57.     return;
  58.   }

  59.   server.send(200, "text/html", "<meta charset='UTF-8'>保存成功");//返回保存成功页面
  60.   delay(2000);
  61.   //连接wifi
  62.   connectNewWifi();
  63. }

  64. void initWebServer(void){//初始化WebServer
  65.   server.on("/", HTTP_GET, handleRoot);//设置主页回调函数
  66.   server.on("/", HTTP_POST, handleRootPost);//设置Post请求回调函数
  67.   server.begin();//启动WebServer
  68.   Serial.println("WebServer started!");
  69. }

  70. void connectNewWifi(void){
  71.   WiFi.mode(WIFI_STA);//切换为STA模式
  72.   WiFi.setAutoConnect(true);//设置自动连接
  73.   WiFi.begin();//连接上一次连接成功的wifi
  74.   Serial.println("");
  75.   Serial.print("Connect to wifi");
  76.   int count = 0;
  77.    while (WiFi.status() != WL_CONNECTED) {
  78.     delay(500);
  79.     Serial.print(".");
  80.   }
  81.   if(WiFi.status() == WL_CONNECTED){//如果连接上 就输出IP信息 防止未连接上break后会误输出
  82.     Serial.println("");
  83.     Serial.println("WIFI Connected!");
  84.     Serial.print("IP address: ");
  85.     Serial.println(WiFi.localIP());
  86.     server.stop();
  87.   }
  88. }

  89. void setup() {
  90.   initBasic();
  91.   initSoftAP();
  92.   initWebServer();
  93. }

  94. void loop() {
  95.   server.handleClient();
  96.   dnsServer.processNextRequest();
  97. }
复制代码
强制门户详解
要想实现强制门户,就要在以上的普通Web配网的基础上加上DNS服务。
具体实现思路:当手机连接上一个无需密码的wifi后(看上面的initSoftAP就可以发现设置的是无需密码的AP),会访问一个手机内部的网址去查看是否可以上网,在访问此网址的时候会先发起DNS请求,向服务器问域名的IP地址。然后再发起HTTP请求,请求想要的内容。

1.png
  1. DNSServer dnsServer;//创建dnsServer实例
  2. IPAddress apIP(192, 168, 4, 1);//esp8266-AP-IP地址
  3. const byte DNS_PORT = 53;//DNS端口号

  4. dnsServer.start(DNS_PORT, "*", apIP)
复制代码
不管收到什么http请求,都将html页面回复过去
  1.   ESP8266WebServer server(80);//创建WebServer
  2.   
  3.   //server.on("/",handleRoot);
  4.   //上面那行必须在第二个参数上添加上HTTP_GET才能不影响强制门户,防止有些设备无法弹出强制门户,要用域名访问,如果不加第二个参数,就只能实现域名访问而无法强制门户
  5.   //在无法响应的http请求响应回调设置为主页的回调函数,才可以强制门户
  6.   server.on("/", HTTP_GET, handleRoot);//设置主页回调函数
  7.   server.onNotFound(handleRoot);//设置无法响应的http请求的回调函数
  8.   server.on("/", HTTP_POST, handleRootPost);//设置Post请求回调函数
  9.   server.begin();//启动WebServer
复制代码
完整代码
  1. #include <ESP8266WiFi.h>
  2. #include <DNSServer.h>
  3. #include <ESP8266WebServer.h>

  4. const char* AP_NAME = "配网WIFI";//wifi名字
  5. //暂时存储wifi账号密码
  6. char sta_ssid[32] = {0};
  7. char sta_password[64] = {0};
  8. //配网页面代码
  9. const char* page_html = "\
  10. <!DOCTYPE html>\r\n\
  11. <html lang='en'>\r\n\
  12. <head>\r\n\
  13.   <meta charset='UTF-8'>\r\n\
  14.   <meta name='viewport' content='width=device-width, initial-scale=1.0'>\r\n\
  15.   <title>Document</title>\r\n\
  16. </head>\r\n\
  17. <body>\r\n\
  18.   <form name='input' action='/' method='POST'>\r\n\
  19.         wifi名称: <br>\r\n\
  20.         <input type='text' name='ssid'><br>\r\n\
  21.         wifi密码:<br>\r\n\
  22.         <input type='text' name='password'><br>\r\n\
  23.         <input type='submit' value='保存'>\r\n\
  24.     </form>\r\n\
  25. </body>\r\n\
  26. </html>\r\n\
  27. ";

  28. const byte DNS_PORT = 53;//DNS端口号
  29. IPAddress apIP(192, 168, 4, 1);//esp8266-AP-IP地址
  30. DNSServer dnsServer;//创建dnsServer实例
  31. ESP8266WebServer server(80);//创建WebServer

  32. void handleRoot() {//访问主页回调函数
  33.   server.send(200, "text/html", page_html);
  34. }

  35. void handleRootPost() {//Post回调函数
  36.   Serial.println("handleRootPost");
  37.   if (server.hasArg("ssid")) {//判断是否有账号参数
  38.     Serial.print("got ssid:");
  39.     strcpy(sta_ssid, server.arg("ssid").c_str());//将账号参数拷贝到sta_ssid中
  40.     Serial.println(sta_ssid);
  41.   } else {//没有参数
  42.     Serial.println("error, not found ssid");
  43.     server.send(200, "text/html", "<meta charset='UTF-8'>error, not found ssid");//返回错误页面
  44.     return;
  45.   }
  46.   //密码与账号同理
  47.   if (server.hasArg("password")) {
  48.     Serial.print("got password:");
  49.     strcpy(sta_password, server.arg("password").c_str());
  50.     Serial.println(sta_password);
  51.   } else {
  52.     Serial.println("error, not found password");
  53.     server.send(200, "text/html", "<meta charset='UTF-8'>error, not found password");
  54.     return;
  55.   }

  56.   server.send(200, "text/html", "<meta charset='UTF-8'>保存成功");//返回保存成功页面
  57.   delay(2000);
  58.   //连接wifi
  59.   connectNewWifi();
  60. }

  61. void initBasic(void){//初始化基础
  62.   Serial.begin(115200);
  63.   WiFi.hostname("Smart-ESP8266");//设置ESP8266设备名
  64. }

  65. void initSoftAP(void){//初始化AP模式
  66.   WiFi.mode(WIFI_AP);
  67.   WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
  68.   if(WiFi.softAP(AP_NAME)){
  69.     Serial.println("ESP8266 SoftAP is right");
  70.   }
  71. }

  72. void initWebServer(void){//初始化WebServer
  73.   //server.on("/",handleRoot);
  74.   //上面那行必须以下面这种格式去写否则无法强制门户
  75.   server.on("/", HTTP_GET, handleRoot);//设置主页回调函数
  76.   server.onNotFound(handleRoot);//设置无法响应的http请求的回调函数
  77.   server.on("/", HTTP_POST, handleRootPost);//设置Post请求回调函数
  78.   server.begin();//启动WebServer
  79.   Serial.println("WebServer started!");
  80. }

  81. void initDNS(void){//初始化DNS服务器
  82.   if(dnsServer.start(DNS_PORT, "*", apIP)){//判断将所有地址映射到esp8266的ip上是否成功
  83.     Serial.println("start dnsserver success.");
  84.   }
  85.   else Serial.println("start dnsserver failed.");
  86. }

  87. void connectNewWifi(void){
  88.   WiFi.mode(WIFI_STA);//切换为STA模式
  89.   WiFi.setAutoConnect(true);//设置自动连接
  90.   WiFi.begin();//连接上一次连接成功的wifi
  91.   Serial.println("");
  92.   Serial.print("Connect to wifi");
  93.   int count = 0;
  94.    while (WiFi.status() != WL_CONNECTED) {
  95.     delay(500);
  96.     count++;
  97.     if(count > 10){//如果5秒内没有连上,就开启Web配网 可适当调整这个时间
  98.       initSoftAP();
  99.       initWebServer();
  100.       initDNS();
  101.       break;//跳出 防止无限初始化
  102.     }
  103.     Serial.print(".");
  104.   }
  105.   Serial.println("");
  106.   if(WiFi.status() == WL_CONNECTED){//如果连接上 就输出IP信息 防止未连接上break后会误输出
  107.     Serial.println("WIFI Connected!");
  108.     Serial.print("IP address: ");
  109.     Serial.println(WiFi.localIP());//打印esp8266的IP地址
  110.     server.stop();
  111.   }
  112. }

  113. void setup() {
  114.   initBasic();
  115.   connectNewWifi();
  116. }

  117. void loop() {
  118.   server.handleClient();
  119.   dnsServer.processNextRequest();
  120. }
复制代码
2.jpg



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Geek Planet ( 陕ICP备19010480号 )

GMT+8, 2024-9-8 09:03 , Processed in 0.068379 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表