From 9af4f58417103a21d31f70fc6e44bfba55d36789 Mon Sep 17 00:00:00 2001 From: dnc40085 Date: Sat, 31 Mar 2018 00:06:18 -0700 Subject: [PATCH] Added functions wifi.getcountry() and wifi.setcountry() (#2330) --- app/modules/wifi.c | 123 ++++++++++++++++++++++++++++++++++++++++ docs/en/modules/wifi.md | 72 +++++++++++++++++++++++ 2 files changed, 195 insertions(+) diff --git a/app/modules/wifi.c b/app/modules/wifi.c index eb98adce..426fa11a 100644 --- a/app/modules/wifi.c +++ b/app/modules/wifi.c @@ -215,6 +215,124 @@ static int wifi_exit_smart( lua_State* L ) } #endif // WIFI_SMART_ENABLE +// Lua: wifi.getcountry() +static int wifi_getcountry( lua_State* L ){ + + wifi_country_t cfg = {0}; + + + if(wifi_get_country(&cfg)){ + lua_newtable(L); + + lua_pushstring(L, "country"); + lua_pushstring(L, cfg.cc); + lua_rawset(L, -3); + + lua_pushstring(L, "start_ch"); + lua_pushnumber(L, cfg.schan); + lua_rawset(L, -3); + + lua_pushstring(L, "end_ch"); + lua_pushnumber(L, (cfg.schan + cfg.nchan)-1); + lua_rawset(L, -3); + + lua_pushstring(L, "policy"); + lua_pushnumber(L, cfg.policy); + lua_rawset(L, -3); + + return 1; + } + else{ + return luaL_error(L, "Unable to get country info"); + } +} + +// Lua: wifi.setcountry() +static int wifi_setcountry( lua_State* L ){ + size_t len; + uint8 start_ch; + uint8 end_ch; + wifi_country_t cfg = {0}; + + if(lua_istable(L, 1)){ + lua_getfield(L, 1, "country"); + if (!lua_isnil(L, -1)){ + if( lua_isstring(L, -1) ){ + const char *country_code = luaL_checklstring( L, -1, &len ); + luaL_argcheck(L, (len==2 && isalpha(country_code[0]) && isalpha(country_code[1])), 1, "country: country code must be 2 chars"); + c_memcpy(cfg.cc, country_code, len); + if(cfg.cc[0] >= 0x61) cfg.cc[0]=cfg.cc[0]-32; //if lowercase change to uppercase + if(cfg.cc[1] >= 0x61) cfg.cc[1]=cfg.cc[1]-32; //if lowercase change to uppercase + } + else + return luaL_argerror( L, 1, "country: must be string" ); + } + else{ + cfg.cc[0]='C'; + cfg.cc[1]='N'; + cfg.cc[2]=0x00; + } + lua_pop(L, 1); + + lua_getfield(L, 1, "start_ch"); + if (!lua_isnil(L, -1)){ + if(lua_isnumber(L, -1)){ + start_ch = (uint8)luaL_checknumber(L, -1); + luaL_argcheck(L, (start_ch >= 1 && start_ch <= 14), 1, "start_ch: Range:1-14"); + cfg.schan = start_ch; + } + else + luaL_argerror(L, 1, "start_ch: must be a number"); + } + else + cfg.schan = 1; + + lua_pop(L, 1); + + lua_getfield(L, 1, "end_ch"); + if (!lua_isnil(L, -1)){ + if(lua_isnumber(L, -1)){ + end_ch = (uint8)luaL_checknumber(L, -1); + luaL_argcheck(L, (end_ch >= 1 && end_ch <= 14), 1, "end_ch: Range:1-14"); + luaL_argcheck(L, (end_ch >= cfg.schan), 1, "end_ch: can't be less than start_ch"); + cfg.nchan = (end_ch-cfg.schan)+1; //cfg.nchan must equal total number of channels + } + else + luaL_argerror(L, 1, "end_ch: must be a number"); + } + else + cfg.nchan = (13-cfg.schan)+1; + lua_pop(L, 1); + + lua_getfield(L, 1, "policy"); + if (!lua_isnil(L, -1)){ + if(lua_isnumber(L, -1)){ + uint8 policy = (uint8)luaL_checknumber(L, -1); + luaL_argcheck(L, (policy == WIFI_COUNTRY_POLICY_AUTO || policy == WIFI_COUNTRY_POLICY_MANUAL), 1, "policy: must be 0 or 1"); + cfg.policy = policy; + } + else + luaL_argerror(L, 1, "policy: must be a number"); + } + else + cfg.policy = WIFI_COUNTRY_POLICY_AUTO; + lua_pop(L, 1); + + lua_pop(L, 1); //pop table from stack + + bool retval = wifi_set_country(&cfg); + WIFI_DBG("\n country_cfg:\tcc:\"%s\"\tschan:%d\tnchan:%d\tpolicy:%d\n", cfg.cc, cfg.schan, cfg.nchan, cfg.policy); + + if (retval==1) + lua_pushboolean(L, true); + else + return luaL_error(L, "Unable to set country info"); + } + else + return luaL_argerror(L, 1, "Table not found!"); + return 1; +} + // Lua: wifi.setmode(mode, save_to_flash) static int wifi_setmode( lua_State* L ) { @@ -1787,6 +1905,8 @@ static const LUA_REG_TYPE wifi_map[] = { { LSTRKEY( "getmode" ), LFUNCVAL( wifi_getmode ) }, { LSTRKEY( "getdefaultmode" ), LFUNCVAL( wifi_getdefaultmode ) }, { LSTRKEY( "getchannel" ), LFUNCVAL( wifi_getchannel ) }, + { LSTRKEY( "getcountry" ), LFUNCVAL( wifi_getcountry ) }, + { LSTRKEY( "setcountry" ), LFUNCVAL( wifi_setcountry ) }, { LSTRKEY( "setphymode" ), LFUNCVAL( wifi_setphymode ) }, { LSTRKEY( "getphymode" ), LFUNCVAL( wifi_getphymode ) }, { LSTRKEY( "setmaxtxpower" ), LFUNCVAL( wifi_setmaxtxpower ) }, @@ -1835,6 +1955,9 @@ static const LUA_REG_TYPE wifi_map[] = { { LSTRKEY( "STA_FAIL" ), LNUMVAL( STATION_CONNECT_FAIL ) }, { LSTRKEY( "STA_GOTIP" ), LNUMVAL( STATION_GOT_IP ) }, + { LSTRKEY( "COUNTRY_AUTO" ), LNUMVAL( WIFI_COUNTRY_POLICY_AUTO ) }, + { LSTRKEY( "COUNTRY_MANUAL" ), LNUMVAL( WIFI_COUNTRY_POLICY_MANUAL ) }, + { LSTRKEY( "__metatable" ), LROVAL( wifi_map ) }, { LNILKEY, LNILVAL } }; diff --git a/docs/en/modules/wifi.md b/docs/en/modules/wifi.md index 68502260..2cc73a77 100644 --- a/docs/en/modules/wifi.md +++ b/docs/en/modules/wifi.md @@ -58,6 +58,36 @@ Gets the current WiFi channel. #### Returns current WiFi channel +## wifi.getcountry() + +Get the current country info. + +#### Syntax +`wifi.getcountry()` + +#### Parameters +`nil` + +#### Returns +- `country_info` this table contains the current country info configuration + - `country` Country code, 2 character string. + - `start_ch` Starting channel. + - `end_ch` Ending channel. + - `policy` The policy parameter determines which country info configuration to use, country info given to station by AP or local configuration. + - `0` Country policy is auto, NodeMCU will use the country info provided by AP that the station is connected to. + - `1` Country policy is manual, NodeMCU will use locally configured country info. + +#### Example + +```lua +for k, v in pairs(wifi.getcountry()) do + print(k, v) +end +``` + +#### See also +[`wifi.setcountry()`](#wifisetcountry) + ## wifi.getdefaultmode() Gets default WiFi operation mode. @@ -165,6 +195,48 @@ wifi.resume(function() print("WiFi resume") end) - [`node.sleep()`](node.md#nodesleep) - [`node.dsleep()`](node.md#nodedsleep) +## wifi.setcountry() + +Set the current country info. + +#### Syntax +`wifi.setcountry(country_info)` + +#### Parameters +- `country_info` This table contains the country info configuration. (If a blank table is passed to this function, default values will be configured.) + - `country` Country code, 2 character string containing the country code (a list of country codes can be found [here](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements)). (Default:"CN") + - `start_ch` Starting channel (range:1-14). (Default:1) + - `end_ch` Ending channel, must not be less than starting channel (range:1-14). (Default:13) + - `policy` The policy parameter determines which country info configuration to use, country info given to station by AP or local configuration. (default:`wifi.COUNTRY_AUTO`) + - `wifi.COUNTRY_AUTO` Country policy is auto, NodeMCU will use the country info provided by AP that the station is connected to. + - while in stationAP mode, beacon/probe respose will reflect the country info of the AP that the station is connected to. + - `wifi.COUNTRY_MANUAL` Country policy is manual, NodeMCU will use locally configured country info. + +#### Returns +`true` If configuration was sucessful. + +#### Example + +```lua +do + country_info={} + country_info.country="US" + country_info.start_ch=1 + country_info.end_ch=13 + country_info.policy=wifi.COUNTRY_AUTO; + wifi.setcountry(country_info) +end + +--compact version + wifi.setcountry({country="US", start_ch=1, end_ch=13, policy=wifi.COUNTRY_AUTO}) + +--Set defaults + wifi.setcountry({}) +``` + +#### See also +[`wifi.getcountry()`](#wifigetcountry) + ## wifi.setmode() Configures the WiFi mode to use. NodeMCU can run in one of four WiFi modes: