Sun, 24 Nov 2019 16:44:00 +0100
Version 0.3.7. The WiFi task uses the new event handlers. Cooling temperature top is now 45 instead of 30 degreees for pitching Kveik. One extra cosmetic message during OTA update.
/** * @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. wifi_scan_config_t scan_config = { ///< WiFi scanner configuration. .ssid = 0, .bssid = 0, .channel = 0, .show_hidden = false }; 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. extern bool System_TimeOk; extern time_t now; extern char strftime_buf[64]; extern struct tm timeinfo; 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); /** * @brief local callback function. Is called when the timesync is valid * from a timeserver. Sets the global boolean System_TimeOk value. * @param tv is the received time. Not used. */ void time_sync_notification_cb(struct timeval *tv); /** * @brief Array with AP security names */ const char *apsec[] = { "Open", "WEP", "WPA", "WPA2", "WPA WPA2", "Enterprise" }; /****************************************************************************/ 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_LOGD(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) >= 0)) { /* 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; } 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)); _wifi_Scanned = ap_num; _wifi_ScanDone = true; break; case WIFI_EVENT_STA_START: // 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; case WIFI_EVENT_STA_CONNECTED: { system_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, 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); } else { ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_CONNECTED"); } 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; wifi_ap_record_t ap; ESP_LOGW(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, 25) == 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"); } xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); sntp_stop(); if (disconnected->reason == WIFI_REASON_NO_AP_FOUND && ! _wifi_ScanAPs) { ESP_LOGI(TAG, "Request scan for another AP"); _wifi_ScanAPs = true; _wifi_ScanDone = false; ap_num = MAX_AP_NUM; ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false)); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); // Keep looping active. break; } if (disconnected->reason == WIFI_REASON_NO_AP_FOUND && _wifi_ScanAPs && _wifi_ScanDone) { ESP_LOGD(TAG, "Scan completed, look for another AP, found:%d", _wifi_Scanned); _wifi_ScanAPs = false; _wifi_ScanDone = false; for (int i = 0; i < _wifi_Scanned; i++) { ap = accessp_records[i]; if ((read_station(ap.ssid) != -1)) { if (wifiStation.hide) { continue; // Blacklisted. } /* We know this one */ 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)); ESP_LOGD(TAG, "new AP %s %s", wifiStation.SSID, wifiStation.Password); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); break; } } break; } /* * Reconnect previous AP. */ if (FetchStaConfig()) { xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); } break; } case WIFI_EVENT_AP_START: xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_AP_STARTED); if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { wifi_state->AP_active = true; wifi_state->AP_clients = 0; xSemaphoreGive(xSemaphoreWiFi); } else { ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_AP_START"); } break; case WIFI_EVENT_AP_STOP: xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_AP_STARTED); if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { wifi_state->AP_active = false; wifi_state->AP_clients = 0; xSemaphoreGive(xSemaphoreWiFi); } else { ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_AP_STOP"); } break; case WIFI_EVENT_AP_STACONNECTED: { if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { wifi_state->AP_clients++; xSemaphoreGive(xSemaphoreWiFi); } else { ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_AP_STACONNECTED"); } wifi_event_ap_staconnected_t* staconnected = (wifi_event_ap_staconnected_t*) event_data; // const system_event_ap_staconnected_t *staconnected = &event->event_info.sta_connected; ESP_LOGI(TAG, "Event AP connected, mac:" MACSTR ", aid:%d, conns:%d", MAC2STR(staconnected->mac), staconnected->aid, wifi_state->AP_clients); break; } case WIFI_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); } else { ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_AP_STADISCONNECTED"); } wifi_event_ap_stadisconnected_t* stadisconnected = (wifi_event_ap_stadisconnected_t*) event_data; // const system_event_ap_stadisconnected_t *stadisconnected = &event->event_info.sta_disconnected; ESP_LOGI(TAG, "Event AP disconnected, mac:" MACSTR ", aid:%d, conns:%d", MAC2STR(stadisconnected->mac), stadisconnected->aid, wifi_state->AP_clients); break; } default: ESP_LOGW(TAG, "Unknown WiFi event %d", 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, "%s", ip4addr_ntoa(&event->ip_info.ip)); snprintf(wifi_state->STA_nm, 16, "%s", ip4addr_ntoa(&event->ip_info.netmask)); snprintf(wifi_state->STA_gw, 16, "%s", ip4addr_ntoa(&event->ip_info.gw)); xSemaphoreGive(xSemaphoreWiFi); } else { ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_GOT_IP"); } /* * There doesn't seem to be support for configuring NTP via DHCP so * we need to hardcode the ntp servers. The preffered server can be * set via the setup screen. It should be on your LAN, else leave it * empty. And if you are on a different lan someday, there is no extra * delay because the hostname will not be found. */ sntp_stop(); if (strlen(config.ntp_server)) sntp_setservername(0, config.ntp_server); sntp_setservername(1, (char *)"pool.ntp.org"); // Will get you servers nearby sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED); sntp_set_time_sync_notification_cb(time_sync_notification_cb); sntp_init(); #if 0 if (strlen(config.ntp_server)) ESP_LOGI(TAG, "NTP server %s", sntp_getservername(0)); ESP_LOGI(TAG, "NTP server %s", sntp_getservername(1)); #endif break; case SYSTEM_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"); } sntp_stop(); break; default: ESP_LOGW(TAG, "Unknown IP event %d", event_id); break; } } void time_sync_notification_cb(struct timeval *tv) { int rc = sntp_get_sync_status(); if (rc == SNTP_SYNC_STATUS_COMPLETED) { time(&now); localtime_r(&now, &timeinfo); System_TimeOk = true; strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); log_msg(TAG, "NTP time is set: %s", strftime_buf); } else { ESP_LOGI(TAG, "NTP unknown time sync event rc=%d", rc); } } void task_wifi( void * pvParameters ) { esp_err_t ret; ESP_LOGI(TAG, "Starting WiFi"); /* * 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_create_default()); /* * 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_online = false; wifi_state->STA_rssi = 0; /* * 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)); /* * 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_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_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_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, "AP 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 STA 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); } 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); } /* * 3 scenarios here: connection is successful and TASK_WIFI_STA_CONNECTED will be posted * or it's a failure and we get a TASK_WIFI_STA_FAILED with a reason code. * Or, option 3, the 5 seconds timeout is reached. This happens when the AP is not in range. * Note that the reason code is not exploited. For all intent and purposes a failure is a failure. */ // ESP_LOGI(TAG, "2 wait for %08x", TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED); uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED, pdFALSE, pdFALSE, 5000 / portTICK_PERIOD_MS); // ESP_LOGI(TAG, "2 waitbits %08x", uxBits & (TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED)); if (uxBits & (TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED)) { /* * only save the config if the connection was successful! */ if (uxBits & TASK_WIFI_STA_CONNECTED) { /* save wifi config */ SaveStaConfig(); } else { ESP_LOGW(TAG, "Connection failed"); /* failed attempt to connect regardles of the reason */ /* otherwise: reset the config */ memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t)); } xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); } else { /* hit 10 seconds timeout */ ESP_LOGW(TAG, "Connection timeout"); xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); vTaskDelay(100 / portTICK_PERIOD_MS); xEventGroupSetBits(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); } } /* for(;;) */ vTaskDelay( (TickType_t)10); } /** * @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[96]; switch (Main_Screen) { case MAIN_TOOLS_SETUP_WIFI: TopMessage((char *)"WiFi"); TFT_setFont(DEJAVU24_FONT, NULL); _fg = TFT_WHITE; TFT_print((char *)"Momentje ..", CENTER, CENTER); _wifi_ScanAPs = true; _wifi_ScanDone = false; Buttons_Add(260, 200, 60, 40, (char *)"Ok", 0); Buttons[0].dark = true; Buttons_Show(); // Now add the buttons we draw manually. Buttons_Add( 0, 30, 250, 30, (char *)"", 1); Buttons_Add( 0, 60, 250, 30, (char *)"", 2); Buttons_Add( 0, 90, 250, 30, (char *)"", 3); Buttons_Add( 0,120, 250, 30, (char *)"", 4); Buttons_Add( 0,150, 250, 30, (char *)"", 5); Buttons_Add( 0,180, 250, 30, (char *)"", 6); Buttons_Add( 0,210, 250, 30, (char *)"", 7); break; case MAIN_TOOLS_SETUP_WIFI_CUR: TopMessage((char *)"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((char *)"SSID", 155 - TFT_getStringWidth((char *)"SSID"), 40); TFT_print((char *)"Kanaal", 155 - TFT_getStringWidth((char *)"Kanaal"), 60); TFT_print((char *)"Rssi", 155 - TFT_getStringWidth((char *)"Rssi"), 80); TFT_print((char *)"Mode", 155 - TFT_getStringWidth((char *)"Mode"), 100); TFT_print((char *)"IP adres", 155 - TFT_getStringWidth((char *)"IP adres"), 120); TFT_print((char *)"Netmask", 155 - TFT_getStringWidth((char *)"Netmask"), 140); TFT_print((char *)"Gateway", 155 - TFT_getStringWidth((char *)"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, (char *)"Ok", 0); Buttons[0].dark = true; Buttons_Show(); break; case MAIN_TOOLS_SETUP_WIFI_CON: TopMessage((char *)"WiFi verbinden"); TFT_setFont(DEJAVU18_FONT, NULL); _fg = TFT_WHITE; TFT_print((char *)"SSID", 155 - TFT_getStringWidth((char *)"SSID"), 70); _fg = TFT_YELLOW; TFT_print((char*)_wifi_ssid, 165, 70); Buttons_Add( 0, 200, 100, 40, (char *)"Annuleer", 0); Buttons_Add(110, 200, 100, 40, (char *)"Vergeet", 1); Buttons_Add(220, 200, 100, 40, (char *)"Verbind", 2); Buttons_Show(); Buttons[0].dark = true; break; case MAIN_TOOLS_SETUP_WIFI_NEW: TopMessage((char *)"WiFi nieuw"); snprintf(pmpt, 95, "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((char *)"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; _wifi_ScanAPs = false; _wifi_ScanDone = false; ESP_ERROR_CHECK(esp_wifi_scan_stop()); } else 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((char *)"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; }