1、WiFi配网方式
物联网Wi-Fi配网方式,你知道几种?-阿里云开发者社区 (aliyun.com)
这篇文章介绍并分析了几种WiFi配网的方式,推荐看一下,目前主流的WiFi配网有设备热点配网、蓝牙配网、一键配网(SmartConfig);
- 设备热点配网:手机连设备创建的热点,把能够上网的WiFi名和密码发给设备;
- 蓝牙配网:手机连设备蓝牙,把能够上网的WiFi名和密码发给设备;
- 一键配网:手机仍然连能上网的WiFi,广播WiFi名和密码,设备开启sniffer模式监听,得到WiFi名和密码;
2、SmartConfig配网
- 设备进入sniffer模式(又叫混杂模式,即不过滤数据报文),监听环境中所有的802.11报文;
- 设备需要在所支持的信道(通常1-13)上轮询监听(因为设备不知道用户手机和目标路由器的信道);
- 捕获到符合配网规则的数据报文后停止信道轮询,尝试在在此信道上接收完成所有报文;
- 当前信道接收失败或超时重新回到步骤2;
- 数据报文接收完成则关闭sniffer模式,回到station模式并开始尝试连接路由器,狭义的配网过程完成。
3、ESP8266的SmartConfig接口
设置SmartConfig模式,开启SmartConfig,根据配网不同的阶段有回调函数,随后关闭SmartConfig;
3.1、smartconfig_set_type
因为使用的是微信的Airkiss功能,所以选择SC_TYPE_AIRKISS;
ESPTOUCH是乐鑫开发的一个APP,用于配网的,这里不用;
3.2、smartconfig_start
按照说明就好了,先设置STA模式再调用此API,回调函数的参数在配网的不同阶段不同,所以就可以switch case根据状态来执行相应的操作,而且官方API文档下还有示例参考;
3.3、smartconfig_stop
关闭SmartConfig模式,释放内存,在获取到IP之后调用;
4、代码
是根据上次MQTT的程序改的,我想加的功能是,Flash中的SSID和密码连接AP失败10次之后,进入SmartConfig配网,然后在“安信可科技”公众号上配网,并把新的SSID和密码更新到Flash,这样下次上电就不需要配网了;当然,比如只是WiFi断线你可以不配网重启下(说起来要是能自动恢复才好呢,挖个坑)
实现上述功能只需要修改wifi.c的代码,算是wifi功能加入了SmartConfig的扩展吧,要包含的头文件#include "smartconfig.h" ,原有wifi_check_ip中要添加的内容如下,设置未获取到IP 10次后进入一键配网;
// 定时函数:检查IP获取情况
static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg)
{
static u8 fail_num = 0;
// 未获取到IP地址-------------------------------------------------------------
else{
fail_num++;
if(fail_num >= 10){
fail_num = 0;
INFO("--------------START SmartConfig------------------\r\n");
//wifi_set_opmode(STATION_MODE); // 设为STA模式
smartconfig_set_type(SC_TYPE_AIRKISS); // ESP8266配网方式【AIRKISS】
smartconfig_start(smartconfig_done); // 进入【智能配网模式】,并设置回调函数
return;
}
}
}
然后添加SmartConfig的回调函数,重点在如何更新SSID和密码到Flash,还有调用user_main.c中WiFi连接后的回调函数,从而进入SNTP、TCP、MQTT等后续操作,别忘了重启定时器,别忘了把默认的SSID信息改错;
// SmartConfig状态发生改变时,进入此回调函数
// 参数1:sc_status status / 参数2:无类型指针【在不同状态下,[void *pdata]的传入参数是不同的】
void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata)
{
switch(status)
{
// CmartConfig等待
case SC_STATUS_WAIT:
os_printf("\r\nSC_STATUS_WAIT\r\n");
break;
// 发现【WIFI信号】(8266在这种状态下等待配网)
case SC_STATUS_FIND_CHANNEL:
os_printf("\r\nSC_STATUS_FIND_CHANNEL\r\n");
os_printf("\r\n---- Please Use WeChat to SmartConfig ------\r\n\r\n");
break;
// 正在获取【SSID】【PSWD】(8266正在抓取并解密【SSID+PSWD】)
case SC_STATUS_GETTING_SSID_PSWD:
os_printf("\r\nSC_STATUS_GETTING_SSID_PSWD\r\n");
// 配网方式
sc_type *type = pdata;
if (*type == SC_TYPE_ESPTOUCH){
os_printf("\r\nSC_TYPE:SC_TYPE_ESPTOUCH\r\n");
}else{
os_printf("\r\nSC_TYPE:SC_TYPE_AIRKISS\r\n");
}
break;
// 成功获取到【SSID】【PSWD】,保存STA参数,并连接WIFI
case SC_STATUS_LINK:
os_printf("\r\nSC_STATUS_LINK\r\n");
struct station_config *sta_conf = pdata; // 获取【STA参数】指针
// 将【SSID】【PASS】保存到【外部Flash】中
os_strncpy(sysCfg.sta_ssid, sta_conf->ssid, 32); // 【STA_SSID】WIFI名称
os_strncpy(sysCfg.sta_pwd, sta_conf->password, 64); // 【STA_PASS】WIFI密码
CFG_Save(); // 将更新后的系统参数烧录到Flash中
//连接WiFi
wifi_station_set_config(sta_conf); // 设置STA参数【Flash】
wifi_station_disconnect(); // 断开STA连接
wifi_station_connect(); // ESP8266连接WIFI
break;
// ESP8266作为STA,成功连接到WIFI
case SC_STATUS_LINK_OVER:
os_printf("\r\nSC_STATUS_LINK_OVER\r\n");
smartconfig_stop(); // 停止SmartConfig,释放内存
if(wifiCb){ // 判断是否设置了[wifiConnectCb]函数
wifiStatus = wifi_station_get_connect_status(); // 获取接入状态
wifiCb(wifiStatus); // wifiCb(wifiStatus)=wifiConnectCb(wifiStatus)
}
// 再次开启定时器-------------------------------------------------------
os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
os_timer_arm(&WiFiLinker, 1000, 0); // 1s定时
break;
}
}