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

监听到的数据包信息结构体定义如下:

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)

参数

返回值

  • 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地址。

该函数用于获取当前的连接状态。

函数原型

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 无线局域网