Fixing ethernet and wifi connection to be more robust
This commit is contained in:
@@ -21,6 +21,9 @@ internal esp_err_t get_ip_info(esp_netif_ip_info_t *ip_info);
|
||||
internal void led_blink_number(int n, uint8_t r, uint8_t g, uint8_t b);
|
||||
internal void blink_last_ip_octet();
|
||||
|
||||
// Internal states
|
||||
internal esp_netif_ip_info_t s_current_ip_info = {};
|
||||
|
||||
// === Ethernet ===
|
||||
|
||||
internal constexpr char kLogEthernet[] = "ETH";
|
||||
@@ -31,26 +34,43 @@ internal uint8_t s_eth_count = 0;
|
||||
internal esp_eth_netif_glue_handle_t s_eth_glue = nullptr;
|
||||
internal esp_netif_t *s_eth_netif = nullptr;
|
||||
internal SemaphoreHandle_t s_semph_get_ip_addrs = nullptr;
|
||||
internal SemaphoreHandle_t s_semph_eth_link = nullptr;
|
||||
internal volatile bool s_eth_link_up = false;
|
||||
#ifndef NDEBUG
|
||||
internal bool s_ethernet_connected = false;
|
||||
#endif
|
||||
|
||||
void eth_on_got_ip(void *arg, esp_event_base_t event_base, int32_t event_id,
|
||||
void *event_data) {
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
bool isEthernetNetif =
|
||||
strncmp(kNetifDescEth, esp_netif_get_desc(event->esp_netif),
|
||||
strlen(kNetifDescEth) - 1) == 0;
|
||||
if (!isEthernetNetif) {
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(kLogEthernet, "Got IPv4 event: Interface \"%s\" address: " IPSTR,
|
||||
esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
|
||||
void ethernet_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data) {
|
||||
if (event_base == IP_EVENT && event_id == IP_EVENT_ETH_GOT_IP) {
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
if (event->esp_netif != s_eth_netif) {
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(kLogEthernet, "Got IPv4 event: Interface \"%s\" address: " IPSTR,
|
||||
esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
|
||||
|
||||
xSemaphoreGive(s_semph_get_ip_addrs);
|
||||
s_current_ip_info = event->ip_info;
|
||||
xSemaphoreGive(s_semph_get_ip_addrs);
|
||||
} else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_CONNECTED) {
|
||||
ESP_LOGI(kLogEthernet, "Ethernet Link Up");
|
||||
s_eth_link_up = true;
|
||||
if (s_semph_eth_link) {
|
||||
xSemaphoreGive(s_semph_eth_link);
|
||||
}
|
||||
} else if (event_base == ETH_EVENT &&
|
||||
event_id == ETHERNET_EVENT_DISCONNECTED) {
|
||||
ESP_LOGI(kLogEthernet, "Ethernet Link Down");
|
||||
s_eth_link_up = false;
|
||||
}
|
||||
}
|
||||
|
||||
void teardown_ethernet() {
|
||||
if (s_semph_eth_link != nullptr) {
|
||||
vSemaphoreDelete(s_semph_eth_link);
|
||||
s_semph_eth_link = nullptr;
|
||||
}
|
||||
|
||||
if (s_semph_get_ip_addrs != nullptr) {
|
||||
vSemaphoreDelete(s_semph_get_ip_addrs);
|
||||
s_semph_get_ip_addrs = nullptr;
|
||||
@@ -59,7 +79,9 @@ void teardown_ethernet() {
|
||||
if (s_eth_netif) {
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP,
|
||||
ð_on_got_ip));
|
||||
ðernet_event_handler));
|
||||
ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID,
|
||||
ðernet_event_handler));
|
||||
ESP_ERROR_CHECK(esp_eth_stop(s_eth_handles[0]));
|
||||
ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue));
|
||||
esp_netif_destroy(s_eth_netif);
|
||||
@@ -82,7 +104,8 @@ internal esp_err_t connect_ethernet(bool blockUntilIPAcquired) {
|
||||
#endif
|
||||
|
||||
s_semph_get_ip_addrs = xSemaphoreCreateBinary();
|
||||
if (s_semph_get_ip_addrs == NULL) {
|
||||
s_semph_eth_link = xSemaphoreCreateBinary();
|
||||
if (s_semph_get_ip_addrs == NULL || s_semph_eth_link == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
// Connection is split in two steps. First we open the connection and ask for
|
||||
@@ -107,7 +130,9 @@ internal esp_err_t connect_ethernet(bool blockUntilIPAcquired) {
|
||||
|
||||
// Register user defined event handlers
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP,
|
||||
ð_on_got_ip, NULL));
|
||||
ðernet_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID,
|
||||
ðernet_event_handler, NULL));
|
||||
|
||||
ESP_ERROR_CHECK(esp_eth_start(s_eth_handles[0]));
|
||||
|
||||
@@ -135,6 +160,15 @@ void disconnect_ethernet() {
|
||||
}
|
||||
|
||||
internal esp_err_t check_ethernet_connection(uint32_t timeoutSeconds) {
|
||||
// Wait up to 5000ms for the physical link to negotiate
|
||||
if (!s_eth_link_up) {
|
||||
if (!xSemaphoreTake(s_semph_eth_link, pdMS_TO_TICKS(5000))) {
|
||||
ESP_LOGE(kLogEthernet,
|
||||
"No physical Ethernet link detected. Skipping DHCP wait.");
|
||||
return ESP_ERR_INVALID_STATE; // Special error to skip retries
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(kLogEthernet, "Waiting for IP address for %d seconds.",
|
||||
timeoutSeconds);
|
||||
if (xSemaphoreTake(s_semph_get_ip_addrs,
|
||||
@@ -151,30 +185,50 @@ internal esp_err_t check_ethernet_connection(uint32_t timeoutSeconds) {
|
||||
internal constexpr char kLogWifi[] = "WIFI";
|
||||
internal esp_netif_t *s_wifi_netif = nullptr;
|
||||
internal SemaphoreHandle_t s_semph_get_wifi_ip_addrs = nullptr;
|
||||
internal SemaphoreHandle_t s_semph_wifi_link = nullptr;
|
||||
internal volatile bool s_wifi_link_up = false;
|
||||
#ifndef NDEBUG
|
||||
internal bool s_wifi_connected = false;
|
||||
#endif
|
||||
|
||||
void wifi_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_DISCONNECTED) {
|
||||
ESP_LOGI(kLogWifi, "WiFi disconnected, retrying...");
|
||||
esp_wifi_connect();
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
|
||||
ESP_LOGI(kLogWifi, "WiFi associated with AP.");
|
||||
s_wifi_link_up = true;
|
||||
if (s_semph_wifi_link) {
|
||||
xSemaphoreGive(s_semph_wifi_link);
|
||||
}
|
||||
} else if (event_base == WIFI_EVENT &&
|
||||
event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
ESP_LOGI(kLogWifi, "WiFi disconnected.");
|
||||
s_wifi_link_up = false;
|
||||
} 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;
|
||||
if (event->esp_netif != s_wifi_netif) {
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(kLogWifi, "Got IPv4 event: Interface \"%s\" address: " IPSTR,
|
||||
esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
|
||||
|
||||
s_current_ip_info = event->ip_info;
|
||||
xSemaphoreGive(s_semph_get_wifi_ip_addrs);
|
||||
}
|
||||
}
|
||||
|
||||
void teardown_wifi() {
|
||||
if (s_semph_wifi_link != nullptr) {
|
||||
vSemaphoreDelete(s_semph_wifi_link);
|
||||
s_semph_wifi_link = nullptr;
|
||||
}
|
||||
|
||||
if (s_semph_get_wifi_ip_addrs != nullptr) {
|
||||
vSemaphoreDelete(s_semph_get_wifi_ip_addrs);
|
||||
s_semph_get_wifi_ip_addrs = nullptr;
|
||||
}
|
||||
|
||||
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
|
||||
&wifi_event_handler);
|
||||
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED,
|
||||
&wifi_event_handler);
|
||||
esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP,
|
||||
@@ -197,7 +251,8 @@ internal esp_err_t connect_wifi(const char *ssid, const char *password,
|
||||
#endif
|
||||
|
||||
s_semph_get_wifi_ip_addrs = xSemaphoreCreateBinary();
|
||||
if (s_semph_get_wifi_ip_addrs == NULL) {
|
||||
s_semph_wifi_link = xSemaphoreCreateBinary();
|
||||
if (s_semph_get_wifi_ip_addrs == NULL || s_semph_wifi_link == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -208,6 +263,8 @@ internal esp_err_t connect_wifi(const char *ssid, const char *password,
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(
|
||||
WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &wifi_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(
|
||||
WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &wifi_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
|
||||
@@ -248,6 +305,15 @@ void disconnect_wifi() {
|
||||
}
|
||||
|
||||
internal esp_err_t check_wifi_connection(uint32_t timeoutSeconds) {
|
||||
// Wait up to 10000ms for the physical link to associate with the AP
|
||||
if (!s_wifi_link_up) {
|
||||
if (!xSemaphoreTake(s_semph_wifi_link, pdMS_TO_TICKS(10000))) {
|
||||
ESP_LOGE(kLogWifi,
|
||||
"Failed to associate with WiFi AP. Skipping DHCP wait.");
|
||||
return ESP_ERR_INVALID_STATE; // Special error to skip retries
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(kLogWifi, "Waiting for IP address for %d seconds.", timeoutSeconds);
|
||||
if (xSemaphoreTake(s_semph_get_wifi_ip_addrs,
|
||||
pdMS_TO_TICKS(timeoutSeconds * 1000))) {
|
||||
@@ -259,12 +325,8 @@ internal esp_err_t check_wifi_connection(uint32_t timeoutSeconds) {
|
||||
}
|
||||
|
||||
internal esp_err_t get_ip_info(esp_netif_ip_info_t *ip_info) {
|
||||
if (s_eth_netif) {
|
||||
return esp_netif_get_ip_info(s_eth_netif, ip_info);
|
||||
} else if (s_wifi_netif) {
|
||||
return esp_netif_get_ip_info(s_wifi_netif, ip_info);
|
||||
}
|
||||
return ESP_FAIL;
|
||||
*ip_info = s_current_ip_info;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
internal void led_blink_number(int n, uint8_t r, uint8_t g, uint8_t b);
|
||||
@@ -280,8 +342,12 @@ internal void blink_last_ip_octet() {
|
||||
int t = (last_octet / 10) % 10;
|
||||
int u = last_octet % 10;
|
||||
|
||||
led_blink_number(h, 255, 255, 255);
|
||||
led_blink_number(t, 255, 255, 255);
|
||||
if (h > 0) {
|
||||
led_blink_number(h, 255, 255, 255);
|
||||
}
|
||||
if (h > 0 || t > 0) {
|
||||
led_blink_number(t, 255, 255, 255);
|
||||
}
|
||||
led_blink_number(u, 255, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user