Skip to content

Commit 96c21a3

Browse files
bogdanarduinopennam
authored andcommitted
ZEP-55: Implemented WiFi.scan() functionality.
1 parent cbf7e44 commit 96c21a3

File tree

3 files changed

+104
-15
lines changed

3 files changed

+104
-15
lines changed

libraries/WiFi/src/WiFi.cpp

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
WiFiClass WiFi;
44

5+
WiFiClass *WiFiClass::instance = nullptr;
6+
57
String WiFiClass::firmwareVersion() {
68
#if defined(ARDUINO_PORTENTA_C33)
79
return "v1.5.0";
@@ -18,21 +20,30 @@ int WiFiClass::begin(const char *ssid, const char *passphrase, wl_enc_type secur
1820
sta_config.ssid_length = strlen(ssid);
1921
sta_config.psk = (const uint8_t *)passphrase;
2022
sta_config.psk_length = strlen(passphrase);
21-
// TODO: change these fields with scan() results
22-
sta_config.security = WIFI_SECURITY_TYPE_PSK;
23-
sta_config.channel = WIFI_CHANNEL_ANY;
24-
sta_config.band = WIFI_FREQ_BAND_2_4_GHZ;
25-
sta_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
26-
int ret = net_mgmt(NET_REQUEST_WIFI_CONNECT, sta_iface, &sta_config,
27-
sizeof(struct wifi_connect_req_params));
28-
if (ret) {
29-
return false;
30-
}
31-
NetworkInterface::begin(false, NET_EVENT_WIFI_MASK);
32-
if (blocking) {
33-
net_mgmt_event_wait_on_iface(sta_iface, NET_EVENT_WIFI_CONNECT_RESULT, NULL, NULL, NULL,
34-
K_FOREVER);
23+
24+
// Register the Wi-Fi event callback
25+
net_mgmt_init_event_callback(&wifiCb, scanEventDispatcher,
26+
NET_EVENT_WIFI_SCAN_RESULT | NET_EVENT_WIFI_SCAN_DONE);
27+
28+
net_mgmt_add_event_callback(&wifiCb);
29+
30+
(void)scanNetworks();
31+
32+
// Check if the network we were seekin was found and attempt to connect to it
33+
if (getSoughtNetworkFound() != true) {
34+
int ret = net_mgmt(NET_REQUEST_WIFI_CONNECT, sta_iface, &sta_config,
35+
sizeof(struct wifi_connect_req_params));
36+
if (ret) {
37+
return false;
38+
}
39+
40+
NetworkInterface::begin(false, NET_EVENT_WIFI_MASK);
41+
if (blocking) {
42+
net_mgmt_event_wait_on_iface(sta_iface, NET_EVENT_WIFI_CONNECT_RESULT, NULL, NULL, NULL,
43+
K_FOREVER);
44+
}
3545
}
46+
3647
return status();
3748
}
3849

@@ -79,7 +90,18 @@ int WiFiClass::status() {
7990
}
8091

8192
int8_t WiFiClass::scanNetworks() {
82-
// TODO: borrow code from mbed core for scan results handling
93+
resultCount = 0u;
94+
setScanSequenceFinished(false);
95+
setSoughtNetworkFound(false);
96+
97+
// Trigger a new scan
98+
net_mgmt(NET_REQUEST_WIFI_SCAN, sta_iface, nullptr, 0u);
99+
100+
// Wait for the scan to finish. This is by design a blocking call
101+
while (getScanSequenceFinished() != true)
102+
;
103+
104+
return resultCount;
83105
}
84106

85107
char *WiFiClass::SSID() {

libraries/WiFi/src/WiFi.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
#include "utility/wl_definitions.h"
44
#include <zephyr/net/wifi_mgmt.h>
55

6+
// Max number of scan results to store
7+
#define MAX_SCAN_RESULTS 20
8+
69
#define NET_EVENT_WIFI_MASK \
710
(NET_EVENT_WIFI_CONNECT_RESULT | NET_EVENT_WIFI_DISCONNECT_RESULT | \
811
NET_EVENT_WIFI_AP_ENABLE_RESULT | NET_EVENT_WIFI_AP_DISABLE_RESULT | \
@@ -31,6 +34,62 @@ class WiFiClass : public NetworkInterface {
3134

3235
String firmwareVersion();
3336

37+
static void scanEventDispatcher(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
38+
struct net_if *iface) {
39+
if (instance != nullptr) {
40+
instance->handleScanEvent(cb, mgmt_event, iface);
41+
}
42+
}
43+
44+
void handleScanEvent(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
45+
struct net_if *iface) {
46+
if (mgmt_event == NET_EVENT_WIFI_SCAN_RESULT) {
47+
const struct wifi_scan_result *entry =
48+
reinterpret_cast<const struct wifi_scan_result *>(cb->info);
49+
if (resultCount < MAX_SCAN_RESULTS) {
50+
memcpy(&scanResults[resultCount], entry, sizeof(struct wifi_scan_result));
51+
resultCount++;
52+
53+
// for each new result found, compare network name with desired one
54+
if (!memcmp(entry->ssid, sta_config.ssid, entry->ssid_length)) {
55+
// if a match is found, add missing info to config before attempting to connect
56+
sta_config.security = entry->security;
57+
sta_config.channel = entry->channel;
58+
sta_config.band = entry->band;
59+
sta_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
60+
61+
setSoughtNetworkFound(true);
62+
}
63+
}
64+
}
65+
66+
if (mgmt_event == NET_EVENT_WIFI_SCAN_DONE) {
67+
setScanSequenceFinished(true);
68+
69+
if (resultCount = 0) {
70+
printk("No networks found.\n");
71+
}
72+
}
73+
}
74+
75+
void setScanSequenceFinished(bool scanFinished) {
76+
scanSequenceFinished = scanFinished;
77+
}
78+
79+
void setSoughtNetworkFound(bool networkFound) {
80+
soughtNetworkFound = networkFound;
81+
}
82+
83+
bool getScanSequenceFinished(void) {
84+
return scanSequenceFinished;
85+
}
86+
87+
bool getSoughtNetworkFound(void) {
88+
return soughtNetworkFound;
89+
}
90+
91+
static WiFiClass *instance;
92+
3493
private:
3594
struct net_if *sta_iface = nullptr;
3695
struct net_if *ap_iface = nullptr;
@@ -39,6 +98,13 @@ class WiFiClass : public NetworkInterface {
3998
struct wifi_connect_req_params sta_config;
4099

41100
struct wifi_iface_status sta_state = {0};
101+
102+
struct wifi_scan_result scanResults[MAX_SCAN_RESULTS];
103+
uint8_t resultCount;
104+
struct net_mgmt_event_callback wifiCb;
105+
106+
bool soughtNetworkFound = false;
107+
bool scanSequenceFinished = false;
42108
};
43109

44110
extern WiFiClass WiFi;

loader/llext_exports.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ FORCE_EXPORT_SYM(tls_credential_add);
113113
FORCE_EXPORT_SYM(net_if_get_wifi_sta);
114114
FORCE_EXPORT_SYM(net_if_get_wifi_sap);
115115
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_CONNECT);
116+
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_SCAN);
116117
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_IFACE_STATUS);
117118
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_AP_ENABLE);
118119
#endif

0 commit comments

Comments
 (0)