Skip to content

Commit ee72310

Browse files
committed
STA scan and connection rewrite
Implement our own AP selection algorithm, do not rely on SDK. The algorithm tries to connect to AP with best signal but doesn't get stuck on one (or a subset) of them. If there is an AP that can be connected to, it should eventually be found. Also implement roaming: if device is connected to an AP with RSII less than wifi.sta_roam_rssi_thr, it will periodically (wifi.sta_roam_interval) scan for a better AP and try to reconnect. AP must be at least 5 dbm better than the one we are connected to. Roaming is not seamless, i.e. connection is lost during attempt. Scanning also introduces blips, so if connection stability is more important, roaming should not be used.
1 parent a981536 commit ee72310

File tree

9 files changed

+772
-262
lines changed

9 files changed

+772
-262
lines changed

README.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ which contains configuration settings for the Access Point mode, and
4040

4141
#### Multiple Station Configurations
4242

43-
Station configurations will be tried starting from `sta_cfg_idx` and each one that is enabled will be given `sta_connect_timeout` seconds to connect. Successfully connected station's index will be saved in `sta_cfg_idx` so next boot will start with previously used configuration.
44-
45-
Setting `sta_connect_timeout` to 0 disables this logic.
43+
Up to 3 different station configurations are allowed and those that are enabled will be considered for connection.
4644

4745
### Access Point configuration
4846

include/mgos_wifi_hal.h

+3-6
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@
1919
* HAL wifi interface, to be implemented by ports.
2020
*/
2121

22-
#ifndef CS_MOS_LIBS_WIFI_SRC_MGOS_WIFI_HAL_H_
23-
#define CS_MOS_LIBS_WIFI_SRC_MGOS_WIFI_HAL_H_
22+
#pragma once
2423

2524
#include "mgos_net.h"
2625
#include "mgos_wifi.h"
2726

2827
#ifdef __cplusplus
2928
extern "C" {
30-
#endif /* __cplusplus */
29+
#endif
3130

3231
bool mgos_wifi_dev_ap_setup(const struct mgos_config_wifi_ap *cfg);
3332

@@ -66,6 +65,4 @@ void mgos_wifi_dev_deinit(void);
6665

6766
#ifdef __cplusplus
6867
}
69-
#endif /* __cplusplus */
70-
71-
#endif /* CS_MOS_LIBS_WIFI_SRC_MGOS_WIFI_HAL_H_ */
68+
#endif

include/mgos_wifi_sta.h

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) Mongoose OS Contributors
3+
* All rights reserved
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the ""License"");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an ""AS IS"" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#pragma once
19+
20+
#include "mgos_sys_config.h"
21+
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
bool mgos_wifi_sta_add_cfg(const struct mgos_config_wifi_sta *cfg);
27+
void mgos_wifi_sta_clear_cfgs(void);
28+
void mgos_wifi_sta_init(void);
29+
30+
#ifdef __cplusplus
31+
}
32+
#endif

mos.yml

+5-8
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ config_schema:
3434
- ["wifi.sta.enable", "b", {title: "Connect to existing WiFi"}]
3535
- ["wifi.sta.ssid", "s", {title: "SSID"}]
3636
- ["wifi.sta.pass", "s", {title: "Password", type: "password"}]
37+
- ["wifi.sta.bssid", "s", {title: "Specific AP to connect to"}]
3738
- ["wifi.sta.user", "s", {title: "Username for WPA-PEAP mode"}]
3839
- ["wifi.sta.anon_identity", "s", {title: "Anonymous identity for WPA mode"}]
3940
- ["wifi.sta.cert", "s", {title: "Client certificate for WPA-TTLS mode"}]
@@ -49,12 +50,10 @@ config_schema:
4950
- ["wifi.sta1.enable", false]
5051
- ["wifi.sta2", "wifi.sta", {title: "WiFi Station Config 2"}]
5152
- ["wifi.sta2.enable", false]
52-
# Station configurations will be tried starting from sta_cfg_idx and each one that is enabled
53-
# will be given sta_connect_timeout seconds to connect. Successfully connected station's index
54-
# will be saved in sta_cfg_idx so next boot will start with previously used configuration.
55-
# Setting sta_connect_timeout to 0 will disable this logic.
56-
- ["wifi.sta_cfg_idx", "i", 0, {title: "WiFi station config index to use, 0, 1 or 2"}]
57-
- ["wifi.sta_connect_timeout", "i", 30, {title: "Timeout for connection, seconds"}]
53+
- ["wifi.sta_rssi_thr", "i", -95, {title: "Do not consider APs with weaker signal"}]
54+
- ["wifi.sta_connect_timeout", "i", 15, {title: "Timeout for connection, seconds"}]
55+
- ["wifi.sta_roam_rssi_thr", "i", -80, {title: "If connected to AP with weaker signal, try to find a better one."}]
56+
- ["wifi.sta_roam_interval", "i", 900, {title: "Scan for better APs at this interval. Set to 0 to disable."}]
5857

5958
build_vars:
6059
MGOS_WIFI_ENABLE_AP_STA: 0
@@ -84,7 +83,6 @@ conds:
8483
- origin: https://github.com/mongoose-os-libs/lwip
8584
config_schema:
8685
- ["wifi.ap.keep_enabled", "b", true, {title: "Keep AP enabled when station is on"}]
87-
- ["wifi.sta_all_chan_scan", "b", true, {title: "true to scan all channels or false to perform fast scan"}]
8886
# min/max values are from enum RATE_11{B,G,N}_ID in the SDK, see user_interface.h for declarations.
8987
- ["wifi.tx_rate_limit_11b", "i", -1, {title: "TX rate limit for 11B mode, ((max << 8) | min)"}]
9088
- ["wifi.tx_rate_limit_11g", "i", -1, {title: "TX rate limit for 11G mode, ((max << 8) | min)"}]
@@ -99,7 +97,6 @@ conds:
9997
- ["wifi.ap.bandwidth_20mhz", "b", false, {title: "enable 20MHz bandwidth AP operation"}]
10098
- ["wifi.ap.protocol", "s", "BGN", {title: "802.11 Wi-Fi Protocol for AP Mode, defaults to BGN, can be any combination of BGNLR. Note LR only works between 2 ESP32 devices."}]
10199
- ["wifi.sta_ps_mode", "i", 0, {title: "Power save mode for station: 0 - none, 1 - min, 2 - max."}]
102-
- ["wifi.sta_all_chan_scan", "b", true, {title: "true to scan all channels or false to perform fast scan"}]
103100
- ["wifi.sta.protocol", "s", "BGN", {title: "802.11 Wi-Fi Protocol for STA Mode, defaults to BGN, can be any combination of BGNLR. Note LR only works between 2 ESP32 devices."}]
104101
- ["wifi.sta.listen_interval_ms", "i", 0, {title: "DTIM Listen Interval (ms)"}]
105102
cdefs:

src/cc32xx/cc32xx_wifi.c

+4
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ static bool ensure_role_sta(void) {
138138
if (s_current_role == ROLE_STA) return true;
139139
if (!restart_nwp(ROLE_STA)) return false;
140140
_u32 scan_interval = WIFI_SCAN_INTERVAL_SECONDS;
141+
/* Setting scan policy also initiates scan. */
141142
sl_WlanPolicySet(SL_WLAN_POLICY_SCAN, 1 /* enable */, (_u8 *) &scan_interval,
142143
sizeof(scan_interval));
143144
return true;
@@ -620,6 +621,9 @@ bool mgos_wifi_dev_start_scan(void) {
620621

621622
if (!ensure_role_sta()) goto out;
622623

624+
/* TODO: Set scan policy to initate scan, right now we are getting
625+
* results from a previous scan. */
626+
623627
for (i = 0; (n = sl_WlanGetNetworkList(i, 2, info)) > 0; i += 2) {
624628
res = (struct mgos_wifi_scan_result *) realloc(
625629
res, (num_res + n) * sizeof(*res));

src/esp32/esp32_wifi.c

+19-19
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,7 @@ static esp_err_t wifi_sta_set_host_name(
304304
bool mgos_wifi_dev_sta_setup(const struct mgos_config_wifi_sta *cfg) {
305305
bool result = false;
306306
esp_err_t r;
307-
wifi_config_t wcfg;
308-
memset(&wcfg, 0, sizeof(wcfg));
307+
wifi_config_t wcfg = {0};
309308
wifi_sta_config_t *stacfg = &wcfg.sta;
310309

311310
s_user_sta_enabled = cfg->enable;
@@ -321,10 +320,21 @@ bool mgos_wifi_dev_sta_setup(const struct mgos_config_wifi_sta *cfg) {
321320
/* In case already connected, disconnect. */
322321
esp_wifi_disconnect();
323322

324-
stacfg->scan_method =
325-
(wifi_scan_method_t) mgos_sys_config_get_wifi_sta_all_chan_scan();
326-
327323
strncpy((char *) stacfg->ssid, cfg->ssid, sizeof(stacfg->ssid));
324+
325+
if (!mgos_conf_str_empty(cfg->bssid)) {
326+
unsigned int bssid[6] = {0};
327+
if (sscanf(cfg->bssid, "%02x:%02x:%02x:%02x:%02x:%02x", &bssid[0],
328+
&bssid[1], &bssid[2], &bssid[3], &bssid[4], &bssid[5]) != 6) {
329+
LOG(LL_ERROR, ("Invalid BSSID!"));
330+
return false;
331+
}
332+
for (int i = 0; i < 6; i++) {
333+
stacfg->bssid[i] = bssid[i];
334+
}
335+
stacfg->bssid_set = true;
336+
}
337+
328338
if (mgos_conf_str_empty(cfg->user) /* Not using EAP */ &&
329339
!mgos_conf_str_empty(cfg->pass)) {
330340
strncpy((char *) stacfg->password, cfg->pass, sizeof(stacfg->password));
@@ -618,23 +628,13 @@ int mgos_wifi_sta_get_rssi(void) {
618628
}
619629

620630
bool mgos_wifi_dev_start_scan(void) {
621-
esp_err_t r = ESP_OK;
622-
wifi_mode_t cur_mode = esp32_wifi_get_mode();
623-
if (cur_mode != WIFI_MODE_STA && cur_mode != WIFI_MODE_APSTA) {
624-
r = esp32_wifi_add_mode(WIFI_MODE_STA);
625-
if (r == ESP_OK) r = esp32_wifi_ensure_start();
626-
}
631+
esp_err_t r = esp32_wifi_add_mode(WIFI_MODE_STA);
632+
if (r == ESP_OK) r = esp32_wifi_ensure_start();
627633
if (r == ESP_OK) {
628634
wifi_scan_config_t scan_cfg = {
629635
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
630-
.scan_time =
631-
{
632-
.active =
633-
{
634-
.min = 150,
635-
.max = 200,
636-
},
637-
},
636+
.scan_time.active.min = 100,
637+
.scan_time.active.max = 150,
638638
};
639639
if (s_connecting) {
640640
esp_wifi_disconnect();

src/esp8266/esp_wifi.c

+31-19
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,7 @@ static void esp_wifi_set_rate_limits(const struct mgos_config_wifi *cfg) {
236236
}
237237

238238
bool mgos_wifi_dev_sta_setup(const struct mgos_config_wifi_sta *cfg) {
239-
struct station_config sta_cfg = {
240-
#if ESP_SDK_VERSION_MAJOR >= 3
241-
.all_channel_scan = mgos_sys_config_get_wifi_sta_all_chan_scan(),
242-
#else
243-
0
244-
#endif
245-
};
239+
struct station_config sta_cfg = {0};
246240

247241
if (!cfg->enable) {
248242
return mgos_wifi_remove_mode(STATION_MODE);
@@ -254,7 +248,18 @@ bool mgos_wifi_dev_sta_setup(const struct mgos_config_wifi_sta *cfg) {
254248

255249
if (!mgos_wifi_add_mode(STATION_MODE)) return false;
256250

257-
sta_cfg.bssid_set = 0;
251+
if (cfg->bssid != NULL) {
252+
unsigned int bssid[6] = {0};
253+
if (sscanf(cfg->bssid, "%02x:%02x:%02x:%02x:%02x:%02x", &bssid[0],
254+
&bssid[1], &bssid[2], &bssid[3], &bssid[4], &bssid[5]) != 6) {
255+
LOG(LL_ERROR, ("Invalid BSSID!"));
256+
return false;
257+
}
258+
for (int i = 0; i < 6; i++) {
259+
sta_cfg.bssid[i] = bssid[i];
260+
}
261+
sta_cfg.bssid_set = true;
262+
}
258263
strncpy((char *) sta_cfg.ssid, cfg->ssid, sizeof(sta_cfg.ssid));
259264

260265
if (!mgos_conf_str_empty(cfg->ip) && !mgos_conf_str_empty(cfg->netmask)) {
@@ -470,19 +475,23 @@ void wifi_scan_done(void *arg, STATUS status) {
470475
mgos_wifi_dev_scan_cb(-1, NULL);
471476
return;
472477
}
473-
STAILQ_HEAD(, bss_info) *info = arg;
474-
struct mgos_wifi_scan_result *res = NULL;
475-
struct bss_info *p;
476478
int n = 0;
477-
STAILQ_FOREACH(p, info, next) n++;
478-
res = calloc(n, sizeof(*res));
479-
if (n > 0 && res == NULL) {
479+
struct bss_info *info = (struct bss_info *) arg;
480+
for (struct bss_info *p = info; p != NULL; p = p->next.stqe_next) {
481+
n++;
482+
}
483+
if (n == 0) {
484+
mgos_wifi_dev_scan_cb(0, NULL);
485+
return;
486+
}
487+
struct mgos_wifi_scan_result *res = calloc(n, sizeof(*res));
488+
if (res == NULL) {
480489
LOG(LL_ERROR, ("Out of memory"));
481490
mgos_wifi_dev_scan_cb(-1, NULL);
482491
return;
483492
}
484493
struct mgos_wifi_scan_result *r = res;
485-
STAILQ_FOREACH(p, info, next) {
494+
for (struct bss_info *p = info; p != NULL; p = p->next.stqe_next) {
486495
strncpy(r->ssid, (const char *) p->ssid, sizeof(r->ssid));
487496
memcpy(r->bssid, p->bssid, sizeof(r->bssid));
488497
r->ssid[sizeof(r->ssid) - 1] = '\0';
@@ -514,10 +523,13 @@ void wifi_scan_done(void *arg, STATUS status) {
514523

515524
bool mgos_wifi_dev_start_scan(void) {
516525
/* Scanning requires station. If in AP-only mode, switch to AP+STA. */
517-
if (wifi_get_opmode() == SOFTAP_MODE) {
518-
wifi_set_opmode_current(STATIONAP_MODE);
519-
}
520-
return wifi_station_scan(NULL, wifi_scan_done);
526+
if (!mgos_wifi_add_mode(STATION_MODE)) return false;
527+
struct scan_config cfg = {
528+
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
529+
.scan_time.active.min = 100,
530+
.scan_time.active.max = 150,
531+
};
532+
return wifi_station_scan(&cfg, wifi_scan_done);
521533
}
522534

523535
void mgos_wifi_dev_init(void) {

0 commit comments

Comments
 (0)