main/task_wifi.c

Wed, 04 Oct 2023 11:28:49 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 04 Oct 2023 11:28:49 +0200
changeset 80
715785443a95
parent 79
332e85569339
permissions
-rw-r--r--

Version 0.3.1. Remove obsolete files from spiffs filesystem. Removed obsolete wifi stations.conf file and functions. Removed obsolete user screens.

/**
 * @file task_wifi.c
 * @brief WiFi task. Connect to the known AP with the strongest signal.
 */


#include "config.h"

#define	MAX_AP_NUM		10

static const char *TAG = "task_wifi";


SemaphoreHandle_t       	xSemaphoreWiFi = NULL;		///< Semaphore WiFi task.
EventGroupHandle_t		xEventGroupWifi;		///< Events WiFi task.
uint16_t			ap_num = MAX_AP_NUM;		///< Scan counter.
wifi_ap_record_t		*accessp_records;		///< [MAX_AP_NUM] records array with scan results.
wifi_config_t			*task_wifi_ConfigSTA = NULL;	///< Current STA configuration.
WIFI_State			*wifi_state = NULL;		///< Public state for other tasks.
esp_netif_t			*sta_netif = NULL;		///< Station interface


wifi_scan_config_t scan_config = {				///< WiFi scanner configuration.
    .ssid = (uint8_t *)CONFIG_ESP_WIFI_SSID,
    .bssid = 0,
    .channel = 0,
    .show_hidden = false
};

bool				_wifi_ScanDone = false;		///< Scan ready
bool				_wifi_BetterAP = false;		///< If better AP available.
int8_t				_wifi_RSSI = -127;		///< Latest RSSI level.
uint16_t			_wifi_Scanned = 0;		///< Total scanned APs.

extern char			hostname[];			///< Generated hostname



const int TASK_WIFI_REQUEST_STA_DISCONNECT = BIT0;		///< When set, means a client requested to disconnect from currently connected AP.
const int TASK_WIFI_REQUEST_STA_CONNECT = BIT1;			///< When set, means a client requested to connect to an access point.
const int TASK_WIFI_REQUEST_STA_SCAN = BIT2;			///< When set, means a client requested a AP scan.
const int TASK_WIFI_REQUEST_STA_STATUS = BIT3;			///< When set, means a client requested to update the connection status.

const int TASK_WIFI_HAS_IP = BIT4;				///< Indicate that we have an IP address
const int TASK_WIFI_STA_FAILED = BIT5;				///< Indicate that we could not get a connection to AP as station.
const int TASK_WIFI_STA_DISCONNECTED = BIT6;			///< Indicate that we are disconnected from an ap station.
const int TASK_WIFI_STA_CONNECTED = BIT7;			///< Indicate that we are connected to AP as station, flip of BIT5.



/**
 * @brief Array with AP security names
 */
const char *apsec[] = { "Open", "WEP", "WPA", "WPA2", "WPA WPA2", "Enterprise" };


/****************************************************************************/


bool ready_WiFi(void)
{
    if (wifi_state->STA_connected && wifi_state->STA_online)
        return true;
    return false;
}



void status_WiFi(void)
{
    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_STATUS);
}



void request_WiFi(void)
{
    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
}


void scan_WiFi(void)
{
    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_SCAN);
}


void disconnect_WiFi(void)
{
    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT);
    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
}



static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    switch (event_id) {

	case WIFI_EVENT_SCAN_DONE:
	    {
            	/* Get the results so the memory used is freed. */
            	ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, accessp_records));
		ESP_LOGI(TAG, "Event wifi Scane done, %d records", ap_num);
		_wifi_BetterAP = false;
		for (int i = 0; i < ap_num; i++) {
		    wifi_ap_record_t ap = accessp_records[i];
		    ESP_LOGI(TAG, "AP:%d bssid:%02x:%02x:%02x:%02x:%02x:%02x ssid:%s ch:%d rssi:%d",
					i, ap.bssid[0], ap.bssid[1], ap.bssid[2], ap.bssid[3], ap.bssid[4], ap.bssid[5],
					ap.ssid, ap.primary, ap.rssi);
		    if (ap.rssi > CONFIG_ESP_WIFI_ROAMING_LEVEL && ap.rssi > (_wifi_RSSI + 3)) {
			_wifi_BetterAP = true;
			ESP_LOGI(TAG, "AP:%d is a better AP", i);
		    }
		}
            	_wifi_Scanned = ap_num;
            	_wifi_ScanDone = true;
		if (_wifi_BetterAP) {
		    ESP_LOGI(TAG, "Disconnect current AP");
		    disconnect_WiFi();
		}
	    	break;
	    }

	case WIFI_EVENT_STA_START:
	    {
		ESP_LOGI(TAG, "Event wifi START");
        	// Set the configured hostname for the dhcp client.
        	ESP_ERROR_CHECK(esp_netif_set_hostname(sta_netif, hostname));
        	esp_wifi_connect();
		_wifi_BetterAP = false;
		break;
	    }

	case WIFI_EVENT_STA_CONNECTED:
	    {
		wifi_event_sta_connected_t* event = (wifi_event_sta_connected_t*) event_data;
                wifi_ap_record_t ap_info;
                esp_wifi_sta_get_ap_info(&ap_info);
		ESP_LOGI(TAG, "Event STA connected, ssid:%s, bssid:" MACSTR ", channel:%d, rssi: %d, authmode:%s",
                       ap_info.ssid, MAC2STR(ap_info.bssid), event->channel, ap_info.rssi, apsec[event->authmode]);
                if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) {
                    wifi_state->STA_connected = true;
                    wifi_state->STA_rssi = ap_info.rssi;
		    wifi_state->STA_channel = ap_info.primary;
                    sprintf(wifi_state->STA_ssid, "%s", ap_info.ssid);
		    snprintf(wifi_state->STA_bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
			     ap_info.bssid[0], ap_info.bssid[1], ap_info.bssid[2], ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]);
                    xSemaphoreGive(xSemaphoreWiFi);
                } else {
		    ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_CONNECTED");
		}
		_wifi_BetterAP = false;
                xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
                xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
	    	break;
	    }

	case WIFI_EVENT_STA_DISCONNECTED:
	    {
		wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data;

                ESP_LOGI(TAG, "Event STA disconnected, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d",
                       disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason);
                if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) {
                    wifi_state->STA_connected = false;
                    wifi_state->STA_online = false;
                    wifi_state->STA_rssi = 0;
                    xSemaphoreGive(xSemaphoreWiFi);
                } else {
		    ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_DISCONNECTED");
		}
		_wifi_BetterAP = false;
                xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
                xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
		break;
	    }

	default:
	    ESP_LOGW(TAG, "Unknown WiFi event %ld", event_id);
	    break;
    }
}



static void got_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    switch (event_id) {

	case IP_EVENT_STA_GOT_IP:
		xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_HAS_IP);
		ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
		if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
			wifi_state->STA_online = true;
			snprintf(wifi_state->STA_ip, 16, IPSTR, IP2STR(&event->ip_info.ip));
			snprintf(wifi_state->STA_nm, 16, IPSTR, IP2STR(&event->ip_info.netmask));
			snprintf(wifi_state->STA_gw, 16, IPSTR, IP2STR(&event->ip_info.gw));
			xSemaphoreGive(xSemaphoreWiFi);
		} else {
			ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_GOT_IP");
		}
		connect_mqtt(true);
		break;

	case IP_EVENT_STA_LOST_IP:
		ESP_LOGW(TAG, "Lost IP address");
		xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_HAS_IP);
		if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
			wifi_state->STA_ip[0] = '\0';
			wifi_state->STA_nm[0] = '\0';
			wifi_state->STA_gw[0] = '\0';
			wifi_state->STA_online = false;
			xSemaphoreGive(xSemaphoreWiFi);
		} else {
			ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_LOST_IP");
		}
		break;

	case IP_EVENT_AP_STAIPASSIGNED:
		ESP_LOGI(TAG, "IP_EVENT_AP_STAIPASSIGNED");
		break;

	default:
		ESP_LOGW(TAG, "Unknown IP event %ld", event_id);
		break;
    }
}



void task_wifi( void * pvParameters )
{
    ESP_LOGI(TAG, "Starting WiFi");

    /* event handler and event group for the wifi driver */
    xEventGroupWifi = xEventGroupCreate();
    /* initialize the tcp stack */
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    /*
     * memory allocation of objects used by the task 
     */
    accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * MAX_AP_NUM);
    xSemaphoreWiFi = xSemaphoreCreateMutex();
    wifi_state = malloc(sizeof(WIFI_State));
    memset(wifi_state, 0x00, sizeof(WIFI_State));

    /*
     * init wifi as station
     */
    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, &wifi_event_handler, NULL, &instance_any_id) );
    ESP_ERROR_CHECK( esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, &got_ip_event_handler, NULL, &instance_got_ip) );

    wifi_config_t wifi_config = {
	.sta = {
	    .ssid = CONFIG_ESP_WIFI_SSID,
	    .password = CONFIG_ESP_WIFI_PASSWORD,
#if CONFIG_WIFI_ALL_CHANNEL_SCAN
	    .scan_method = WIFI_ALL_CHANNEL_SCAN,
#elif CONFIG_WIFI_FAST_SCAN
	    .scan_method = WIFI_FAST_SCAN,
#endif
	    .failure_retry_cnt = 3,
	    .sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
	    .threshold.rssi = CONFIG_ESP_FAST_SCAN_MINIMUM_SIGNAL,
	    .threshold.authmode = WIFI_AUTH_WPA2_PSK,
	},
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());

//    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));

    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
    EventBits_t uxBits;

    for(;;) {

	/* actions that can trigger: request a connection, a scan, or a disconnection */
	uxBits = xEventGroupWaitBits(xEventGroupWifi, 
		       TASK_WIFI_REQUEST_STA_CONNECT | TASK_WIFI_REQUEST_STA_DISCONNECT | TASK_WIFI_REQUEST_STA_SCAN | TASK_WIFI_REQUEST_STA_STATUS,
		       pdFALSE, pdFALSE, portMAX_DELAY );

	if (uxBits & TASK_WIFI_REQUEST_STA_DISCONNECT) {
	    /*
	     * user requested a disconnect, this will in effect disconnect the wifi
	     */
	    ESP_LOGI(TAG, "Request STA disconnect");
	    ESP_ERROR_CHECK(esp_wifi_disconnect());
	    xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY );

	    /* finally: release the scan request bit */
	    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT);
	    ESP_LOGI(TAG, "Request STA disconnect is done");

	} else if (uxBits & TASK_WIFI_REQUEST_STA_CONNECT) {

	    ESP_LOGI(TAG, "Request STA connect");
	    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_FAILED);
	    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);

	    ESP_LOGI(TAG, "Connecting to `%s'", CONFIG_ESP_WIFI_SSID);
	    esp_err_t wifierror = esp_wifi_connect();
	    if (wifierror != ESP_OK) {
		ESP_LOGE(TAG, "esp_wifi_connect() `%s' rc=%04x", CONFIG_ESP_WIFI_SSID, (int)wifierror);
		xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_FAILED);
	    }
	    uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED, pdFALSE, pdFALSE, 5000 / portTICK_PERIOD_MS);
//	    if (uxBits & TASK_WIFI_STA_CONNECTED)
//		xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); // Only clear when connected.

	} else if (uxBits & TASK_WIFI_REQUEST_STA_STATUS) {
	    /*
	     * Request WiFi update status, refresh the rssi.
	     */
	    ESP_LOGD(TAG, "Request STA status");
	    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_STATUS);
	    wifi_ap_record_t ap_info;
            esp_wifi_sta_get_ap_info(&ap_info);
            ESP_LOGI(TAG, "Event STA status, ssid:%s, bssid:" MACSTR ", rssi: %d", ap_info.ssid, MAC2STR(ap_info.bssid), ap_info.rssi);
	    _wifi_RSSI = ap_info.rssi;
	    _wifi_BetterAP = false;
	    if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) {
                wifi_state->STA_rssi = ap_info.rssi;
		wifi_state->STA_channel = ap_info.primary;
		snprintf(wifi_state->STA_bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
			 ap_info.bssid[0], ap_info.bssid[1], ap_info.bssid[2], ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]);
                xSemaphoreGive(xSemaphoreWiFi);
            } else {
                ESP_LOGE(TAG, "lock error TASK_WIFI_REQUEST_STA_STATUS");
            }
	    user_refresh();

	} else if (uxBits & TASK_WIFI_REQUEST_STA_SCAN) {

	    ESP_LOGI(TAG, "Request STA scan");
	    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_SCAN);
	    /* safe guard against overflow */
	    ap_num = MAX_AP_NUM;
	    _wifi_ScanDone = false;
	    _wifi_BetterAP = false;
	    ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false));
	}

    } /* for(;;) */
//    vTaskDelay(10 / portTICK_PERIOD_MS);
}

mercurial