Files
snapclient/components/network_interface/wifi_interface.c
Karl Osterseher cec14ad15b fix bug in OTA leading to freeze during upgrade if music playback is running during upgrade
wait for free space in flac write callback if none can be aquired.

Signed-off-by: Karl Osterseher <karl_osterseher@gmx.at>
2025-03-02 21:13:35 +01:00

278 lines
8.6 KiB
C

/*
Wifi related functionality
Connect to pre defined wifi
Must be taken over/merge with wifi provision
*/
#include "wifi_interface.h"
#include <string.h> // for memcpy
#include "esp_event.h"
#include "esp_log.h"
#include "esp_mac.h"
#include "esp_netif_types.h"
#include "esp_timer.h"
#include "esp_wifi.h"
#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
#include "freertos/semphr.h"
#include "network_interface.h"
#include "nvs_flash.h"
#if ENABLE_WIFI_PROVISIONING
#include "wifi_provisioning.h"
#endif
static const char *TAG = "WIFI_IF";
static void reset_reason_timer_counter_cb(void *);
static char mac_address[18];
static int s_retry_num = 0;
static esp_netif_t *esp_wifi_netif = NULL;
static esp_netif_ip_info_t ip_info = {{0}, {0}, {0}};
static bool connected = false;
static SemaphoreHandle_t connIpSemaphoreHandle = NULL;
#if ENABLE_WIFI_PROVISIONING
static esp_timer_handle_t resetReasonTimerHandle = NULL;
static const esp_timer_create_args_t resetReasonTimerArgs = {
.callback = &reset_reason_timer_counter_cb,
.dispatch_method = ESP_TIMER_TASK,
.name = "rstCnt",
.skip_unhandled_events = false};
static uint8_t resetReasonCounter = 0;
static void reset_reason_timer_counter_cb(void *args) {
nvs_handle_t nvs_handle;
esp_err_t err = nvs_open("storage", NVS_READWRITE, &nvs_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: Error (%s) opening NVS handle!", __func__,
esp_err_to_name(err));
} else {
ESP_LOGI(TAG, "resetting POR reset counter ...");
resetReasonCounter = 0;
err |= nvs_set_u8(nvs_handle, "restart_counter", resetReasonCounter);
err |= nvs_commit(nvs_handle);
ESP_LOGI(TAG, "%s", (err != ESP_OK) ? "Failed!" : "Done");
nvs_close(nvs_handle);
}
esp_timer_delete(resetReasonTimerHandle);
}
#endif
/* The event group allows multiple bits for each event,
but we only care about one event - are we connected
to the AP with an IP? */
// Event handler for catching system events
static void event_handler(void *arg, esp_event_base_t event_base, int event_id,
void *event_data) {
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT &&
event_id == WIFI_EVENT_STA_DISCONNECTED) {
if ((s_retry_num < WIFI_MAXIMUM_RETRY) || (WIFI_MAXIMUM_RETRY == 0)) {
xSemaphoreTake(connIpSemaphoreHandle, portMAX_DELAY);
connected = false;
xSemaphoreGive(connIpSemaphoreHandle);
esp_wifi_connect();
s_retry_num++;
ESP_LOGV(TAG, "retry to connect to the AP");
}
ESP_LOGV(TAG, "connect to the AP fail");
}
}
/** Event handler for IP_EVENT_ETH_GOT_IP */
static void got_ip_event_handler(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;
if (!network_is_our_netif(NETWORK_INTERFACE_DESC_STA, event->esp_netif)) {
return;
}
xSemaphoreTake(connIpSemaphoreHandle, portMAX_DELAY);
memcpy((void *)&ip_info, (const void *)&event->ip_info,
sizeof(esp_netif_ip_info_t));
connected = true;
xSemaphoreGive(connIpSemaphoreHandle);
ESP_LOGI(TAG, "Wifi Got IP Address");
ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "WIFIIP:" IPSTR, IP2STR(&ip_info.ip));
ESP_LOGI(TAG, "WIFIMASK:" IPSTR, IP2STR(&ip_info.netmask));
ESP_LOGI(TAG, "WIFIGW:" IPSTR, IP2STR(&ip_info.gw));
ESP_LOGI(TAG, "~~~~~~~~~~~");
s_retry_num = 0;
}
static void lost_ip_event_handler(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;
if (!network_is_our_netif(NETWORK_INTERFACE_DESC_STA, event->esp_netif)) {
return;
}
// const esp_netif_ip_info_t *ip_info = &event->ip_info;
xSemaphoreTake(connIpSemaphoreHandle, portMAX_DELAY);
memcpy((void *)&ip_info, (const void *)&event->ip_info,
sizeof(esp_netif_ip_info_t));
connected = false;
xSemaphoreGive(connIpSemaphoreHandle);
ESP_LOGI(TAG, "Wifi Lost IP Address");
}
/**
*/
bool wifi_get_ip(esp_netif_ip_info_t *ip) {
xSemaphoreTake(connIpSemaphoreHandle, portMAX_DELAY);
if (ip) {
memcpy((void *)ip, (const void *)&ip_info, sizeof(esp_netif_ip_info_t));
}
bool _connected = connected;
xSemaphoreGive(connIpSemaphoreHandle);
return _connected;
}
/**
*/
void wifi_start(void) {
if (!connIpSemaphoreHandle) {
connIpSemaphoreHandle = xSemaphoreCreateMutex();
}
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_netif_inherent_config_t esp_netif_config =
ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
// Warning: the interface desc is used in tests to capture actual connection
// details (IP, gw, mask)
esp_netif_config.if_desc = NETWORK_INTERFACE_DESC_STA;
esp_netif_config.route_prio = 128;
esp_wifi_netif = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
esp_wifi_set_default_wifi_sta_handlers();
// esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
// esp_wifi_set_ps(WIFI_PS_NONE);
#if ENABLE_WIFI_PROVISIONING
esp_reset_reason_t resetReason = esp_reset_reason();
ESP_LOGI(TAG, "reset reason was: %d", resetReason);
esp_timer_create(&resetReasonTimerArgs, &resetReasonTimerHandle);
esp_timer_start_once(resetReasonTimerHandle, 5000000);
if (resetReason == ESP_RST_POWERON) {
nvs_handle_t nvs_handle;
esp_err_t err = nvs_open("storage", NVS_READWRITE, &nvs_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: Error (%s) opening NVS handle!", __func__,
esp_err_to_name(err));
} else {
ESP_LOGI(TAG, "get POR reset counter ...");
err |= nvs_get_u8(nvs_handle, "restart_counter", &resetReasonCounter);
ESP_LOGI(TAG, "reset counter %d", resetReasonCounter);
resetReasonCounter++;
if (resetReasonCounter > 3) {
ESP_LOGW(TAG, "resetting WIFI credentials!");
resetReasonCounter = 0;
esp_wifi_restore();
// esp_wifi_set_bandwidth (WIFI_IF_STA, WIFI_BW_HT20);
esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40);
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B |
WIFI_PROTOCOL_11G |
WIFI_PROTOCOL_11N);
esp_timer_stop(resetReasonTimerHandle);
esp_timer_delete(resetReasonTimerHandle);
}
err |= nvs_set_u8(nvs_handle, "restart_counter", resetReasonCounter);
err |= nvs_commit(nvs_handle);
ESP_LOGI(TAG, "%s", (err != ESP_OK) ? "Failed!" : "Done");
nvs_close(nvs_handle);
}
}
/* Start Wi-Fi station */
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_protocol(
WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N));
ESP_ERROR_CHECK(esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40));
wifi_config_t wifi_config;
ESP_ERROR_CHECK(esp_wifi_get_config(WIFI_IF_STA, &wifi_config));
wifi_config.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL;
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_event_handler_register(
WIFI_EVENT, ESP_EVENT_ANY_ID, (esp_event_handler_t)&event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
&got_ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_LOST_IP,
&lost_ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "Starting provisioning");
improv_init();
#else
wifi_config_t wifi_config = {
.sta =
{
.ssid = WIFI_SSID,
.password = WIFI_PASSWORD,
.sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
.pmf_cfg = {.capable = true, .required = false},
},
};
/* Start Wi-Fi station */
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
ESP_ERROR_CHECK(esp_event_handler_register(
WIFI_EVENT, ESP_EVENT_ANY_ID, (esp_event_handler_t)&event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
&got_ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_LOST_IP,
&lost_ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_sta finished. Trying to connect to %s",
wifi_config.sta.ssid);
#endif
}