ESP8266配网思路(不使用SmartConfig)
一、ESP8266配网(使用手机APP来给模组配置)
假设已经开发了一个手机APP,这个APP完成的功能如下:
1、连接设备接的模块ESP8266生成的热点
2、给设备热点发送要连接的路由器的名字和密码
配网流程
1、设备让ESP8266进入AP模式设备MCU通过串口给ESP8266发送AT+CWMODE=2,让ESP8266进入AP模式。如果进入AP模式成功,用手机可以搜索到ESP8266模块的热点信息。
2、用手机APP去连接这个热点发送路由器ssid和password,假设格式为: ssid:“xxx”,password:“xxxx”
3、解析APP发过来的字符串格式ESP8266串口收到格式:
ssid:“xxx”,password:"xxxx"这个字符串设备MCU处理收到的这个字符串,将ssid和password提取出来。分别保存到缓存区SSID、PASSWORD。
4、设备让ESP8266进入STA模式设备MCU通过串口给ESP8266发送AT+CWMODE=1,让ESP8266进入STA模式。
5、设备连接路由器拿保存在缓存区的SSID和PASSWORD,设备通过串口给ESP8266发送连接指令AT+CWJAP=“SSID”,“PASSWORD”
6、连接公网服务器
===>120.78.136.134:8888AT+CIPSTART=“TCP”,“120.78.136.134”,9002
配网成功!如果以后不在初始化设置模式下,不会执行该流程,默认开机直接连接对应的热点和服务器。
二、ESP8266配网(使用上位机串口来给模组配置)
假设已经开发了一个上位机,这个上位机完成的功能如下:
1、上位机通过串口连接设备
2、具有设置wifi帐号和密码的功能(其实就是发送一条串口指令,带有wifi帐号和密码)
3、具有设置服务器ip和端口号的功能(其实就是发送一条串口指令,带有服务器ip和端口号)
配网流程
1、直接让设备进入STA模式 上位机通过串口给接有ESP8266的设备发送AT+CWMODE=1,让ESP8266进入STA模式。
2、设备接收到上位机发送过来的进入STA模式的指令,透传给ESP8266, 这时ESP8266如果设置成功,则处于STA模式。
3、特定模式下(初始化设置),线程等待上位机下发的指令指令格式:(1)设置wifi连接路由器SSID:“xxxx”,“PASSWORD”:“xxxxx”(2)设置wifi连接服务器SERVER_IP:“xxx.xxx.xxx.xxx”,PORT:“xxxx”
4、设备接收到上位机下发的指令,进行解析后分别保存在缓存区中。
5、设备连接路由器 拿保存在缓存区的SSID和PASSWORD,设备通过串口给ESP8266发送连接指令AT+CWJAP=“SSID”,“PASSWORD”
6、连接公网服务器
===>xxx.xx.xxx.xxx:xxxx例如:AT+CIPSTART=“TCP”,“120.78.136.134”,9002
配网成功!如果以后不在初始化设置模式下,不会执行该流程,默认开机直接连接对应的热点和服务器。
三、ESP8266配网(使用上位机网络TCP来给模组配置)
假设以及开发了一个上位机,这个上位机完成的功能如下:
1、上位机可以用TCP/IP连接wifi热点(ESP8266)===>需要知道esp8266的ip和端口号,通过window网络状态可以查到。
2、具有设置wifi帐号和密码的功能(其实就是发送一条串口指令,带有wifi帐号和密码)
3、具有设置服务器ip和端口号的功能(其实就是发送一条串口指令,带有服务器ip和端口号)
配网流程
设备端
1、直接让设备进入AP模式上位机通过串口给接有ESP8266的设备发送AT+CWMODE=2,让ESP8266进入AP模式。
指令:
AT+CWMODE=2
2、重启设备,确保AP模式设置成功指令:
AT+RST
3、开启多路连接指令:
AT+CIPMUX=1
4、为设备端创建热点指令:
AT+CWSAP=“WIFI名称”,“WIFI密码”,1,4
5、设备端启动服务器指令:
AT+CIPSERVER=1,8080
PC端
1、事先需要让PC去连接wifi热点===>WIFI名称、WIFI密码
2、通过网络连接详情查看当前热点的IPv4服务器地址
3、PC端开发的上位机连接IPv4服务器地址,端口号就是设备端指定的端口号:8080
4、PC端开发的上位机下发指令给设备端指令格式:
(1)设置wifi连接路由器SSID:“xxxx”,“PASSWORD”:“xxxxx”
(2)设置wifi连接服务器
SERVER_IP:“xxx.xxx.xxx.xxx”,PORT:“xxxx”
设备端
1、解析字符串,如果含有
SSID:“xxxx”,“PASSWORD”:“xxxxx”,取得ssid和password,保存到设备端的FLASH中,如果为其它,则设定接收出错的条件。
2、解析字符串,如果含有如下字符串:
SERVER_IP:“xxx.xxx.xxx.xxx”,PORT:“xxxx”
这时候程序解析取得server_ip和port,保存到设备端的FLASH中,如果为其它,则设定接收出错的条件。
3、如果已经解析完两个字符串,自动重启,切换到STA模式,取出ssid和password,连接ap,连接成功后,接下来取出flash中的server_ip和port,连接服务器,如果成功,则可进入数据上传,如果不成功,则返回ap连接,依次进行,直到成功后,此时程序中连接成功的标志会置一。
4、定时查询与服务器端确认是否连接成功,如果不成功,需要重新连接服务器。
5、可上传数据
ESP8266端,其实我已经写好了一个程序,只是还不是那么的完善,但现在已经可以用了,分享出来,大家可以去完善它。
大致程序框架设计如下,分别是配置WIFI的过程以及正常连接WIFI的过程:
//配置wifi网络
int Cofig_Wifi_NetWork(void)
{
int ret = -1 ;
char *buf = NULL;
while(1)
{
switch(ESP8266_INFO.config_network_status)
{
case CHECK_WIFI_EXIST:
ret = Wifi_Test_Exist();
if(0 != ret)
{
printf("wifi初始化失败,请检查硬件是否连接!rn");
ESP8266_INFO.config_network_status = CHECK_WIFI_EXIST ;
LED1(ON);
return -1 ;
}
else
{
ESP8266_INFO.config_network_status = WIFI_SET_MODE ;
LED1(OFF);
}
break ;
case WIFI_SET_MODE:
ret = Wifi_Set_Mode(3);
if(0 != ret)
{
printf("wifi设置模式失败rn");
ESP8266_INFO.config_network_status = CHECK_WIFI_EXIST ;
LED1(ON);
}
else
{
ESP8266_INFO.config_network_status = WIFI_BUILD_AP ;
LED1(OFF);
}
break ;
case WIFI_BUILD_AP:
printf("准备ap....n");
ret = ESP8266_BuildAP("ESP8266", "123456", WPA2_PSK);
if(1 != ret)
{
printf("wifi创建AP失败...rn");
ESP8266_INFO.config_network_status = CHECK_WIFI_EXIST ;
LED1(ON);
}
else
{
ESP8266_INFO.config_network_status = WIFI_CONFIG_MULTI ;
LED1(OFF);
printf("创建ap成功n");
}
break ;
case WIFI_CONFIG_MULTI:
printf("配置多连接模式!rn");
ret = ESP8266_Enable_MultipleId(ENABLE);
if(1 != ret)
{
printf("配置多连接失败n");
ESP8266_INFO.config_network_status = WIFI_BUILD_AP ;
LED1(ON);
}
else
{
ESP8266_INFO.config_network_status = WIFI_START_SERVER ;
LED1(OFF);
}
break ;
case WIFI_START_SERVER:
ret = ESP8266_StartOrShutServer(ENABLE, "8080", "10") ;
if(1 != ret)
{
printf("创建端口号:%d失败rn", 8080);
ESP8266_INFO.config_network_status = WIFI_CONFIG_MULTI ;
LED1(ON);
}
else
{
printf("创建端口号:%d成功rn", 8080);
ESP8266_INFO.config_network_status = WIFI_GET_AP_IP ;
LED1(OFF);
}
break ;
case WIFI_GET_AP_IP:
buf = malloc(20);
if(buf == NULL)
return -1;
if(1 != ESP8266_Inquire_ApIp(buf, 20))
{
if(1 == ESP8266_StartOrShutServer(DISABLE, "8080", "5000"))
{
printf("关闭服务器成功!rn");
ESP8266_INFO.config_network_status = WIFI_START_SERVER ; //回到开启服务器的流程
LED1(OFF);
}
free(buf);
}
printf("获取ap ip:%s成功rn", buf);
free(buf);
ESP8266_INFO.config_network_status = WAIT_CLIENT_CONNECT;
break ;
case WAIT_CLIENT_CONNECT:
while(1)
{
//接收上位机连接
ret = ESP8266_Get_IdLinkStatus();
if(0 != ret)
{
printf("设备已和上位机建立连接....rn");
ESP8266_INFO.config_network_status = BACK_TO_CONFIG_PROCESS ;
LED1(ON);
break ;
}
LED2(ON);
Delay_ms (10);
LED2(OFF);
Delay_ms(10);
}
break ;
default:
break ;
}
if(ESP8266_INFO.config_network_status == BACK_TO_CONFIG_PROCESS)
{
LED1(OFF);
LED2(OFF);
LED3(OFF);
break ;
}
}
return 0 ;
}
//wifi正常连接流程
void Wifi_NetWork_Process(void)
{
int ret = -1 ;
while(1)
{
switch(ESP8266_INFO.wifi_status)
{
case WIFI_EXIST_CHECK:
ret = Wifi_Test_Exist();
if(0 != ret)
{
printf("wifi硬件故障!n");
return ;
}
ESP8266_INFO.wifi_status = WIFI_SET_MODE ;
break ;
case WIFI_SET_MODE:
ret = Wifi_Set_Mode(STA);
if(0 != ret)
{
printf("wifi设置模式失败rn");
ESP8266_INFO.wifi_status = WIFI_EXIST_CHECK ;
}
else
ESP8266_INFO.wifi_status = WIFI_CONNECT_ROUTER;
break ;
case WIFI_CONNECT_ROUTER:
ret = Wifi_Connect_Router((const char *)ESP8266_INFO.wifi_ssid, (const char *)ESP8266_INFO.wifi_password);
if(ret != 0)
{
printf("连接wifi热点失败n");
ESP8266_INFO.wifi_status = WIFI_SET_MODE ;
return ;
}
else
{
printf("连接wifi热点:%s成功n", ESP8266_INFO.wifi_ssid);
ESP8266_INFO.wifi_status = WIFI_CLOSE_MULTI ;
}
case WIFI_CLOSE_MULTI:
//关闭多连接
if(1 != ESP8266_Enable_MultipleId(DISABLE))
{
printf("关闭多连接失败!n");
ESP8266_INFO.wifi_status = WIFI_CONNECT_ROUTER ;
}
else
{
printf("关闭多连接成功!n");
ESP8266_INFO.wifi_status = WIFI_CONNECT_SERVER ;
}
break ;
case WIFI_CONNECT_SERVER:
ret = Wifi_Connect_Server("TCP", (const char *)ESP8266_INFO.server_ip, atoi((char *)ESP8266_INFO.server_port));
if(ret != 0)
{
printf("连接服务器失败n");
ESP8266_INFO.wifi_status = WIFI_CONNECT_ROUTER ;
}
else
{
printf("连接服务器:%s成功n", ESP8266_INFO.server_ip);
ESP8266_INFO.wifi_status = WIFI_CONFIG_OK ;
}
break ;
default:
break ;
}
//wifi连接成功
if(WIFI_CONFIG_OK == ESP8266_INFO.wifi_status)
{
LED3(ON);
break ;
}
}
return ;
}
//返回当前子串在原字符串中的索引
int Sub_String_Index(char *str, char *sub_str)
{
char *p1 = NULL ;
char *__str = str ;
char *__sub_str = sub_str ;
p1 = strstr(__str, __sub_str);
return p1 - __str ;
}
/////////////////////////////////////ESP8266解析参数
int Esp8266_Process_Para(void)
{
char *str = NULL ;
char *p1 = NULL ;
char *p2 = NULL ;
int index1 = 0, index2 = 0 ;
//开始wifi配置
while(1)
{
//如果该标志为0,则代表上位机已经连上设备了
if(BACK_TO_CONFIG_PROCESS == ESP8266_INFO.config_network_status)
{
if(0 == ESP8266_Get_IdLinkStatus())
{
printf("客户端已掉线,需重新连接....n");
LED2(ON);
Delay_ms(300);
LED2(OFF);
Delay_ms(300);
}
//此时客户端没有掉线
else
{
printf("客户端已连接,可下发数据....n");
//准备配置wifi_ssid
str = ESP8266_ReceiveString(DISABLE);
p1 = str + 12 ;
if(NULL != strstr(p1, "SSID"))
{
//拷贝wifi ssid
index1 = Sub_String_Index(p1, "=");
index2 = Sub_String_Index(p1, ";");
memcpy(ESP8266_INFO.wifi_ssid, p1 + index1 + 1, index2 - index1 - 1);
//拷贝wifi密码
p2 = p1 + index2 + 1 ;
index1 = Sub_String_Index(p2, "=") ;
index2 = Sub_String_Index(p2, ";") ;
memcpy(ESP8266_INFO.wifi_password, p2 + index1 + 1, index2 - index1 - 1);
printf("wifi_ssid:%s wifi_password:%srn", ESP8266_INFO.wifi_ssid, ESP8266_INFO.wifi_password);
macESP8266_Usart ("setting ssid_password success");
ESP8266_INFO.wifi_config_ap_flag = 1 ;
}
else if(NULL != strstr(p1, "SERVER_IP"))
{
//拷贝服务器相关参数===>server_ip
index1 = Sub_String_Index(p1, "=");
index2 = Sub_String_Index(p1, ";");
memcpy(ESP8266_INFO.server_ip, p1 + index1 + 1, index2 - index1 - 1);
//拷贝服务器相关参数===>server_port
p2 = p1 + index2 + 1 ;
index1 = Sub_String_Index(p2, "=") ;
index2 = Sub_String_Index(p2, ";") ;
memcpy(ESP8266_INFO.server_port, p2 + index1 + 1, index2 - index1 - 1);
printf("server_ip:%s server_port:%srn", ESP8266_INFO.server_ip, ESP8266_INFO.server_port);
macESP8266_Usart ("setting server_ip port success");
ESP8266_INFO.wifi_cofnig_server_flag = 1 ;
}
//如果都配置了,则进入正常启动流程
if((1 == ESP8266_INFO.wifi_config_ap_flag) && (1 == ESP8266_INFO.wifi_cofnig_server_flag))
{
ESP8266_INFO.config_network_status = 1 ;
return ESP8266_INFO.config_network_status ;
}
}
}
else if(1 == ESP8266_INFO.config_network_status)
{
return ESP8266_INFO.config_network_status ;
}
}
}
手机APP设计得比较简陋
以下使用QT设计的一个简单的配置工具界面
- 为你的WordPress 博客文章页面增加多彩排版条
- java: web应用中不经意的内存泄露
- java: web应用中不经意的内存泄露
- velocity模板引擎学习(4)-在standalone的java application中使用velocity及velocity-tools
- mac上开启ftp
- Web前端开发的四个阶段
- 使用Visual Studio 2015 开发ASP.NET MVC 5 项目部署到Mono/Jexus
- 关于把本地应用封装成windows app发布审核通不过的问题
- java并发编程学习:用 Semaphore (信号量)控制并发资源
- java并发编程学习: ThreadLocal使用及原理
- 使用Autofac IOC组织多项目应用程序
- 国内首个“人工智能与变革管理研究院”成立
- 解决WordPress缩略图插件timthumb不支持站外图片的问题
- 让 http 2来得更猛烈些吧
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 统一定制API返回格式,我只做了这几件事
- 《一起学sentinel》三、Slot的子类及实现之NodeSelectorSlot和ClusterBuilderSlot
- 《一起学sentinel》四、Slot的子类及实现之LogSlot和StatisticSlot
- 《一起学sentinel》五、Slot的子类及实现之AuthoritySlot和SystemSlot
- Python 之pyaudio使用随笔
- Determining 32 vs 64 bit in C++
- 在线、离线激活鉴权实战
- Spark vs Dask Python生态下的计算引擎
- 表达差异基因分析
- threadlocal记录
- 2020-09-22:已知两个数的最大公约数,如何...
- 【超详细】分布式一致性协议 - Paxos
- MySQL 8.0新特性 — 降序索引
- TRTC横竖屏切换2,重力感应
- Elasticsearch 日志配置详解【技术创作101训练营】