AliOS-Things ESP8266 配网 学习

  • 1、环境搭建
  • 2、流程

1、环境搭建

参考官网

2、流程

确认流程通过浏览源码、增加打印以及查看打印来确认,如果遇到乐鑫SDK的函数,不作详细说明。
platform\mcu\esp8266\bsp\entry.c

static kinit_t kinit = {.argc = 0,.argv = NULL,.cli_enable = 1
};static void app_entry(void *arg)
{aos_components_init(&kinit);
#ifndef AOS_BINSapplication_start(kinit.argc, kinit.argv);  /* jump to app/example entry */
#endif
}
extern uart_dev_t uart_0;
extern hal_wifi_module_t aos_wifi_esp8266;
void user_init(void)
{int ret = 0;extern int32_t hal_uart_init(uart_dev_t *uart);extern void key_gpio_init(void);key_gpio_init();hal_uart_init(&uart_0);hal_wifi_register_module(&aos_wifi_esp8266);  //全局,hal_wifi_module_t *moduleret = hal_wifi_init();if (ret){printf("waring: wifi init fail ret is %d \r\n", ret);}
#if defined(SUPPORT_SINGAPORE_DOMAIN)aos_task_new("main", app_entry, 0, 7.5*1024);
#elif defined(ESP8266_CHIPSET)aos_task_new("main", app_entry, 0, 2*1024);
#elseaos_task_new("main", app_entry, 0, 6*1024);
#endif
}

1、user_init的工作,注册 aos_wifi_esp8266 模块,然后初始化,创建app_entry任务。
2、app_entry 做了一些组建的初始化工作,然后application_start启动我们的sample

hal_wifi_module_t aos_wifi_esp8266 = {.base.name           = "aos_wifi_esp8266",.init                =  wifi_init,.get_mac_addr        =  wifi_get_mac_addr,.start               =  wifi_start,.start_adv           =  wifi_start_adv,.get_ip_stat         =  get_ip_stat,.get_link_stat       =  get_link_stat,.start_scan          =  start_scan,.start_scan_adv      =  start_scan_adv,.power_off           =  power_off,.power_on            =  power_on,.suspend             =  suspend,.suspend_station     =  suspend_station,.suspend_soft_ap     =  suspend_soft_ap,.set_channel         =  set_channel,.start_monitor       =  start_monitor,.stop_monitor        =  stop_monitor,.start_ap            =  start_ap,.stop_ap             =  stop_ap,.register_monitor_cb =  register_monitor_cb,.register_wlan_mgnt_monitor_cb = register_wlan_mgnt_monitor_cb,.wlan_send_80211_raw_frame = wlan_send_80211_raw_frame,.get_wireless_info   = get_wireless_info,
};
void hal_wifi_register_module(hal_wifi_module_t *module)
{dlist_add_tail(&module->base.list, &g_wifi_module);}
int hal_wifi_init(void)
{int          err = 0;dlist_t *t;/* do low level init */dlist_for_each(t, &g_wifi_module) {hal_wifi_module_t *m = (hal_wifi_module_t *)t;
#if ((WIFI_CONFIG_SUPPORT_LOWPOWER > 0) && (WIFI_CONFIG_LISTENSET_BINIT > 0))m->set_listeninterval(m, WIFI_CONFIG_LISTEN_INTERVAL);
#endifm->init(m);
#if ((WIFI_CONFIG_SUPPORT_LOWPOWER > 0) && (WIFI_CONFIG_LISTENSET_BINIT == 0))m->set_listeninterval(m, WIFI_CONFIG_LISTEN_INTERVAL);
#endif}return err;
}static int wifi_init(hal_wifi_module_t *m)
{static int inited;if (inited) {printf("Wifi already started.\r\n");return 0;}wifi_station_set_auto_connect(false);       //默认不连接保存的APset_on_station_connect(on_wifi_connect);    //设置连接上后的回调,就是一句打印set_on_station_disconnect(on_wifi_disconnect); //设置连接断开后的回调init_esp_wifi();inited = 1;printf("Wifi init success!!\n");return 0;
};void ICACHE_FLASH_ATTR set_on_station_first_connect(wifi_state_cb_t cb){on_station_first_connect = cb;
}
void ICACHE_FLASH_ATTR set_on_station_connect(wifi_state_cb_t cb){on_station_connect = cb;
}
void ICACHE_FLASH_ATTR set_on_station_disconnect(wifi_disco_cb_t cb){on_station_disconnect = cb;
}
void ICACHE_FLASH_ATTR set_on_client_connect(wifi_state_cb_t cb){on_client_connect = cb;
}
void ICACHE_FLASH_ATTR set_on_client_disconnect(wifi_state_cb_t cb){on_client_disconnect = cb;
}LOCAL void ICACHE_FLASH_ATTR on_wifi_connect(){printf("Wifi connected.\n");
}
LOCAL void ICACHE_FLASH_ATTR on_wifi_disconnect(uint8_t reason){hal_wifi_module_t *m = hal_wifi_get_default_module();printf("Wifi disconnected (reason: %d)\n", reason);if (m->ev_cb && m->ev_cb->stat_chg) {m->ev_cb->stat_chg(m, NOTIFY_STATION_DOWN, NULL);}
}WIFI_MODE ICACHE_FLASH_ATTR init_esp_wifi(){wifi_set_event_handler_cb(wifi_event_handler_cb);  //注册消息回调WIFI_MODE mode = wifi_get_opmode_default();wifi_set_mode(mode);return mode;
}
int aos_components_init(kinit_t *kinit)
{#ifdef AOS_COMP_VFSvfs_init();
#endif...ulog_init();kv_init();vfs_device_init();aos_loop_init();...aos_show_welcome();...und_update_statis(UND_STATIS_DEV_EXCEPTION_IDX, (int)debug_reboot_reason_get());...return 0;
}

源代码并非如此,我将没有执行的代码,以及宏都给删了,这里认为是一些组件吧。
接下来看应用启动后的。

int application_start(int argc, char **argv)
{...aos_set_log_level(AOS_LL_DEBUG);   set_iotx_info();netmgr_init();aos_register_event_filter(EV_KEY, linkkit_key_process, NULL);aos_register_event_filter(EV_WIFI, wifi_service_event, NULL);aos_register_event_filter(EV_YUNIO, cloud_service_event, NULL);IOT_RegisterCallback(ITE_MQTT_CONNECT_SUCC, mqtt_connected_event_handler);...IOT_SetLogLevel(IOT_LOG_DEBUG);#ifdef EN_COMBO_NETcombo_net_init();
#else
#ifdef AWSS_SUPPORT_DEV_APaos_task_new("dap_open", awss_open_dev_ap, NULL, 4096);
#elseaos_task_new("netmgr_start", start_netmgr, NULL, 5120);
#endif
#endifaos_loop_run();return 0;
}
void set_iotx_info()
{char _device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};HAL_GetDeviceName(_device_name);if (strlen(_device_name) == 0) {HAL_SetProductKey(PRODUCT_KEY);HAL_SetProductSecret(PRODUCT_SECRET);HAL_SetDeviceName(DEVICE_NAME);HAL_SetDeviceSecret(DEVICE_SECRET);}
}

1、设置打印级别
2、设置iotx_info,这个信息是几段字符串,后面再说。
3、 初始化
4、 注册几个回调
5、 创建任务 start_netmgr
先看看初始化函数netmgr_init

int netmgr_init(void)
{#ifdef NET_WITH_WIFIreturn netmgr_wifi_init();
#elif defined(NET_WITH_CELLULAR)return netmgr_cellular_init();
#endif
}int netmgr_wifi_init(void)
{hal_wifi_module_t *module;aos_register_event_filter(EV_WIFI, netmgr_events_executor, NULL);#ifdef AOS_COMP_CLIaos_cli_register_command(&ncmd);
#endifmodule = hal_wifi_get_default_module();memset(&g_netmgr_cxt, 0, sizeof(g_netmgr_cxt));g_netmgr_cxt.ip_available = false;g_netmgr_cxt.wifi_scan_complete_cb_finished = false;g_netmgr_cxt.wifi_hal_mod = module;
#if !defined(WITH_SAL) || defined(DEV_SAL_ATHOST)
#if defined(CONFIG_YWSS) && (!defined(CSP_LINUXHOST) || defined(DEV_SAL_ATHOST))add_autoconfig_plugin(&g_alink_smartconfig);
#elseadd_autoconfig_plugin(&g_def_smartconfig);
#endif
#endifhal_wifi_install_event(g_netmgr_cxt.wifi_hal_mod, &g_wifi_hal_event);read_persistent_conf();#ifdef CONFIG_AOS_MESHumesh_init(MODE_RX_ON);
#endifreturn 0;
}

1、获取wifi模块,这里是8266,并赋值给g_netmgr_cxt.wifi_hal_mod
2、注册一些函数,然后读配置文件,获取文件里保存的wifi信息
初始化函数接着写内容了,接着看管理的函数start_netmgr

static void start_netmgr(void *p)
{iotx_event_regist_cb(linkkit_event_monitor);  //注册,其实就只是一个状态的打印LOG("%s\n", __func__);aos_msleep(2000);netmgr_start(true);aos_task_exit(0);
}
int netmgr_start(bool autoconfig)
{#ifdef NET_WITH_WIFIreturn netmgr_wifi_start(autoconfig);
#elif defined(NET_WITH_CELLULAR)return netmgr_cellular_start(autoconfig);
#endif
}
int netmgr_wifi_start(bool autoconfig)
{stop_mesh();if (has_valid_ap() == 1) {   //如果已经保存了IPaos_post_event(EV_WIFI, CODE_WIFI_CMD_RECONNECT, 0);return 1;}
#ifdef CONFIG_AOS_NETMGRYTS_NOSMARTCONFIGelse {LOGI("netmgr","netmgr yts only supports valid AP connect test, ""please ensure you have correct AP/passwd information set"" in kv before you do this test.");return -1;}
#endifif (autoconfig) {#ifndef PREVALIDATE_TEST    //使用测试的AP SSID 和 PASSWD 连接 WIFI netmgr_wifi_config_start();
#endifreturn 0;}start_mesh(false); return -1;
}

1、mesh 函数可以先忽略,这里默认的未配置。
2、判断如果已经配过网,则直接连接。
3、autoconfig传进来的是true, 执行netmgr_wifi_config_start

static void netmgr_wifi_config_start(void)
{autoconfig_plugin_t *valid_plugin = g_netmgr_cxt.autoconfig_chain;if (valid_plugin != NULL) {  //初始化时赋值g_netmgr_cxt.doing_smartconfig = true;valid_plugin->autoconfig_start();  //smart_config_start} else {LOGW(TAG, "net mgr none config policy");start_mesh(false);}
}

这里的autoconfig_start调用执行下面的函数,进入awss_start()

static int smart_config_start(void)
{extern int awss_start();awss_start();return 0;
}
int awss_start(void)
{if (awss_stopped == 0) {awss_debug("awss already running\n");return -1;}awss_stopped = 0;awss_event_post(IOTX_AWSS_START);produce_random(aes_random, sizeof(aes_random));do {__awss_start();......

awss_start 先这么看着,why? 流程会卡在_awss_start()函数里面。

int __awss_start(void)
{char ssid[OS_MAX_SSID_LEN + 1] = {0}, passwd[OS_MAX_PASSWD_LEN + 1] = {0};
/*    enum AWSS_AUTH_TYPE auth = AWSS_AUTH_TYPE_INVALID;enum AWSS_ENC_TYPE encry = AWSS_ENC_TYPE_INVALID;uint8_t channel = 0;*/uint8_t bssid[OS_ETH_ALEN] = {0};uint8_t token[ZC_MAX_TOKEN_LEN] = {0};uint8_t find_token = 0;int ret;uint8_t i;awss_stop_connecting = 0;awss_finished = 0;/* these params is useless, keep it for compatible reason */aws_start(NULL, NULL, NULL, NULL);...

__awss_start 会调用 aws_start(NULL, NULL, NULL, NULL);

void aws_start(char *pk, char *dn, char *ds, char *ps)
{aws_info = awss_zalloc(sizeof(struct aws_info));if (!aws_info) {return;}aws_state = AWS_SCANNING;/* start from -1 */aws_chn_index = 0xff;memcpy(aws_chn_list, aws_fixed_scanning_channels,sizeof(aws_fixed_scanning_channels));memset(aws_result_ssid, 0, sizeof(aws_result_ssid));memset(aws_result_passwd, 0, sizeof(aws_result_passwd));memset(aws_result_bssid, 0, sizeof(aws_result_bssid));aws_result_auth = ZC_AUTH_TYPE_INVALID;aws_result_encry = ZC_ENC_TYPE_INVALID;aws_result_channel = 0;zconfig_init();HAL_Awss_Open_Monitor(aws_80211_frame_handler);  //register_monitor_cb data_func
#ifndef AWSS_DISABLE_ENROLLEEawss_init_enrollee_info();
#endifaws_main_thread_func();
}

1、zconfig是一种管理和配置的方式,zconfig_init 负责分配内存。
2、HAL_Awss_Open_Monitor 设置Wi-Fi网卡工作在监听(Monitor)模式, 并在收到802.11帧的时候调用被传入的回调函数
3、开启一个线程,后面再说。

/** @brief   设置Wi-Fi网卡工作在监听(Monitor)模式,* 并在收到802.11帧的时候调用被传入的回调函数** @param[in] cb @n A function pointer, called back when wifi receive a frame.*/
void HAL_Awss_Open_Monitor(awss_recv_80211_frame_cb_t cb)
{hal_wifi_module_t *module = hal_wifi_get_default_module();if (module == NULL) {return;}
#ifdef AOS_COMP_PWRMGMTaos_pwrmgmt_lowpower_suspend(PWRMGMT_NETMGR);
#endifg_ieee80211_handler = cb;   hal_wifi_register_monitor_cb(module, monitor_data_handler);hal_wifi_start_wifi_monitor(module);HAL_Awss_Switch_Channel(6, 0, NULL);
}awss_recv_80211_frame_cb_t g_ieee80211_handler;static void monitor_data_handler(uint8_t *buf, int len, hal_wifi_link_info_t *info)
{int with_fcs  = 0;unsigned char rssi = -1;int link_type = AWSS_LINK_TYPE_NONE;if (info) {rssi = info->rssi;}(*g_ieee80211_handler)((char *)buf, len, link_type, with_fcs, rssi);
}static void start_monitor(hal_wifi_module_t *m)
{wifi_set_mode(STATION_MODE);    //设置 8266 sta模式wifi_station_disconnect();      //断开连接wifi_promiscuous_enable(0);     //禁用混杂模式,百度翻译滥交...wifi_set_promiscuous_rx_cb(sniffer_wifi_promiscuous_rx); //设置数据回调wifi_promiscuous_enable(1);     //启用混杂模式
}

1、获取wifi模块
2、给g_ieee80211_handler 赋值,并注册数据回调
3、hal_wifi_start_wifi_monitor 最终调用启动混杂模式
4、设置Wi-Fi网卡、模组或芯片切换到指定的信道(channel)上 6
sniffer_wifi_promiscuous_rx 数据处理函数 会调用到注册的 aws_80211_frame_handler函数

void aws_main_thread_func(void)
{int interval = 0;aws_start_timestamp = os_get_time_ms();/* channel switch init */aws_switch_channel();
rescanning:/* start scaning channel */memset(zc_bssid, 0, ETH_ALEN);while (aws_amend_dst_chan != 0 || aws_state == AWS_SCANNING) {awss_update_config_press();switch (aws_is_chnscan_timeout()) {case CHNSCAN_ONGOING:break;case CHNSCAN_NEXT_CHN:aws_switch_channel();break;case CHNSCAN_TIMEOUT:goto timeout_scanning;default:break;}if (aws_stop == AWS_STOPPING) { /* interrupt by user */goto timeout_scanning;}if (aws_state != AWS_SCANNING) { /* channel is locked, don't need to tx probe req */break;}interval = (awss_get_channel_scan_interval_ms() + 2) / 3;if (interval < 1) {interval = 1;}/* 80211 frame handled by callback */HAL_SleepMs(interval);
#ifndef AWSS_DISABLE_ENROLLEEawss_broadcast_enrollee_info();
#endifHAL_SleepMs(interval);
#ifdef AWSS_SUPPORT_DISCOVERaws_discover_send_beacon();
#endifHAL_SleepMs(interval);
#ifdef AWSS_SUPPORT_AHAaws_send_aha_probe_req();
#endif}...

在未配网的情况下,一直卡在这个wihle循环里面。

默认配网是通过按键触发的,GPIO14 我的8266管脚是D5,旁边就是 GND和3.3V的引脚,我们可以通过将D5先接GND,再接3.3V方式模拟,当然这样做很容易引起芯片复位重启。
默认配网触发函数在 application_start 函数里,前面已经讲过

aos_register_event_filter(EV_KEY, linkkit_key_process, NULL);
void linkkit_key_process(input_event_t *eventinfo, void *priv_data)
{if (eventinfo->type != EV_KEY) {return;}LOG("awss config press %u\n", eventinfo->value);if (eventinfo->code == CODE_BOOT) {if (eventinfo->value == VALUE_KEY_CLICK) {do_awss_active();} else if (eventinfo->value == VALUE_KEY_LTCLICK) {do_awss_reset();}}
}void do_awss_active()
{LOG("do_awss_active %d\n", awss_running);awss_running = 1;
#ifdef WIFI_PROVISION_ENABLEDextern int awss_config_press();awss_config_press();
#endif
}

awss_config_press 函数路径 middleware\linkkit\wifi_provision\frameworks\awss.c

int awss_config_press(void)
{config_press_start_timestamp = os_get_time_ms();awss_trace("enable awss\r\n");g_user_press = 1;awss_event_post(IOTX_AWSS_ENABLE);return 0;
}

awss_event_post 函数路径 middleware\linkkit\wifi_provision\dev_bind\awss_event.c

int awss_event_post(int event)
{int ret = 0;void *cb = NULL;ret = iotx_event_post(event);  //一句打印而已cb = (void *)iotx_event_callback(ITE_AWSS_STATUS);if (cb) {ret = ((int (*)(int))cb)(event);}return ret;
}
int iotx_event_regist_cb(void (*monitor_cb)(int event))
{g_event_monitor = (void *)monitor_cb;return 0;
}
int iotx_event_post(int event)
{if (g_event_monitor == NULL) {return -1;}((void (*)(int))g_event_monitor)(event);return 0;
}

awss_event_post 是调用函数,相应的,iotx_event_regist_cb是注册函数,配网注册的函数为

iotx_event_regist_cb(linkkit_event_monitor);

linkkit_event_monitor 里关于配网 IOTX_AWSS_ENABLE 的调用只是一行打印

static void linkkit_event_monitor(int event)
{switch (event) {case IOTX_AWSS_START: // AWSS start without enbale, just supports device discover// operate led to indicate userLOG("IOTX_AWSS_START");break;case IOTX_AWSS_ENABLE: // AWSS enable, AWSS doesn't parse awss packet until AWSS is enabled.LOG("IOTX_AWSS_ENABLE");// operate led to indicate userbreak;....

回到 cb = (void *)iotx_event_callback(ITE_AWSS_STATUS) 调用的地方。
iotx_event_callback 这个函数找了很久,最好发现没调用。也就是返回了NULL,所以这个地方只修改了两个标志位。
这个标志位可以通过awss_get_config_press 函数返回,加了打印,确认总共有一下三个函数调用用到它,智能配网 应该就是第三个,只是其它两个也应该脱不了干系。

awss_ieee80211_zconfig_process
awss_ieee80211_wps_process
awss_ieee80211_smartconfig_process

所以配网过程中,是放开了上面某个函数的流程,去检测分析了某类包

AliOS-Things ESP8266 配网 学习相关推荐

  1. ESP8266配网并将IP显示至oled液晶屏 ESP8266远程连接服务器控制灯或继电器

    智能车与机器人技术交流平台 概述 可能已经有人很熟练的编写ESP8266程序,但是因为我学习运用的时间也就一周左右,踩了好多坑,所以不喜就不要看勿喷.文章仅此分享交流一些经验,供此参考. 主要做的工作 ...

  2. stm32 esp8266配网-smartConfig和BT串口方式配网

    stm32 esp8266 ota系列文章: stm32 esp8266 ota-快速搭建web服务器之docker安装openresty stm32 esp8266 ota升级-tcp模拟http ...

  3. ESP8266配网最方便快捷的库

    ESP8266配网最方便快捷的库 WiFiManager.h应该是我见过的配网库里面最快捷方便,而且功能齐全的库. 库的地址:GitHub 不需要手动写配置页面.省去了html代码的编写. 实例程序代 ...

  4. 如何给esp8266 配网?

    玩ESP8266也有一段时间了,发一篇博客记录一下ESP8266配网的方法,也希望能给大家提供一点帮助,我使用的是Arduino的开发环境. 1. 固定在程序里 首先是测试时我们经常将自己家的WIFI ...

  5. ESP8266开发、ESP8266连接阿里云物联网、天猫精灵控制esp8266、esp8266一键配网、智能家居

    ESP8266开发.ESP8266连接阿里云物联网.天猫精灵控制esp8266.esp8266一键配网.智能家居 项目介绍 最近会 将arduino IDE开发ESP8266中一些值得记录得部分写下来 ...

  6. ESP8266固件SDK开发之微信配网(AIRKISS)原理(一)

    一.ESP8266开发可以有两种方式: 1.AT指令编程开发 2.基于SDK编程开发 二.ESP8266配网方式有三种: 1.网页配网 2.APP配网 3.微信配网 AIRKISS 这里,微信配网是最 ...

  7. STM32 ESP8266 微信Airkiss智能配网连接WiFi并接入OneNET

    你是否还在直接将wifi的ssid和密码直接写入STM32程序中通过串口发送给ESP8266?本文教你用微信Airkiss协议实现可视化地为ESP8266发送WiFi ssid和密码信息并连接WiFi ...

  8. AliOS Things的SDK ESP8266 连接阿里生活物联网平台 配网失败解决方案

    SDK版本:1.6.6AliOS Things的SDK(基于AliOS Things V1.3.4) APP版本:云智能3.7.0       此方法只适用  ESP8266 可以通过事先写入到程序中 ...

  9. 乐鑫esp8266学习rtos3.0笔记第4篇:带你捋一捋微信公众号 airkiss 配网 esp8266 并绑定设备的过程,移植并成功实现在 esp8266 rtos3.1 sdk。(附带demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. Esp8266之 搭建开发环境,开始一个"hello ...

最新文章

  1. WebService(1)名词了解
  2. Python3内置模块之json编码解码方法讲解
  3. linux统计某个目录大小,Linux下统计某个目录的文件个数(转)
  4. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)(转)
  5. k8s 拉取镜像失败_k8s 拉取私有仓库失败
  6. boolean类型默认值_【Java基础】还在问String属于什么数据类型
  7. BZOJ4066 简单题(KD-Tree)
  8. FastReport.Net使用:[1]屏蔽打印对话框
  9. oracle有rtf函数,Delphi中对Oracle存取RTF文档(作者:苏涌)
  10. #GNS3,wireshark,CRT的安装
  11. Krpano(虚拟漫游)
  12. golang如何实现静态变量的效果
  13. 第九章 9.3.4节练习 9.3.5节练习
  14. 【English】 详解 祈使句的用法
  15. 阻容感基础06:电容器分类(3)-薄膜电容器
  16. 单播,组播,广播概念
  17. 图解网络(三)——IP
  18. FusionCloud 桌面云时钟同步方案介绍
  19. Android官方文档翻译 五 1.3Building a Simple User Interface
  20. 【附源码】Python计算机毕业设计社区养老信息管理系统

热门文章

  1. linux下微信不能同步,Linux下微信安装
  2. 雷电2接口_让轻薄本不再受制于接口少 - Belkin 雷电3扩展坞-核心版
  3. AI赛车手登上Nature封面,人工智能选手如何狂虐人类顶级玩家?
  4. 据说可以让男人看一遍就哭的文章
  5. 【一周新闻荟】速看!本周互联网热点话题(第一期)
  6. 雨伞连线题php fgetcsv,如何使用纯CSS实现一把雨伞开合的动画效果(附源码)
  7. 移动机器人系列1——移动机器人分类
  8. qq打不开微信连接到服务器错误怎么回事,微信QQ打不开视频链接是怎么回事?附原因介绍...
  9. 写给iOS程序员的命令行使用秘籍
  10. MySQL原理--隔离级别的实现方式--MVCC