Merge pull request #47 from badgeteam/wifi_test

Basic scanning routines finished
This commit is contained in:
Robot 2022-05-30 18:09:47 +02:00 committed by GitHub
commit d61750ceed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 178 additions and 26 deletions

View file

@ -2,10 +2,36 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "esp_wifi.h"
// Simpler interpretation of WiFi signal strength.
typedef enum {
WIFI_STRENGTH_VERY_BAD,
WIFI_STRENGTH_BAD,
WIFI_STRENGTH_GOOD,
WIFI_STRENGTH_VERY_GOOD,
} wifi_strength_t;
// Thresholds for aforementioned signal strength definitions.
#define WIFI_THRESH_BAD -80
#define WIFI_THRESH_GOOD -70
#define WIFI_THRESH_VERY_GOOD -67
// Firt time initialisation of the WiFi stack.
void wifi_init();
// Connect to a traditional username/password WiFi network.
bool wifi_connect(const char* aSsid, const char* aPassword, wifi_auth_mode_t aAuthmode, uint8_t aRetryMax);
// Connect to a WPA2 enterprise WiFi network.
bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonIdent, const char* aPassword, uint8_t aRetryMax);
void wifi_scan();
// Scan for WiFi networks.
// Updates the APs pointer if non-null.
// Returns the number of APs found.
size_t wifi_scan(wifi_ap_record_t **aps);
// Get the strength value for a given RSSI.
wifi_strength_t wifi_rssi_to_strength(int8_t rssi);

View file

@ -306,10 +306,6 @@ void display_fatal_error(pax_buf_t* pax_buffer, ILI9341* ili9341, const char* li
ili9341_write(ili9341, pax_buffer->buf);
}
// void wifi_connect_to_stored() {
// wifi_connect_ent("MCH2022-legacy", "thefunny", "q", "nope, you are not", 3);
// }
void wifi_connect_to_stored() {
// Open NVS.
nvs_handle_t handle;
@ -893,6 +889,9 @@ void app_main(void) {
char buffer[300];
snprintf(buffer, sizeof(buffer), "SSID is %s\nPassword is %s", ssid, password);
graphics_task(pax_buffer, ili9341, NULL, buffer);
} else if (menu_action == ACTION_WIFI_SCAN) {
// Scan for WiFi networks.
wifi_scan(NULL);
} else {
break;
}

View file

@ -16,35 +16,47 @@ static const char *TAG = "wifi_connection";
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
#define WIFI_STARTED_BIT BIT2
static EventGroupHandle_t s_wifi_event_group;
static EventGroupHandle_t wifiEventGroup;
static uint8_t gRetryCounter = 0;
static uint8_t gRetryMax = 3;
static uint8_t retryCount = 0;
static uint8_t maxRetries = 3;
static bool isScanning = false;
static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
xEventGroupSetBits(wifiEventGroup, WIFI_STARTED_BIT);
if (!isScanning) {
// Connect only if we're not scanning the WiFi.
esp_wifi_connect();
}
ESP_LOGI(TAG, "WiFi station start.");
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_STOP) {
xEventGroupClearBits(wifiEventGroup, WIFI_STARTED_BIT);
ESP_LOGI(TAG, "WiFi station stop.");
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
if (gRetryCounter < 3) {
if (retryCount < 3) {
esp_wifi_connect();
gRetryCounter++;
ESP_LOGI(TAG, "retry to connect to the AP");
retryCount++;
ESP_LOGI(TAG, "Retrying connection");
} else {
ESP_LOGI(TAG,"connect to the AP fail");
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
ESP_LOGI(TAG, "Connection failed");
xEventGroupSetBits(wifiEventGroup, WIFI_FAIL_BIT);
}
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
gRetryCounter = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
ESP_LOGI(TAG, "Got ip:" IPSTR, IP2STR(&event->ip_info.ip));
retryCount = 0;
xEventGroupSetBits(wifiEventGroup, WIFI_CONNECTED_BIT);
}
}
void wifi_init() {
s_wifi_event_group = xEventGroupCreate();
// Create an event group for WiFi things.
wifiEventGroup = xEventGroupCreate();
// Initialise WiFi stack.
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
@ -53,17 +65,22 @@ void wifi_init() {
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
// Register event handlers for WiFi.
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip));
// Turn off WiFi hardware.
ESP_ERROR_CHECK(esp_wifi_stop());
}
bool wifi_connect(const char* aSsid, const char* aPassword, wifi_auth_mode_t aAuthmode, uint8_t aRetryMax) {
gRetryCounter = 0;
gRetryMax = aRetryMax;
// Set the retry counts.
retryCount = 0;
maxRetries = aRetryMax;
// Create a config.
wifi_config_t wifi_config = {0};
strcpy((char*) wifi_config.sta.ssid, aSsid);
strcpy((char*) wifi_config.sta.password, aPassword);
@ -81,7 +98,7 @@ bool wifi_connect(const char* aSsid, const char* aPassword, wifi_auth_mode_t aAu
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
EventBits_t bits = xEventGroupWaitBits(wifiEventGroup, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually happened. */
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "Connected to WiFi");
@ -97,8 +114,8 @@ bool wifi_connect(const char* aSsid, const char* aPassword, wifi_auth_mode_t aAu
}
bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonIdent, const char* aPassword, uint8_t aRetryMax) {
gRetryCounter = 0;
gRetryMax = aRetryMax;
retryCount = 0;
maxRetries = aRetryMax;
wifi_config_t wifi_config = {0};
if (strlen(aSsid) > 32) {
ESP_LOGE(TAG, "SSID is too long (%zu > 32)!", strlen(aSsid));
@ -126,7 +143,7 @@ bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonId
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
EventBits_t bits = xEventGroupWaitBits(wifiEventGroup, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually happened. */
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "Connected to WiFi");
@ -141,6 +158,116 @@ bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonId
return false;
}
void wifi_scan() {
// Shows a nice info message describing an AP record.
static inline void wifi_desc_record(wifi_ap_record_t *record) {
// Make a string representation of BSSID.
char *bssid_str = malloc(3*6);
if (!bssid_str) return;
snprintf(bssid_str, 3*6, "%02X:%02X:%02X:%02X:%02X:%02X",
record->bssid[0], record->bssid[1], record->bssid[2],
record->bssid[3], record->bssid[4], record->bssid[5]
);
// Make a string representation of 11b/g/n modes.
char *phy_str = malloc(9);
if (!phy_str) {
free(bssid_str);
return;
}
*phy_str = 0;
if (record->phy_11b | record->phy_11g | record->phy_11n) {
strcpy(phy_str, " 1");
}
if (record->phy_11b) {
strcat(phy_str, "/b");
}
if (record->phy_11g) {
strcat(phy_str, "/g");
}
if (record->phy_11n) {
strcat(phy_str, "/n");
}
phy_str[2] = '1';
ESP_LOGI(TAG, "AP %s %s rssi=%hhd%s", bssid_str, record->ssid, record->rssi, phy_str);
free(bssid_str);
free(phy_str);
}
// Scan for WiFi access points.
size_t wifi_scan(wifi_ap_record_t **aps_out) {
isScanning = true;
// Scan for any non-hidden APs on all channels.
wifi_scan_config_t cfg = {
.ssid = NULL,
.bssid = NULL,
.channel = 0,
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
.scan_time = { .active={ 0, 0 } },
};
// Start the scan now.
ESP_LOGI(TAG, "Starting scan...");
esp_err_t res = esp_wifi_scan_start(&cfg, true);
// Whether to call esp_wifi_stop() on finish.
bool stopWhenDone = false;
if (res == ESP_ERR_WIFI_NOT_STARTED) {
// If it complains that the wifi wasn't started, then do so.
ESP_LOGI(TAG, "Starting WiFi for scan");
// Set to station but don't connect.
res = esp_wifi_set_mode(WIFI_MODE_STA);
if (res) goto ohno;
// Start WiFi.
res = esp_wifi_start();
if (res) goto ohno;
stopWhenDone = true;
// Await the STA started bit.
xEventGroupWaitBits(wifiEventGroup, WIFI_STARTED_BIT, pdFALSE, pdFALSE, pdMS_TO_TICKS(2000));
// Try again.
res = esp_wifi_scan_start(&cfg, true);
}
if (res) {
ohno:
ESP_LOGE(TAG, "Error in WiFi scan: %s", esp_err_to_name(res));
isScanning = false;
return 0;
}
// Allocate memory for AP list.
uint16_t num_ap = 0;
esp_wifi_scan_get_ap_num(&num_ap);
wifi_ap_record_t *aps = malloc(sizeof(wifi_ap_record_t) * num_ap);
// Collect APs and report findings.
esp_wifi_scan_get_ap_records(&num_ap, aps);
for (uint16_t i = 0; i < num_ap; i++) {
wifi_desc_record(&aps[i]);
}
// Clean up.
if (aps_out) {
// Output pointer is non-null, return the APs list.
*aps_out = aps;
} else {
// Output pointer is null, free the APs list.
free(aps);
}
if (stopWhenDone) {
// Stop WiFi because it was started only for this scan.
esp_wifi_stop();
}
isScanning = false;
return num_ap;
}
// Get the strength value for a given RSSI.
wifi_strength_t wifi_rssi_to_strength(int8_t rssi) {
if (rssi > WIFI_THRESH_VERY_GOOD) return WIFI_STRENGTH_VERY_GOOD;
else if (rssi > WIFI_THRESH_GOOD) return WIFI_STRENGTH_GOOD;
else if (rssi > WIFI_THRESH_BAD) return WIFI_STRENGTH_BAD;
else return WIFI_STRENGTH_VERY_BAD;
}