前言
本文主要在官方DEMO上分析扫描和连接WIFI的步骤和所调用的函数。
一、WIFI扫描
1.函数解析
首先我们来看一下WIFI扫描所调用的函数,如下:
int wifi_scan(void)
{
tls_wifi_scan_result_cb_register(wifi_scan_handler);
tls_wifi_scan();
return WM_SUCCESS;
}
我们先来看第一个函数tls_wifi_scan_result_cb_register,在注释中可以知道函数的功能是登记回调函数。其中wifi_scan_handler是另外一个函数的入口,在调用tls_wifi_scan之前必须使用tls_wifi_scan_result_cb_register进行登记。运行完tls_wifi_scan函数后,再运行回调函数(也就是wifi_scan_handler)。
下面来看一下wifi_scan_handler函数,具体解析请看注释
static void wifi_scan_handler(void)
{
char *buf = NULL; //缓存指针,用于接收wifi扫描的 “全部” 结果
char *buf1 = NULL; //缓存指针,用于从buf复制wifi扫描结果的“单条”wifi信息
u32 buflen; //缓存buf的长度
int i, j;
int err; //错误标志
u8 ssid[33]; //wifi名称
struct tls_scan_bss_t *wsr; //存放wifi扫描结果的个数和长度指针
struct tls_bss_info_t *bss_info; //存放“单条”wifi扫描结果的结构体指针
buflen = 2000; //申请内存
buf = tls_mem_alloc(buflen);
if (!buf)
{
goto end;
}
buf1 = tls_mem_alloc(300);
if(!buf1)
{
goto end;
}
memset(buf1, 0, 300);
err = tls_wifi_get_scan_rslt((u8 *)buf, buflen); //获取wifi扫描结果
if (err)
{
goto end;
}
wsr = (struct tls_scan_bss_t *)buf; //复制wifi扫描结果的个数和长度,占8个字节
bss_info = (struct tls_bss_info_t *)(buf + 8); //复制扫描结果开始处指针(buf的前8字节为个数和长度,已经存放在wsr)
printf("\n");
for(i = 0; i < wsr->count; i++)
{
j = sprintf(buf1, "bssid:%02X%02X%02X%02X%02X%02X, ", bss_info->bssid[0], bss_info->bssid[1],
bss_info->bssid[2], bss_info->bssid[3], bss_info->bssid[4], bss_info->bssid[5]); //路由器MAC地址
j += sprintf(buf1 + j, "ch:%d, ", bss_info->channel); //WiFi信道
j += sprintf(buf1 + j, "rssi:%d, ", (signed char)bss_info->rssi); //接收信号强度
j += sprintf(buf1 + j, "wps:%d, ", bss_info->wps_support); //是否支持WPS
j += sprintf(buf1 + j, "max_rate:%dMbps, ", bss_info->max_data_rate); //最大传输速率
j += sprintf(buf1 + j, "%s, ", scan_mode_string(bss_info->mode)); //ap类型
j += sprintf(buf1 + j, "%s, ", scan_privacy_string(bss_info->privacy)); //加密方式
memcpy(ssid, bss_info->ssid, bss_info->ssid_len);
ssid[bss_info->ssid_len] = '\0';
j += sprintf(buf1 + j, "%s", ssid); //完成wifi名称的复制
printf("%s\n", buf1); //打印所有信息
bss_info ++;
}
//以下被注释的地方是官方的代码,可能会是bug。因为在上面代码发生错误后指针仍为NULL,
//会导致申请的内存不能释放
end:
/*if(buf)
{
tls_mem_free(buf);
}
if(buf1)
{
tls_mem_free(buf1);
}*/
tls_mem_free(buf);
tls_mem_free(buf1);
}
2.演示
在user_main()中直接调用wifi_scan()。下载运行后,打开串口接收wifi扫描信息,如下:
二、连接WIFI
1.函数解析
步骤:
- 断开原有的连接;
- 设置协议参数;
- 登记回调函数;
- 调用连接函数。
//参数 ssid:wifi名称
// pwd:wifi密码
int wifi_connect(char *ssid, char *pwd)
{
struct tls_param_ip *ip_param = NULL; //存在ip地址,掩码,DNS地址等参数
u8 wireless_protocol = 0; //协议标准
if (!ssid)
{
return WM_FAILED;
}
printf("\nssid:%s\n", ssid);
printf("password=%s\n", pwd);
tls_wifi_disconnect(); //断开原有连接
tls_param_get(TLS_PARAM_ID_WPROTOCOL, (void *) &wireless_protocol, TRUE); //获取协议参数
if (TLS_PARAM_IEEE80211_INFRA != wireless_protocol)
{
tls_wifi_softap_destroy();
wireless_protocol = TLS_PARAM_IEEE80211_INFRA;
tls_param_set(TLS_PARAM_ID_WPROTOCOL, (void *) &wireless_protocol, FALSE);
} //设置infrastructure连接模式
tls_wifi_set_oneshot_flag(0); //关闭一键连接
ip_param = tls_mem_alloc(sizeof(struct tls_param_ip));
if (ip_param)
{
tls_param_get(TLS_PARAM_ID_IP, ip_param, FALSE);
ip_param->dhcp_enable = TRUE;
tls_param_set(TLS_PARAM_ID_IP, ip_param, FALSE);
//tls_mem_free(ip_param);
}
tls_mem_free(ip_param); //开启DHCP(动态的获得IP地址、Gateway地址、DNS服务器地址等信息)
tls_netif_add_status_event(con_net_status_changed_event);
//登记回调函数(当网络状态参数,如IP地址、子网掩码改变时,调用此回调函数)
tls_wifi_connect((u8 *)ssid, strlen(ssid), (u8 *)pwd, strlen(pwd)); //连接wifi
printf("\nplease wait connect net......\n");
return WM_SUCCESS;
}
然后再看一下网络状态改变时,调用的回调函数。
static void con_net_status_changed_event(u8 status )
{
switch(status)
{
case NETIF_WIFI_JOIN_SUCCESS: //连接成功
printf("NETIF_WIFI_JOIN_SUCCESS\n");
break;
case NETIF_WIFI_JOIN_FAILED: //连接失败
printf("NETIF_WIFI_JOIN_FAILED\n");
break;
case NETIF_WIFI_DISCONNECTED: //断开wifi
printf("NETIF_WIFI_DISCONNECTED\n");
break;
case NETIF_IP_NET_UP: //获得ip地址
{
struct tls_ethif *tmpethif = tls_netif_get_ethif();
print_ipaddr(&tmpethif->ip_addr);
#if TLS_CONFIG_IPV6
print_ipaddr(&tmpethif->ip6_addr[0]);
print_ipaddr(&tmpethif->ip6_addr[1]);
print_ipaddr(&tmpethif->ip6_addr[2]); //打印ip地址
#endif
}
break;
default:
//printf("UNKONWN STATE:%d\n", status);
break;
}
}
2.演示
在void UserMain(void)中调用wifi_connect(char *ssid, char *pwd)函数,设置和打开手机热点。
void UserMain(void)
{
printf("\n user main \n");
wifi_connect("程序猿Aki", "1234567890");
}
串口发送如下:
此时在手机上可以看到连接的设备
三、进群讨论分享!
如果你喜欢我的文章,欢迎关注下方公众号,在公众号内回复“交流群”,进群一起讨论分享!