Wi-Fi开发指南
引言
移远通信FC41D模块、FCM100D模块、FCM740D模块和FLMx40D模块支持QuecOpen®方案;QuecOpen®是基于RTOS系统的嵌入式开发平台,可简化IoT应用的软件设计和开发过程。有关QuecOpen®的详细信息,请参考 快速入门指南。
本文档适用于SDK构建环境的QuecOpen®方案,主要介绍在QuecOpen®方案下,FC41D模块、FCM100D模块、FCM740D模块和FLMx40D模块的Wi-Fi API和相关示例。
适用模块
适用模块:
| 模块系列 | 模块 |
|---|---|
| FC41D | |
| FCM100D | |
| FCM740D | |
| FLMx40D | FLM040D |
| FLM140D | |
| FLM240D | |
| FLM340D |
Wi-Fi API
头文件
Wi-Fi API的头文件为ql_wlan.h,位于SDK包的ql_components/qadpt/include/目录下。若无特别说明,本文档所涉及头文件均在该目录下。
函数概览
函数概览:
| 函数 | 说明 |
|---|---|
ql_wlan_start() |
启动网络连接,包括STA和AP |
ql_wlan_start_sta_adv() |
启动STA快速连接网络 |
ql_wlan_stop() |
关闭网络连接,包括STA和AP |
ql_wlan_start_scan() |
启动扫描网络 |
ql_wlan_scan_ap_reg_cb() |
注册扫描结束后调用的回调函数 |
ql_wlan_sta_scan_result() |
获取扫描到的结果 |
ql_wlan_start_assign_scan() |
扫描指定的网络 |
ql_wlan_start_monitor() |
启动监听模式 |
ql_wlan_stop_monitor() |
关闭监听模式 |
ql_wlan_register_monitor_cb() |
注册监听回调函数 |
ql_wlan_get_ip_status() |
获取当前的网络状态 |
ql_wlan_get_link_status() |
获取当前的连接状态 |
ql_wlan_ap_para_info_get() |
获取当前的AP信息 |
ql_wlan_get_channel() |
获取当前的信道 |
ql_sta_chiper_type() |
获取当前STA的加密方式 |
ql_wlan_set_channel() |
设置信道 |
ql_wlan_ota_download() |
升级模块固件 |
函数详解
ql_wlan_start
该函数用于启动网络连接,包括STA和AP。上层应用获得SSID与密码后,即可启动网络连接。
函数原型:
int ql_wlan_start(ql_network_InitTypeDef_s *inNetworkInitPara)
参数:
inNetworkInitPara:
[In] 网络连接配置信息;详见ql_network_InitTypeDef_s。
返回值:
0函数执行成功其他值 函数执行失败
ql_network_InitTypeDef_s
网络连接配置信息结构体定义如下:
typedef struct
{
char wifi_mode;
char wifi_ssid[33];
char wifi_key[64];
char local_ip_addr[16];
char net_mask[16];
char gateway_ip_addr[16];
char dns_server_ip_addr[16];
char dhcp_mode;
char wifi_bssid[6];
char reserved[26];
int wifi_retry_interval;
} ql_network_InitTypeDef_s
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| char | wifi_mode |
Wi-Fi模式。 |
| char | wifi_ssid |
待连接或建立的网络SSID。 |
| char | wifi_key |
待连接或建立的网络密码。 |
| char | local_ip_addr |
静态IP地址;在DHCP禁用时有效。 |
| char | net_mask |
静态子网掩码;在DHCP禁用时有效。 |
| char | gateway_ip_addr |
静态网关地址;在DHCP禁用时有效。 |
| char | dns_server_ip_addr |
静态DNS地址;在DHCP禁用时有效。 |
| char | dhcp_mode |
DHCP模式。 |
| char | wifi_bssid |
AP的MAC地址。 |
| char | reserved |
预留。 |
| int | wifi_retry_interval |
重连间隔;单位:毫秒。 |
ql_wlan_start_sta_adv
该函数用于启动STA快速连接网络。
函数原型:
int ql_wlan_start_sta_adv(ql_network_InitTypeDef_s *inNetworkInitParaAdv)
参数:
inNetworkInitParaAdv:
[In] 网络参数;详见ql_network_InitTypeDef_s。
返回值:
0函数执行成功
其他值 函数执行失败
ql_network_InitTypeDef_adv_s
网络参数结构体定义如下:
typedef struct ql_network_InitTypeDef_adv_st
{
ql_apinfo_adv_s ap_info;
char key[64];
int key_len;
char local_ip_addr[16];
char net_mask[16];
char gateway_ip_addr[16];
char dns_server_ip_addr[16];
char dhcp_mode;
char reserved[32];
int wifi_retry_interval;
} ql_network_InitTypeDef_adv_s
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
ql_apinfo_adv_s |
ap_info |
待快速连接的网络信息;详见ql_apinfo_adv_s。 |
| char | key |
待快速连接的网络密码。 |
| int | key_len |
网络密码长度;单位:字节。 |
| char | local_ip_addr |
静态IP地址;在DHCP禁用时有效。 |
| char | net_mask |
静态子网掩码;在DHCP禁用时有效。 |
| char | gateway_ip_addr |
静态网关地址;在DHCP禁用时有效。 |
| char | dns_server_ip_addr |
静态DNS地址;在DHCP禁用时有效。 |
| char | dhcp_mode |
DHCP模式。 |
| char | reserved |
预留。 |
| int | wifi_retry_interval |
重连间隔;单位:毫秒。 |
ql_apinfo_adv_s
待快速连接的网络信息结构体定义如下:
typedef struct
{
char ssid[32];
char bssid[6];
uint8_t channel;
uint8_t security;
} ql_apinfo_adv_s
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| char | ssid |
待快速连接的网络的SSID。 |
| char | bssid |
待快速连接的网络的BSSID。 |
| uint8_t | channel |
待快速连接的网络的通道。 |
| uint8_t | security |
AP加密方式;详见ql_wlan_sec_type_e。 |
ql_wlan_sec_type_e
AP加密方式的枚举定义如下:
typedef enum
{
QL_SECURITY_TYPE_NONE,
QL_SECURITY_TYPE_WEP,
QL_SECURITY_TYPE_WPA_TKIP,
QL_SECURITY_TYPE_WPA_AES,
QL_SECURITY_TYPE_WPA2_TKIP,
QL_SECURITY_TYPE_WPA2_AES,
QL_SECURITY_TYPE_WPA2_MIXED,
QL_SECURITY_TYPE_WPA3_SAE,
QL_SECURITY_TYPE_WPA3_WPA2_MIXED,
QL_SECURITY_TYPE_EAP,
QL_SECURITY_TYPE_OWE,
QL_SECURITY_TYPE_AUTO,
}ql_wlan_sec_type_e
成员:
| 成员 | 描述 |
|---|---|
QL_SECURITY_TYPE_NONE |
无加密。 |
QL_SECURITY_TYPE_WEP |
WEP加密。 |
QL_SECURITY_TYPE_WPA_TKIP |
WPA_TKIP加密。 |
QL_SECURITY_TYPE_WPA_AES |
WPA_AES加密。 |
QL_SECURITY_TYPE_WPA2_TKIP |
WPA2_TKIP加密。 |
QL_SECURITY_TYPE_WPA2_AES |
WPA2_AES加密。 |
QL_SECURITY_TYPE_WPA2_MIXED |
WPA2混合加密。 |
QL_SECURITY_TYPE_WPA3_SAE |
WPA3_SAE加密。 |
QL_SECURITY_TYPE_WPA3_WPA2_MIXED |
WPA3与WPA2混合加密。 |
QL_SECURITY_TYPE_AUTO |
自动加密。 |
ql_wlan_stop
该函数用于关闭网络工作模式,包括STA和AP。
函数原型:
int ql_wlan_stop(ql_wlanInterface_Typedef_e mode)
参数:
mode:
[In] 待关闭的网络工作模式;详见ql_wlanInterface_Typedef_e。
返回值:
0函数执行成功其他值 函数执行失败
ql_wlanInterface_Typedef_e
待关闭的网络工作模式枚举定义如下:
typedef enum
{
QL_SOFT_AP = BK_SOFT_AP,
QL_STATION = BK_STATION
} ql_wlanInterface_Typedef_e
成员:
| 成员 | 描述 |
|---|---|
QL_SOFT_AP |
AP模式 |
QL_STATION |
STA模式 |
ql_wlan_start_scan
该函数用于启动扫描网络。
函数原型:
int ql_wlan_start_scan(void)
参数:
无
返回值:
0函数执行成功其他值 函数执行失败
ql_wlan_scan_ap_reg_cb
该函数用于注册扫描结束后调用的回调函数。
函数原型:
int ql_wlan_scan_ap_reg_cb(ql_func_scan_callback ind_cb)
参数:
ind_cb:
[In] 扫描结束后调用的回调函数;详见ql_func_scan_callback。
返回值:
0函数执行成功其他值 函数执行失败
ql_func_scan_callback
该函数为扫描结束后调用的回调函数。
函数原型:
typedef void (*ql_func_scan_callback)(void *arg, uint8_t vif_idx)
参数:
arg:[Out] 输出参数。
vif_idx:[Out] 暂无意义。
ql_wlan_sta_scan_result
该函数用于获取扫描到的结果,可在扫描结束后调用的回调函数中使用。
函数原型:
int ql_wlan_sta_scan_result(ScanResult_adv *results)
参数:
results:
[In] 扫描结果;详见ScanResult_adv。
返回值:
0函数执行成功其他值 函数执行失败
ScanResult_adv
扫描结果结构体定义如下:
typedef struct _ScanResult_adv
{
char ApNum;
struct ApListStruct
{
char ssid[33];
char ApPower;
uint8_t bssid[6];
char channel;
wlan_sec_type_t security;
} *ApList;
} ScanResult_adv
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| char | ApNum |
扫描到的AP数量。 |
| char | ssid |
扫描到的AP的SSID。 |
| char | ApPower |
扫描到AP的信号强度。最小值:0;最大值:100。 |
| char | bssid |
扫描到的AP的BSSID。 |
| char | channel |
扫描到的AP的通道。 |
wlan_sec_type_t |
security |
AP加密方式;详见ql_wlan_sec_type_e。 |
ql_wlan_start_assign_scan
该函数用于扫描指定的网络。
函数原型:
int ql_wlan_start_assign_scan(UINT8 **ssid_ary, UINT8 ssid_num)
参数:
ssid_ary:[In] 指定网络的SSID。
ssid_num:[In] 指定网络的数量。
返回值:
0函数执行成功其他值 函数执行失败
ql_wlan_start_monitor
该函数用于启动监听模式。
函数原型:
int ql_wlan_start_monitor(void)
参数:
无
返回值:
0函数执行成功其他值 函数执行失败
ql_wlan_stop_monitor
该函数用于关闭监听模式。
函数原型:
int ql_wlan_stop_monitor(void)
参数:
无
返回值:
0函数执行成功其他值 函数执行失败
ql_wlan_register_monitor_cb
该函数注册用于监听回调函数。
函数原型:
int ql_wlan_register_monitor_cb(monitor_cb_t fn)
参数:
fn:
[In] 监听回调函数;详见monitor_cb_t。
返回值:
0函数执行成功其他值 函数执行失败
monitor_cb_t
该函数为待注册的监听回调函数。
函数原型:
typedef void (* monitor_cb_t )(uint8_t *data, int len, wifi_link_info_t *info)
参数:
data:[Out] 监听返回的数据。
len:[Out] 监听返回的数据长度;单位:字节。
info:[Out] 监听返回的信息;详见wifi_link_info_t。
wifi_link_info_t
监听到的数据包信息结构体定义如下:
typedef struct
{
int8_t rssi;
}wifi_link_info_t
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| Int8 | rssi |
监听到数据包的信号强度。 |
ql_wlan_get_ip_status
该函数用于获取当前的网络状态。
函数原型:
int ql_wlan_get_ip_status(IPStatusTypedef *outNetpara, WiFi_Interface inInterface)
参数:
outNetpara:[Out] 网络状态;详见IPStatusTypedef。
inInterface:[In] 网络工作模式;详见IPStatusTypedef。
返回值:
0函数执行成功其他值 函数执行失败
IPStatusTypedef
网络状态结构体定义如下:
typedef struct
{
uint8_t dhcp;
char ip[16];
char gate[16];
char mask[16];
char dns[16];
char mac[16];
char broadcastip[16];
} IPStatusTypedef
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint8_t | dhcp |
获取的DHCP模式。 |
| char | ip |
获取的IP地址。 |
| char | gate |
获取的网关IP地址。 |
| char | mask |
获取的子网掩码。 |
| char | dns |
DNS服务IP地址。 |
| char | mac |
获取的MAC地址。 |
| char | broadcastip |
获取的广播IP地址。 |
ql_wlan_get_link_status
该函数用于获取当前的连接状态。
函数原型:
int ql_wlan_get_link_status(LinkStatusTypeDef *outStatus)
参数:
outStatus:
[Out] 连接状态;详见LinkStatusTypeDef。
返回值:
0函数执行成功其他值 函数执行失败
LinkStatusTypeDef
连接状态结构体定义如下:
typedef struct _linkStatus_t
{
int conn_state;
int wifi_strength;
uint8_t ssid[32];
uint8_t bssid[6];
int channel;
uint8_t security;
} LinkStatusTypeDef
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| int | conn_state |
当前模块Wi-Fi的连接状态;详见ql_wlan_evt_type。 |
| int | wifi_strength |
当前的信号强度。 |
| uint8_t | ssid |
当前网络的SSID。 |
| uint8_t | bssid |
AP的MAC地址。 |
| int | channel |
当前网络的信道。 |
| uint8_t | security |
AP加密方式;详见ql_wlan_sec_type_e。 |
ql_wlan_evt_type
当前模块Wi-Fi的连接状态枚举定义如下:
typedef enum { QL_WLAN_EVT_STA_IDLE = 0,
QL_WLAN_EVT_STA_CONNECTING,
QL_WLAN_EVT_STA_BEACON_LOSE,
QL_WLAN_EVT_STA_PASSWORD_WRONG,
QL_WLAN_EVT_STA_NO_AP_FOUND,
QL_WLAN_EVT_STA_ASSOC_FULL,
QL_WLAN_EVT_STA_DISCONNECTED,
QL_WLAN_EVT_STA_CONNECT_FAILED,
QL_WLAN_EVT_STA_CONNECTED,
QL_WLAN_EVT_STA_GOT_IP, QL_WLAN_EVT_AP_CONNECTED,
QL_WLAN_EVT_AP_DISCONNECTED,
QL_WLAN_EVT_AP_CONNECT_FAILED,
QL_WLAN_EVT_MAX
}ql_wlan_evt_type
成员:
| 成员 | 描述 |
|---|---|
QL_WLAN_EVT_STA_IDLE |
空闲 |
QL_WLAN_EVT_STA_CONNECTING |
模块作为STA与AP连接中 |
QL_WLAN_EVT_STA_BEACON_LOSE |
Beacon帧丢失 |
QL_WLAN_EVT_STA_PASSWORD_WRONG |
密码错误 |
QL_WLAN_EVT_STA_NO_AP_FOUND |
未找到目标AP |
QL_WLAN_EVT_STA_ASSOC_FULL |
模块作为STA与AP连接,AP可供连接的数量已达最大值 |
QL_WLAN_EVT_STA_DISCONNECTED |
模块作为STA与AP连接断开 |
QL_WLAN_EVT_STA_CONNECT_FAILED |
模块作为STA与AP连接失败 |
QL_WLAN_EVT_STA_CONNECTED |
模块作为STA与AP已连接,正在获取IP |
QL_WLAN_EVT_STA_GOT_IP |
模块作为STA与AP已连接,成功获取IP |
QL_WLAN_EVT_AP_CONNECTED |
模块作为AP与STA连接成功 |
QL_WLAN_EVT_AP_DISCONNECTED |
模块作为AP与STA连接断开 |
QL_WLAN_EVT_AP_CONNECT_FAILED |
模块作为AP与STA连接失败 |
ql_wlan_ap_para_info_get
该函数用于获取当前AP信息。
函数原型:
int ql_wlan_ap_para_info_get(network_InitTypeDef_ap_st *ap_info)
参数:
ap_info:
[Out] AP信息;详见network_InitTypeDef_ap_st。
返回值:
0函数执行成功其他值 函数执行失败
network_InitTypeDef_ap_st
AP信息结构体定义如下:
typedef struct _network_InitTypeDef_ap_st
{
char wifi_ssid[32];
char wifi_key[64];
uint8_t channel;
wlan_sec_type_t security;
uint8_t ssid_hidden;
uint8_t max_con;
char local_ip_addr[16];
char net_mask[16];
char gateway_ip_addr[16];
char dns_server_ip_addr[16];
char dhcp_mode;
char reserved[32];
int wifi_retry_interval;
} network_InitTypeDef_ap_st
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| char | wifi_ssid |
待连接或建立的网络SSID。 |
| char | wifi_key |
待连接或建立的网络密码。 |
| uint8_t | channel |
当前网络的信道。 |
wlan_sec_type_t |
security |
AP加密方式;详见ql_wlan_sec_type_e。 |
| uint8_t | ssid_hidden |
隐藏SSID广播使能。 |
| uint8_t | max_con |
最大并发STA连接数。 |
| char | local_ip_addr |
静态IP地址;在DHCP禁用时有效。 |
| char | net_mask |
静态子网掩码;在DHCP禁用时有效。 |
| char | gateway_ip_addr |
静态网关地址;在DHCP禁用时有效。 |
| char | dns_server_ip_addr |
静态DNS地址;在DHCP禁用时有效。 |
| char | dhcp_mode |
DHCP模式。 |
| char | reserved |
预留。 |
| int | wifi_retry_interval |
重连间隔;单位:毫秒。 |
ql_wlan_get_channel
该函数用于获取当前的信道。
函数原型:
int ql_wlan_get_channel(void)
参数:
无
返回值:
当前信道
ql_sta_chiper_type
该函数用于获取当前STA的加密方式。
函数原型:
int ql_sta_chiper_type(void)
参数:
无
返回值:
STA的加密方式;详见ql_wlan_sec_type_e。
ql_wlan_set_channel
该函数用于设置信道。
函数原型:
int ql_wlan_set_channel(int channel)
参数:
channel:
[In] 信道。
返回值:
0函数执行成功其他值 函数执行失败
ql_wlan_ota_download
该函数用于升级模块固件。
函数原型:
int ql_wlan_ota_download(const char *uri)
参数:
uri:
[In] 升级包存储的HTTP服务器域名。
返回值:
0函数执行成功其他值 函数执行失败
示例
常量定义
LinkStatusTypeDef
#define DHCP_DISABLE (0) /*DHCP禁用*/
#define DHCP_CLIENT (1) /*DHCP客户端模式*/
#define DHCP_SERVER (2) /* DHCP服务端模式*/
示例代码
启动STA连接网络
void demo_sta_app_init(char *oob_ssid,char *connect_key)
{
/*定义一个结构体,用于传入参数*/
network_InitTypeDef_st wNetConfig;
int len;
/*置空结构体*/
os_memset(&wNetConfig, 0x0, sizeof(network_InitTypeDef_st));
/*检查SSID的长度,不能超过32字节*/
len = os_strlen(oob_ssid);
if(SSID_MAX_LEN < len)
{
os_printf("ssid name more than 32 Bytes\r\n");
return;
}
/*将SSID跟密码传入结构体*/
os_strcpy((char *)wNetConfig.wifi_ssid, oob_ssid);
os_strcpy((char *)wNetConfig.wifi_key, connect_key);
/*当前为客户端模式*/
wNetConfig.wifi_mode = QL_STATION;
/*采用DHCP CLIENT的方式获得,从路由器动态获取IP地址*/
wNetConfig.dhcp_mode = DHCP_CLIENT;
wNetConfig.wifi_retry_interval = 100;
os_printf("ssid:%s key:%s\r\n", wNetConfig.wifi_ssid,
wNetConfig.wifi_key);
/*启动Wi-Fi连接*/
ql_wlan_start(&wNetConfig);
}
启动AP
void demo_softap_app_init(char *ap_ssid, char *ap_key)
{
/*定义一个结构体,用于传入参数*/
network_InitTypeDef_st wNetConfig;
int len;
/*置空结构体*/
os_memset(&wNetConfig, 0x0, sizeof(network_InitTypeDef_st));
len = os_strlen(ap_ssid);
if(SSID_MAX_LEN < len)
{
os_printf("ssid name more than 32 Bytes\r\n");
return;
}
/*传入要连接的ap ssid 和 ap key*/
os_strcpy((char *)wNetConfig.wifi_ssid, ap_ssid);
os_strcpy((char *)wNetConfig.wifi_key, ap_key);
/*当前为ap模式*/
wNetConfig.wifi_mode = QL_SOFT_AP;
/*采用DHCP SERVER模式,需要将静态地址分配为本地地址*/
wNetConfig.dhcp_mode = DHCP_SERVER;
wNetConfig.wifi_retry_interval = 100;
os_strcpy((char *)wNetConfig.local_ip_addr, WLAN_DEFAULT_IP);
os_strcpy((char *)wNetConfig.net_mask, WLAN_DEFAULT_MASK);
os_strcpy((char *)wNetConfig.gateway_ip_addr, WLAN_DEFAULT_GW);
os_strcpy((char *)wNetConfig.dns_server_ip_addr, WLAN_DEFAULT_GW);
os_printf("ssid:%s key:%s\r\n", wNetConfig.wifi_ssid,
wNetConfig.wifi_key);
/*启动ap*/
ql_wlan_start(&wNetConfig);
}
启动STA快速连接网络
void demo_sta_adv_app_init(char *oob_ssid,char *connect_key)
{
/*定义一个结构体,用于传入参数*/
network_InitTypeDef_adv_st wNetConfigAdv;
/*置空结构体*/
os_memset( &wNetConfigAdv, 0x0, sizeof(network_InitTypeDef_adv_st) );
/*传入要连接的SSID*/
os_strcpy((char*)wNetConfigAdv.ap_info.ssid, oob_ssid);
/*传入要连接的网络的bssid,下面这个bssid仅供参考*/
hwaddr_aton("48:ee:0c:48:93:12", (u8 *)(wNetConfigAdv.ap_info.bssid));
/*要连接网络的加密方式。具体参数参考该结构体说明。*/
wNetConfigAdv.ap_info.security = QL_SECURITY_TYPE_WPA2_MIXED;
/*要连接的网络的信道*/
wNetConfigAdv.ap_info.channel = 11;
/*要连接的网络密码以及密码长度*/
os_strcpy((char*)wNetConfigAdv.key, connect_key);
wNetConfigAdv.key_len = os_strlen(connect_key);
/*通过DHCP的方式获取IP地址等网络信息*/
wNetConfigAdv.dhcp_mode = DHCP_CLIENT;
wNetConfigAdv.wifi_retry_interval = 100;
/*启动快速连接*/
ql_wlan_start_sta_adv(&wNetConfigAdv);
}
启动扫描,并分析扫描的结果
/*回调函数,用于scan结束后解析scan结果*/
static void scan_cb(void *ctxt, uint8_t param)
{
#if !CFG_WPA_CTRL_IFACE
/*指向scan结果的指针*/
struct scanu_rst_upload *scan_rst;
/*保存解析结果的结构体*/
ScanResult apList;
int i;
GLOBAL_INT_DECLARATION();
apList.ApList = NULL;
GLOBAL_INT_DISABLE();
/*启动scan*/
scan_rst = sr_get_scan_results();
/*如果什么都没有scan到,返回;否则记录scan到的网络数量*/
if (scan_rst == NULL) {
GLOBAL_INT_RESTORE();
apList.ApNum = 0;
return;
} else {
apList.ApNum = scan_rst->scanu_num;
}
if (apList.ApNum > 0) {
/*申请对应的内存,用于保存scan的结果*/
apList.ApList = (void *)os_zalloc(sizeof(*apList.ApList) * apList.ApNum);
if(apList.ApList == NULL){
GLOBAL_INT_RESTORE();
os_printf("Got ap count: %d,but malloc failed\r\n", apList.ApNum);
return;
}
for (i = 0; i < scan_rst->scanu_num; i++) {
/*将scan到的网络ssid与rssi记录下来*/
os_memcpy(apList.ApList[i].ssid, scan_rst->res[i]->ssid, 32);
apList.ApList[i].ApPower = scan_rst->res[i]->level;
}
}
GLOBAL_INT_RESTORE();
if (apList.ApList == NULL)
apList.ApNum = 0;
/*打印scan的结果*/
os_printf("Got ap count: %d\r\n", apList.ApNum);
for (i = 0; i < apList.ApNum; i++) {
if (os_strlen(apList.ApList[i].ssid) >= SSID_MAX_LEN) {
char temp_ssid[33];
os_memset(temp_ssid, 0, 33);
os_memcpy(temp_ssid, apList.ApList[i].ssid, 32);
os_printf(" %s, RSSI=%d\r\n", temp_ssid, apList.ApList[i].ApPower);
} else {
os_printf(" %s, RSSI=%d\r\n", apList.ApList[i].ssid, apList.ApList[i].ApPower);
}
}
os_printf("Get ap end.......\r\n\r\n");
/*结束后释放申请的内存*/
if (apList.ApList != NULL) {
os_free(apList.ApList);
apList.ApList = NULL;
}
#if CFG_ROLE_LAUNCH
rl_pre_sta_set_status(RL_STATUS_STA_LAUNCHED);
#endif
sr_release_scan_results(scan_rst);
#else /* CFG_WPA_CTRL_IFACE */
static const char *crypto_str[] = {
"None",
"WEP",
"WPA_TKIP",
"WPA_AES",
"WPA2_TKIP",
"WPA2_AES",
"WPA2_MIXED", ////QL_SECURITY_TYPE_WPA3_SAE
"WPA3_SAE", /**< WPA3 SAE */
"WPA3_WPA2_MIXED", /** WPA3 SAE or WPA2 AES */
"AUTO",
};
ScanResult_adv apList;
if (wlan_sta_scan_result(&apList) == 0) {
int ap_num = apList.ApNum;
int i;
os_printf("Got ap count: %d\r\n", apList.ApNum);
for (i = 0; i < ap_num; i++)
os_printf(" \\"%s\\", " MACSTR "\\b, %d, %s, %d\n", apList.ApList[i].ssid, MAC2STR(apList.ApList[i].bssid), apList.ApList[i].ApPower, crypto_str[apList.ApList[i].security], apList.ApList[i].channel);
os_free(apList.ApList);
}
#endif /* CFG_WPA_CTRL_IFACE */
}
void demo_scan_app_init(void)
{
/*注册scan回调函数*/
mhdr_scanu_reg_cb(scan_cb, 0);
/*开始scan*/
ql_wlan_start_scan();
}
获取当前网络状态
void demo_ip_app_init(void)
{
IPStatusTypedef ipStatus;
os_memset(&ipStatus, 0x0, sizeof(IPStatusTypedef));
ql_wlan_get_ip_status(&ipStatus, QL_STATION);
os_printf("dhcp=%d ip=%s gate=%s mask=%s mac=" MACSTR "\r\n", ipStatus.dhcp, ipStatus.ip, ipStatus.gate, ipStatus.mask, MAC2STR((unsigned char*)ipStatus.mac));
}
连接成功后,获取连接状态
void demo_state_app_init(void)
{
/*定义结构体用于保存连接状态*/
LinkStatusTypeDef linkStatus;
network_InitTypeDef_ap_st ap_info;
char ssid[33] = {0};
#if CFG_IEEE80211N
os_printf("sta: %d, softap: %d, b/g/n\r\n", sta_ip_is_start(), uap_ip_is_start());
#else
os_printf("sta: %d, softap: %d, b/g\r\n", sta_ip_is_start(),
uap_ip_is_start());
#endif
/*STATION模式下的连接状态*/
if (sta_ip_is_start()) {
/*将用于保存状态的结构体置空*/
os_memset(&linkStatus, 0x0, sizeof(LinkStatusTypeDef));
/*获取连接状态*/
ql_wlan_get_link_status(&linkStatus);
os_memcpy(ssid, linkStatus.ssid, 32);
/*打印连接状态*/
os_printf("sta:rssi=%d,ssid=%s,bssid=" MACSTR ",channel=%d,cipher_type:", linkStatus.wifi_strength, ssid, MAC2STR(linkStatus.bssid), linkStatus.channel);
switch (ql_sta_chiper_type()) {
case QL_SECURITY_TYPE_NONE:
os_printf("OPEN\r\n");
break;
case QL_SECURITY_TYPE_WEP :
os_printf("WEP\r\n");
break;
case QL_SECURITY_TYPE_WPA_TKIP:
os_printf("TKIP\r\n");
break;
case QL_SECURITY_TYPE_WPA_AES:
os_printf("WPA_AES\r\n");
break;
case QL_SECURITY_TYPE_WPA2_AES:
os_printf("CCMP\r\n");
break;
case QL_SECURITY_TYPE_WPA2_TKIP:
os_printf("WPA2_TKIP\r\n");
break;
case QL_SECURITY_TYPE_WPA2_MIXED:
os_printf("WPA/WPA2 MIXED\r\n");
break;
case QL_SECURITY_TYPE_AUTO:
os_printf("AUTO\r\n");
break;
case QL_SECURITY_TYPE_WPA3_SAE:
os_printf("WPA3\n");
break;
case QL_SECURITY_TYPE_WPA3_WPA2_MIXED:
os_printf("WPA2/WPA3 MIXED\n");
break;
default:
os_printf("Error\r\n");
break;
}
}
/*AP模式下的连接状态*/
if (uap_ip_is_start()) {
/*将用于保存连接状态的结构体置空*/
os_memset(&ap_info, 0x0, sizeof(network_InitTypeDef_ap_st));
/*获取连接状态*/
ql_wlan_ap_para_info_get(&ap_info);
os_memcpy(ssid, ap_info.wifi_ssid, 32);
/*打印出获取的连接状态值*/
os_printf("softap:ssid=%s,channel=%d,dhcp=%d,cipher_type:", ssid, ap_info.channel, ap_info.dhcp_mode);
switch (ap_info.security) {
case QL_SECURITY_TYPE_NONE:
os_printf("OPEN\r\n");
break;
case QL_SECURITY_TYPE_WEP :
os_printf("WEP\r\n");
break;
case QL_SECURITY_TYPE_WPA_TKIP:
os_printf("TKIP\r\n");
break;
case QL_SECURITY_TYPE_WPA2_AES:
os_printf("CCMP\r\n");
break;
case QL_SECURITY_TYPE_WPA2_MIXED:
os_printf("WPA/WPA2 MIXED\r\n");
break;
case QL_SECURITY_TYPE_AUTO:
os_printf("AUTO\r\n");
break;
case QL_SECURITY_TYPE_WPA3_SAE:
os_printf("WPA3\n");
break;
case QL_SECURITY_TYPE_WPA3_WPA2_MIXED:
os_printf("WPA2/WPA3 MIXED\n");
break;
default:
os_printf("Error\r\n");
break;
}
os_printf("ip=%s,gate=%s,mask=%s,dns=%s\r\n",ap_info.local_ip_addr,
ap_info.gateway_ip_addr,ap_info.net_mask,ap_info.dns_server_ip_addr);
}
}
扫描指定SSID
void demo_scan_adv_app_init(uint8_t *oob_ssid)
{
uint8_t **ssid_array;
ssid_array = &oob_ssid;
/*注册扫描应答函数*/
mhdr_scanu_reg_cb(scan_cb, 0);
os_printf("scan for ssid:%s\r\n", oob_ssid);
ql_wlan_start_assign_scan(ssid_array, 1);
}
操作说明
Wi-Fi API的示例代码文件为ql_wlan_demo.c,位于ql_application/quectel_demo/目录下,用户可自行查看完整示例。系统默认已经打开WLAN功能,模块上电后,在模块调试串口输入相应命令即可运行不同程序。
启动扫描
模块Log如下:
scan
[sa_sta]MM_RESET_REQ
[sa_sta]ME_CONFIG_REQ
[sa_sta]ME_CHAN_CONFIG_REQ
[sa_sta]MM_START_REQ
no ht in scan
scan_start_req_handler
# Got ap count: 32
cx_wifi3, RSSI=-24
ASUS_2G, RSSI=-36
billy1, RSSI=-45
billy2, RSSI=-48
GSWiFi-207F, RSSI=-52
Quectel-SH, RSSI=-56
Visitor-Quectel, RSSI=-57
Visitor-Quectel, RSSI=-58
Quectel-SH, RSSI=-59
, RSSI=-59
, RSSI=-62
Quectel-SH, RSSI=-62
Visitor-Quectel, RSSI=-64
Visitor-Quectel, RSSI=-64
Quectel-SH, RSSI=-65
, RSSI=-67
, RSSI=-68
Visitor-Quectel, RSSI=-72
SupermaniPhone, RSSI=-74
, RSSI=-74
Quectel-SH, RSSI=-74
Visitor-Quectel, RSSI=-74
Visitor-Quectel, RSSI=-74
Quectel-SH, RSSI=-74
123456, RSSI=-75
YY-zhanting, RSSI=-82
Quectel-SH, RSSI=-82
, RSSI=-83
, RSSI=-83
, RSSI=-83
DIRECT-AVSH-PD-DAVISN1ms2K, RSSI=-87
, RSSI=-90
Get ap end.......
扫描指定网络
模块上电后,在模块调试串口输入advscan your_SSID,模块开始扫描特定网络。模块Log如下:
advscan cx_wifi3
scan for ssid:cx_wifi3
[sa_sta]MM_RESET_REQ
[sa_sta]ME_CONFIG_REQ
[sa_sta]ME_CHAN_CONFIG_REQ
[sa_sta]MM_START_REQ
no ht in scan
scan_start_req_handler
# Got ap count: 1
cx_wifi3, RSSI=-26
Get ap end.......
开启AP
模块上电后,在模块调试串口输入softap your_SSID your_key,模块将开启一个SSID为"your_SSID"、密钥为"your_key"的AP。模块Log如下:
softap test 12345678
SOFTAP_COMMAND
ssid:test key:12345678
sending broadcast_deauth failed vif_entry == NULL
Soft_AP_start
[saap]MM_RESET_REQ
[saap]ME_CONFIG_REQ
[saap]ME_CHAN_CONFIG_REQ
[saap]MM_START_REQ
[csa]csa_in_progress[0:0]-clear
mm_add_if_req_handler:0
hapd_intf_add_vif,type:3, s:0, id:0
apm start with vif:0
------beacon_int_set:100 TU
set_active param 0
[msg]APM_STOP_CFM
update_ongoing_1_bcn_update
mm_set_vif_state_req_handler
vif_idx:0, ch_idx:0, bcmc_idx:2
cal dpll!
temperature_type=2
do td cur_t:343--last:idx:13,t:350 -- new:idx:14,t:340
--0xc:00, shift_b:0, shift_g:0, shift_ble:0 X:0
update_ongoing_1_bcn_update
hapd_intf_add_key CCMP
add is_broadcast_ether_addr
sta:255, vif:0, key:1
add hw key idx:1
enter low level!
mac c8:47:8c:42: 0:49
leave low level!
[net]addvif_idx:0
uap_ip_start
Configuring interface uap (with Static IP)[THD]dhcp-server:[tcb]414578 [stack]4140f0-414570:1152:2
def netif is no ap's netif, sending boardcast or no-subnet ip packets may failed
sending broadcast_deauth:5
#
关闭AP/STA
开启AP/STA后,在模块调试串口输入stopintf 0/1,模块会停止AP/STA,模块Log如下:
stopintf 0
stop_wlan_intface_Command
stop wlan intface:0
sending broadcast_deauth:5
uap_ip_down
sta test 12345678
sta_Command
ssid:test key:12345678
[sa_sta]MM_RESET_REQ
[sa_sta]ME_CONFIG_REQ
[sa_sta]ME_CHAN_CONFIG_REQ
[sa_sta]MM_START_REQ
[THD]pskc:[tcb]410348 [stack]40ff40-410340:1024:4
PSKC: ssid test, passphrase 12345678
sizeof(wpa_supplicant)=768
mm_add_if_req_handler:0
hapd_intf_add_vif,type:2, s:0, id:0
wpa_dInit
enter low level!
mac c8:47:8c:42: 0:48
leave low level!
[net]addvif_idx:0
连接AP
模块上电后,在调试串口输入:sta your_ssid your_key,模块会连接SSID为"your_SSID"的AP,模块Log如下:
wpa_supplicant_req_scan
Setting scan request: 0.000000 sec
wpa_supplicant_scan
wpa_drv_scan
wpa_send_scan_req
no ht in scan
scan_start_req_handler
wpa_driver_scan_start_cb
scan_cancel_req_handler
# scan_send_cancel_cfm
wpa_driver_scan_cb
Scan completed in 0.100000 seconds
wpa_get_scan_rst:1
cipher2security 2 2 16 16
PSKC: end
cipher2security 2 2 16 16
wpa_supplicant_connect
Cancelling scan request
wpa_driver_associate: auth_alg 0x1
found scan rst rssi -27 > -50 0
sm_auth_send:1
sm_auth_handler
ht in assoc req
sm_assoc_rsp_handler
rc_init: station_id=0 format_mod=2 pre_type=0 short_gi=1 max_bw=0
rc_init: nss_max=0 mcs_max=7 r_idx_min=0 r_idx_max=3 no_samples=10
mm_set_vif_state_req_handler
chan_bcn_detect_start
---------SM_CONNECT_IND_ok
Cancelling scan request
WPA: TK 0eb538f828d1e2a6d0a417736a3ff17c
new dtim period:2
new ie: 0 : 74 65 73 74
new ie: 1 : 82 84 8b c 12 96 18 24
new ie: 3 : 1
new ie: 30 : 1 0 0 f ac 4 1 0 0 f ac 4 1 0 0 f ac 2 c 0
new ie: 2d : ad 1 17 ff ff 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
hapd_intf_add_key CCMP
add sta_mgmt_get_sta
sta:0, vif:0, key:0
sta_mgmt_add_key
获取Wi-Fi状态
模块上电后,在模块调试串口输入wifistate,模块会输出当前Wi-Fi工作状态,模块Log如下:
add hw key idx:24
WPA: GTK bbd21fb387e9a66215df725673e64fbd
hapd_intf_add_key CCMP
add is_broadcast_ether_addr
sta:255, vif:0, key:1
add hw key idx:1
ctrl_port_hdl:1
me_set_ps_disable:869 0 0 0 0 1
dis set ps 1!!
WLAN_EVENT_CONNECTED
sta_ip_start
configuring interface mlan (with DHCP client)
dhcp_check_status_init_timer:20000
ip_addr: 372ba8c0
cal dpll!
cal_bias!
cal dpll!
do td cur_t:312--last:idx:16,t:320 -- new:idx:17,t:310
--0xc:00, shift_b:0, shift_g:0, shift_ble:0 X:-2
init_xtal:0, delta:-2, last_xtal:0
wifistate
wifistate_Command
sta: 1, softap: 0, b/g/n
sta:rssi=-32,ssid=test,bssid=82:54:40:e2:05:72 ,channel=1,cipher_type:CCMP
附录 参考文档及术语缩写
参考文档:
| 文档名称 |
|---|
| Quectel_FC41D&FCM100D&FCM740D&FLMx40D_QuecOpen(SDK)_快速开发指导 |
术语缩写:
| 缩写 | 英文全称 | 中文全称 |
|---|---|---|
| AP | Access Point | 接入点 |
| API | Application Programming Interface | 应用程序编程接口 |
| DHCP | Dynamic Host Configuration Protocol | 动态主机设置协议 |
| DNS | Domain Name Server | 域名服务器 |
| HTTP | Hypertext Transfer Protocol | 超文本传输协议 |
| IoT | Internet of Things | 物联网 |
| IP | Internet Protocol | 网际协议 |
| MAC | Medium Access Control | 媒体访问控制 |
| RTOS | Real-Time Operation | 实时操作系统 |
| SDK | Software Development Kit | 软件开发工具包 |
| SSID | Service Set Identifier | 服务集标识符 |
| STA | Station | 站点 |
| USB | Universal Serial Bus | 通用串行总线 |
| WLAN | Wireless Local Area Network | 无线局域网 |