您的位置:首页 > 其它

ESP8266 基础篇:国家码使用

2017-11-30 11:01 2016 查看

一:简介

WiFi 设备工作在 2.4G 频段或 5G 频段,由于无线信号的开放性,不同的无线设备间会存在相互干扰。因此,不同国家对 WiFi 设备都有一定的要求和限制。主要体现在频谱、射频功率、安全性及其他方面。因此,在不同国家销售的 WiFi 设备应遵循该国家或地区的要求。在 ESP8266 和 ESP32 中,国家码主要就是针对不同国家可使用的频率不同而设计的。因为 WiFi 协议中将可发射的频率划分为不同的信道,所以也可以理解为国家码就是针对不同国家的信道要求而设计。因为 ESP8266 和 ESP32 目前只支持 2.4G 频段,所以本文就以 2.4G 频段中的信道为例来说明。

国家码

下图是主要国家对于 2.4G 频段的信道要求,不同的国家对信道要求不同,如中国和欧洲支持的信道为 1-13(所以欧洲的路由器在中国是可以直接使用的),而北美只支持 1-11,日本则支持 1-14。



因为国内支持的信道为 1-13,所以在使用国内的路由器时,WiFi 信道只能在 1-13 之间任选;



美国所支持的信道是 1-11,那么路由器中只可以使用 1-11,12 和 13 即为非法信道。如果将国内的路由器带到美国,并设置信道为 12,那么用美国的手机将扫描不到这个路由器的信息。所以如果不能自由转换国家码,必然会对售往不同国家的 WiFi 设备产生影响。

二:国家码接口

在 ESP32 中,国家码相关的接口主要包含设置国家码和获取国家码

/**
* @brief     configure country info
*
* @attention 1. The default country is {.cc="CN", .schan=1, .nchan=13, policy=WIFI_COUNTRY_POLICY_AUTO}
*
* @param     wifi_country_t *country: the configured country info
*
* @return
*    - ESP_OK: succeed
*    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
*    - ESP_ERR_WIFI_ARG: invalid argument
*/
esp_err_t esp_wifi_set_country(const wifi_country_t *country);

/**
* @brief     get the current country info
*
* @param     country  country info
*
* @return
*    - ESP_OK: succeed
*    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
*    - ESP_ERR_WIFI_ARG: invalid argument
*/
esp_err_t esp_wifi_get_country(wifi_country_t *country);


其中 esp_wifi_set_country (ESP8266 中称为 wifi_set_country) 用来设置国家码信息,esp_wifi_get_country (ESP8266 中称为 wifi_get_country) 用来获取当前的国家码信息。国家码参数信息 wifi_country_t 主要由以下几部分组成:

typedef struct {
char cc[3];               /**< country code string */
uint8_t schan;            /**< start channel */
uint8_t nchan;            /**< total channel number */
uint8_t policy;           /**< country policy */
} wifi_country_t;


其中 cc 为国家代码,如中国的国家代码为 CN,美国为 US;schan 为起始信道,nchan 为总信道数,如美国的起始信道为 1,信道数为 11,policy 为国家码选项,目前只支持如下两种:

typedef enum {
WIFI_COUNTRY_POLICY_AUTO,   /**< Country policy is auto, use the country info of AP to which the station is connected */
WIFI_COUNTRY_POLICY_MANUAL, /**< Country policy is manual, always use the configured country info */
} WIFI_COUNTRY_POLICY;


如果选择 auto 那么将会使用所连接 AP 的国家码信息,而 manual 表示由用户配置信息决定。

三:国家码使用

3.1 STATION 模式

当国家码 policy 为 auto 时,STA 的国家码信息由所连接的 AP 决定,如果 AP 中不含国家码信

息,则使用默认值 {“CN”, 1, 13}。比如国家码设置为 {“US”, 1, 11},连接中国的路由器后,其国家码会被自动更新为 {“CN”, 1, 13}。

当国家码 policy 为 manual 时,STA 的国家码信息由 esp_wifi_set_country 中配置信息决定,

仅扫描国家码规定的信道。

3.2 SOFTAP 模式

在 AP 模式下,国家码 policy 不会生效,可以省略,如果配置了国家为 {“US”, 1, 11},则AP可配置的信道范围为 1~11。默认的国家码信息为 {“CN”, 1, 13}。

需要注意的是配置的国家码信息会对 AP 参数的配置有影响,例如在 ESP32 中,esp_wifi_set_config 能够配置的信道范围就是由配置的国家码决定的。

3.3 AP + STATION 模式

当国家码 policy 为 auto 时,AP 的国家码信息跟随 STA 所连接的外部 AP 的国家码信息,此时

AP 会动态更新 beacon/probe response 中的国家码信息。当 STA 连接的外部 AP 的国家码信息

与 AP 配置的国家码信息不同时,会打出一条 Warning 信息,如果 STA 与连接的 AP 断开连接,

国家码依然使用最近连接过的 AP 的国家码。

当国家码 policy 为 manual 时,AP 的国家码信息由配置所决定

四:运行分析

本文以ESP8266 RTOS 的 AP + STATION 模式下的 一个 ConnectAP 的 Demo (Conn_AP_DEMO)来分析国家码的具体实现。

根据这个 demo,主要修改代码如下:

void wifi_handle_event_cb(System_Event_t *evt)
{

switch (evt->event_id) {
case EVENT_STAMODE_CONNECTED:
printf("connect to ssid %s, channel %d\n", evt->event_info.connected.ssid,
evt->event_info.connected.channel);
wifi_country_t config_country;
wifi_get_country(&config_country);
printf("Country info:CC:%c%c,SC:%d,NC:%d\n",config_country.cc[0],config_country.cc[1],config_country.schan,config_country.nchan);
break;
case EVENT_STAMODE_DISCONNECTED:
printf("disconnect from ssid %s, reason %d\n", evt->event_info.disconnected.ssid,
evt->event_info.disconnected.reason);
break;
......
}
}

void conn_ap_init(void)
{
// wifi_country_t config_country = {.cc="US", .schan=1, .nchan=11, WIFI_COUNTRY_POLICY_AUTO};

wifi_country_t config_country = {.cc="US", .schan=1, .nchan=11, WIFI_COUNTRY_POLICY_MANUAL};
wifi_set_country(&config_country);

wifi_set_opmode(STATIONAP_MODE);
struct station_config config;
memset(&config, 0, sizeof(config));  //set value of config from address of &config to width of size to be value '0'
sprintf(config.ssid, DEMO_AP_SSID);
sprintf(config.password, DEMO_AP_PASSWORD);
wifi_station_set_config(&config);
wifi_set_event_handler_cb(wifi_handle_event_cb);
wifi_station_connect();
}


代码中设置的国家码为美国,policy 为 manual,如果路由器的信道为 11,运行程序,程序可以正常连接到路由,并打印如下信息:



可以看到此时通过 wifi_get_country 获得的国家码为代码中设置的国家码。使用 OmniPeak 抓包,发现 ESP32 上 AP 的国家码信息也会设置为美国。



如果将路由器的信道更改为 12,此时重新运行程序,会发现无法连接到此路由器,串口会打印如下信息:



因为程序根据设置的国家码要求在信道 1-11 扫描,但路由器是在信道 12 上广播的,所以没有办法扫描到 SSID。

如果将国家码 policy 从 WIFI_COUNTRY_POLICY_MANUAL 设置为 WIFI_COUNTRY_POLICY_AUTO,重新运行程序,会发现即使路由器信道改为 12 依然可以连接上,在 wifi_get_country 中打印的信息为路由器中的国家码信息。



此时使用OmniPeek抓取空中包,发现 ESP32 上的 softap 回复的 Probe Rsp 包中的国家码信息已经变成路由器中的国家码信息。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐