main/task_wifi.c

Mon, 22 Oct 2018 21:43:45 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 22 Oct 2018 21:43:45 +0200
changeset 6
e84200edc852
parent 1
ad2c8b13eb88
child 22
90f22a101fc6
permissions
-rw-r--r--

Updated esp-ide. Removed VNC server corre encoding because no clients would use it. Enabled WiFi error logmessages. Write runtime record is now debug logging. Removed recipe.Record number, not usefull and was wrong too. Removed console print of json log data.

/**
 * @file task_wifi.c
 * @brief WiFi task. Connects to a known Access Point. If we know more then
 *        one AP, try to connect all of them until it succeeds (Not yet written).
 */


#include "config.h"


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.


uint8_t				_wifi_ssid[33];			///< Current SSID
bool				_wifi_ScanAPs = false;		///< Scanning
bool				_wifi_ScanDone = false;		///< Scan ready
uint16_t			_wifi_Scanned = 0;		///< Total scanned APs.

extern int			Main_Screen;			///< Current Screen number.
extern sButton			Buttons[MAXBUTTONS];		///< Buttons definitions.
extern uint32_t			TimeSpent;			///< Counter that is increased each second.

const int TASK_WIFI_REQUEST_WIFI_SCAN = BIT0;			///< When set, means a client requested to scan wireless networks.
const int TASK_WIFI_REQUEST_STA_DISCONNECT = BIT1;		///< When set, means a client requested to disconnect from currently connected AP.
const int TASK_WIFI_REQUEST_STA_CONNECT = BIT2;			///< When set, means a client requested to connect to an access point.

const int TASK_WIFI_HAS_IP = BIT3;				///< Indicate that we have an IP address
const int TASK_WIFI_AP_STARTED = BIT4;				///< Indicate that the SoftAP is started
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 BIT6.


/**
 * @brief Local function, save station configuration.
 * @return Esp error code.
 */
esp_err_t SaveStaConfig(void);

/**
 * @brief Local function, fetch last connected station configuration.
 * @return True if there was a last connection, false if there was not.
 */
bool FetchStaConfig(void);

/**
 * @brief Local function, WiFi event handler.
 * @param ctx Context
 * @param event The event
 * @return Esp error code.
 */
esp_err_t task_wifi_EventHandler(void *ctx, system_event_t *event);


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



esp_err_t SaveStaConfig(void)
{
    int		record;

    if (task_wifi_ConfigSTA && strlen((char *)task_wifi_ConfigSTA->sta.ssid)) {
	/*
	 * Store in /spiffs/stations.conf if it's a new station.
	 */
	record = read_station(task_wifi_ConfigSTA->sta.ssid);
	if (record == -1) {
	    add_station(task_wifi_ConfigSTA->sta.ssid, task_wifi_ConfigSTA->sta.password);
	}

	/*
	 * Update main configuration if needed.
	 */
	if (strcmp(config.lastSSID, (char *)task_wifi_ConfigSTA->sta.ssid)) {
	    sprintf(config.lastSSID, "%s", task_wifi_ConfigSTA->sta.ssid);
	    write_config();
	}
	ESP_LOGI(TAG, "SaveStaConfig %s, record %d", wifiStation.SSID, record);
    }

    return ESP_OK;
}



bool FetchStaConfig(void)
{
    if (task_wifi_ConfigSTA == NULL) {
	task_wifi_ConfigSTA = (wifi_config_t*)malloc(sizeof(wifi_config_t));
    }
    memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t));

    /*
     * Search last connected AP as station.
     */
    if (strlen(config.lastSSID)) {
	read_station((uint8_t *)config.lastSSID);

	/* ssid */
	size_t sz = sizeof(task_wifi_ConfigSTA->sta.ssid);
	memcpy(task_wifi_ConfigSTA->sta.ssid, wifiStation.SSID, sz);

	/* password */
	sz = sizeof(task_wifi_ConfigSTA->sta.password);
	memcpy(task_wifi_ConfigSTA->sta.password, wifiStation.Password, sz);

	ESP_LOGI(TAG, "FetchStaConfig: last connected to ssid: %s", task_wifi_ConfigSTA->sta.ssid);
	return task_wifi_ConfigSTA->sta.ssid[0] != '\0';
    }

    ESP_LOGI(TAG, "FetchStaConfig: no last connection found");
    return false;
}



esp_err_t task_wifi_EventHandler(void *ctx, system_event_t *event)
{
    switch(event->event_id) {
	case SYSTEM_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));
		_wifi_Scanned = ap_num;
		_wifi_ScanDone = true;
		break;

	case SYSTEM_EVENT_STA_START:
		ESP_LOGD(TAG, "Event STA started");
		// Set the configured hostname for the dhcp client.
		ESP_ERROR_CHECK(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, config.hostname));   
		esp_wifi_connect();
		break;

	//   SYSTEM_EVENT_STA_STOP		3
	case SYSTEM_EVENT_STA_CONNECTED:
		ESP_LOGI(TAG, "Event STA connected, turn off AP");
		wifi_ap_record_t ap_info;
		esp_wifi_sta_get_ap_info(&ap_info);
		if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
		    wifi_state->STA_connected = true;
		    wifi_state->STA_rssi = ap_info.rssi;
		    sprintf(wifi_state->STA_ssid, "%s", ap_info.ssid);
		    xSemaphoreGive(xSemaphoreWiFi);
		}
		// Turn off AP
		ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
		xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
		xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
		break;

	case SYSTEM_EVENT_STA_DISCONNECTED:
		ESP_LOGI(TAG, "Event STA disconnected, turn on AP");
		if (xSemaphoreTake(xSemaphoreWiFi, 10) == pdTRUE) {
		    wifi_state->STA_connected = false;
		    wifi_state->STA_rssi = 0;
		    xSemaphoreGive(xSemaphoreWiFi);
		}
		// Turn on AP
		ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
		xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
		xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);

		/*
		 * Meanwhile, try to reconnect.
		 */
		if (FetchStaConfig()) {
		    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
		}
		break;

	//   SYSTEM_EVENT_STA_AUTHMODE_CHANGE	6
	case SYSTEM_EVENT_STA_GOT_IP:
//		printf("SYSTEM_EVENT_STA_GOT_IP\n");
		xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_HAS_IP);
		tcpip_adapter_ip_info_t ip;
		memset(&ip, 0, sizeof(tcpip_adapter_ip_info_t));
		if (tcpip_adapter_get_ip_info(ESP_IF_WIFI_STA, &ip) == 0) {
		    if (xSemaphoreTake(xSemaphoreWiFi, 10) == pdTRUE) {
		    	snprintf(wifi_state->STA_ip, 15, IPSTR, IP2STR(&ip.ip));
			snprintf(wifi_state->STA_nm, 15, IPSTR, IP2STR(&ip.netmask));
			snprintf(wifi_state->STA_gw, 15, IPSTR, IP2STR(&ip.gw));
		    	xSemaphoreGive(xSemaphoreWiFi);
		    }
		}
		break;

	case SYSTEM_EVENT_STA_LOST_IP:
		ESP_LOGI(TAG, "Lost IP address");
		xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_HAS_IP);
		if (xSemaphoreTake(xSemaphoreWiFi, 10) == pdTRUE) {
		    wifi_state->STA_ip[0] = '\0';
		    wifi_state->STA_nm[0] = '\0';
		    wifi_state->STA_gw[0] = '\0';
		    xSemaphoreGive(xSemaphoreWiFi);
		}
		break;

	//   SYSTEM_EVENT_STA_WPS_ER_SUCCESS	9
	//   SYSTEM_EVENT_STA_WPS_ER_FAILED	10
	//   SYSTEM_EVENT_STA_WPS_ER_TIMEOUT	11
	//   SYSTEM_EVENT_STA_WPS_ER_PIN	12

    	case SYSTEM_EVENT_AP_START:
		ESP_LOGD(TAG, "Event AP started");
    		xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_AP_STARTED);
		if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
		    wifi_state->AP_active = true;
		    wifi_state->AP_clients = 0;
		    xSemaphoreGive(xSemaphoreWiFi);
		}
		break;

	case SYSTEM_EVENT_AP_STOP:
		ESP_LOGD(TAG, "Event AP stopped");
		xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_AP_STARTED);
		if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
		    wifi_state->AP_active = false;
		    wifi_state->AP_clients = 0;
		    xSemaphoreGive(xSemaphoreWiFi);
		}
		break;

    	case SYSTEM_EVENT_AP_STACONNECTED:
		if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
		    wifi_state->AP_clients++;
		    xSemaphoreGive(xSemaphoreWiFi);
		}
		ESP_LOGI(TAG, "Event AP new client, %d connections", wifi_state->AP_clients);
		break;

    	case SYSTEM_EVENT_AP_STADISCONNECTED:
		if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
		    if (wifi_state->AP_clients > 0)
		    	wifi_state->AP_clients--;
		    else
		    	wifi_state->AP_clients = 0;
		    xSemaphoreGive(xSemaphoreWiFi);
		}
		ESP_LOGI(TAG, "Event AP client disconnect, %d connections", wifi_state->AP_clients);
		break;

	//   SYSTEM_EVENT_AP_PROBEREQRECVED	17
	//   SYSTEM_EVENT_GOT_IP6		18
	//   SYSTEM_EVENT_ETH_START		19
	//   SYSTEM_EVENT_ETH_STOP		20
	//   SYSTEM_EVENT_ETH_CONNECTED		21
	//   SYSTEM_EVENT_ETH_DISCONNECTED	22
	//   SYSTEM_EVENT_ETH_GOT_IP		23

	default:
		printf("Unknown event %d\n", event->event_id);
        	break;
    }
    return ESP_OK;
}



void task_wifi( void * pvParameters )
{
    esp_err_t		ret;

    ESP_LOGI(TAG, "Starting WiFi driver");

    /*
     * Initialize NVS
     */
    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
	ESP_ERROR_CHECK(nvs_flash_erase());
	ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    /* event handler and event group for the wifi driver */
    xEventGroupWifi = xEventGroupCreate();
    /* initialize the tcp stack */
    tcpip_adapter_init();
    ESP_ERROR_CHECK(esp_event_loop_init(task_wifi_EventHandler, NULL));

    /*
     * memory allocation of objects used by the task 
     */
    accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * MAX_AP_NUM);
    task_wifi_ConfigSTA = (wifi_config_t*)malloc(sizeof(wifi_config_t));
    memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t));

    xSemaphoreWiFi = xSemaphoreCreateMutex();
    wifi_state = malloc(sizeof(WIFI_State));
    wifi_state->AP_clients = 0;
    wifi_state->AP_active = false;
    wifi_state->STA_connected = false;
    wifi_state->STA_rssi = 0;

    /* wifi scanner config */
    wifi_scan_config_t scan_config = {
	.ssid = 0,
	.bssid = 0,
	.channel = 0,
	.show_hidden = false
    };

    /*
     * start the softAP access point
     * stop DHCP server
     */
    ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP));

    /*
     * Assign a static IP to the AP network interface
     */
    tcpip_adapter_ip_info_t info;
    memset(&info, 0x00, sizeof(info));
    IP4_ADDR(&info.ip, 192, 168, 1, 1);
    IP4_ADDR(&info.gw, 192, 168, 1, 1);
    IP4_ADDR(&info.netmask, 255, 255, 255, 0);
    ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info));

    /* start dhcp server */
    ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP));
    ESP_LOGI(TAG, "AP start dhcps ip: 192.168.1.1 nm: 255.255.255.0 gw: 192.168.1.1");

    /* start dhcp client */
    ESP_ERROR_CHECK(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA));
    ESP_LOGI(TAG, "Start DHCP client for STA interface.");

    /*
     * init wifi as station + access point
     */
    wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
    ESP_ERROR_CHECK(esp_wifi_set_bandwidth(WIFI_IF_AP, config.ap_bandwidth));

    // configure the softAP and start it */
    wifi_config_t ap_config = {
	.ap = {
	    .ssid_len = 0,
	    .channel = config.ap_channel,
	    .authmode = WIFI_AUTH_WPA2_PSK,
	    .ssid_hidden = config.ap_ssid_hidden,
	    .max_connection = AP_MAX_CONNECTIONS,
	    .beacon_interval = 100,
	},
    };
    memcpy(ap_config.ap.ssid, config.ap_ssid , sizeof(config.ap_ssid));
    memcpy(ap_config.ap.password, config.ap_pwd, sizeof(config.ap_pwd));
    ret = esp_wifi_set_config(WIFI_IF_AP, &ap_config);
    if (ret != ESP_OK) {
	ESP_LOGE(TAG, "esp_wifi_set_config(WIFI_IF_AP, nnn) rc=%d", ret);
    }
    ESP_ERROR_CHECK(esp_wifi_start());

    ESP_LOGI(TAG, "SoftAP start ssid: `%s' pwd: `%s' channel: %d, hidden: %s", 
		    ap_config.ap.ssid, ap_config.ap.password, ap_config.ap.channel, ap_config.ap.ssid_hidden ? "yes":"no");

    /*
     * try to get access to previously saved wifi
     */
    if (FetchStaConfig()) {
	xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
    }

    /* 
     * Wait for access point to start
     */
    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
    xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_AP_STARTED, pdFALSE, pdTRUE, portMAX_DELAY );
    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_WIFI_SCAN | TASK_WIFI_REQUEST_STA_DISCONNECT,
		                     pdFALSE, pdFALSE, portMAX_DELAY );

	if (uxBits & TASK_WIFI_REQUEST_STA_DISCONNECT) {
	    /*
	     * user requested a disconnect, this will in effect disconnect the wifi but also erase NVS memory
	     */
	    ESP_LOGI(TAG, "Request disconnect");
	    sntp_stop();
	    ESP_ERROR_CHECK(esp_wifi_disconnect());
	    xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY );
	    
	    /*
	     * erase configuration
	     */
	    if (task_wifi_ConfigSTA) {
		memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t));
	    }
	    config.lastSSID[0] = '\0';
	    write_config();

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

	} else if (uxBits & TASK_WIFI_REQUEST_STA_CONNECT) {

	    //someone requested a connection!
	    ESP_LOGI(TAG, "Request STA connect `%s'", task_wifi_ConfigSTA->sta.ssid);
	    /* set the new config and connect - reset the failed bit first as it is later tested */
	    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_FAILED);
	    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, task_wifi_ConfigSTA));

            esp_err_t wifierror = esp_wifi_connect();
	    if (wifierror != ESP_OK) {
	    	ESP_LOGE(TAG, "esp_wifi_connect() rc=%04x", (int)wifierror);
		xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_FAILED);
	    }

	    /* 
	     * 2 scenarios here: connection is successful and TASK_WIFI_HAS_IP will be posted
	     * or it's a failure and we get a TASK_WIFI_STA_FAILED with a reason code.
	     * Note that the reason code is not exploited. For all intent and purposes a failure is a failure.
	     */
	    uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_HAS_IP | TASK_WIFI_STA_FAILED, pdFALSE, pdFALSE, portMAX_DELAY );

	    if (uxBits & (TASK_WIFI_HAS_IP | TASK_WIFI_STA_FAILED)) {
		/* 
		 * only save the config if the connection was successful! 
		 */
		if(uxBits & TASK_WIFI_HAS_IP) {
		    /* save wifi config */
		    SaveStaConfig();
		    sntp_setservername(0, "nl.pool.ntp.org");
		    sntp_init();
		    ESP_LOGI(TAG, "Initialized SNTP %s", sntp_getservername(0));
		} else {
		    ESP_LOGI(TAG, "Connection failed");	// TODO: Scan other SSID's for known networks.
		    /* failed attempt to connect regardles of the reason */

		    /* otherwise: reset the config */
		    memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t));
		}
	    } else {
		/* hit portMAX_DELAY limit ? */
		abort();
	    }

	    /* finally: release the connection request bit */
	    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);

	} else if (uxBits & TASK_WIFI_REQUEST_WIFI_SCAN) {

	    /* safe guard against overflow */
	    ap_num = MAX_AP_NUM;
	    ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false));

	    /* finally: release the scan request bit */
	    xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_WIFI_SCAN);
	}

	/*
	 * Here we should check for reconnect actions.
	 */

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


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


/**
 * @brief Show an AP station as a button. The buttons are already defined.
 * @param idx The index position on the display, 1 to 7.
 * @param ap The AP information from the WiFi scan.
 * @param show How to display. 0 is blank, 1 is unknown, 2 is known, 3 is a connected AP.
 */
void Show_AP(uint8_t idx, wifi_ap_record_t ap, int show)
{
    char	tmp[33];

    if ((idx > 7) || (idx < 1))
	return;

    if (show == 0) {
	_bg = TFT_BLACK;
    } else {
    	_bg = (color_t){ 63, 63, 64 };
    }

    TFT_fillRect(Buttons[idx].x, Buttons[idx].y, Buttons[idx].w, Buttons[idx].h, _bg);
    if (show == 0)
	return;

    TFT_drawRect(Buttons[idx].x, Buttons[idx].y, Buttons[idx].w, Buttons[idx].h, TFT_NAVY);
    if (show == 3) {
	_fg = TFT_WHITE;
    } else if (show == 1) {
    	_fg = TFT_YELLOW;
    } else {
	_fg = TFT_CYAN;
    }

    TFT_setFont(DEJAVU18_FONT, NULL);
    sprintf(tmp, "%s", ap.ssid);
    TFT_print(tmp, Buttons[idx].x + 5, Buttons[idx].y + 6);
    sprintf(tmp, "%d", ap.rssi);
    TFT_setFont(DEF_SMALL_FONT, NULL);
    TFT_print(tmp, Buttons[idx].x + Buttons[idx].w - (TFT_getStringWidth(tmp) + 5), Buttons[idx].y + 4);
    sprintf(tmp, "%s", apsec[ap.authmode]);
    TFT_print(tmp, Buttons[idx].x + Buttons[idx].w - (TFT_getStringWidth(tmp) + 5), Buttons[idx].y + 15);
}



bool WiFi_Init(void)
{
    char	pwd[65], pmpt[32];

    switch (Main_Screen) {
	case MAIN_TOOLS_SETUP_WIFI:
			TopMessage("WiFi");
			TFT_setFont(DEJAVU24_FONT, NULL);
			_fg = TFT_WHITE;
			TFT_print("Momentje ..", CENTER, CENTER);
			_wifi_ScanAPs = true;
			_wifi_ScanDone = false;
			Buttons_Add(260, 200, 60, 40, "Ok", 0);
			Buttons[0].dark = true;
			Buttons_Show();
			// Now add the buttons we draw manually.
			Buttons_Add(  0, 30, 250, 30, "", 1);
			Buttons_Add(  0, 60, 250, 30, "", 2);
			Buttons_Add(  0, 90, 250, 30, "", 3);
			Buttons_Add(  0,120, 250, 30, "", 4);
			Buttons_Add(  0,150, 250, 30, "", 5);
			Buttons_Add(  0,180, 250, 30, "", 6);
			Buttons_Add(  0,210, 250, 30, "", 7);
			break;

	case MAIN_TOOLS_SETUP_WIFI_CUR:
			TopMessage("WiFi verbinding");
			// Get extra information.
			wifi_ap_record_t ap_info;
			esp_wifi_sta_get_ap_info(&ap_info);

			wifi_config_t *wconfig = task_wifi_ConfigSTA /*task_wifi_GetWifiStaConfig( ) */;
			if (wconfig) {

			    tcpip_adapter_ip_info_t ip_info;
			    ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
			    char ip[IP4ADDR_STRLEN_MAX];
			    char gw[IP4ADDR_STRLEN_MAX];
			    char netmask[IP4ADDR_STRLEN_MAX];
			    strcpy(ip, ip4addr_ntoa(&ip_info.ip));
			    strcpy(netmask, ip4addr_ntoa(&ip_info.netmask));
			    strcpy(gw, ip4addr_ntoa(&ip_info.gw));
			    TFT_setFont(DEFAULT_FONT, NULL);
			    _fg = TFT_WHITE;
			    TFT_print("SSID", 155 - TFT_getStringWidth("SSID"), 40);
			    TFT_print("Kanaal", 155 - TFT_getStringWidth("Kanaal"), 60);
			    TFT_print("Rssi", 155 - TFT_getStringWidth("Rssi"), 80);
			    TFT_print("Mode", 155 - TFT_getStringWidth("Mode"), 100);
			    TFT_print("IP adres", 155 - TFT_getStringWidth("IP adres"), 120);
			    TFT_print("Netmask", 155 - TFT_getStringWidth("Netmask"), 140);
			    TFT_print("Gateway", 155 - TFT_getStringWidth("Gateway"), 160);
			    _fg = TFT_YELLOW;
			    TFT_print((char*)wconfig->sta.ssid, 165, 40);
			    sprintf(pmpt, "%d", ap_info.primary);
			    TFT_print(pmpt, 165, 60);
			    sprintf(pmpt, "%d", ap_info.rssi);
			    TFT_print(pmpt, 165, 80);
			    sprintf(pmpt, "%s%s%s", ap_info.phy_11b ? "b":"", ap_info.phy_11g ? "g":"", ap_info.phy_11n ? "n":"");
			    TFT_print(pmpt, 165, 100);
			    TFT_print((char*)ip, 165, 120);
			    TFT_print((char*)netmask, 165, 140);
			    TFT_print((char*)gw, 165, 160);
			}
			Buttons_Add(130, 200, 60, 40, "Ok", 0);
			Buttons[0].dark = true;
			Buttons_Show();
			break;

	case MAIN_TOOLS_SETUP_WIFI_CON:
			TopMessage("WiFi verbinden");
			TFT_setFont(DEJAVU18_FONT, NULL);
			_fg = TFT_WHITE;
			TFT_print("SSID", 155 - TFT_getStringWidth("SSID"), 70);
			_fg = TFT_YELLOW;
			TFT_print((char*)_wifi_ssid, 165, 70);
			Buttons_Add(  0, 200, 100, 40, "Annuleer", 0);
			Buttons_Add(110, 200, 100, 40, "Vergeet",  1);
			Buttons_Add(220, 200, 100, 40, "Verbind",  2);
			Buttons_Show();
			Buttons[0].dark = true;
			break;

	case MAIN_TOOLS_SETUP_WIFI_NEW:
			TopMessage("WiFi nieuw");
			snprintf(pmpt, 32, "Password for %s", _wifi_ssid);
			pwd[0] = '\0';
			EditTextMin(pmpt, pwd, 64, 8);
			/*
			 * Disconnect first
			 */
			_bg = TFT_BLACK;
			TFT_fillScreen(_bg);
			TFT_setFont(DEJAVU24_FONT, NULL);
			_fg = TFT_WHITE;
			TFT_print("Momentje ..", CENTER, CENTER);
			xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT);
			vTaskDelay(100 / portTICK_PERIOD_MS);
			xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY );

			/*
			 * Setup new connection
			 */
			if (strlen(pwd)) {
			    wifi_config_t* config = task_wifi_ConfigSTA;
			    memset(config, 0x00, sizeof(wifi_config_t));
			    memcpy(config->sta.ssid, _wifi_ssid, strlen((char*)_wifi_ssid));
			    memcpy(config->sta.password, pwd, strlen(pwd));
			    ESP_LOGI(TAG, "new AP %s %s", _wifi_ssid, pwd);
			    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
			} else {
			    // TODO: what about WPS, it works but how to insert it in this app.
			    return true;
			}
			// We must wait here for the result.
			break;

	default:
			break;
    }

    return false;
}


bool WiFi_Loop(void)
{
    uint8_t		idx;
    int			Choice;
    static int		AP[8];
    wifi_ap_record_t	ap;

    switch (Main_Screen) {
	case MAIN_TOOLS_SETUP_WIFI:
			if (_wifi_ScanAPs) {
			    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_WIFI_SCAN);
			    _wifi_ScanAPs = false;
			    TimeSpent = 0;
			}
			if (_wifi_ScanDone) {
			    /*
			     * Show scan results. There is room for 7 entries. If we have a connection,
			     * the first one is that connection followed by available Access Points.
			     * If there is no connection yet, there is only a iist of available Access
			     * points.
			     * The list is sorted by signal strength and is filled by the eventhandler.
			     */
			    idx = 1;
			    _wifi_ScanDone = false;

			    if ((xEventGroupGetBits(xEventGroupWifi) & TASK_WIFI_STA_CONNECTED) == TASK_WIFI_STA_CONNECTED) {
				// We are connected. Search and display this one.
				if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
				    for (int i = 0; i < _wifi_Scanned; i++) {
					ap = accessp_records[i];
					if (strcmp(wifi_state->STA_ssid, (char *)ap.ssid) == 0) {
					    AP[idx] = i;
					    Show_AP(idx, ap, 3);
					    idx++;
					    break;
					}
				    }
				    xSemaphoreGive(xSemaphoreWiFi);
				}
			    }

			    // Display available Access Points.
			    for (int i = 0; i < _wifi_Scanned; i++) {
				// The connected AP can be somewhere in this list, don't display it again.
				ap = accessp_records[i];
				if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
				    if (strcmp(wifi_state->STA_ssid, (char *)ap.ssid) == 0) {
					xSemaphoreGive(xSemaphoreWiFi);
					continue;	// Skip connected AP, already on top of the list.
				    }
				    xSemaphoreGive(xSemaphoreWiFi);
				}
				// Check if we know this AP in the database.
				if ((read_station(ap.ssid) == -1)) {
				    Show_AP(idx, ap, 2);	// Unknown
				} else {
				    if (wifiStation.hide) {
					continue;		// Blacklisted.
				    }
				    Show_AP(idx, ap, 1);	// We know this one.
				}
				AP[idx] = i;
				idx++;
				if (idx ==  8)
				    break;
			    }
			    if (idx < 7) {
				for (int i = idx; i < 8; i++) {
				    Show_AP(i, ap, 0);
				    AP[i] = 0;
				}
			    }
			}

			Choice = Buttons_Scan();
			if ((Choice >= 1) && (Choice <= 7)) {
			    ap = accessp_records[AP[Choice]];
			    sprintf((char *)_wifi_ssid, "%s", ap.ssid);		// Save selected SSID.
			}
			if ((Choice == 1) && ((xEventGroupGetBits(xEventGroupWifi) & TASK_WIFI_STA_CONNECTED) == TASK_WIFI_STA_CONNECTED)) {
			    Main_Screen = MAIN_TOOLS_SETUP_WIFI_CUR;
			    // Cancel a possible scan.
			    ESP_ERROR_CHECK(esp_wifi_scan_stop());
			} else if ((Choice >= 1) && (Choice <= 7)) {
			    if ((read_station(_wifi_ssid) != -1)) {
				Main_Screen = MAIN_TOOLS_SETUP_WIFI_CON;
			    } else {
				Main_Screen = MAIN_TOOLS_SETUP_WIFI_NEW;
			    }
			    ESP_ERROR_CHECK(esp_wifi_scan_stop());
			} else if (Choice == 0) {
			    Main_Screen = MAIN_TOOLS_SETUP;
			    ESP_ERROR_CHECK(esp_wifi_scan_stop());
			}
			if (TimeSpent > 10) {
			     _wifi_ScanAPs = true;
			}
			break;

	case MAIN_TOOLS_SETUP_WIFI_CUR:

			if (Buttons_Scan() == 0) {
			    Main_Screen = MAIN_TOOLS_SETUP_WIFI;
			}
			break;

	case MAIN_TOOLS_SETUP_WIFI_CON:
			switch (Buttons_Scan()) {
			    case 0:	// Cancel choice
				    	Main_Screen = MAIN_TOOLS_SETUP_WIFI;
					break;

			    case 1:	// Forget connection
					remove_station(_wifi_ssid);
					Main_Screen = MAIN_TOOLS_SETUP_WIFI;
					break;

			    case 2:	// Connect
					_bg = TFT_BLACK;
					TFT_fillScreen(_bg);
					TFT_setFont(DEJAVU24_FONT, NULL);
					_fg = TFT_WHITE;
					TFT_print("Momentje ..", CENTER, CENTER);
					/*
					 * Disconnect old connections and wait until it's gone.
					 */
					xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT);
					vTaskDelay(100 / portTICK_PERIOD_MS);
					xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY );
					/*
					 * Setup new connection.
					 */
					if ((read_station(_wifi_ssid) != -1)) {
					    wifi_config_t* config = task_wifi_ConfigSTA;
					    memset(config, 0x00, sizeof(wifi_config_t));
					    memcpy(config->sta.ssid, wifiStation.SSID, strlen(wifiStation.SSID));
					    memcpy(config->sta.password, wifiStation.Password, strlen(wifiStation.Password));
					    xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
					    vTaskDelay(1000 / portTICK_PERIOD_MS);
					}
					Main_Screen = MAIN_TOOLS_SETUP_WIFI;
					break;

			    default:	break;
			}
			break;
												         
	case MAIN_TOOLS_SETUP_WIFI_NEW:
			// All work is already done, jump to the base screen.
			Main_Screen = MAIN_TOOLS_SETUP_WIFI;
			break;

	default:
			break;
    }

    return false;
}

mercurial