无网不进  
软硬件开发

一、前言


听到 SmartConfig这个单词,字义上就是智能配置,但是我们电子发烧友都是称之为一键配网,

听到Airkiss这个单词就有点意思了。飞吻,象征着速度飞一般的快。


这里写图片描述


本博文的配网截图:

这里写图片描述


8266串口打印信息:

这里写图片描述

1.1、问题来了。


①、都不懂!SmartConfig和AirKiss是什么东东!

  • 答:大家买智能设备时候都会出现以下界面提示您要输入wifi账号和密码!然后下一步操作搜索,设备成功连接网络成功就可以使用啦!这里就引出了, SmartConfig 和 AirKiss 就是给设备配网的方式,皆为无线操作给设备发wifi名字和密码的方式。

①、既然方式一样,二者有啥不同吗!

  • 答:其实原理都是一样,手机发出广播,这广播里面有WIfi的名字 和密码,也就是接下来设备要接收的广播,以及去连接这个Wifi!,其然 ,Airkiss是微信专门为物联网配网开发的,是对SmartConfig的进一步封装。如果你没有去集成微信开发环境去给设备配网,大不可去了解airkiss,只需要懂得用SmartConfig配网就好了!

二、原理。


这里我引用微信官网画的一个通俗易懂一张图片。图下的智能插座是要配网的设备,而微信客户端也就是我们的发送端:APP软件 ;

  • 步骤

    • 在APP软件输入将要连接的WIfi的名字和密码。

    • 之后App会空中发网,带有wifi的名字和密码的信息暴露。

    • 智能设备收到信息广播之后,尝试不断去连接,一旦连接成功。就会返回信息给APP通知配网成功!


配网原理


三、走进8266一键配网的SmartConfig。


1. 翻开8266的编程SDK手册,看看有哪些已经封装好的接口,如图 :

这里写图片描述


2. 主要的函数方法,如图 :

这里写图片描述

这里写图片描述


3. 为了更好展示主要方法,我做个表格,大家可以方便查阅,如下 :


函数名字函数参数返回值备注
smartconfig_start() sc_callback_t cb:SmartConfig 状态发⽣生改变时,进⼊入回调函数 true:成功 ,false:失败 开启快连模式,快速连接 ESP8266 Station 到 AP
smartconfig_stop () SC_TYPE_ESPTOUCH,SC_TYPE_AIRKISS,SC_TYPE_ESPTOUCH_AIRKISS true:成功 ,false:失败 关闭快连模式,释放 smartconfig_start 占⽤用的内存。

三、电路图与代码分析。


3、1 电路图。

仅仅只是一个按键触发配网模式,这个按键接GPIO14与GND端。

这里写图片描述


3、2 代码分析。

第一步:按键初始化,这里我使用的是机智云SOC方案提炼出来的按键中断初始化 hal_key.h 和 hal_key.c 文件封装。

第二步:按键触发回调的函数 :如下,其中的smartconfig_done是方法回调函数,见第三步骤。


//短按按键函数回调
LOCAL void ICACHE_FLASH_ATTR keyShortPress(void) {

    //配置一键配网类型
    smartconfig_set_type(SC_TYPE_ESPTOUCH); 

    //开启station模式
    wifi_set_opmode(STATION_MODE);

    //开始一键配网等待
    smartconfig_start(smartconfig_done);
}

 

第三步: smartconfig_done函数 : 如下

void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata) {

switch (status) {

    //连接未开始,请勿在此阶段开始连接。
    case SC_STATUS_WAIT:
        os_printf("SC_STATUS_WAIT\n");
        break;

    //发现WIfi信道
    case SC_STATUS_FIND_CHANNEL:
        os_printf("SC_STATUS_FIND_CHANNEL\n");
        break;

    //得到wifi名字和密码
    case SC_STATUS_GETTING_SSID_PSWD:
        os_printf("SC_STATUS_GETTING_SSID_PSWD\n");
        sc_type *type = pdata;
        if (*type == SC_TYPE_ESPTOUCH) {
            os_printf("SC_TYPE:SC_TYPE_ESPTOUCH\n");
        } else {
            os_printf("SC_TYPE:SC_TYPE_AIRKISS\n");
        }
        break;

     //已经获取wifi名字与密码在连接路由器
    case SC_STATUS_LINK:
        os_printf("SC_STATUS_LINK\n");
        struct station_config *sta_conf = pdata;
        wifi_station_set_config(sta_conf);
        wifi_station_disconnect();
        wifi_station_connect();
        break;

    //成功获取到IP,连接路由完成。
    case SC_STATUS_LINK_OVER:
        if (pdata != NULL) {
        uint8 phone_ip[4] = { 0 };          
        os_memcpy(phone_ip, (uint8*) pdata, 4);     

        //打印发广播过来的设备IP地址    
        os_printf("Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1],  phone_ip[2], phone_ip[3]);
        } 

        //停止配置
        smartconfig_stop();
        break;
    }

}

 


四、完整代码。



#include "../include/debug.h"
#include "hal_key.h"
#include "../include/uart.h"
#include "ets_sys.h"
#include "osapi.h"
#include "ip_addr.h"
#include "espconn.h"
#include "mem.h"
#include "user_interface.h"
#include "smartconfig.h"
#include "airkiss.h"

//按键定义
#define GPIO_KEY_NUM                            1
#define KEY_0_IO_MUX                            PERIPHS_IO_MUX_MTMS_U
#define KEY_0_IO_NUM                            14
#define KEY_0_IO_FUNC                           FUNC_GPIO14

LOCAL key_typedef_t * singleKey[GPIO_KEY_NUM]; 
LOCAL keys_typedef_t keys; 

LOCAL esp_udp ssdp_udp;
LOCAL struct espconn pssdpudpconn;
LOCAL os_timer_t ssdp_time_serv;

uint8_t lan_buf[200];
uint16_t lan_buf_len;
uint8 udp_sent_cnt = 0;

void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata) {

    switch (status) {

    //连接未开始,请勿在此阶段开始连接
    case SC_STATUS_WAIT:
        os_printf("SC_STATUS_WAIT\n");
        break;

    //发现信道
    case SC_STATUS_FIND_CHANNEL:
        os_printf("SC_STATUS_FIND_CHANNEL\n");
        break;


    //得到wifi名字和密码
    case SC_STATUS_GETTING_SSID_PSWD:
        os_printf("SC_STATUS_GETTING_SSID_PSWD\n");
        sc_type *type = pdata;
        if (*type == SC_TYPE_ESPTOUCH) {
            os_printf("SC_TYPE:SC_TYPE_ESPTOUCH\n");
        } else {
            os_printf("SC_TYPE:SC_TYPE_AIRKISS\n");
        }
        break;

    case SC_STATUS_LINK:
        os_printf("SC_STATUS_LINK\n");
        struct station_config *sta_conf = pdata;

        wifi_station_set_config(sta_conf);
        wifi_station_disconnect();
        wifi_station_connect();
        break;

    //成功获取到IP,连接路由完成。
    case SC_STATUS_LINK_OVER:
        os_printf("SC_STATUS_LINK_OVER \n\n");
        if (pdata != NULL) {
            uint8 phone_ip[4] = { 0 };
            os_memcpy(phone_ip, (uint8*) pdata, 4);
            os_printf("Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1],  phone_ip[2], phone_ip[3]);
        }

        //停止配置
        smartconfig_stop();
        break;
    }

}

//用户自定义 RF_CAL 参数存放在 Flash 的扇区号
uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void) {
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
    case FLASH_SIZE_4M_MAP_256_256:
        rf_cal_sec = 128 - 5;
        break;

    case FLASH_SIZE_8M_MAP_512_512:
        rf_cal_sec = 256 - 5;
        break;

    case FLASH_SIZE_16M_MAP_512_512:
    case FLASH_SIZE_16M_MAP_1024_1024:
        rf_cal_sec = 512 - 5;
        break;

    case FLASH_SIZE_32M_MAP_512_512:
    case FLASH_SIZE_32M_MAP_1024_1024:
        rf_cal_sec = 1024 - 5;
        break;

    default:
        rf_cal_sec = 0;
        break;
    }

    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR user_rf_pre_init(void) {
}

//长按五秒按键回调
LOCAL void ICACHE_FLASH_ATTR keyLongPress(void) {

}

//短按按键回调
LOCAL void ICACHE_FLASH_ATTR keyShortPress(void) {
    os_printf("----------2 开始进去SmartConfig配网模式\n\n\n-----");
    smartconfig_set_type(SC_TYPE_ESPTOUCH); 
    wifi_set_opmode(STATION_MODE);
    smartconfig_start(smartconfig_done);
}

//按键初始化
LOCAL void ICACHE_FLASH_ATTR keyInit(void) {
    singleKey[0] = keyInitOne(KEY_0_IO_NUM, KEY_0_IO_MUX, KEY_0_IO_FUNC,
            keyLongPress, keyShortPress);
    keys.singleKey = singleKey;
    keyParaInit(&keys);
}

void ICACHE_FLASH_ATTR

user_init(void) {
    uart_init(BIT_RATE_115200, BIT_RATE_115200);
    os_printf("SDK version:%s\n", system_get_sdk_version());
    os_printf("----------BIT_RATE_115200\n\n\n-----");
    keyInit();
}

 


附加:相关调试工具下载。

适配安卓7.0的中文版调试一键配网APK下载: http://download.csdn.net/download/xh870189248/10141647

本博文的8266代码demo下载:http://download.csdn.net/download/xh870189248/10141671

8266教程系列的代码汇总:https://github.com/xuhongv/StudyInEsp8266

版权声明:本文为博主半颗心脏一心一血敲出来的原创作品,未经博主允许不得转载,多谢支持。 https://blog.csdn.net/xh870189248/article/details/78677952
个人分类: 8266
所属专栏: 乐鑫esp8266学习之旅
posted on 2018-05-30 16:33  无网不进  阅读(2160)  评论(0)    收藏  举报