Skip to content

Commit f769b0c

Browse files
committed
WiFI: Implemented WiFI.scan() functionality.
ZEP-55: WiFi: try to connect using default connection parameters Device will try to connect using default connection parameters, if an SSID and a password were provided, even if the scan was unsuccessful. ZEP-55: Implemented WiFi.scan() functionality.
1 parent 6847a9c commit f769b0c

File tree

4 files changed

+193
-71
lines changed

4 files changed

+193
-71
lines changed

libraries/WiFi/examples/WiFiWebClient/WiFiWebClient.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ void setup() {
5050
Serial.println(ssid);
5151
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
5252
status = WiFi.begin(ssid, pass);
53-
// wait 3 seconds for connection:
54-
delay(3000);
53+
// wait 6 seconds for connection:
54+
delay(6000);
5555
}
5656
Serial.println("Connected to wifi");
5757
printWifiStatus();

libraries/WiFi/src/WiFi.cpp

Lines changed: 169 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,217 @@
11
#include "WiFi.h"
22

3-
WiFiClass WiFi;
3+
// Static Wi-Fi state instance
4+
struct WiFiState {
5+
struct net_if *sta_iface = nullptr;
6+
struct net_if *ap_iface = nullptr;
7+
struct wifi_connect_req_params ap_config;
8+
struct wifi_connect_req_params sta_config;
9+
struct wifi_iface_status sta_state = {0};
10+
struct wifi_scan_result scanResults[MAX_SCAN_RESULTS];
11+
uint8_t resultCount = 0;
12+
struct net_mgmt_event_callback wifiCb;
13+
bool soughtNetworkFound = false;
14+
bool scanSequenceFinished = false;
15+
};
416

5-
String WiFiClass::firmwareVersion() {
6-
#if defined(ARDUINO_PORTENTA_C33)
7-
return "v1.5.0";
8-
#else
9-
return "v0.0.0";
10-
#endif
17+
WiFiClass::WiFiClass() {
1118
}
1219

20+
WiFiClass::~WiFiClass() {
21+
}
22+
23+
// Static instance of Wi-Fi state
24+
struct WiFiState WiFiClass::wifiState;
25+
1326
int WiFiClass::begin(const char *ssid, const char *passphrase, wl_enc_type security,
1427
bool blocking) {
15-
sta_iface = net_if_get_wifi_sta();
16-
netif = sta_iface;
17-
sta_config.ssid = (const uint8_t *)ssid;
18-
sta_config.ssid_length = strlen(ssid);
19-
sta_config.psk = (const uint8_t *)passphrase;
20-
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;
28+
wifi_security_type wifi_security = convert_enc_type_to_security_type(security);
29+
30+
wifiState.sta_iface = net_if_get_wifi_sta();
31+
netif = wifiState.sta_iface;
32+
wifiState.sta_config.ssid = (const uint8_t *)ssid;
33+
wifiState.sta_config.ssid_length = strlen(ssid);
34+
wifiState.sta_config.psk = (const uint8_t *)passphrase;
35+
wifiState.sta_config.psk_length = strlen(passphrase);
36+
37+
// Set Wi-Fi security type if specified
38+
if (wifi_security != WIFI_SECURITY_TYPE_NONE) {
39+
wifiState.sta_config.security = wifi_security;
40+
} else {
41+
wifiState.sta_config.security = WIFI_SECURITY_TYPE_PSK;
3042
}
3143

32-
ret = status();
33-
if (ret != WL_CONNECTED && blocking) {
34-
net_mgmt_event_wait_on_iface(sta_iface, NET_EVENT_WIFI_CONNECT_RESULT, NULL, NULL, NULL,
35-
K_FOREVER);
44+
wifiState.sta_config.channel = WIFI_CHANNEL_ANY;
45+
wifiState.sta_config.band = WIFI_FREQ_BAND_2_4_GHZ;
46+
wifiState.sta_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
47+
48+
// Register the Wi-Fi event callback
49+
net_mgmt_init_event_callback(&wifiState.wifiCb, scanEventDispatcher,
50+
NET_EVENT_WIFI_SCAN_RESULT | NET_EVENT_WIFI_SCAN_DONE);
51+
net_mgmt_add_event_callback(&wifiState.wifiCb);
52+
53+
// Trigger a network scan
54+
(void)scanNetworks(); // Blocking call
55+
56+
// Attempt to connect to the network if configuration is valid
57+
if (wifiState.sta_config.ssid && wifiState.sta_config.psk) {
58+
int ret = net_mgmt(NET_REQUEST_WIFI_CONNECT, wifiState.sta_iface, &wifiState.sta_config,
59+
sizeof(struct wifi_connect_req_params));
60+
if (ret) {
61+
return false;
62+
}
63+
64+
NetworkInterface::begin(false, NET_EVENT_WIFI_MASK);
65+
if (blocking) {
66+
net_mgmt_event_wait_on_iface(wifiState.sta_iface, NET_EVENT_WIFI_CONNECT_RESULT, NULL,
67+
NULL, NULL, K_FOREVER);
68+
}
3669
}
37-
NetworkInterface::begin(blocking, NET_EVENT_WIFI_MASK);
70+
3871
return status();
3972
}
4073

4174
bool WiFiClass::beginAP(char *ssid, char *passphrase, int channel, bool blocking) {
42-
if (ap_iface != NULL) {
43-
return false;
75+
if (wifiState.ap_iface != nullptr) {
76+
return false; // AP already initialized
4477
}
45-
ap_iface = net_if_get_wifi_sap();
46-
netif = ap_iface;
47-
ap_config.ssid = (const uint8_t *)ssid;
48-
ap_config.ssid_length = strlen(ssid);
49-
ap_config.psk = (const uint8_t *)passphrase;
50-
ap_config.psk_length = strlen(passphrase);
51-
ap_config.security = WIFI_SECURITY_TYPE_PSK;
52-
ap_config.channel = channel;
53-
ap_config.band = WIFI_FREQ_BAND_2_4_GHZ;
54-
ap_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
55-
int ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, ap_iface, &ap_config,
78+
79+
wifiState.ap_iface = net_if_get_wifi_sap();
80+
netif = wifiState.ap_iface;
81+
wifiState.ap_config.ssid = (const uint8_t *)ssid;
82+
wifiState.ap_config.ssid_length = strlen(ssid);
83+
wifiState.ap_config.psk = (const uint8_t *)passphrase;
84+
wifiState.ap_config.psk_length = strlen(passphrase);
85+
wifiState.ap_config.security = WIFI_SECURITY_TYPE_PSK;
86+
wifiState.ap_config.channel = channel;
87+
wifiState.ap_config.band = WIFI_FREQ_BAND_2_4_GHZ;
88+
wifiState.ap_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
89+
90+
int ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, wifiState.ap_iface, &wifiState.ap_config,
5691
sizeof(struct wifi_connect_req_params));
5792
if (ret) {
5893
return false;
5994
}
60-
enable_dhcpv4_server(ap_iface);
95+
96+
enable_dhcpv4_server(wifiState.ap_iface);
97+
6198
if (blocking) {
62-
net_mgmt_event_wait_on_iface(ap_iface, NET_EVENT_WIFI_AP_ENABLE_RESULT, NULL, NULL, NULL,
63-
K_FOREVER);
99+
net_mgmt_event_wait_on_iface(wifiState.ap_iface, NET_EVENT_WIFI_AP_ENABLE_RESULT, NULL,
100+
NULL, NULL, K_FOREVER);
64101
}
102+
65103
return true;
66104
}
67105

68106
int WiFiClass::status() {
69-
sta_iface = net_if_get_wifi_sta();
70-
netif = sta_iface;
71-
if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, netif, &sta_state,
107+
wifiState.sta_iface = net_if_get_wifi_sta();
108+
netif = wifiState.sta_iface;
109+
if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, netif, &wifiState.sta_state,
72110
sizeof(struct wifi_iface_status))) {
73111
return WL_NO_SHIELD;
74112
}
75-
if (sta_state.state >= WIFI_STATE_ASSOCIATED) {
113+
if (wifiState.sta_state.state >= WIFI_STATE_ASSOCIATED) {
76114
return WL_CONNECTED;
77115
} else {
78116
return WL_DISCONNECTED;
79117
}
80-
return WL_NO_SHIELD;
81118
}
82119

83120
int8_t WiFiClass::scanNetworks() {
84-
// TODO: borrow code from mbed core for scan results handling
121+
wifiState.resultCount = 0u;
122+
wifiState.soughtNetworkFound = false;
123+
wifiState.scanSequenceFinished = false;
124+
125+
// Trigger a new scan
126+
net_mgmt(NET_REQUEST_WIFI_SCAN, wifiState.sta_iface, nullptr, 0u);
127+
128+
// Wait for the scan to finish (this is a blocking call)
129+
while (!wifiState.scanSequenceFinished)
130+
;
131+
132+
return wifiState.resultCount;
133+
}
134+
135+
void WiFiClass::scanEventDispatcher(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
136+
struct net_if *iface) {
137+
// Use the global Wi-Fi state instance to handle the event
138+
if (wifiState.sta_iface != nullptr) {
139+
WiFi.handleScanEvent(cb, mgmt_event, iface);
140+
}
141+
}
142+
143+
void WiFiClass::handleScanEvent(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
144+
struct net_if *iface) {
145+
if (mgmt_event == NET_EVENT_WIFI_SCAN_RESULT) {
146+
const struct wifi_scan_result *entry =
147+
reinterpret_cast<const struct wifi_scan_result *>(cb->info);
148+
if (wifiState.resultCount < MAX_SCAN_RESULTS) {
149+
memcpy(&wifiState.scanResults[wifiState.resultCount], entry,
150+
sizeof(struct wifi_scan_result));
151+
wifiState.resultCount++;
152+
153+
// Compare SSID of the scanned network with the desired network SSID
154+
if (!memcmp(entry->ssid, wifiState.sta_config.ssid, entry->ssid_length)) {
155+
wifiState.sta_config.security = entry->security;
156+
wifiState.sta_config.channel = entry->channel;
157+
wifiState.sta_config.band = entry->band;
158+
wifiState.sta_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
159+
160+
wifiState.soughtNetworkFound = true;
161+
}
162+
}
163+
}
164+
165+
if (mgmt_event == NET_EVENT_WIFI_SCAN_DONE) {
166+
wifiState.scanSequenceFinished = true;
167+
168+
if (wifiState.resultCount == 0) {
169+
printk("No networks found.\n");
170+
}
171+
}
85172
}
86173

87174
char *WiFiClass::SSID() {
88175
if (status() == WL_CONNECTED) {
89-
return (char *)sta_state.ssid;
176+
return (char *)wifiState.sta_state.ssid;
90177
}
91178
return nullptr;
92179
}
93180

94181
int32_t WiFiClass::RSSI() {
95182
if (status() == WL_CONNECTED) {
96-
return sta_state.rssi;
183+
return wifiState.sta_state.rssi;
97184
}
98185
return 0;
99186
}
187+
188+
String WiFiClass::firmwareVersion() {
189+
#if defined(ARDUINO_PORTENTA_C33)
190+
return "v1.5.0";
191+
#else
192+
return "v0.0.0";
193+
#endif
194+
}
195+
196+
wifi_security_type WiFiClass::convert_enc_type_to_security_type(wl_enc_type enc_type) {
197+
switch (enc_type) {
198+
case ENC_TYPE_WEP:
199+
return WIFI_SECURITY_TYPE_WEP;
200+
case ENC_TYPE_WPA:
201+
return WIFI_SECURITY_TYPE_WPA_PSK; // Could also map to WPA_AUTO_PERSONAL
202+
case ENC_TYPE_WPA2:
203+
return WIFI_SECURITY_TYPE_PSK; // Could also map to WPA_AUTO_PERSONAL
204+
case ENC_TYPE_WPA3:
205+
return WIFI_SECURITY_TYPE_SAE; // Could also map to SAE_AUTO
206+
case ENC_TYPE_NONE:
207+
return WIFI_SECURITY_TYPE_NONE;
208+
case ENC_TYPE_UNKNOWN:
209+
case ENC_TYPE_AUTO:
210+
return WIFI_SECURITY_TYPE_UNKNOWN;
211+
default:
212+
return WIFI_SECURITY_TYPE_UNKNOWN; // Default case for any undefined or unexpected values
213+
}
214+
}
215+
216+
// Global Wi-Fi object, uses the static wifiState struct
217+
WiFiClass WiFi;

libraries/WiFi/src/WiFi.h

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
#include "SocketHelpers.h"
1+
#ifndef WIFI_H
2+
#define WIFI_H
23

4+
#include "SocketHelpers.h"
35
#include "utility/wl_definitions.h"
46
#include <zephyr/net/wifi_mgmt.h>
57

8+
// Max number of scan results to store
9+
#define MAX_SCAN_RESULTS 20
10+
11+
// Wi-Fi event mask for the various events
612
#define NET_EVENT_WIFI_MASK \
713
(NET_EVENT_WIFI_CONNECT_RESULT | NET_EVENT_WIFI_DISCONNECT_RESULT | \
814
NET_EVENT_WIFI_AP_ENABLE_RESULT | NET_EVENT_WIFI_AP_DISABLE_RESULT | \
@@ -11,34 +17,31 @@
1117

1218
class WiFiClass : public NetworkInterface {
1319
public:
14-
WiFiClass() {
15-
}
20+
WiFiClass();
21+
~WiFiClass();
1622

17-
~WiFiClass() {
18-
}
19-
20-
int begin(const char *ssid, const char *passphrase, wl_enc_type security = ENC_TYPE_UNKNOWN,
23+
int begin(const char *ssid, const char *passphrase, wl_enc_type security = ENC_TYPE_WPA,
2124
bool blocking = true);
25+
2226
bool beginAP(char *ssid, char *passphrase, int channel = WIFI_CHANNEL_ANY,
2327
bool blocking = false);
2428

2529
int status();
26-
2730
int8_t scanNetworks();
28-
2931
char *SSID();
3032
int32_t RSSI();
31-
3233
String firmwareVersion();
34+
wifi_security_type convert_enc_type_to_security_type(wl_enc_type enc_type);
3335

34-
private:
35-
struct net_if *sta_iface = nullptr;
36-
struct net_if *ap_iface = nullptr;
37-
38-
struct wifi_connect_req_params ap_config;
39-
struct wifi_connect_req_params sta_config;
36+
static struct WiFiState wifiState; // Static instance to hold Wi-Fi state
4037

41-
struct wifi_iface_status sta_state = {0};
38+
private:
39+
static void scanEventDispatcher(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
40+
struct net_if *iface);
41+
void handleScanEvent(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
42+
struct net_if *iface);
4243
};
4344

44-
extern WiFiClass WiFi;
45+
extern WiFiClass WiFi; // Global Wi-Fi object
46+
47+
#endif // WIFI_H

loader/llext_exports.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ FORCE_EXPORT_SYM(tls_credential_get);
115115
FORCE_EXPORT_SYM(net_if_get_wifi_sta);
116116
FORCE_EXPORT_SYM(net_if_get_wifi_sap);
117117
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_CONNECT);
118+
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_SCAN);
118119
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_IFACE_STATUS);
119120
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_AP_ENABLE);
120121
#endif

0 commit comments

Comments
 (0)