diff --git a/src/wifi/WiFiManagerNew.cpp b/src/wifi/WiFiManagerNew.cpp index fd4baf30..f9f5037d 100644 --- a/src/wifi/WiFiManagerNew.cpp +++ b/src/wifi/WiFiManagerNew.cpp @@ -4,6 +4,7 @@ const char* const TAG = "WiFiManager"; +#include #include #include @@ -29,6 +30,16 @@ const uint32_t OPENSHOCK_WIFI_SCAN_MIN_MS_PER_CHANNEL = 100; 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 const uint32_t OPENSHOCK_WIFI_SCAN_TIMEOUT_MS = 10 * 1000; +const uint32_t OPENSHOCK_DNS_MAIN = 0x01010101; // 1.1.1.1 +const uint32_t OPENSHOCK_DNS_BACKUP = 0x08080808; // 8.8.8.8 +const uint32_t OPENSHOCK_DNS_FALLBACK = 0x09090909; // 9.9.9.9 + +enum class WiFiTaskNotification : uint8_t { + None, + ScanFailed, + ScanCompleted +} + enum class WiFiState : uint8_t { Disconnected = 0, Scanning = 1 << 0, @@ -38,17 +49,18 @@ enum class WiFiState : uint8_t { struct ScanResult { uint8_t scanId; - uint8_t size; - uint8_t capacity; + uint16_t size; + uint16_t capacity; wifi_ap_record_t* records; }; +static QueueHandle_t s_event_queue = nullptr; static esp_netif_t* s_wifi_sta = nullptr; static esp_netif_t* s_wifi_ap = nullptr; static WiFiState s_state = WiFiState::Disconnected; static uint8_t s_target_creds = 0; -static uint8_t s_scan_current_ch = 0; -static ScanResult s_scan_results[OPENSHOCK_WIFI_SCAN_MAX_CHANNEL] = {}; +static uint8_t s_scan_channel_current = 0; +static ScanResult s_scan_channel[OPENSHOCK_WIFI_SCAN_MAX_CHANNEL] = {}; template static bool is_zero(const uint8_t (&array)[N]) @@ -83,7 +95,7 @@ static bool configure_sta_dns() esp_netif_dns_info_t dns; dns.ip.type = ESP_IPADDR_TYPE_V4; - dns.ip.u_addr.ip4.addr = 0x01010101; // 1.1.1.1 + dns.ip.u_addr.ip4.addr = OPENSHOCK_DNS_MAIN; err = esp_netif_set_dns_info(s_wifi_sta, ESP_NETIF_DNS_MAIN, &dns); if (err != ERR_OK) { @@ -91,7 +103,7 @@ static bool configure_sta_dns() return false; } - dns.ip.u_addr.ip4.addr = 0x08080808; // 8.8.8.8 + dns.ip.u_addr.ip4.addr = OPENSHOCK_DNS_BACKUP; err = esp_netif_set_dns_info(s_wifi_sta, ESP_NETIF_DNS_BACKUP, &dns); if (err != ERR_OK) { @@ -99,7 +111,7 @@ static bool configure_sta_dns() return false; } - dns.ip.u_addr.ip4.addr = 0x09090909; // 9.9.9.9 + dns.ip.u_addr.ip4.addr = OPENSHOCK_DNS_FALLBACK; err = esp_netif_set_dns_info(s_wifi_sta, ESP_NETIF_DNS_FALLBACK, &dns); if (err != ERR_OK) { @@ -171,71 +183,6 @@ static bool mark_network_as_attempted(const uint8_t (&bssid)[6]) return true; } -static void wifi_event_wifi_ready_handler(void* event_data) -{ - OS_LOGV(TAG, "WiFi Ready!"); -} - -static void wifi_event_scan_done_handler(void* event_data) -{ - auto data = reinterpret_cast(event_data); - - if (data->status == 1) { - // TODO: what to do? - OS_LOGE(TAG, "WiFi Scan failed!"); - return; - } - - if (s_scan_current_ch <= 0 || s_scan_current_ch >= OPENSHOCK_WIFI_SCAN_MAX_CHANNEL) { - // TODO: what to do? - OS_LOGE(TAG, "WiFi Scanned channel is invalid!"); - return; - } - - OS_LOGD(TAG, "WiFi scan completed, results: %hhu scan id: %hhu", data->number, data->scan_id); - - ScanResult* result = s_scan_results[s_scan_current_ch]; - - result->scanId = data->scan_id; - result->size = data->number; - - if (result->records == nullptr || result->capacity < data->number) { - OS_LOGD(TAG, "Initializing scan results at %hhu to %hhu elements", s_scan_current_ch, data->number); - result->capacity = data->number; - result->records = reinterpret_cast(malloc(data->number * sizeof(wifi_ap_record_t))); - } else if (result->capacity < data->number) { - OS_LOGD(TAG, "Resizing scan results at %hhu from %hhu to %hhu elements", s_scan_current_ch, data->number); - free(result->records); - result->capacity = data->number; - result->records = reinterpret_cast(malloc(data->number * sizeof(wifi_ap_record_t))); - } - - esp_err_t err = esp_wifi_scan_get_ap_records(result->size, result->records); - if (err != nullptr) { - OS_LOGE(TAG, "Failed to get scan results: %d", err); - return; - } - - // TODO: Check if scan is finished, start next channel scan if not. -} - -static void wifi_event_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) -{ - (void)event_handler_arg; - (void)event_base; - - switch (event_id) { - case WIFI_EVENT_WIFI_READY: - wifi_event_wifi_ready_handler(event_data); - break; - case WIFI_EVENT_SCAN_DONE: - wifi_event_scan_done_handler(event_data); - break; - default: - break; - } -} - static bool get_next_network(OpenShock::Config::WiFiCredentials& creds) { return find_network([&creds](const OpenShock::WiFiNetwork& net) { @@ -255,7 +202,7 @@ static bool get_next_network(OpenShock::Config::WiFiCredentials& creds) }) != s_wifiNetworks.end(); } -static bool wifi_start_scan(uint8_t channel = OPENSHOCK_WIFI_SCAN_MAX_CHANNEL) +static bool wifi_scan_start(uint8_t channel = OPENSHOCK_WIFI_SCAN_MAX_CHANNEL) { wifi_scan_config_t scan_cfg = { .ssid = nullptr, @@ -272,9 +219,16 @@ static bool wifi_start_scan(uint8_t channel = OPENSHOCK_WIFI_SCAN_MAX_CHANNEL) .home_chan_dwell_time = OPENSHOCK_WIFI_SCAN_DWELL_PER_CHANNEL, }; + uint8_t lastChannel = s_scan_channel_current; + s_scan_channel_current = channel; + esp_err_t err = esp_wifi_scan_start(&scan_cfg, /* block: */ false); if (err != ERR_OK) { + // Restore previous variable ASAP + s_scan_channel_current = lastChannel; + OS_LOGE(TAG, "Failed to start scan: %d", err); + return false; } @@ -330,7 +284,7 @@ static bool wifi_start_connect(std::string_view ssid, std::string_view password, err = esp_wifi_connect(); if (err != ERR_OK) { s_state = WiFiState::Disconnected; - OS_LOGE(TAG, "Failed to stat wifi connect: %d", err); + OS_LOGE(TAG, "Failed to stat wifi conhuhnect: %d", err); return false; } @@ -364,22 +318,154 @@ static bool wifi_connect_target_or_next() return wifi_start_connect(creds.ssid, creds.password, nullptr); } -static void wifi_task(void*) +static void task_handle_scan_failed() +{ + // TODO: Wtf to do here? +} + +static void task_handle_scan_completed() +{ +} + +static void task_handle_disconnected() +{ + static int64_t lastScanRequest = 0; + if (wifi_connect_target_or_next()) return; + + int64_t now = OpenShock::millis(); + + if (lastScanRequest == 0 || now - lastScanRequest > 30'000) { + lastScanRequest = now; + + OS_LOGV(TAG, "No networks to connect to, starting scan..."); + wifi_scan_start(); + } +} + +static void task_main(void*) { - int64_t lastScanRequest = 0; + bool isScanning = false; while (true) { - if (s_state == WiFiState::Disconnected) { - if (!wifi_connect_target_or_next()) { - int64_t now = OpenShock::millis(); - if (lastScanRequest == 0 || now - lastScanRequest > 30'000) { - lastScanRequest = now; - - OS_LOGV(TAG, "No networks to connect to, starting scan..."); - wifi_start_scan(); - } + WiFiTaskNotification eventType; + if (xQueueReceive(s_event_queue, &eventType, portMAX_DELAY) == pdTRUE) { + switch (eventType) { + case WiFiTaskNotification::ScanFailed: + task_handle_scan_failed(); + break; + case WiFiTaskNotification::ScanCompleted: + task_handle_scan_completed(); + break; + default: + break; } } - vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +static void event_notify_task(WiFiTaskNotification notification) +{ + if (xQueueSend(s_event_queue, ¬ification, portMAX_DELAY) != pdTRUE) { + OS_PANIC(TAG, "Unable to queue wifi event!"); + } +} + +static void event_wifi_ready_handler(void* event_data) +{ + OS_LOGV(TAG, "WiFi Ready!"); +} + +static void event_wifi_scan_done_handler(void* event_data) +{ + auto data = reinterpret_cast(event_data); + + if (data->status == 1) { + OS_LOGE(TAG, "WiFi Scan failed!"); + event_notify_task(WiFiTaskNotification::ScanFailed); + return; + } + + if (s_scan_channel_current <= 0 || s_scan_channel_current > OPENSHOCK_WIFI_SCAN_MAX_CHANNEL) { + OS_LOGE(TAG, "WiFi Scanned channel is invalid!"); + event_notify_task(WiFiTaskNotification::ScanFailed); + return; + } + + OS_LOGD(TAG, "WiFi scan completed, results: %hhu scan id: %hhu", data->number, data->scan_id); + + ScanResult& result = s_scan_channel[s_scan_channel_current]; + + esp_err_t err; + + uint16_t numRecords; + err = esp_wifi_scan_get_ap_num(&numRecords); + if (err != ERR_OK) { + OS_LOGE(TAG, "Failed to get scan result count: %d", err); + event_notify_task(WiFiTaskNotification::ScanFailed); + return; + } + + OS_LOGI(TAG, "Values: %hhu <-> %hu", data->number, numRecords); + + result.scanId = data->scan_id; + result.size = numRecords; + + if (result.records == nullptr || result.capacity < numRecords) { + OS_LOGD(TAG, "Initializing scan results at %hhu to %hhu elements", s_scan_channel_current, numRecords); + result.capacity = numRecords; + result.records = reinterpret_cast(malloc(numRecords * sizeof(wifi_ap_record_t))); + } else if (result.capacity < numRecords) { + OS_LOGD(TAG, "Resizing scan results at %hhu from %hhu to %hhu elements", s_scan_channel_current, numRecords); + free(result.records); + result.capacity = numRecords; + result.records = reinterpret_cast(malloc(numRecords * sizeof(wifi_ap_record_t))); + } + + err = esp_wifi_scan_get_ap_records(&result.size, result.records); + if (err != ERR_OK) { + OS_LOGE(TAG, "Failed to get scan results: %d", err); + event_notify_task(WiFiTaskNotification::ScanFailed); + return; + } + + if (--s_scan_channel_current == 0) { + event_notify_task(WiFiTaskNotification::ScanCompleted); + return; + } + + wifi_scan_start(s_scan_channel_current); +} + +static void event_wifi_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + (void)event_handler_arg; + (void)event_base; + + switch (event_id) { + case WIFI_EVENT_WIFI_READY: + event_wifi_ready_handler(event_data); + break; + case WIFI_EVENT_SCAN_DONE: + event_wifi_scan_done_handler(event_data); + break; + case WIFI_EVENT_STA_START: + break; + case WIFI_EVENT_STA_STOP: + break; + case WIFI_EVENT_STA_CONNECTED: + break; + case WIFI_EVENT_STA_DISCONNECTED: + break; + case WIFI_EVENT_AP_START: + break; + case WIFI_EVENT_AP_STOP: + break; + case WIFI_EVENT_AP_STACONNECTED: + break; + case WIFI_EVENT_AP_STADISCONNECTED: + break; + default: + OS_LOGW(TAG, "Received unknown event with ID: %i", event_id); + break; } } @@ -392,9 +478,14 @@ bool OpenShock::WiFiManager::Init() esp_err_t err; - memset(s_scan_results, 0, sizeof(ScanResult) * OPENSHOCK_WIFI_SCAN_MAX_CHANNEL); + s_event_queue = xQueueCreate(32, sizeof(WiFiTaskNotification)); + if (s_event_queue == nullptr) { + OS_PANIC(TAG, "Failed to allocate event queue, probably out of memory!"); + } + + memset(s_scan_channel, 0, sizeof(ScanResult) * OPENSHOCK_WIFI_SCAN_MAX_CHANNEL); - err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, nullptr); + err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, event_wifi_handler, nullptr); if (err != ERR_OK) { OS_LOGE(TAG, "Failed to subscribe to WiFi events: %d", err); return false; diff --git a/src/wifi/WiFiScanManager.cpp b/src/wifi/WiFiScanManager.cpp index d7d3aa8a..bc7f92cb 100644 --- a/src/wifi/WiFiScanManager.cpp +++ b/src/wifi/WiFiScanManager.cpp @@ -28,62 +28,8 @@ static std::map using namespace OpenShock; -bool _notifyTask(WiFiScanTaskNotificationFlags flags) -{ - ScopedLock lock__(&s_scanTaskMutex); - - if (s_scanTaskHandle == nullptr) { - return false; - } - - return xTaskNotify(s_scanTaskHandle, flags, eSetBits) == pdPASS; -} - -void _notifyStatusChangedHandlers(OpenShock::WiFiScanStatus status) -{ - for (auto& it : s_statusChangedHandlers) { - it.second(status); - } -} - -bool _isScanError(int16_t retval) -{ - return retval < 0 && retval != WIFI_SCAN_RUNNING; -} - -void _handleScanError(int16_t retval) -{ - if (retval >= 0) return; - - _notifyTask(WiFiScanTaskNotificationFlags::ERROR); - - if (retval == WIFI_SCAN_FAILED) { - OS_LOGE(TAG, "Failed to start scan on channel %u", s_currentChannel); - return; - } - - if (retval == WIFI_SCAN_RUNNING) { - OS_LOGE(TAG, "Scan is running on channel %u", s_currentChannel); - return; - } - - OS_LOGE(TAG, "Scan returned an unknown error"); -} - -int16_t _scanChannel(uint8_t channel) -{ - int16_t retval = WiFi.scanNetworks(true, true, false, OPENSHOCK_WIFI_SCAN_MAX_MS_PER_CHANNEL, channel); - if (!_isScanError(retval)) { - return retval; - } - - _handleScanError(retval); - - return retval; -} - WiFiScanStatus _scanningTaskImpl() -{ +{WiFi.scanNetworks // Start the scan on the highest channel and work our way down uint8_t channel = OPENSHOCK_WIFI_SCAN_MAX_CHANNEL;