main/task_wifi.c

Tue, 03 Oct 2023 17:24:06 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 03 Oct 2023 17:24:06 +0200
changeset 77
15dc572a7fcb
parent 70
e82bb707c671
child 79
332e85569339
permissions
-rw-r--r--

Version 0.3.0. Backported network code from experimental roaming project. Will now connect after reset to the strongest AP. Id the signal level drops below -67, extra scans are done to see for a better AP. Nothing is done yet. Removed config.conf file, all info is taken from the project menu and live tests. Better log the board type and send it via json mqtt. Send bssid and current channel too.

/**
 * @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);
		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;
	    	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