Merge pull request #50 from badgeteam/wifi_test

WiFi
This commit is contained in:
Renze Nicolai 2022-06-01 23:44:57 +02:00 committed by GitHub
commit 7448c6d23a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 404 additions and 43 deletions

View file

@ -5,6 +5,15 @@
#include <stddef.h>
#include "esp_wifi.h"
#include "esp_wifi_types.h"
#include "esp_wpa2.h"
#define WIFI_MCH2022_SSID "MCH2022"
#define WIFI_MCH2022_USER "mch2022"
#define WIFI_MCH2022_IDENT "mch2022"
#define WIFI_MCH2022_PASSWORD "mch2022"
#define WIFI_MCH2022_AUTH WIFI_AUTH_WPA2_ENTERPRISE
#define WIFI_MCH2022_PHASE2 ESP_EAP_TTLS_PHASE2_MSCHAPV2
// Simpler interpretation of WiFi signal strength.
typedef enum {
@ -26,7 +35,7 @@ void wifi_init();
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);
bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonIdent, const char* aPassword, esp_eap_ttls_phase2_types phase2, uint8_t aRetryMax);
// Scan for WiFi networks.
// Updates the APs pointer if non-null.

View file

@ -19,17 +19,44 @@
#include "system_wrapper.h"
#include "bootscreen.h"
#include "wifi_connect.h"
#include "wifi_connection.h"
#include "wifi_ota.h"
#include "graphics_wrapper.h"
static const char *TAG = "wifi menu";
typedef enum action {
/* ==== GENERIC ACTIONS ==== */
// Nothing happens.
ACTION_NONE,
// Go back to the parent menu.
ACTION_BACK,
/* ==== MAIN MENU ACTIONS ==== */
// Show the current WiFi settings.
ACTION_SHOW,
// Scan for networks and pick one to connect to.
ACTION_SCAN,
ACTION_MANUAL
// Manually edit the current WiFi settings.
ACTION_MANUAL,
/* ==== AUTH MODES ==== */
ACTION_AUTH_OPEN,
ACTION_AUTH_WEP,
ACTION_AUTH_WPA_PSK,
ACTION_AUTH_WPA2_PSK,
ACTION_AUTH_WPA_WPA2_PSK,
ACTION_AUTH_WPA2_ENTERPRISE,
ACTION_AUTH_WPA3_PSK,
ACTION_AUTH_WPA2_WPA3_PSK,
ACTION_AUTH_WAPI_PSK,
/* ==== PHASE2 AUTH MODES ==== */
ACTION_PHASE2_EAP,
ACTION_PHASE2_MSCHAPV2,
ACTION_PHASE2_MSCHAP,
ACTION_PHASE2_PAP,
ACTION_PHASE2_CHAP,
} menu_wifi_action_t;
void render_wifi_help(pax_buf_t* pax_buffer) {
@ -40,6 +67,9 @@ void render_wifi_help(pax_buf_t* pax_buffer) {
void wifi_show(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341);
void wifi_setup(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, bool scan);
wifi_ap_record_t *wifi_scan_results(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, size_t num_aps, wifi_ap_record_t *aps);
int wifi_auth_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, wifi_auth_mode_t default_mode);
int wifi_phase2_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, esp_eap_ttls_phase2_types default_mode);
void menu_wifi(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341) {
menu_t* menu = menu_alloc("WiFi configuration");
@ -137,10 +167,8 @@ void wifi_show(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341
char buffer[300];
pax_noclip(pax_buffer);
pax_background(pax_buffer, 0xFFFFFF);
snprintf(buffer, sizeof(buffer), "SSID is %s", ssid);
pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 0, 20*0, buffer);
snprintf(buffer, sizeof(buffer), "Password is %s", password);
pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 0, 20*1, buffer);
snprintf(buffer, sizeof(buffer), "WiFi SSID:\n%s\nWiFi password:\n%s", ssid, password);
pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 0, 0, buffer);
ili9341_write(ili9341, pax_buffer->buf);
bool quit = false;
@ -165,37 +193,347 @@ void wifi_show(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341
}
}
void wifi_setup(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, bool scan) {
nvs_handle_t handle;
nvs_open("system", NVS_READWRITE, &handle);
char ssid[33];
char password[33];
size_t requiredSize;
esp_err_t res = nvs_get_str(handle, "wifi.ssid", NULL, &requiredSize);
if (res != ESP_OK) {
strcpy(ssid, "");
strcpy(password, "");
} else if (requiredSize < sizeof(ssid)) {
res = nvs_get_str(handle, "wifi.ssid", ssid, &requiredSize);
if (res != ESP_OK) strcpy(ssid, "");
res = nvs_get_str(handle, "wifi.password", NULL, &requiredSize);
if (res != ESP_OK) {
strcpy(password, "");
} else if (requiredSize < sizeof(password)) {
res = nvs_get_str(handle, "wifi.password", password, &requiredSize);
if (res != ESP_OK) strcpy(password, "");
wifi_ap_record_t *wifi_scan_results(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, size_t num_aps, wifi_ap_record_t *aps) {
menu_t *menu = menu_alloc("Select network");
wifi_ap_record_t *picked = NULL;
render_wifi_help(pax_buffer);
for (size_t i = 0; i < num_aps; i++) {
menu_insert_item(menu, (const char*) aps[i].ssid, NULL, (void *) (i + 1), -1);
}
bool render = true;
size_t selection = 0;
while (1) {
rp2040_input_message_t buttonMessage = {0};
selection = -1;
if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) {
uint8_t pin = buttonMessage.input;
bool value = buttonMessage.state;
switch(pin) {
case RP2040_INPUT_JOYSTICK_DOWN:
if (value) {
menu_navigate_next(menu);
render = true;
}
break;
case RP2040_INPUT_JOYSTICK_UP:
if (value) {
menu_navigate_previous(menu);
render = true;
}
break;
case RP2040_INPUT_BUTTON_HOME:
case RP2040_INPUT_BUTTON_BACK:
if (value) {
selection = 0;
}
break;
case RP2040_INPUT_BUTTON_ACCEPT:
case RP2040_INPUT_JOYSTICK_PRESS:
case RP2040_INPUT_BUTTON_SELECT:
case RP2040_INPUT_BUTTON_START:
if (value) {
selection = (size_t) menu_get_callback_args(menu, menu_get_position(menu));
}
break;
default:
break;
}
}
if (render) {
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF2f55a8);
ili9341_write(ili9341, pax_buffer->buf);
render = false;
}
if (selection != (size_t) -1) {
if (selection == 0) {
break;
} else {
// You picked one, yay!
picked = &aps[selection-1];
break;
}
render = true;
selection = -1;
render_wifi_help(pax_buffer);
}
}
menu_free(menu);
return picked;
}
int wifi_auth_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, wifi_auth_mode_t default_mode) {
menu_t* menu = menu_alloc("Authentication mode");
menu_insert_item(menu, "Insecure", NULL, (void*) ACTION_AUTH_OPEN, -1);
menu_insert_item(menu, "WEP", NULL, (void*) ACTION_AUTH_WEP, -1);
menu_insert_item(menu, "WPA PSK", NULL, (void*) ACTION_AUTH_WPA_PSK, -1);
menu_insert_item(menu, "WPA2 PSK", NULL, (void*) ACTION_AUTH_WPA2_PSK, -1);
// menu_insert_item(menu, "QQQQQQQQQQQQ", NULL, (void*) ACTION_AUTH_WPA_WPA2_PSK, -1);
menu_insert_item(menu, "WPA2 Enterprise", NULL, (void*) ACTION_AUTH_WPA2_ENTERPRISE, -1);
menu_insert_item(menu, "WPA3 PSK", NULL, (void*) ACTION_AUTH_WPA3_PSK, -1);
// menu_insert_item(menu, "QQQQQQQQQQQQ", NULL, (void*) ACTION_AUTH_WPA2_WPA3_PSK, -1);
// menu_insert_item(menu, "WAPI PSK", NULL, (void*) ACTION_AUTH_WAPI_PSK, -1);
bool render = true;
menu_wifi_action_t action = ACTION_NONE;
wifi_auth_mode_t pick = default_mode;
render_wifi_help(pax_buffer);
while (1) {
rp2040_input_message_t buttonMessage = {0};
if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) {
uint8_t pin = buttonMessage.input;
bool value = buttonMessage.state;
switch(pin) {
case RP2040_INPUT_JOYSTICK_DOWN:
if (value) {
menu_navigate_next(menu);
render = true;
}
break;
case RP2040_INPUT_JOYSTICK_UP:
if (value) {
menu_navigate_previous(menu);
render = true;
}
break;
case RP2040_INPUT_BUTTON_HOME:
case RP2040_INPUT_BUTTON_BACK:
if (value) {
action = ACTION_BACK;
}
break;
case RP2040_INPUT_BUTTON_ACCEPT:
case RP2040_INPUT_JOYSTICK_PRESS:
case RP2040_INPUT_BUTTON_SELECT:
case RP2040_INPUT_BUTTON_START:
if (value) {
action = (menu_wifi_action_t) menu_get_callback_args(menu, menu_get_position(menu));
}
break;
default:
break;
}
}
if (render) {
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF2f55a8);
ili9341_write(ili9341, pax_buffer->buf);
render = false;
}
if (action != ACTION_NONE) {
if (action == ACTION_BACK) {
break;
} else {
pick = (wifi_auth_mode_t) (action - ACTION_AUTH_OPEN);
break;
}
render = true;
action = ACTION_NONE;
render_wifi_help(pax_buffer);
}
}
menu_free(menu);
return pick;
}
int wifi_phase2_menu(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, esp_eap_ttls_phase2_types default_mode) {
menu_t* menu = menu_alloc("Phase 2 authentication mode");
menu_insert_item(menu, "ESP", NULL, (void*) ACTION_PHASE2_EAP, -1);
menu_insert_item(menu, "MSCHAPv2", NULL, (void*) ACTION_PHASE2_MSCHAPV2, -1);
menu_insert_item(menu, "MSCHAP", NULL, (void*) ACTION_PHASE2_MSCHAP, -1);
menu_insert_item(menu, "PAP", NULL, (void*) ACTION_PHASE2_PAP, -1);
menu_insert_item(menu, "CHAP", NULL, (void*) ACTION_PHASE2_CHAP, -1);
bool render = true;
menu_wifi_action_t action = ACTION_NONE;
esp_eap_ttls_phase2_types pick = default_mode;
render_wifi_help(pax_buffer);
while (1) {
rp2040_input_message_t buttonMessage = {0};
if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) {
uint8_t pin = buttonMessage.input;
bool value = buttonMessage.state;
switch(pin) {
case RP2040_INPUT_JOYSTICK_DOWN:
if (value) {
menu_navigate_next(menu);
render = true;
}
break;
case RP2040_INPUT_JOYSTICK_UP:
if (value) {
menu_navigate_previous(menu);
render = true;
}
break;
case RP2040_INPUT_BUTTON_HOME:
case RP2040_INPUT_BUTTON_BACK:
if (value) {
action = ACTION_BACK;
}
break;
case RP2040_INPUT_BUTTON_ACCEPT:
case RP2040_INPUT_JOYSTICK_PRESS:
case RP2040_INPUT_BUTTON_SELECT:
case RP2040_INPUT_BUTTON_START:
if (value) {
action = (menu_wifi_action_t) menu_get_callback_args(menu, menu_get_position(menu));
}
break;
default:
break;
}
}
if (render) {
menu_render(pax_buffer, menu, 0, 0, 320, 220, 0xFF2f55a8);
ili9341_write(ili9341, pax_buffer->buf);
render = false;
}
if (action != ACTION_NONE) {
if (action == ACTION_BACK) {
break;
} else {
pick = (wifi_auth_mode_t) (action - ACTION_PHASE2_EAP);
break;
}
render = true;
action = ACTION_NONE;
render_wifi_help(pax_buffer);
}
}
menu_free(menu);
return pick;
}
// Sorts WiFi APs by RSSI (best RSSI first in the list).
static int wifi_ap_sorter(const void *a0, const void *b0) {
const wifi_ap_record_t *a = a0;
const wifi_ap_record_t *b = b0;
return b->rssi - a->rssi;
}
void wifi_setup(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili9341, bool scan) {
char ssid[33] = {0};
char username[33] = {0};
char password[33] = {0};
nvs_handle_t handle;
nvs_open("system", NVS_READWRITE, &handle);
bool accepted = true;
wifi_auth_mode_t authmode = WIFI_AUTH_WPA2_PSK;
esp_eap_ttls_phase2_types phase2 = ESP_EAP_TTLS_PHASE2_EAP;
/* ==== scanning phase ==== */
if (scan) {
// Show a little bit of text.
char *text = "Scanning...";
pax_vec1_t dims = pax_text_size(NULL, 1, text);
float scale = pax_buffer->width / dims.x;
pax_background(pax_buffer, 0xffffffff);
pax_draw_text(pax_buffer, 0xff000000, NULL, scale, 0, (pax_buffer->height - dims.y*scale)/2, text);
ili9341_write(ili9341, pax_buffer->buf);
// Scan for networks.
wifi_ap_record_t *aps;
size_t n_aps = wifi_scan(&aps);
// Sort them by RSSI.
qsort(aps, n_aps, sizeof(wifi_ap_record_t), wifi_ap_sorter);
// Make a de-duplicated list.
wifi_ap_record_t *dedup = malloc(sizeof(wifi_ap_record_t) * n_aps);
size_t n_dedup = 0;
for (size_t i = 0; i < n_aps; ) {
for (size_t x = 0; x < n_dedup; x++) {
if (!strcmp((const char *) aps[i].ssid, (const char *) dedup[x].ssid)) goto cont;
}
dedup[n_dedup] = aps[i];
n_dedup ++;
cont:
i++;
}
// Open a little menu for picking a network.
wifi_ap_record_t *pick = wifi_scan_results(buttonQueue, pax_buffer, ili9341, n_dedup, dedup);
if (!pick) {
nvs_close(handle);
return;
}
// Copy the SSID in.
memcpy(ssid, pick->ssid, 33);
authmode = pick->authmode;
// Free memories.
free(aps);
free(dedup);
} else {
size_t requiredSize;
esp_err_t res = nvs_get_str(handle, "wifi.ssid", NULL, &requiredSize);
if (res != ESP_OK) {
strcpy(ssid, "");
strcpy(password, "");
} else if (requiredSize < sizeof(ssid)) {
res = nvs_get_str(handle, "wifi.ssid", ssid, &requiredSize);
if (res != ESP_OK) strcpy(ssid, "");
res = nvs_get_str(handle, "wifi.password", NULL, &requiredSize);
if (res != ESP_OK) {
strcpy(password, "");
} else if (requiredSize < sizeof(password)) {
res = nvs_get_str(handle, "wifi.password", password, &requiredSize);
if (res != ESP_OK) strcpy(password, "");
}
}
// Select SSID.
accepted = keyboard(buttonQueue, pax_buffer, ili9341, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "WiFi SSID", "Press HOME to cancel", ssid, sizeof(ssid));
// Select auth mode.
if (accepted) {
authmode = wifi_auth_menu(buttonQueue, pax_buffer, ili9341, -1);
accepted = authmode != -1;
}
}
/* ==== manual entering phase ==== */
if (authmode == WIFI_AUTH_WPA2_ENTERPRISE) {
if (accepted) {
// Phase2 method.
phase2 = wifi_phase2_menu(buttonQueue, pax_buffer, ili9341, -1);
accepted = phase2 != -1;
}
if (accepted) {
// Username.
accepted = keyboard(buttonQueue, pax_buffer, ili9341, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "WiFi username", "Press HOME to cancel", username, sizeof(username));
}
}
bool accepted = keyboard(buttonQueue, pax_buffer, ili9341, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "WiFi SSID", "Press HOME to exit", ssid, sizeof(ssid));
if (accepted) {
accepted = keyboard(buttonQueue, pax_buffer, ili9341, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "WiFi password", "Press HOME to exit", password, sizeof(password));
// Password.
accepted = keyboard(buttonQueue, pax_buffer, ili9341, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "WiFi password", "Press HOME to cancel", password, sizeof(password));
}
if (accepted) {
nvs_set_str(handle, "wifi.ssid", ssid);
nvs_set_str(handle, "wifi.password", password);
nvs_set_u8 (handle, "wifi.authmode", authmode);
if (authmode == WIFI_AUTH_WPA2_ENTERPRISE) {
nvs_set_str(handle, "wifi.username", username);
nvs_set_u8 (handle, "wifi.phase2", phase2);
}
display_boot_screen(pax_buffer, ili9341, "WiFi settings stored");
}
nvs_set_u8(handle, "wifi.use_ent", 0);
nvs_close(handle);
}

View file

@ -21,7 +21,8 @@ bool wifi_connect_to_stored() {
// Open NVS.
nvs_handle_t handle;
nvs_open("system", NVS_READWRITE, &handle);
uint8_t use_ent;
wifi_auth_mode_t authmode = 0;
esp_eap_ttls_phase2_types phase2 = 0;
char *ssid = NULL;
char *ident = NULL;
char *anon_ident = NULL;
@ -36,22 +37,36 @@ bool wifi_connect_to_stored() {
ssid = malloc(len);
res = nvs_get_str(handle, "wifi.ssid", ssid, &len);
if (res) goto errcheck;
// Check whether connection is enterprise.
res = nvs_get_u8(handle, "wifi.use_ent", &use_ent);
res = nvs_get_u8(handle, "wifi.authmode", &authmode);
bool use_ent = authmode == WIFI_AUTH_WPA2_ENTERPRISE;
if (res) goto errcheck;
if (use_ent) {
// Read enterprise-specific parameters.
// Read phase2 mode.
res = nvs_get_u8(handle, "wifi.phase2", &phase2);
if (res) goto errcheck;
// Read identity.
res = nvs_get_str(handle, "wifi.ident", NULL, &len);
res = nvs_get_str(handle, "wifi.username", NULL, &len);
if (res) goto errcheck;
ident = malloc(len);
res = nvs_get_str(handle, "wifi.ident", ident, &len);
res = nvs_get_str(handle, "wifi.username", ident, &len);
// Read anonymous identity.
res = nvs_get_str(handle, "wifi.anon_ident", NULL, &len);
if (res) goto errcheck;
anon_ident = malloc(len);
res = nvs_get_str(handle, "wifi.anon_ident", anon_ident, &len);
if (res) goto errcheck;
if (res == ESP_ERR_NVS_NOT_FOUND) {
// Default is use the same thing.
anon_ident = strdup(ident);
} else {
if (res) goto errcheck;
anon_ident = malloc(len);
res = nvs_get_str(handle, "wifi.anon_ident", anon_ident, &len);
if (res) goto errcheck;
}
}
// Read password.
res = nvs_get_str(handle, "wifi.password", NULL, &len);
@ -65,9 +80,9 @@ bool wifi_connect_to_stored() {
// Open the appropriate connection.
if (use_ent) {
result = wifi_connect_ent(ssid, ident, anon_ident, password, 3);
result = wifi_connect_ent(ssid, ident, anon_ident, password, phase2, 3);
} else {
result = wifi_connect(ssid, password, WIFI_AUTH_WPA2_PSK, 3);
result = wifi_connect(ssid, password, authmode, 3);
}
errcheck:

View file

@ -3,8 +3,6 @@
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "lwip/err.h"
@ -113,7 +111,7 @@ bool wifi_connect(const char* aSsid, const char* aPassword, wifi_auth_mode_t aAu
return false;
}
bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonIdent, const char* aPassword, uint8_t aRetryMax) {
bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonIdent, const char* aPassword, esp_eap_ttls_phase2_types phase2, uint8_t aRetryMax) {
retryCount = 0;
maxRetries = aRetryMax;
wifi_config_t wifi_config = {0};
@ -131,7 +129,7 @@ bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonId
esp_wifi_sta_wpa2_ent_set_identity((const uint8_t *) aAnonIdent, strlen(aAnonIdent));
esp_wifi_sta_wpa2_ent_set_username((const uint8_t *) aIdent, strlen(aIdent));
esp_wifi_sta_wpa2_ent_set_password((const uint8_t *) aPassword, strlen(aPassword));
esp_wifi_sta_wpa2_ent_set_ttls_phase2_method(ESP_EAP_TTLS_PHASE2_MSCHAPV2);
esp_wifi_sta_wpa2_ent_set_ttls_phase2_method(phase2);
// Enable enterprise auth.
esp_wifi_sta_wpa2_ent_enable();
// Disable 11b as NOC asked.
@ -139,7 +137,8 @@ bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonId
// Start the connection.
esp_wifi_start();
ESP_LOGI(TAG, "Connecting to WiFi...");
ESP_LOGI(TAG, "Connecting to '%s' as '%s'/'%s': %s", aSsid, aIdent, aAnonIdent, aPassword);
ESP_LOGI(TAG, "Phase2 mode: %d", phase2);
/* 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) */