Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/unittest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
with:
esp_idf_version: v5.5.3
target: esp32s3
command: GITHUB_ACTIONS="true" idf.py build
command: idf.py add-dependency "espressif/esp_tinyusb^2.0.1~1" ; GITHUB_ACTIONS="true" idf.py build
path: 'test-ci'

- name: Run tests
Expand Down
4 changes: 4 additions & 0 deletions components/connect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
idf_component_register(
SRCS
"connect.c"
"connect_wifi.c"
"usb_net.c"

INCLUDE_DIRS
"include"
Expand All @@ -13,4 +15,6 @@ REQUIRES
"esp_wifi"
"esp_event"
"stratum"
"esp_eth"
"esp_tinyusb"
)
214 changes: 71 additions & 143 deletions components/connect/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "esp_wifi_types_generic.h"

#include "connect.h"
#include "connect_wifi.h"
#include "usb_net.h"
#include "global_state.h"
#include "nvs_config.h"

Expand Down Expand Up @@ -57,8 +59,6 @@ static int s_retry_num = 0;
static int clients_connected_to_ap = 0;

static const char *get_wifi_reason_string(int reason);
static void wifi_softap_on(void);
static void wifi_softap_off(void);

esp_err_t get_wifi_current_rssi(int8_t *rssi)
{
Expand Down Expand Up @@ -138,7 +138,7 @@ static void ip_timeout_callback(TimerHandle_t xTimer)
GlobalState *GLOBAL_STATE = (GlobalState *)pvTimerGetTimerID(xTimer);
if (!GLOBAL_STATE->SYSTEM_MODULE.is_connected) {
ESP_LOGI(TAG, "Timeout waiting for IP address. Disconnecting...");
strcpy(GLOBAL_STATE->SYSTEM_MODULE.wifi_status, "IP Acquire Timeout");
strcpy(GLOBAL_STATE->SYSTEM_MODULE.network_status, "IP Acquire Timeout");
esp_wifi_disconnect();
}
}
Expand All @@ -164,13 +164,13 @@ static void event_handler(void * arg, esp_event_base_t event_base, int32_t event

if (event_id == WIFI_EVENT_STA_START) {
ESP_LOGI(TAG, "Connecting...");
strcpy(GLOBAL_STATE->SYSTEM_MODULE.wifi_status, "Connecting...");
strcpy(GLOBAL_STATE->SYSTEM_MODULE.network_status, "Connecting...");
esp_wifi_connect();
}

if (event_id == WIFI_EVENT_STA_CONNECTED) {
ESP_LOGI(TAG, "Acquiring IP...");
strcpy(GLOBAL_STATE->SYSTEM_MODULE.wifi_status, "Acquiring IP...");
strcpy(GLOBAL_STATE->SYSTEM_MODULE.network_status, "Acquiring IP...");

if (ip_acquire_timer == NULL) {
ip_acquire_timer = xTimerCreate("ip_acquire_timer", pdMS_TO_TICKS(30000), pdFALSE, (void *)GLOBAL_STATE, ip_timeout_callback);
Expand All @@ -190,15 +190,12 @@ static void event_handler(void * arg, esp_event_base_t event_base, int32_t event
ESP_LOGI(TAG, "Could not connect to '%.*s' [rssi %d]: reason %d", event->ssid_len, event->ssid, event->rssi, event->reason);
if (clients_connected_to_ap > 0) {
ESP_LOGI(TAG, "Client(s) connected to AP, not retrying...");
snprintf(GLOBAL_STATE->SYSTEM_MODULE.wifi_status, sizeof(GLOBAL_STATE->SYSTEM_MODULE.wifi_status), "Config AP connected!");
snprintf(GLOBAL_STATE->SYSTEM_MODULE.network_status, sizeof(GLOBAL_STATE->SYSTEM_MODULE.network_status), "Config AP connected!");
return;
}

GLOBAL_STATE->SYSTEM_MODULE.is_connected = false;
wifi_softap_on();

snprintf(GLOBAL_STATE->SYSTEM_MODULE.wifi_status, sizeof(GLOBAL_STATE->SYSTEM_MODULE.wifi_status), "%s (Error %d, retry #%d)", get_wifi_reason_string(event->reason), event->reason, s_retry_num);
ESP_LOGI(TAG, "Wi-Fi status: %s", GLOBAL_STATE->SYSTEM_MODULE.wifi_status);
snprintf(GLOBAL_STATE->SYSTEM_MODULE.network_status, sizeof(GLOBAL_STATE->SYSTEM_MODULE.network_status), "%s (Error %d, retry #%d)", get_wifi_reason_string(event->reason), event->reason, s_retry_num);
ESP_LOGI(TAG, "Wi-Fi status: %s", GLOBAL_STATE->SYSTEM_MODULE.network_status);

// Wait a little
vTaskDelay(5000 / portTICK_PERIOD_MS);
Expand Down Expand Up @@ -245,9 +242,7 @@ static void event_handler(void * arg, esp_event_base_t event_base, int32_t event
GLOBAL_STATE->SYSTEM_MODULE.is_connected = true;

ESP_LOGI(TAG, "Connected to SSID: %s", GLOBAL_STATE->SYSTEM_MODULE.ssid);
strcpy(GLOBAL_STATE->SYSTEM_MODULE.wifi_status, "Connected!");

wifi_softap_off();
strcpy(GLOBAL_STATE->SYSTEM_MODULE.network_status, "Connected!");

// Create IPv6 link-local address after WiFi connection
esp_netif_t *netif = event->esp_netif;
Expand Down Expand Up @@ -323,163 +318,96 @@ static bool is_wifi_operation_allowed(esp_err_t err)
void toggle_wifi_softap(void)
{
wifi_mode_t mode = WIFI_MODE_NULL;
esp_err_t err = esp_wifi_get_mode(&mode);
if (is_wifi_operation_allowed(err)) {
ESP_ERROR_CHECK(err);

if (mode == WIFI_MODE_APSTA) {
wifi_softap_off();
} else {
wifi_softap_on();
}
}
}

static void wifi_softap_off(void)
{
esp_err_t err = esp_wifi_set_mode(WIFI_MODE_STA);
if (is_wifi_operation_allowed(err)) {
ESP_ERROR_CHECK(err);
}
}
esp_err_t err = esp_wifi_get_mode(&mode);

static void wifi_softap_on(void)
{
esp_err_t err = esp_wifi_set_mode(WIFI_MODE_APSTA);
if (is_wifi_operation_allowed(err)) {
ESP_ERROR_CHECK(err);
}
}

/* Initialize wifi station */
esp_netif_t * wifi_init_sta(const char * wifi_ssid, const char * wifi_pass)
{
esp_netif_t * esp_netif_sta = esp_netif_create_default_wifi_sta();

/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8).
* If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value
* to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to
* WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.
*/
wifi_auth_mode_t authmode;

if (strlen(wifi_pass) == 0) {
ESP_LOGI(TAG, "No Wi-Fi password provided, using open network");
authmode = WIFI_AUTH_OPEN;
} else {
ESP_LOGI(TAG, "Wi-Fi Password provided, using WPA2");
authmode = WIFI_AUTH_WPA2_PSK;
}

wifi_config_t wifi_sta_config = {
.sta =
{
.threshold.authmode = authmode,
.btm_enabled = 1,
.rm_enabled = 1,
.scan_method = WIFI_ALL_CHANNEL_SCAN,
.sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
.pmf_cfg =
{
.capable = true,
.required = false
},
},
};

size_t ssid_len = strlen(wifi_ssid);
if (ssid_len > 32) ssid_len = 32;
memcpy(wifi_sta_config.sta.ssid, wifi_ssid, ssid_len);
if (ssid_len < 32) {
wifi_sta_config.sta.ssid[ssid_len] = '\0';
}

if (authmode != WIFI_AUTH_OPEN) {
strncpy((char *) wifi_sta_config.sta.password, wifi_pass, sizeof(wifi_sta_config.sta.password));
wifi_sta_config.sta.password[sizeof(wifi_sta_config.sta.password) - 1] = '\0';
switch (mode) {
case WIFI_MODE_NULL:
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
break;
case WIFI_MODE_STA:
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
break;
case WIFI_MODE_AP:
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
break;
case WIFI_MODE_APSTA:
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
break;
default:
break;
}
}
// strncpy((char *) wifi_sta_config.sta.password, wifi_pass, 63);
// wifi_sta_config.sta.password[63] = '\0';

ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_sta_config));

// IPv6 link-local address will be created after WiFi connection

// Start DHCP client for IPv4
esp_netif_dhcpc_start(esp_netif_sta);

ESP_LOGI(TAG, "wifi_init_sta finished.");

return esp_netif_sta;
}

void wifi_init(void * pvParameters)
void connect_init(void *pvParameters)
{
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;

ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());

esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
esp_event_handler_instance_t instance_got_ip6;
esp_event_handler_instance_t instance_any_id, instance_got_ip, instance_got_ip6;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, GLOBAL_STATE, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, GLOBAL_STATE, &instance_got_ip));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_GOT_IP6, &event_handler, GLOBAL_STATE, &instance_got_ip6));

/* Initialize Wi-Fi */
// Initialize Wi-Fi
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));

wifi_softap_on();
// Configure and start SoftAP
esp_err_t err = esp_wifi_set_mode(GLOBAL_STATE->SYSTEM_MODULE.network_mode == NETWORK_MODE_WIFI ? WIFI_MODE_APSTA : WIFI_MODE_AP);
if (is_wifi_operation_allowed(err)) {
ESP_ERROR_CHECK(err);
}

/* Initialize AP */
// Initialize SoftAP
wifi_init_softap(GLOBAL_STATE);

GLOBAL_STATE->SYSTEM_MODULE.ssid = nvs_config_get_string(NVS_CONFIG_WIFI_SSID);

/* Skip connection if SSID is null */
if (strlen(GLOBAL_STATE->SYSTEM_MODULE.ssid) == 0) {
ESP_LOGI(TAG, "No WiFi SSID provided, skipping connection");

/* Start WiFi */
ESP_ERROR_CHECK(esp_wifi_start());

/* Disable power savings for best performance */
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));

return;
} else {
// Configure STA BEFORE starting WiFi to avoid race condition
if (GLOBAL_STATE->SYSTEM_MODULE.network_mode == NETWORK_MODE_WIFI) {
ESP_LOGI(TAG, "Network mode: WiFi");

char * wifi_pass = nvs_config_get_string(NVS_CONFIG_WIFI_PASS);

/* Initialize STA */
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
esp_netif_t * esp_netif_sta = wifi_init_sta(GLOBAL_STATE->SYSTEM_MODULE.ssid, wifi_pass);

free(wifi_pass);

/* Start Wi-Fi */
ESP_ERROR_CHECK(esp_wifi_start());
// Skip connection if SSID is null
if (strlen(GLOBAL_STATE->SYSTEM_MODULE.ssid) == 0) {
ESP_LOGI(TAG, "No WiFi SSID provided, running in AP-only mode");
} else {
ESP_LOGI(TAG, "Configuring Wi-Fi STA");
connect_wifi_init(GLOBAL_STATE);
}
}

/* Disable power savings for best performance */
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
// Start Wi-Fi
ESP_ERROR_CHECK(esp_wifi_start());
// Disable power savings for best performance
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));

char * hostname = nvs_config_get_string(NVS_CONFIG_HOSTNAME);
if (GLOBAL_STATE->SYSTEM_MODULE.network_mode == NETWORK_MODE_USB) {
ESP_LOGI(TAG, "Network mode: Ethernet-over-USB");
usb_net_init(GLOBAL_STATE);
}

/* Set Hostname */
esp_err_t err = esp_netif_set_hostname(esp_netif_sta, hostname);
if (err != ERR_OK) {
ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err));
} else {
ESP_LOGI(TAG, "ESP_WIFI setting hostname to: %s", hostname);
}
ESP_LOGI(TAG, "Network initialization complete");
}

free(hostname);
void connect_await_connection(void *pvParameters)
{
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;

ESP_LOGI(TAG, "wifi_init_sta finished.");
// Wait for connection to be established
ESP_LOGI(TAG, "Waiting for network connection...");
while (!GLOBAL_STATE->SYSTEM_MODULE.is_connected) {
vTaskDelay(100 / portTICK_PERIOD_MS);
}

return;
// Disable AP after connection is established
ESP_LOGI(TAG, "Connection established, disabling AP");
if (GLOBAL_STATE->SYSTEM_MODULE.network_mode == NETWORK_MODE_WIFI) {
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
} else if (GLOBAL_STATE->SYSTEM_MODULE.network_mode == NETWORK_MODE_USB) {
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
}
}

Expand Down
Loading
Loading