Skip to content

Commit 8e0fd5f

Browse files
committed
esp32/modnetwork.c: Introduce non-blocking scan for WiFi APs.
* Add optional callback to esp_scan to triggers a non-blocking scan * Schedule AP results retrieval when a SCAN_DONE event is emitted * Schedule user callback and pass it the results Signed-off-by: Matt Arcidy <marcidy@gmail.com>
1 parent 4f2e494 commit 8e0fd5f

File tree

1 file changed

+39
-30
lines changed

1 file changed

+39
-30
lines changed

ports/esp32/modnetwork.c

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,16 @@ STATIC const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP};
128128
// Set to "true" if esp_wifi_start() was called
129129
static bool wifi_started = false;
130130

131-
// Set to "true" if the STA interface completed a scan for APs.
132-
static bool wifi_sta_scan_done = false;
133-
134131
// Set to "true" if the STA interface is requested to be connected by the
135132
// user, used for automatic reassociation.
136133
static bool wifi_sta_connect_requested = false;
137134

138135
// Set to "true" if the STA interface is connected to wifi and has IP address.
139136
static bool wifi_sta_connected = false;
140137

138+
// Set to "true" to run a blocking wifi scan, false for non-blocking
139+
static bool wifi_sta_scan_blocking = true;
140+
141141
// Store the current status. 0 means None here, safe to do so as first enum value is WIFI_REASON_UNSPECIFIED=1.
142142
static uint8_t wifi_sta_disconn_reason = 0;
143143

@@ -149,6 +149,21 @@ static bool mdns_initialised = false;
149149
static uint8_t conf_wifi_sta_reconnects = 0;
150150
static uint8_t wifi_sta_reconnects;
151151

152+
STATIC mp_obj_t esp_get_scan_results(void);
153+
154+
// This function is scheduled when a SCAN_DONE event is emitted after a non-blocking scan.
155+
// It allows for retrieving AP records in a list in the context of the scheduler so the
156+
// list can be passed to a user-supplied callback in esp_scan.
157+
STATIC mp_obj_t esp_wifi_scan_cb(mp_obj_t arg) {
158+
ESP_LOGI("wifi", "Scan callback ran");
159+
mp_obj_t handler = MP_STATE_PORT(esp_wifi_scan_cb_handler);
160+
mp_obj_t scan_results = esp_get_scan_results();
161+
mp_sched_schedule(handler, scan_results);
162+
return mp_const_none;
163+
}
164+
165+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_wifi_scan_cb_obj, esp_wifi_scan_cb);
166+
152167
// This function is called by the system-event task and so runs in a different
153168
// thread to the main MicroPython task. It must not raise any Python exceptions.
154169
static esp_err_t event_handler(void *ctx, system_event_t *event) {
@@ -159,7 +174,9 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) {
159174
break;
160175
case SYSTEM_EVENT_SCAN_DONE:
161176
ESP_LOGI("wifi", "SCAN_DONE");
162-
wifi_sta_scan_done = true;
177+
if (!wifi_sta_scan_blocking) {
178+
mp_sched_schedule(MP_OBJ_FROM_PTR(&esp_wifi_scan_cb_obj), mp_const_none);
179+
}
163180
break;
164181
case SYSTEM_EVENT_STA_CONNECTED:
165182
ESP_LOGI("network", "CONNECTED");
@@ -300,6 +317,7 @@ STATIC mp_obj_t esp_initialize() {
300317
ESP_LOGD("modnetwork", "Initializing Event Loop");
301318
ESP_EXCEPTIONS(esp_event_loop_init(event_handler, NULL));
302319
ESP_LOGD("modnetwork", "esp_event_loop_init done");
320+
memset(&MP_STATE_PORT(esp_wifi_scan_cb_handler), 0, sizeof(MP_STATE_PORT(esp_wifi_scan_cb_handler)));
303321
initialized = 1;
304322
}
305323
return mp_const_none;
@@ -465,17 +483,12 @@ STATIC mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) {
465483

466484
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_status_obj, 1, 2, esp_status);
467485

468-
STATIC mp_obj_t esp_get_scan_results(mp_obj_t self_in) {
469-
if (!wifi_sta_scan_done) {
470-
ESP_LOGI("wifi", "Scan not complete");
471-
return mp_const_none;
472-
}
486+
STATIC mp_obj_t esp_get_scan_results() {
473487
mp_obj_t list = mp_obj_new_list(0, NULL);
474488
uint16_t count = 0;
475489
ESP_EXCEPTIONS(esp_wifi_scan_get_ap_num(&count));
476490
if (count == 0) {
477491
ESP_LOGI("wifi", "No AP records found");
478-
wifi_sta_scan_done = false;
479492
return list;
480493
}
481494
wifi_ap_record_t *wifi_ap_records = calloc(count, sizeof(wifi_ap_record_t));
@@ -493,19 +506,20 @@ STATIC mp_obj_t esp_get_scan_results(mp_obj_t self_in) {
493506
mp_obj_list_append(list, MP_OBJ_FROM_PTR(t));
494507
}
495508
free(wifi_ap_records);
496-
wifi_sta_scan_done = false;
497509
return list;
498510
}
499511

500-
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_get_scan_results_obj, esp_get_scan_results);
501-
502512
STATIC mp_obj_t esp_scan(size_t n_args, const mp_obj_t *args) {
503-
mp_obj_t *self_in = MP_OBJ_TO_PTR(args[0]);
504-
bool blocking = true;
513+
wifi_sta_scan_blocking = true;
505514

506515
// If 1 arg or 2nd arg is True, blocking scan
507516
if (n_args > 1) {
508-
blocking = mp_obj_is_true(args[1]);
517+
if (!mp_obj_is_callable(args[1])) {
518+
mp_raise_ValueError(MP_ERROR_TEXT("Invalid callback, must be callable"));
519+
}
520+
MP_STATE_PORT(esp_wifi_scan_cb_handler) = args[1];
521+
wifi_sta_scan_blocking = false;
522+
ESP_LOGI("wifi", "Non-blocking scan");
509523
}
510524

511525
// check that STA mode is active
@@ -518,21 +532,17 @@ STATIC mp_obj_t esp_scan(size_t n_args, const mp_obj_t *args) {
518532
wifi_scan_config_t config = { 0 };
519533
// XXX how do we scan hidden APs (and if we can scan them, are they really hidden?)
520534

521-
if (blocking) {
522-
MP_THREAD_GIL_EXIT();
523-
esp_err_t status = esp_wifi_scan_start(&config, 1);
524-
MP_THREAD_GIL_ENTER();
525-
526-
if (status == 0) {
527-
return esp_get_scan_results(self_in);
528-
}
535+
MP_THREAD_GIL_EXIT();
536+
esp_err_t status = esp_wifi_scan_start(&config, wifi_sta_scan_blocking);
537+
MP_THREAD_GIL_ENTER();
538+
ESP_EXCEPTIONS(status);
539+
540+
if (wifi_sta_scan_blocking) {
541+
ESP_LOGI("wifi", "blocking scan calling get_results");
542+
return esp_get_scan_results();
529543
} else {
530-
ESP_LOGI("wifi", "Attempting non-blocking scan");
531-
ESP_EXCEPTIONS(esp_wifi_scan_start(&config, 0));
544+
return mp_const_none;
532545
}
533-
534-
wifi_sta_scan_done = false;
535-
return mp_const_none;
536546
}
537547

538548
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_scan_obj, 1, 2, esp_scan);
@@ -802,7 +812,6 @@ STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
802812
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&esp_isconnected_obj) },
803813
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&esp_config_obj) },
804814
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
805-
{ MP_ROM_QSTR(MP_QSTR_get_scan_results), MP_ROM_PTR(&esp_get_scan_results_obj) },
806815
};
807816

808817
STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy