11#include < freertos/FreeRTOS.h>
22
3+ #include " wifi/WiFiManager.h"
4+
35const char * const TAG = " WiFiManager" ;
46
57#include < freertos/task.h>
@@ -14,23 +16,39 @@ const char* const TAG = "WiFiManager";
1416#include " ReadWriteMutex.h"
1517#include " Time.h"
1618#include " util/TaskUtils.h"
19+ #include " wifi/WiFiNetwork.h"
1720
1821// Temporary fix to ensure that CDC+JTAG stay on on ESP32-C3
1922#if CONFIG_IDF_TARGET_ESP32C3
2023extern " C" void phy_bbpll_en_usb (bool en);
2124#endif
2225
26+ const uint8_t OPENSHOCK_WIFI_SCAN_MAX_CHANNEL = 13 ;
27+ const uint32_t OPENSHOCK_WIFI_SCAN_DWELL_PER_CHANNEL = 100 ;
28+ const uint32_t OPENSHOCK_WIFI_SCAN_MIN_MS_PER_CHANNEL = 100 ;
29+ const uint32_t OPENSHOCK_WIFI_SCAN_MAX_MS_PER_CHANNEL = 300 ; // Adjusting this value will affect the scan rate, but may also affect the scan results
30+ const uint32_t OPENSHOCK_WIFI_SCAN_TIMEOUT_MS = 10 * 1000 ;
31+
2332enum class WiFiState : uint8_t {
2433 Disconnected = 0 ,
2534 Scanning = 1 << 0 ,
2635 Connecting = 1 << 1 ,
2736 Connected = 1 << 2 ,
2837};
2938
30- static esp_netif_t * s_wifi_sta = nullptr ;
31- static esp_netif_t * s_wifi_ap = nullptr ;
32- static WiFiState s_state = WiFiState::Disconnected;
33- static uint8_t s_target_creds = 0 ;
39+ struct ScanResult {
40+ uint8_t scanId;
41+ uint8_t size;
42+ uint8_t capacity;
43+ wifi_ap_record_t * records;
44+ };
45+
46+ static esp_netif_t * s_wifi_sta = nullptr ;
47+ static esp_netif_t * s_wifi_ap = nullptr ;
48+ static WiFiState s_state = WiFiState::Disconnected;
49+ static uint8_t s_target_creds = 0 ;
50+ static uint8_t s_scan_current_ch = 0 ;
51+ static ScanResult s_scan_results[OPENSHOCK_WIFI_SCAN_MAX_CHANNEL] = {};
3452
3553template <std::size_t N>
3654static bool is_zero (const uint8_t (&array)[N])
@@ -117,7 +135,7 @@ static bool set_ap_enabled(bool enabled)
117135 return true ;
118136}
119137
120- static bool is_connect_ratelimited (const WiFiNetwork& net)
138+ static bool is_connect_ratelimited (const OpenShock:: WiFiNetwork& net)
121139{
122140 if (net.lastConnectAttempt == 0 ) {
123141 return false ;
@@ -132,17 +150,95 @@ static bool is_connect_ratelimited(const WiFiNetwork& net)
132150 return false ;
133151}
134152
135- static std::vector<WiFiNetwork>::iterator find_network (std::function<bool (WiFiNetwork&)> predicate, bool sortByAttractivity = true)
153+ static std::vector<OpenShock:: WiFiNetwork>::iterator find_network (std::function<bool (OpenShock:: WiFiNetwork&)> predicate, bool sortByAttractivity = true)
136154{
137155 if (sortByAttractivity) {
138156 std::sort (s_wifiNetworks.begin (), s_wifiNetworks.end (), _attractivityComparer);
139157 }
140158 return std::find_if (s_wifiNetworks.begin (), s_wifiNetworks.end (), predicate);
141159}
142160
161+ static bool mark_network_as_attempted (const uint8_t (&bssid)[6])
162+ {
163+ auto it = _findNetworkByBSSID (bssid);
164+ if (it == s_wifiNetworks.end ()) {
165+ return false ;
166+ }
167+
168+ it->connectAttempts ++;
169+ it->lastConnectAttempt = OpenShock::millis ();
170+
171+ return true ;
172+ }
173+
174+ static void wifi_event_wifi_ready_handler (void * event_data)
175+ {
176+ OS_LOGV (TAG, " WiFi Ready!" );
177+ }
178+
179+ static void wifi_event_scan_done_handler (void * event_data)
180+ {
181+ auto data = reinterpret_cast <wifi_event_sta_scan_done_t *>(event_data);
182+
183+ if (data->status == 1 ) {
184+ // TODO: what to do?
185+ OS_LOGE (TAG, " WiFi Scan failed!" );
186+ return ;
187+ }
188+
189+ if (s_scan_current_ch <= 0 || s_scan_current_ch >= OPENSHOCK_WIFI_SCAN_MAX_CHANNEL) {
190+ // TODO: what to do?
191+ OS_LOGE (TAG, " WiFi Scanned channel is invalid!" );
192+ return ;
193+ }
194+
195+ OS_LOGD (TAG, " WiFi scan completed, results: %hhu scan id: %hhu" , data->number , data->scan_id );
196+
197+ ScanResult* result = s_scan_results[s_scan_current_ch];
198+
199+ result->scanId = data->scan_id ;
200+ result->size = data->number ;
201+
202+ if (result->records == nullptr || result->capacity < data->number ) {
203+ OS_LOGD (TAG, " Initializing scan results at %hhu to %hhu elements" , s_scan_current_ch, data->number );
204+ result->capacity = data->number ;
205+ result->records = reinterpret_cast <wifi_ap_record_t *>(malloc (data->number * sizeof (wifi_ap_record_t )));
206+ } else if (result->capacity < data->number ) {
207+ OS_LOGD (TAG, " Resizing scan results at %hhu from %hhu to %hhu elements" , s_scan_current_ch, data->number );
208+ free (result->records );
209+ result->capacity = data->number ;
210+ result->records = reinterpret_cast <wifi_ap_record_t *>(malloc (data->number * sizeof (wifi_ap_record_t )));
211+ }
212+
213+ esp_err_t err = esp_wifi_scan_get_ap_records (result->size , result->records );
214+ if (err != nullptr ) {
215+ OS_LOGE (TAG, " Failed to get scan results: %d" , err);
216+ return ;
217+ }
218+
219+ // TODO: Check if scan is finished, start next channel scan if not.
220+ }
221+
222+ static void wifi_event_handler (void * event_handler_arg, esp_event_base_t event_base, int32_t event_id, void * event_data)
223+ {
224+ (void )event_handler_arg;
225+ (void )event_base;
226+
227+ switch (event_id) {
228+ case WIFI_EVENT_WIFI_READY:
229+ wifi_event_wifi_ready_handler (event_data);
230+ break ;
231+ case WIFI_EVENT_SCAN_DONE:
232+ wifi_event_scan_done_handler (event_data);
233+ break ;
234+ default :
235+ break ;
236+ }
237+ }
238+
143239static bool get_next_network (OpenShock::Config::WiFiCredentials& creds)
144240{
145- return find_network ([&creds](const WiFiNetwork& net) {
241+ return find_network ([&creds](const OpenShock:: WiFiNetwork& net) {
146242 if (net.credentialsID == 0 ) {
147243 return false ;
148244 }
@@ -159,6 +255,32 @@ static bool get_next_network(OpenShock::Config::WiFiCredentials& creds)
159255 }) != s_wifiNetworks.end ();
160256}
161257
258+ static bool wifi_start_scan (uint8_t channel = OPENSHOCK_WIFI_SCAN_MAX_CHANNEL)
259+ {
260+ wifi_scan_config_t scan_cfg = {
261+ .ssid = nullptr ,
262+ .bssid = nullptr ,
263+ .channel = channel,
264+ .show_hidden = true ,
265+ .scan_type = WIFI_SCAN_TYPE_ACTIVE,
266+ .scan_time = {
267+ .active = {
268+ .min = OPENSHOCK_WIFI_SCAN_MIN_MS_PER_CHANNEL,
269+ .max = OPENSHOCK_WIFI_SCAN_MAX_MS_PER_CHANNEL,
270+ },
271+ },
272+ .home_chan_dwell_time = OPENSHOCK_WIFI_SCAN_DWELL_PER_CHANNEL,
273+ };
274+
275+ esp_err_t err = esp_wifi_scan_start (&scan_cfg, /* block: */ false );
276+ if (err != ERR_OK) {
277+ OS_LOGE (TAG, " Failed to start scan: %d" , err);
278+ return false ;
279+ }
280+
281+ return true ;
282+ }
283+
162284static bool wifi_start_connect (std::string_view ssid, std::string_view password, uint8_t (&bssid)[6])
163285{
164286 esp_err_t err;
@@ -175,7 +297,10 @@ static bool wifi_start_connect(std::string_view ssid, std::string_view password,
175297
176298 OS_LOGV (TAG, " Connecting to network %s (" BSSID_FMT " )" , ssid, BSSID_ARG (bssid));
177299
178- // TODO: Mark network as attempted
300+ if (!mark_network_as_attempted (bssid)) {
301+ OS_LOGE (TAG, " Network not recognized!" );
302+ return false ;
303+ }
179304
180305 // Create WiFi config
181306 wifi_config_t wifi_cfg;
@@ -185,7 +310,7 @@ static bool wifi_start_connect(std::string_view ssid, std::string_view password,
185310 wifi_cfg.sta .threshold .rssi = -127 ;
186311 if (try_str_copy_fixed (wifi_cfg.sta .ssid , ssid) > 0 ) {
187312 if (try_str_copy_fixed (wifi_cfg.sta .password , password) > 0 ) {
188- wifi_cfg.sta .authmode = WIFI_AUTH_WEP;
313+ wifi_cfg.sta .threshold . authmode = WIFI_AUTH_WEP;
189314 }
190315 if (!is_zero (bssid)) {
191316 wifi_cfg.sta .bssid_set = 1 ;
@@ -196,7 +321,7 @@ static bool wifi_start_connect(std::string_view ssid, std::string_view password,
196321 // Set config before connnect
197322 err = esp_wifi_set_config (WIFI_IF_STA, &wifi_cfg);
198323 if (err != ERR_OK) {
199- OS_LOGE (" Failed to set config: %d" , err);
324+ OS_LOGE (TAG, " Failed to set config: %d" , err);
200325 return false ;
201326 }
202327
@@ -205,7 +330,7 @@ static bool wifi_start_connect(std::string_view ssid, std::string_view password,
205330 err = esp_wifi_connect ();
206331 if (err != ERR_OK) {
207332 s_state = WiFiState::Disconnected;
208- OS_LOGE (" Failed to stat wifi connect: %d" , err);
333+ OS_LOGE (TAG, " Failed to stat wifi connect: %d" , err);
209334 return false ;
210335 }
211336
@@ -225,7 +350,7 @@ static bool wifi_connect_target_or_next()
225350 return false ;
226351 }
227352
228- if (wifi_start_connect (creds.ssid , creds.password , nullptr )) {
353+ if (wifi_start_connect (creds.ssid , creds.password , creds. )) {
229354 return true ;
230355 }
231356
@@ -250,15 +375,15 @@ static void wifi_task(void*)
250375 lastScanRequest = now;
251376
252377 OS_LOGV (TAG, " No networks to connect to, starting scan..." );
253- start_scanning ();
378+ wifi_start_scan ();
254379 }
255380 }
256381 }
257382 vTaskDelay (pdMS_TO_TICKS (1000 ));
258383 }
259384}
260385
261- bool WiFiManager::Init ()
386+ bool OpenShock:: WiFiManager::Init ()
262387{
263388 // Initializtion guard
264389 static bool initialized = false ;
@@ -267,7 +392,13 @@ bool WiFiManager::Init()
267392
268393 esp_err_t err;
269394
270- // TODO: register event handlers
395+ memset (s_scan_results, 0 , sizeof (ScanResult) * OPENSHOCK_WIFI_SCAN_MAX_CHANNEL);
396+
397+ err = esp_event_handler_register (WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, nullptr );
398+ if (err != ERR_OK) {
399+ OS_LOGE (TAG, " Failed to subscribe to WiFi events: %d" , err);
400+ return false ;
401+ }
271402
272403 // Get saved config
273404 std::string hostname;
0 commit comments