Update wifi.sta to support new IDF functionality.

In addition to exposing additional configuration settings, it now also
provides access to the wifi station power-saving control.

Documentation updated, and wifi.sta.getconfig() has been documented. Not
sure why that wasn't already the case.
This commit is contained in:
Johny Mattsson 2022-12-21 14:50:27 +11:00 committed by Johny Mattsson
parent 4379dd9d31
commit bc3aaf6e4b
3 changed files with 236 additions and 15 deletions

View File

@ -137,6 +137,11 @@ LROT_BEGIN(wifi, NULL, 0)
LROT_NUMENTRY ( AUTH_WPA2_WPA3_PSK, WIFI_AUTH_WPA2_WPA3_PSK )
LROT_NUMENTRY ( AUTH_WAPI_PSK, WIFI_AUTH_WAPI_PSK )
LROT_NUMENTRY ( SAE_PWE_UNSPECIFIED, WPA3_SAE_PWE_UNSPECIFIED )
LROT_NUMENTRY ( SAE_PWE_HUNT_AND_PECK, WPA3_SAE_PWE_HUNT_AND_PECK )
LROT_NUMENTRY ( SAE_PWE_HASH_TO_ELEMENT, WPA3_SAE_PWE_HASH_TO_ELEMENT )
LROT_NUMENTRY ( SAE_PWE_BOTH, WPA3_SAE_PWE_BOTH )
LROT_NUMENTRY ( STR_WIFI_SECOND_CHAN_NONE, WIFI_SECOND_CHAN_NONE )
LROT_NUMENTRY ( STR_WIFI_SECOND_CHAN_ABOVE, WIFI_SECOND_CHAN_ABOVE )
LROT_NUMENTRY ( STR_WIFI_SECOND_CHAN_BELOW, WIFI_SECOND_CHAN_BELOW )

View File

@ -42,6 +42,9 @@
#include "esp_netif.h"
#include <math.h>
#define PMF_VAL_AVAILABLE 1
#define PMF_VAL_REQUIRED 2
static esp_netif_t *wifi_sta = NULL;
static int scan_cb_ref = LUA_NOREF;
@ -252,16 +255,18 @@ static int wifi_sta_config (lua_State *L)
if (len > sizeof (cfg.sta.ssid))
len = sizeof (cfg.sta.ssid);
strncpy ((char *)cfg.sta.ssid, str, len);
lua_pop(L, 1);
lua_getfield (L, 1, "pwd");
str = luaL_optlstring (L, -1, "", &len);
if (len > sizeof (cfg.sta.password))
len = sizeof (cfg.sta.password);
strncpy ((char *)cfg.sta.password, str, len);
lua_pop(L, 1);
lua_getfield (L, 1, "bssid");
cfg.sta.bssid_set = false;
if (lua_isstring (L, -1))
if (!lua_isnoneornil(L, -1))
{
const char *bssid = luaL_checklstring (L, -1, &len);
const char *fmts[] = {
@ -284,18 +289,76 @@ static int wifi_sta_config (lua_State *L)
if (!cfg.sta.bssid_set)
return luaL_error (L, "invalid BSSID: %s", bssid);
}
lua_pop(L, 1);
lua_getfield(L, 1, "pmf");
if (lua_isnumber(L, -1))
if (!lua_isnoneornil(L, -1))
{
int pmf_mode = lua_tointeger(L, -1);
if (pmf_mode)
cfg.sta.pmf_cfg.capable = true;
if (pmf_mode == 2)
cfg.sta.pmf_cfg.required = true;
int pmf_mode = luaL_checkinteger(L, -1);
cfg.sta.pmf_cfg.required = (pmf_mode == PMF_VAL_REQUIRED);
}
else
cfg.sta.pmf_cfg.capable = true;
cfg.sta.pmf_cfg.required = false;
lua_pop(L, 1);
lua_getfield(L, 1, "channel");
if (!lua_isnoneornil(L, -1))
cfg.sta.channel = luaL_checkinteger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "scan_method");
if (!lua_isnoneornil(L, -1))
{
static const wifi_scan_method_t vals[] = {
WIFI_FAST_SCAN, WIFI_ALL_CHANNEL_SCAN,
};
static const char *keys[] = { "fast", "all", };
cfg.sta.scan_method = vals[luaL_checkoption(L, -1, NULL, keys)];
}
lua_pop(L, 1);
lua_getfield(L, 1, "listen_interval");
if (!lua_isnoneornil(L, -1))
cfg.sta.listen_interval = luaL_checkinteger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "sort_by");
if (!lua_isnoneornil(L, -1))
{
static const wifi_sort_method_t vals[] = {
WIFI_CONNECT_AP_BY_SIGNAL, WIFI_CONNECT_AP_BY_SECURITY,
};
static const char *keys[] = { "rssi", "authmode", };
cfg.sta.sort_method = vals[luaL_checkoption(L, -1, NULL, keys)];
}
lua_pop(L, 1);
lua_getfield(L, 1, "threshold_rssi");
if (!lua_isnoneornil(L, -1))
cfg.sta.threshold.rssi = luaL_checkinteger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "threshold_authmode");
if (!lua_isnoneornil(L, -1))
cfg.sta.threshold.authmode = luaL_checkinteger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "rm");
cfg.sta.rm_enabled = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "btm");
cfg.sta.btm_enabled = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "mbo");
cfg.sta.mbo_enabled = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "sae_pwe");
if (!lua_isnoneornil(L, -1))
cfg.sta.sae_pwe_h2e = luaL_checkinteger(L, -1);
lua_pop(L, 1);
SET_SAVE_MODE(save);
esp_err_t err = esp_wifi_set_config (WIFI_IF_STA, &cfg);
@ -323,6 +386,7 @@ static int wifi_sta_disconnect (lua_State *L)
static int wifi_sta_getconfig (lua_State *L)
{
wifi_config_t cfg;
memset(&cfg, 0, sizeof(cfg));
esp_err_t err = esp_wifi_get_config (WIFI_IF_STA, &cfg);
if (err != ESP_OK)
return luaL_error (L, "failed to get config, code %d", err);
@ -344,6 +408,59 @@ static int wifi_sta_getconfig (lua_State *L)
lua_setfield (L, -2, "bssid");
}
lua_pushinteger(L,
cfg.sta.pmf_cfg.required ? PMF_VAL_REQUIRED : PMF_VAL_AVAILABLE);
lua_setfield(L, -2, "pmf");
const char *tmp;
switch(cfg.sta.scan_method)
{
case WIFI_FAST_SCAN: tmp = "fast"; break;
case WIFI_ALL_CHANNEL_SCAN: tmp = "all"; break;
default: tmp = NULL; break;
}
if (tmp)
{
lua_pushstring(L, tmp);
lua_setfield(L, -2, "scan_method");
}
lua_pushinteger(L, cfg.sta.channel);
lua_setfield(L, -2, "channel");
lua_pushinteger(L, cfg.sta.listen_interval);
lua_setfield(L, -2, "listen_interval");
switch(cfg.sta.sort_method)
{
case WIFI_CONNECT_AP_BY_SIGNAL: tmp = "rssi"; break;
case WIFI_CONNECT_AP_BY_SECURITY: tmp = "authmode"; break;
default: tmp = NULL; break;
}
if (tmp)
{
lua_pushstring(L, tmp);
lua_setfield(L, -2, "sort_by");
}
lua_pushinteger(L, cfg.sta.threshold.rssi);
lua_setfield(L, -2, "threshold_rssi");
lua_pushinteger(L, cfg.sta.threshold.authmode);
lua_setfield(L, -2, "threshold_authmode");
lua_pushinteger(L, cfg.sta.rm_enabled);
lua_setfield(L, -2, "rm");
lua_pushinteger(L, cfg.sta.btm_enabled);
lua_setfield(L, -2, "btm");
lua_pushinteger(L, cfg.sta.mbo_enabled);
lua_setfield(L, -2, "mbo");
lua_pushinteger(L, cfg.sta.sae_pwe_h2e);
lua_setfield(L, -2, "sae_pwe");
return 1;
}
@ -453,6 +570,43 @@ static int wifi_sta_scan (lua_State *L)
}
static int wifi_sta_powersave(lua_State *L)
{
static const wifi_ps_type_t vals[] = {
WIFI_PS_NONE, WIFI_PS_MIN_MODEM, WIFI_PS_MAX_MODEM,
};
static const char *keys[] = { "none", "min", "max" };
esp_err_t ret = esp_wifi_set_ps(vals[luaL_checkoption(L, 1, NULL, keys)]);
if (ret != ESP_OK)
return luaL_error(L, "set powersave failed, code %d", ret);
return 0;
}
static int wifi_sta_getpowersave(lua_State *L)
{
wifi_ps_type_t ps;
esp_err_t ret = esp_wifi_get_ps(&ps);
if (ret != ESP_OK)
return luaL_error(L, "get powersave failed, code %d", ret);
const char *mode;
switch(ps)
{
case WIFI_PS_NONE: mode = "none"; break;
case WIFI_PS_MIN_MODEM: mode = "min"; break;
case WIFI_PS_MAX_MODEM: mode = "max"; break;
default:
return luaL_error(L, "unknown powersave mode??");
}
lua_pushstring(L, mode);
return 1;
}
LROT_BEGIN(wifi_sta, NULL, 0)
LROT_FUNCENTRY( setip, wifi_sta_setip )
LROT_FUNCENTRY( sethostname, wifi_sta_sethostname)
@ -464,10 +618,11 @@ LROT_BEGIN(wifi_sta, NULL, 0)
LROT_FUNCENTRY( getmac, wifi_sta_getmac )
LROT_FUNCENTRY( on, wifi_sta_on )
LROT_FUNCENTRY( scan, wifi_sta_scan )
LROT_FUNCENTRY( powersave, wifi_sta_powersave )
LROT_FUNCENTRY( getpowersave,wifi_sta_getpowersave )
LROT_NUMENTRY( PMF_OFF, 0 )
LROT_NUMENTRY( PMF_AVAILABLE, 1 )
LROT_NUMENTRY( PMF_REQUIRED, 2 )
LROT_NUMENTRY( PMF_AVAILABLE, PMF_VAL_AVAILABLE )
LROT_NUMENTRY( PMF_REQUIRED, PMF_VAL_REQUIRED )
LROT_END(wifi_sta, NULL, 0)
NODEMCU_ESP_EVENT(WIFI_EVENT, WIFI_EVENT_SCAN_DONE, on_scan_done);

View File

@ -149,11 +149,22 @@ being removed in the SDK/IDF. After start-up it is necessary to call
- "AcDc0123c0DE"
- `pmf` an optional setting to control whether Protected Management Frames
are supported and/or required. One of:
- `wifi.sta.PMF_OFF`
- `wifi.sta.PMF_AVAILABLE`
- `wifi.sta.PMF_REQUIRED`.
Defaults to `wifi.sta.PMF_AVAILABLE`. PMF is required when joining to
WPA3-Personal access points.
WPA3-Personal access points. The value `wifi.sta.PMF_OFF` is no longer
available as it is no longer supported by the wifi stack.
- `channel` optional integer value, the channel number to start scanning for the AP from, if known.
- `scan_method` optional string value, one of `"fast"` or `"all"` do either do a fast scan or all channel scan when looking for the AP to connect to. With fast scan, the first found matching AP is used even if it is not the best/closest one.
- `listen_interval` optional listen interval to receive beacon if max wifi power saving mode is enabled. Units is in AP beacon intervals. Defaults to 3.
- `sort_by` optional string value for preferential selection of AP. Must be one of `"rssi"` or `"authmode"` if present.
- `threshold_rssi` optional integer value to limit APs to only those which have a signal stronger than this value.
- `threshold_authmode` optional value to limit APs to those with an authentication mode of at least this settings. One of `wifi.AUTH_OPEN`, `wifi.AUTH_WEP`, `wifi.AUTH_WPA_PSK`, `wifi.AUTH_WPA2_PSK`, `wifi.AUTH_WPA_WPA2_PSK`, `wifi.AUTH_WPA2_ENTERPRISE`, `wifi.AUTH_WPA3_PSK`, `wifi.AUTH_WPA2_WPA3_PSK`, `wifi.AUTH_WAPI_PSK`.
- `rm` optional integer value, set to 1 to enable Radio Measurements
- `btm` optional integer value, set to 1 to enable BSS Transition Management
- `mbo` optional integer value, set to 1 to enable Multi-Band Operation
- `sae_pwe` optional, configures WPA3 SAE Password Element setting. One of `wifi.SAE_PWE_UNSPECIFIED`, `wifi.SAE_PWE_HUNT_AND_PECK`, `wifi.SAE_PWE_HASH_TO_ELEMENT` or `wifi.SAE_PWE_BOTH`.
- `save` Save station configuration to flash.
- `true` configuration **will** be retained through power cycle.
@ -190,6 +201,21 @@ wifi.sta.config(station_cfg)
- [`wifi.sta.connect()`](#wifistaconnect)
- [`wifi.sta.disconnect()`](#wifistadisconnect)
## wifi.sta.getconfig()
Returns the current station configuration.
#### Syntax
`wifi.sta.getconfig()`
#### Parameters
`nil`
#### Returns
A table with the configuration settings. Refer to [`wifi.sta.config()`](#wifistaconfig) for field details.
## wifi.sta.connect()
Connects to the configured AP in station mode. You will want to call this
@ -254,6 +280,41 @@ A `boolean` where `true` is OK.
wifi.sta.settxpower(8.5)
```
## wifi.sta.powersave
Configures power-saving setting in station mode.
#### Syntax
`wifi.sta.powersave(setting)`
#### Parameters
- `setting` one of `"none"`, `"min"` or `"max"`. In `"min"` mode, the station wakes up every DTIM period to receive the beacon. In `"max"` mode, the station wakes up at the interval configured in `listen_interval` (see [`wifi.sta.config()`](#wifistaconfig). When set to `"none"` the station does not go to sleep and can receive frames immediately.
#### Returns
`nil`
#### See also
- [`wifi.sta.getpowersave()`](#wifistagetpowersave)
## wifi.sta.getpowersave
Returns the configured station power-saving mode.
#### Syntax
`wifi.sta.getpowersave()`
#### Parameters
`nil`
#### Returns
One of `"none"`, `"min"` or `"max"`. Refer to [`wifi.sta.powersave()`](#wifistapowersave) for details.
#### See also
- [`wifi.sta.powersave()`](#wifistapowersave)
## wifi.sta.on()
Registers callbacks for WiFi station status events.
@ -282,7 +343,7 @@ Event information provided for each event is as follows:
- `ssid`: the SSID of the network
- `bssid`: the BSSID of the AP
- `channel`: the primary channel of the network
- `auth` authentication method, one of `wifi.AUTH_OPEN`, `wifi.AUTH_WPA_PSK`, `wifi.AUTH_WPA2_PSK`, `wifi.WPA_WPA2_PSK`, `wifi.AUTH_WPA3_PSK`, `wifi.AUTH_WAPI_PSK`
- `auth` authentication method, one of `wifi.AUTH_OPEN`, `wifi.AUTH_WEP`, `wifi.AUTH_WPA_PSK`, `wifi.AUTH_WPA2_PSK`, `wifi.AUTH_WPA_WPA2_PSK`, `wifi.AUTH_WPA2_ENTERPRISE`, `wifi.AUTH_WPA3_PSK`, `wifi.AUTH_WPA2_WPA3_PSK`, `wifi.AUTH_WAPI_PSK`
- `disconnected`: information about the network/AP that was disconnected from:
- `ssid`: the SSID of the network
- `bssid`: the BSSID of the AP
@ -374,7 +435,7 @@ The following fields are provided for each scanned AP:
- `bssid`: the BSSID of the AP
- `channel`: primary WiFi channel of the AP
- `rssi`: Received Signal Strength Indicator value
- `auth` authentication method, one of `wifi.AUTH_OPEN`, `wifi.AUTH_WPA_PSK`, `wifi.AUTH_WPA2_PSK`, `wifi.AUTH_WPA_WPA2_PSK`, `wifi.AUTH_WPA2_ENTERPRISE`, `wifi.AUTH_WPA2_WPA3_PSK`, `wifi.AUTH_WPA3_PSK`, `wifi.AUTH_WAPI_PSK`
- `auth` authentication method, one of `wifi.AUTH_OPEN`, `wifi.AUTH_WEP`, `wifi.AUTH_WPA_PSK`, `wifi.AUTH_WPA2_PSK`, `wifi.AUTH_WPA_WPA2_PSK`, `wifi.AUTH_WPA2_ENTERPRISE`, `wifi.AUTH_WPA3_PSK`, `wifi.AUTH_WPA2_WPA3_PSK`, `wifi.AUTH_WAPI_PSK`
- `bandwidth`: one of the following constants:
- `wifi.HT20`
- `wifi.HT40_ABOVE`