diff -r 000000000000 -r b74b0e4902c3 main/task_wifi.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/task_wifi.c Sat Oct 20 13:23:15 2018 +0200 @@ -0,0 +1,806 @@ +/** + * @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]; +bool _wifi_ScanAPs = false; +bool _wifi_ScanDone = false; +uint16_t _wifi_Scanned = 0; + +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. + * @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; +} + + + +/** + * @brief WiFi manager task + */ +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); +} + + +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; +} + +