|
1 /** |
|
2 * @file task_wifi.c |
|
3 * @brief WiFi task. Connects to a known Access Point. If we know more then |
|
4 * one AP, try to connect all of them until it succeeds (Not yet written). |
|
5 */ |
|
6 |
|
7 |
|
8 #include "config.h" |
|
9 |
|
10 |
|
11 static const char *TAG = "task_wifi"; |
|
12 |
|
13 |
|
14 SemaphoreHandle_t xSemaphoreWiFi = NULL; ///< Semaphore WiFi task. |
|
15 EventGroupHandle_t xEventGroupWifi; ///< Events WiFi task. |
|
16 uint16_t ap_num = MAX_AP_NUM; ///< Scan counter. |
|
17 wifi_ap_record_t *accessp_records; ///< [MAX_AP_NUM] records array with scan results. |
|
18 wifi_config_t *task_wifi_ConfigSTA = NULL; ///< Current STA configuration. |
|
19 WIFI_State *wifi_state = NULL; ///< Public state for other tasks. |
|
20 |
|
21 |
|
22 uint8_t _wifi_ssid[33]; |
|
23 bool _wifi_ScanAPs = false; |
|
24 bool _wifi_ScanDone = false; |
|
25 uint16_t _wifi_Scanned = 0; |
|
26 |
|
27 extern int Main_Screen; ///< Current Screen number. |
|
28 extern sButton Buttons[MAXBUTTONS]; ///< Buttons definitions. |
|
29 extern uint32_t TimeSpent; ///< Counter that is increased each second. |
|
30 |
|
31 const int TASK_WIFI_REQUEST_WIFI_SCAN = BIT0; ///< When set, means a client requested to scan wireless networks. |
|
32 const int TASK_WIFI_REQUEST_STA_DISCONNECT = BIT1; ///< When set, means a client requested to disconnect from currently connected AP. |
|
33 const int TASK_WIFI_REQUEST_STA_CONNECT = BIT2; ///< When set, means a client requested to connect to an access point. |
|
34 |
|
35 const int TASK_WIFI_HAS_IP = BIT3; ///< Indicate that we have an IP address |
|
36 const int TASK_WIFI_AP_STARTED = BIT4; ///< Indicate that the SoftAP is started |
|
37 const int TASK_WIFI_STA_FAILED = BIT5; ///< Indicate that we could not get a connection to AP as station. |
|
38 const int TASK_WIFI_STA_DISCONNECTED = BIT6; ///* Indicate that we are disconnected from an ap station. |
|
39 const int TASK_WIFI_STA_CONNECTED = BIT7; ///< Indicate that we are connected to AP as station, flip of BIT6. |
|
40 |
|
41 |
|
42 /** |
|
43 * @brief Local function, save station configuration. |
|
44 * @return Esp error code. |
|
45 */ |
|
46 esp_err_t SaveStaConfig(void); |
|
47 |
|
48 /** |
|
49 * @brief Local function, fetch last connected station configuration. |
|
50 * @return True if there was a last connection, false if there was not. |
|
51 */ |
|
52 bool FetchStaConfig(void); |
|
53 |
|
54 /** |
|
55 * @brief Local function, WiFi event handler. |
|
56 * @return Esp error code. |
|
57 */ |
|
58 esp_err_t task_wifi_EventHandler(void *ctx, system_event_t *event); |
|
59 |
|
60 |
|
61 /****************************************************************************/ |
|
62 |
|
63 |
|
64 |
|
65 esp_err_t SaveStaConfig(void) |
|
66 { |
|
67 int record; |
|
68 |
|
69 if (task_wifi_ConfigSTA && strlen((char *)task_wifi_ConfigSTA->sta.ssid)) { |
|
70 /* |
|
71 * Store in /spiffs/stations.conf if it's a new station. |
|
72 */ |
|
73 record = read_station(task_wifi_ConfigSTA->sta.ssid); |
|
74 if (record == -1) { |
|
75 add_station(task_wifi_ConfigSTA->sta.ssid, task_wifi_ConfigSTA->sta.password); |
|
76 } |
|
77 |
|
78 /* |
|
79 * Update main configuration if needed. |
|
80 */ |
|
81 if (strcmp(config.lastSSID, (char *)task_wifi_ConfigSTA->sta.ssid)) { |
|
82 sprintf(config.lastSSID, "%s", task_wifi_ConfigSTA->sta.ssid); |
|
83 write_config(); |
|
84 } |
|
85 ESP_LOGI(TAG, "SaveStaConfig %s, record %d", wifiStation.SSID, record); |
|
86 } |
|
87 |
|
88 return ESP_OK; |
|
89 } |
|
90 |
|
91 |
|
92 |
|
93 bool FetchStaConfig(void) |
|
94 { |
|
95 if (task_wifi_ConfigSTA == NULL) { |
|
96 task_wifi_ConfigSTA = (wifi_config_t*)malloc(sizeof(wifi_config_t)); |
|
97 } |
|
98 memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t)); |
|
99 |
|
100 /* |
|
101 * Search last connected AP as station. |
|
102 */ |
|
103 if (strlen(config.lastSSID)) { |
|
104 read_station((uint8_t *)config.lastSSID); |
|
105 |
|
106 /* ssid */ |
|
107 size_t sz = sizeof(task_wifi_ConfigSTA->sta.ssid); |
|
108 memcpy(task_wifi_ConfigSTA->sta.ssid, wifiStation.SSID, sz); |
|
109 |
|
110 /* password */ |
|
111 sz = sizeof(task_wifi_ConfigSTA->sta.password); |
|
112 memcpy(task_wifi_ConfigSTA->sta.password, wifiStation.Password, sz); |
|
113 |
|
114 ESP_LOGI(TAG, "FetchStaConfig: last connected to ssid: %s", task_wifi_ConfigSTA->sta.ssid); |
|
115 return task_wifi_ConfigSTA->sta.ssid[0] != '\0'; |
|
116 } |
|
117 |
|
118 ESP_LOGI(TAG, "FetchStaConfig: no last connection found"); |
|
119 return false; |
|
120 } |
|
121 |
|
122 |
|
123 |
|
124 esp_err_t task_wifi_EventHandler(void *ctx, system_event_t *event) |
|
125 { |
|
126 switch(event->event_id) { |
|
127 case SYSTEM_EVENT_SCAN_DONE: |
|
128 // Get the results so the memory used is freed. |
|
129 ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, accessp_records)); |
|
130 _wifi_Scanned = ap_num; |
|
131 _wifi_ScanDone = true; |
|
132 break; |
|
133 |
|
134 case SYSTEM_EVENT_STA_START: |
|
135 ESP_LOGD(TAG, "Event STA started"); |
|
136 // Set the configured hostname for the dhcp client. |
|
137 ESP_ERROR_CHECK(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, config.hostname)); |
|
138 esp_wifi_connect(); |
|
139 break; |
|
140 |
|
141 // SYSTEM_EVENT_STA_STOP 3 |
|
142 case SYSTEM_EVENT_STA_CONNECTED: |
|
143 ESP_LOGI(TAG, "Event STA connected, turn off AP"); |
|
144 wifi_ap_record_t ap_info; |
|
145 esp_wifi_sta_get_ap_info(&ap_info); |
|
146 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { |
|
147 wifi_state->STA_connected = true; |
|
148 wifi_state->STA_rssi = ap_info.rssi; |
|
149 sprintf(wifi_state->STA_ssid, "%s", ap_info.ssid); |
|
150 xSemaphoreGive(xSemaphoreWiFi); |
|
151 } |
|
152 // Turn off AP |
|
153 ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); |
|
154 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); |
|
155 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); |
|
156 break; |
|
157 |
|
158 case SYSTEM_EVENT_STA_DISCONNECTED: |
|
159 ESP_LOGI(TAG, "Event STA disconnected, turn on AP"); |
|
160 if (xSemaphoreTake(xSemaphoreWiFi, 10) == pdTRUE) { |
|
161 wifi_state->STA_connected = false; |
|
162 wifi_state->STA_rssi = 0; |
|
163 xSemaphoreGive(xSemaphoreWiFi); |
|
164 } |
|
165 // Turn on AP |
|
166 ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA)); |
|
167 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); |
|
168 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); |
|
169 |
|
170 /* |
|
171 * Meanwhile, try to reconnect. |
|
172 */ |
|
173 if (FetchStaConfig()) { |
|
174 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); |
|
175 } |
|
176 break; |
|
177 |
|
178 // SYSTEM_EVENT_STA_AUTHMODE_CHANGE 6 |
|
179 case SYSTEM_EVENT_STA_GOT_IP: |
|
180 // printf("SYSTEM_EVENT_STA_GOT_IP\n"); |
|
181 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_HAS_IP); |
|
182 tcpip_adapter_ip_info_t ip; |
|
183 memset(&ip, 0, sizeof(tcpip_adapter_ip_info_t)); |
|
184 if (tcpip_adapter_get_ip_info(ESP_IF_WIFI_STA, &ip) == 0) { |
|
185 if (xSemaphoreTake(xSemaphoreWiFi, 10) == pdTRUE) { |
|
186 snprintf(wifi_state->STA_ip, 15, IPSTR, IP2STR(&ip.ip)); |
|
187 snprintf(wifi_state->STA_nm, 15, IPSTR, IP2STR(&ip.netmask)); |
|
188 snprintf(wifi_state->STA_gw, 15, IPSTR, IP2STR(&ip.gw)); |
|
189 xSemaphoreGive(xSemaphoreWiFi); |
|
190 } |
|
191 } |
|
192 break; |
|
193 |
|
194 case SYSTEM_EVENT_STA_LOST_IP: |
|
195 ESP_LOGI(TAG, "Lost IP address"); |
|
196 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_HAS_IP); |
|
197 if (xSemaphoreTake(xSemaphoreWiFi, 10) == pdTRUE) { |
|
198 wifi_state->STA_ip[0] = '\0'; |
|
199 wifi_state->STA_nm[0] = '\0'; |
|
200 wifi_state->STA_gw[0] = '\0'; |
|
201 xSemaphoreGive(xSemaphoreWiFi); |
|
202 } |
|
203 break; |
|
204 |
|
205 // SYSTEM_EVENT_STA_WPS_ER_SUCCESS 9 |
|
206 // SYSTEM_EVENT_STA_WPS_ER_FAILED 10 |
|
207 // SYSTEM_EVENT_STA_WPS_ER_TIMEOUT 11 |
|
208 // SYSTEM_EVENT_STA_WPS_ER_PIN 12 |
|
209 |
|
210 case SYSTEM_EVENT_AP_START: |
|
211 ESP_LOGD(TAG, "Event AP started"); |
|
212 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_AP_STARTED); |
|
213 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { |
|
214 wifi_state->AP_active = true; |
|
215 wifi_state->AP_clients = 0; |
|
216 xSemaphoreGive(xSemaphoreWiFi); |
|
217 } |
|
218 break; |
|
219 |
|
220 case SYSTEM_EVENT_AP_STOP: |
|
221 ESP_LOGD(TAG, "Event AP stopped"); |
|
222 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_AP_STARTED); |
|
223 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { |
|
224 wifi_state->AP_active = false; |
|
225 wifi_state->AP_clients = 0; |
|
226 xSemaphoreGive(xSemaphoreWiFi); |
|
227 } |
|
228 break; |
|
229 |
|
230 case SYSTEM_EVENT_AP_STACONNECTED: |
|
231 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { |
|
232 wifi_state->AP_clients++; |
|
233 xSemaphoreGive(xSemaphoreWiFi); |
|
234 } |
|
235 ESP_LOGI(TAG, "Event AP new client, %d connections", wifi_state->AP_clients); |
|
236 break; |
|
237 |
|
238 case SYSTEM_EVENT_AP_STADISCONNECTED: |
|
239 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { |
|
240 if (wifi_state->AP_clients > 0) |
|
241 wifi_state->AP_clients--; |
|
242 else |
|
243 wifi_state->AP_clients = 0; |
|
244 xSemaphoreGive(xSemaphoreWiFi); |
|
245 } |
|
246 ESP_LOGI(TAG, "Event AP client disconnect, %d connections", wifi_state->AP_clients); |
|
247 break; |
|
248 |
|
249 // SYSTEM_EVENT_AP_PROBEREQRECVED 17 |
|
250 // SYSTEM_EVENT_GOT_IP6 18 |
|
251 // SYSTEM_EVENT_ETH_START 19 |
|
252 // SYSTEM_EVENT_ETH_STOP 20 |
|
253 // SYSTEM_EVENT_ETH_CONNECTED 21 |
|
254 // SYSTEM_EVENT_ETH_DISCONNECTED 22 |
|
255 // SYSTEM_EVENT_ETH_GOT_IP 23 |
|
256 |
|
257 default: |
|
258 printf("Unknown event %d\n", event->event_id); |
|
259 break; |
|
260 } |
|
261 return ESP_OK; |
|
262 } |
|
263 |
|
264 |
|
265 |
|
266 /** |
|
267 * @brief WiFi manager task |
|
268 */ |
|
269 void task_wifi( void * pvParameters ) |
|
270 { |
|
271 esp_err_t ret; |
|
272 |
|
273 ESP_LOGI(TAG, "Starting WiFi driver"); |
|
274 |
|
275 /* |
|
276 * Initialize NVS |
|
277 */ |
|
278 ret = nvs_flash_init(); |
|
279 if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { |
|
280 ESP_ERROR_CHECK(nvs_flash_erase()); |
|
281 ret = nvs_flash_init(); |
|
282 } |
|
283 ESP_ERROR_CHECK(ret); |
|
284 |
|
285 /* event handler and event group for the wifi driver */ |
|
286 xEventGroupWifi = xEventGroupCreate(); |
|
287 /* initialize the tcp stack */ |
|
288 tcpip_adapter_init(); |
|
289 ESP_ERROR_CHECK(esp_event_loop_init(task_wifi_EventHandler, NULL)); |
|
290 |
|
291 /* |
|
292 * memory allocation of objects used by the task |
|
293 */ |
|
294 accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * MAX_AP_NUM); |
|
295 task_wifi_ConfigSTA = (wifi_config_t*)malloc(sizeof(wifi_config_t)); |
|
296 memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t)); |
|
297 |
|
298 xSemaphoreWiFi = xSemaphoreCreateMutex(); |
|
299 wifi_state = malloc(sizeof(WIFI_State)); |
|
300 wifi_state->AP_clients = 0; |
|
301 wifi_state->AP_active = false; |
|
302 wifi_state->STA_connected = false; |
|
303 wifi_state->STA_rssi = 0; |
|
304 |
|
305 /* wifi scanner config */ |
|
306 wifi_scan_config_t scan_config = { |
|
307 .ssid = 0, |
|
308 .bssid = 0, |
|
309 .channel = 0, |
|
310 .show_hidden = false |
|
311 }; |
|
312 |
|
313 /* |
|
314 * start the softAP access point |
|
315 * stop DHCP server |
|
316 */ |
|
317 ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP)); |
|
318 |
|
319 /* |
|
320 * Assign a static IP to the AP network interface |
|
321 */ |
|
322 tcpip_adapter_ip_info_t info; |
|
323 memset(&info, 0x00, sizeof(info)); |
|
324 IP4_ADDR(&info.ip, 192, 168, 1, 1); |
|
325 IP4_ADDR(&info.gw, 192, 168, 1, 1); |
|
326 IP4_ADDR(&info.netmask, 255, 255, 255, 0); |
|
327 ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info)); |
|
328 |
|
329 /* start dhcp server */ |
|
330 ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); |
|
331 ESP_LOGI(TAG, "AP start dhcps ip: 192.168.1.1 nm: 255.255.255.0 gw: 192.168.1.1"); |
|
332 |
|
333 /* start dhcp client */ |
|
334 ESP_ERROR_CHECK(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA)); |
|
335 ESP_LOGI(TAG, "Start DHCP client for STA interface."); |
|
336 |
|
337 /* |
|
338 * init wifi as station + access point |
|
339 */ |
|
340 wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); |
|
341 ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config)); |
|
342 ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); |
|
343 ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA)); |
|
344 ESP_ERROR_CHECK(esp_wifi_set_bandwidth(WIFI_IF_AP, config.ap_bandwidth)); |
|
345 |
|
346 // configure the softAP and start it */ |
|
347 wifi_config_t ap_config = { |
|
348 .ap = { |
|
349 .ssid_len = 0, |
|
350 .channel = config.ap_channel, |
|
351 .authmode = WIFI_AUTH_WPA2_PSK, |
|
352 .ssid_hidden = config.ap_ssid_hidden, |
|
353 .max_connection = AP_MAX_CONNECTIONS, |
|
354 .beacon_interval = 100, |
|
355 }, |
|
356 }; |
|
357 memcpy(ap_config.ap.ssid, config.ap_ssid , sizeof(config.ap_ssid)); |
|
358 memcpy(ap_config.ap.password, config.ap_pwd, sizeof(config.ap_pwd)); |
|
359 ret = esp_wifi_set_config(WIFI_IF_AP, &ap_config); |
|
360 if (ret != ESP_OK) { |
|
361 ESP_LOGE(TAG, "esp_wifi_set_config(WIFI_IF_AP, nnn) rc=%d", ret); |
|
362 } |
|
363 ESP_ERROR_CHECK(esp_wifi_start()); |
|
364 |
|
365 ESP_LOGI(TAG, "SoftAP start ssid: `%s' pwd: `%s' channel: %d, hidden: %s", |
|
366 ap_config.ap.ssid, ap_config.ap.password, ap_config.ap.channel, ap_config.ap.ssid_hidden ? "yes":"no"); |
|
367 |
|
368 /* |
|
369 * try to get access to previously saved wifi |
|
370 */ |
|
371 if (FetchStaConfig()) { |
|
372 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); |
|
373 } |
|
374 |
|
375 /* |
|
376 * Wait for access point to start |
|
377 */ |
|
378 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); |
|
379 xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_AP_STARTED, pdFALSE, pdTRUE, portMAX_DELAY ); |
|
380 EventBits_t uxBits; |
|
381 |
|
382 for(;;) { |
|
383 |
|
384 /* actions that can trigger: request a connection, a scan, or a disconnection */ |
|
385 uxBits = xEventGroupWaitBits(xEventGroupWifi, |
|
386 TASK_WIFI_REQUEST_STA_CONNECT | TASK_WIFI_REQUEST_WIFI_SCAN | TASK_WIFI_REQUEST_STA_DISCONNECT, |
|
387 pdFALSE, pdFALSE, portMAX_DELAY ); |
|
388 |
|
389 if (uxBits & TASK_WIFI_REQUEST_STA_DISCONNECT) { |
|
390 /* |
|
391 * user requested a disconnect, this will in effect disconnect the wifi but also erase NVS memory |
|
392 */ |
|
393 ESP_LOGI(TAG, "Request disconnect"); |
|
394 sntp_stop(); |
|
395 ESP_ERROR_CHECK(esp_wifi_disconnect()); |
|
396 xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY ); |
|
397 |
|
398 /* |
|
399 * erase configuration |
|
400 */ |
|
401 if (task_wifi_ConfigSTA) { |
|
402 memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t)); |
|
403 } |
|
404 config.lastSSID[0] = '\0'; |
|
405 write_config(); |
|
406 |
|
407 /* finally: release the scan request bit */ |
|
408 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT); |
|
409 ESP_LOGI(TAG, "Request disconnect is finished."); |
|
410 |
|
411 } else if (uxBits & TASK_WIFI_REQUEST_STA_CONNECT) { |
|
412 |
|
413 //someone requested a connection! |
|
414 ESP_LOGI(TAG, "Request STA connect `%s'", task_wifi_ConfigSTA->sta.ssid); |
|
415 /* set the new config and connect - reset the failed bit first as it is later tested */ |
|
416 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); |
|
417 ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, task_wifi_ConfigSTA)); |
|
418 |
|
419 esp_err_t wifierror = esp_wifi_connect(); |
|
420 if (wifierror != ESP_OK) { |
|
421 ESP_LOGE(TAG, "esp_wifi_connect() rc=%04x", (int)wifierror); |
|
422 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); |
|
423 } |
|
424 |
|
425 /* |
|
426 * 2 scenarios here: connection is successful and TASK_WIFI_HAS_IP will be posted |
|
427 * or it's a failure and we get a TASK_WIFI_STA_FAILED with a reason code. |
|
428 * Note that the reason code is not exploited. For all intent and purposes a failure is a failure. |
|
429 */ |
|
430 uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_HAS_IP | TASK_WIFI_STA_FAILED, pdFALSE, pdFALSE, portMAX_DELAY ); |
|
431 |
|
432 if (uxBits & (TASK_WIFI_HAS_IP | TASK_WIFI_STA_FAILED)) { |
|
433 /* |
|
434 * only save the config if the connection was successful! |
|
435 */ |
|
436 if(uxBits & TASK_WIFI_HAS_IP) { |
|
437 /* save wifi config */ |
|
438 SaveStaConfig(); |
|
439 sntp_setservername(0, "nl.pool.ntp.org"); |
|
440 sntp_init(); |
|
441 ESP_LOGI(TAG, "Initialized SNTP %s", sntp_getservername(0)); |
|
442 } else { |
|
443 ESP_LOGI(TAG, "Connection failed"); // TODO: Scan other SSID's for known networks. |
|
444 /* failed attempt to connect regardles of the reason */ |
|
445 |
|
446 /* otherwise: reset the config */ |
|
447 memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t)); |
|
448 } |
|
449 } else { |
|
450 /* hit portMAX_DELAY limit ? */ |
|
451 abort(); |
|
452 } |
|
453 |
|
454 /* finally: release the connection request bit */ |
|
455 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); |
|
456 |
|
457 } else if (uxBits & TASK_WIFI_REQUEST_WIFI_SCAN) { |
|
458 |
|
459 /* safe guard against overflow */ |
|
460 ap_num = MAX_AP_NUM; |
|
461 ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false)); |
|
462 |
|
463 /* finally: release the scan request bit */ |
|
464 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_WIFI_SCAN); |
|
465 } |
|
466 |
|
467 /* |
|
468 * Here we should check for reconnect actions. |
|
469 */ |
|
470 |
|
471 } /* for(;;) */ |
|
472 vTaskDelay( (TickType_t)10); |
|
473 } |
|
474 |
|
475 |
|
476 const char *apsec[] = { "Open", "WEP", "WPA", "WPA2", "WPA WPA2", "Enterprise" }; |
|
477 |
|
478 |
|
479 /** |
|
480 * @brief Show an AP station as a button. The buttons are already defined. |
|
481 * @param idx The index position on the display, 1 to 7. |
|
482 * @param ap The AP information from the WiFi scan. |
|
483 * @param show, How to display. 0 is blank, 1 is unknown, 2 is known, 3 is a connected AP. |
|
484 */ |
|
485 void Show_AP(uint8_t idx, wifi_ap_record_t ap, int show) |
|
486 { |
|
487 char tmp[33]; |
|
488 |
|
489 if ((idx > 7) || (idx < 1)) |
|
490 return; |
|
491 |
|
492 if (show == 0) { |
|
493 _bg = TFT_BLACK; |
|
494 } else { |
|
495 _bg = (color_t){ 63, 63, 64 }; |
|
496 } |
|
497 |
|
498 TFT_fillRect(Buttons[idx].x, Buttons[idx].y, Buttons[idx].w, Buttons[idx].h, _bg); |
|
499 if (show == 0) |
|
500 return; |
|
501 |
|
502 TFT_drawRect(Buttons[idx].x, Buttons[idx].y, Buttons[idx].w, Buttons[idx].h, TFT_NAVY); |
|
503 if (show == 3) { |
|
504 _fg = TFT_WHITE; |
|
505 } else if (show == 1) { |
|
506 _fg = TFT_YELLOW; |
|
507 } else { |
|
508 _fg = TFT_CYAN; |
|
509 } |
|
510 |
|
511 TFT_setFont(DEJAVU18_FONT, NULL); |
|
512 sprintf(tmp, "%s", ap.ssid); |
|
513 TFT_print(tmp, Buttons[idx].x + 5, Buttons[idx].y + 6); |
|
514 sprintf(tmp, "%d", ap.rssi); |
|
515 TFT_setFont(DEF_SMALL_FONT, NULL); |
|
516 TFT_print(tmp, Buttons[idx].x + Buttons[idx].w - (TFT_getStringWidth(tmp) + 5), Buttons[idx].y + 4); |
|
517 sprintf(tmp, "%s", apsec[ap.authmode]); |
|
518 TFT_print(tmp, Buttons[idx].x + Buttons[idx].w - (TFT_getStringWidth(tmp) + 5), Buttons[idx].y + 15); |
|
519 } |
|
520 |
|
521 |
|
522 |
|
523 bool WiFi_Init(void) |
|
524 { |
|
525 char pwd[65], pmpt[32]; |
|
526 |
|
527 switch (Main_Screen) { |
|
528 case MAIN_TOOLS_SETUP_WIFI: |
|
529 TopMessage("WiFi"); |
|
530 TFT_setFont(DEJAVU24_FONT, NULL); |
|
531 _fg = TFT_WHITE; |
|
532 TFT_print("Momentje ..", CENTER, CENTER); |
|
533 _wifi_ScanAPs = true; |
|
534 _wifi_ScanDone = false; |
|
535 Buttons_Add(260, 200, 60, 40, "Ok", 0); |
|
536 Buttons[0].dark = true; |
|
537 Buttons_Show(); |
|
538 // Now add the buttons we draw manually. |
|
539 Buttons_Add( 0, 30, 250, 30, "", 1); |
|
540 Buttons_Add( 0, 60, 250, 30, "", 2); |
|
541 Buttons_Add( 0, 90, 250, 30, "", 3); |
|
542 Buttons_Add( 0,120, 250, 30, "", 4); |
|
543 Buttons_Add( 0,150, 250, 30, "", 5); |
|
544 Buttons_Add( 0,180, 250, 30, "", 6); |
|
545 Buttons_Add( 0,210, 250, 30, "", 7); |
|
546 break; |
|
547 |
|
548 case MAIN_TOOLS_SETUP_WIFI_CUR: |
|
549 TopMessage("WiFi verbinding"); |
|
550 // Get extra information. |
|
551 wifi_ap_record_t ap_info; |
|
552 esp_wifi_sta_get_ap_info(&ap_info); |
|
553 |
|
554 wifi_config_t *wconfig = task_wifi_ConfigSTA /*task_wifi_GetWifiStaConfig( ) */; |
|
555 if (wconfig) { |
|
556 |
|
557 tcpip_adapter_ip_info_t ip_info; |
|
558 ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info)); |
|
559 char ip[IP4ADDR_STRLEN_MAX]; |
|
560 char gw[IP4ADDR_STRLEN_MAX]; |
|
561 char netmask[IP4ADDR_STRLEN_MAX]; |
|
562 strcpy(ip, ip4addr_ntoa(&ip_info.ip)); |
|
563 strcpy(netmask, ip4addr_ntoa(&ip_info.netmask)); |
|
564 strcpy(gw, ip4addr_ntoa(&ip_info.gw)); |
|
565 TFT_setFont(DEFAULT_FONT, NULL); |
|
566 _fg = TFT_WHITE; |
|
567 TFT_print("SSID", 155 - TFT_getStringWidth("SSID"), 40); |
|
568 TFT_print("Kanaal", 155 - TFT_getStringWidth("Kanaal"), 60); |
|
569 TFT_print("Rssi", 155 - TFT_getStringWidth("Rssi"), 80); |
|
570 TFT_print("Mode", 155 - TFT_getStringWidth("Mode"), 100); |
|
571 TFT_print("IP adres", 155 - TFT_getStringWidth("IP adres"), 120); |
|
572 TFT_print("Netmask", 155 - TFT_getStringWidth("Netmask"), 140); |
|
573 TFT_print("Gateway", 155 - TFT_getStringWidth("Gateway"), 160); |
|
574 _fg = TFT_YELLOW; |
|
575 TFT_print((char*)wconfig->sta.ssid, 165, 40); |
|
576 sprintf(pmpt, "%d", ap_info.primary); |
|
577 TFT_print(pmpt, 165, 60); |
|
578 sprintf(pmpt, "%d", ap_info.rssi); |
|
579 TFT_print(pmpt, 165, 80); |
|
580 sprintf(pmpt, "%s%s%s", ap_info.phy_11b ? "b":"", ap_info.phy_11g ? "g":"", ap_info.phy_11n ? "n":""); |
|
581 TFT_print(pmpt, 165, 100); |
|
582 TFT_print((char*)ip, 165, 120); |
|
583 TFT_print((char*)netmask, 165, 140); |
|
584 TFT_print((char*)gw, 165, 160); |
|
585 } |
|
586 Buttons_Add(130, 200, 60, 40, "Ok", 0); |
|
587 Buttons[0].dark = true; |
|
588 Buttons_Show(); |
|
589 break; |
|
590 |
|
591 case MAIN_TOOLS_SETUP_WIFI_CON: |
|
592 TopMessage("WiFi verbinden"); |
|
593 TFT_setFont(DEJAVU18_FONT, NULL); |
|
594 _fg = TFT_WHITE; |
|
595 TFT_print("SSID", 155 - TFT_getStringWidth("SSID"), 70); |
|
596 _fg = TFT_YELLOW; |
|
597 TFT_print((char*)_wifi_ssid, 165, 70); |
|
598 Buttons_Add( 0, 200, 100, 40, "Annuleer", 0); |
|
599 Buttons_Add(110, 200, 100, 40, "Vergeet", 1); |
|
600 Buttons_Add(220, 200, 100, 40, "Verbind", 2); |
|
601 Buttons_Show(); |
|
602 Buttons[0].dark = true; |
|
603 break; |
|
604 |
|
605 case MAIN_TOOLS_SETUP_WIFI_NEW: |
|
606 TopMessage("WiFi nieuw"); |
|
607 snprintf(pmpt, 32, "Password for %s", _wifi_ssid); |
|
608 pwd[0] = '\0'; |
|
609 EditTextMin(pmpt, pwd, 64, 8); |
|
610 /* |
|
611 * Disconnect first |
|
612 */ |
|
613 _bg = TFT_BLACK; |
|
614 TFT_fillScreen(_bg); |
|
615 TFT_setFont(DEJAVU24_FONT, NULL); |
|
616 _fg = TFT_WHITE; |
|
617 TFT_print("Momentje ..", CENTER, CENTER); |
|
618 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT); |
|
619 vTaskDelay(100 / portTICK_PERIOD_MS); |
|
620 xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY ); |
|
621 |
|
622 /* |
|
623 * Setup new connection |
|
624 */ |
|
625 if (strlen(pwd)) { |
|
626 wifi_config_t* config = task_wifi_ConfigSTA; |
|
627 memset(config, 0x00, sizeof(wifi_config_t)); |
|
628 memcpy(config->sta.ssid, _wifi_ssid, strlen((char*)_wifi_ssid)); |
|
629 memcpy(config->sta.password, pwd, strlen(pwd)); |
|
630 ESP_LOGI(TAG, "new AP %s %s", _wifi_ssid, pwd); |
|
631 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); |
|
632 } else { |
|
633 // TODO: what about WPS, it works but how to insert it in this app. |
|
634 return true; |
|
635 } |
|
636 // We must wait here for the result. |
|
637 break; |
|
638 |
|
639 default: |
|
640 break; |
|
641 } |
|
642 |
|
643 return false; |
|
644 } |
|
645 |
|
646 |
|
647 bool WiFi_Loop(void) |
|
648 { |
|
649 uint8_t idx; |
|
650 int Choice; |
|
651 static int AP[8]; |
|
652 wifi_ap_record_t ap; |
|
653 |
|
654 switch (Main_Screen) { |
|
655 case MAIN_TOOLS_SETUP_WIFI: |
|
656 if (_wifi_ScanAPs) { |
|
657 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_WIFI_SCAN); |
|
658 _wifi_ScanAPs = false; |
|
659 TimeSpent = 0; |
|
660 } |
|
661 if (_wifi_ScanDone) { |
|
662 /* |
|
663 * Show scan results. There is room for 7 entries. If we have a connection, |
|
664 * the first one is that connection followed by available Access Points. |
|
665 * If there is no connection yet, there is only a iist of available Access |
|
666 * points. |
|
667 * The list is sorted by signal strength and is filled by the eventhandler. |
|
668 */ |
|
669 idx = 1; |
|
670 _wifi_ScanDone = false; |
|
671 |
|
672 if ((xEventGroupGetBits(xEventGroupWifi) & TASK_WIFI_STA_CONNECTED) == TASK_WIFI_STA_CONNECTED) { |
|
673 // We are connected. Search and display this one. |
|
674 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { |
|
675 for (int i = 0; i < _wifi_Scanned; i++) { |
|
676 ap = accessp_records[i]; |
|
677 if (strcmp(wifi_state->STA_ssid, (char *)ap.ssid) == 0) { |
|
678 AP[idx] = i; |
|
679 Show_AP(idx, ap, 3); |
|
680 idx++; |
|
681 break; |
|
682 } |
|
683 } |
|
684 xSemaphoreGive(xSemaphoreWiFi); |
|
685 } |
|
686 } |
|
687 |
|
688 // Display available Access Points. |
|
689 for (int i = 0; i < _wifi_Scanned; i++) { |
|
690 // The connected AP can be somewhere in this list, don't display it again. |
|
691 ap = accessp_records[i]; |
|
692 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { |
|
693 if (strcmp(wifi_state->STA_ssid, (char *)ap.ssid) == 0) { |
|
694 xSemaphoreGive(xSemaphoreWiFi); |
|
695 continue; // Skip connected AP, already on top of the list. |
|
696 } |
|
697 xSemaphoreGive(xSemaphoreWiFi); |
|
698 } |
|
699 // Check if we know this AP in the database. |
|
700 if ((read_station(ap.ssid) == -1)) { |
|
701 Show_AP(idx, ap, 2); // Unknown |
|
702 } else { |
|
703 if (wifiStation.hide) { |
|
704 continue; // Blacklisted. |
|
705 } |
|
706 Show_AP(idx, ap, 1); // We know this one. |
|
707 } |
|
708 AP[idx] = i; |
|
709 idx++; |
|
710 if (idx == 8) |
|
711 break; |
|
712 } |
|
713 if (idx < 7) { |
|
714 for (int i = idx; i < 8; i++) { |
|
715 Show_AP(i, ap, 0); |
|
716 AP[i] = 0; |
|
717 } |
|
718 } |
|
719 } |
|
720 |
|
721 Choice = Buttons_Scan(); |
|
722 if ((Choice >= 1) && (Choice <= 7)) { |
|
723 ap = accessp_records[AP[Choice]]; |
|
724 sprintf((char *)_wifi_ssid, "%s", ap.ssid); // Save selected SSID. |
|
725 } |
|
726 if ((Choice == 1) && ((xEventGroupGetBits(xEventGroupWifi) & TASK_WIFI_STA_CONNECTED) == TASK_WIFI_STA_CONNECTED)) { |
|
727 Main_Screen = MAIN_TOOLS_SETUP_WIFI_CUR; |
|
728 // Cancel a possible scan. |
|
729 ESP_ERROR_CHECK(esp_wifi_scan_stop()); |
|
730 } else if ((Choice >= 1) && (Choice <= 7)) { |
|
731 if ((read_station(_wifi_ssid) != -1)) { |
|
732 Main_Screen = MAIN_TOOLS_SETUP_WIFI_CON; |
|
733 } else { |
|
734 Main_Screen = MAIN_TOOLS_SETUP_WIFI_NEW; |
|
735 } |
|
736 ESP_ERROR_CHECK(esp_wifi_scan_stop()); |
|
737 } else if (Choice == 0) { |
|
738 Main_Screen = MAIN_TOOLS_SETUP; |
|
739 ESP_ERROR_CHECK(esp_wifi_scan_stop()); |
|
740 } |
|
741 if (TimeSpent > 10) { |
|
742 _wifi_ScanAPs = true; |
|
743 } |
|
744 break; |
|
745 |
|
746 case MAIN_TOOLS_SETUP_WIFI_CUR: |
|
747 |
|
748 if (Buttons_Scan() == 0) { |
|
749 Main_Screen = MAIN_TOOLS_SETUP_WIFI; |
|
750 } |
|
751 break; |
|
752 |
|
753 case MAIN_TOOLS_SETUP_WIFI_CON: |
|
754 switch (Buttons_Scan()) { |
|
755 case 0: // Cancel choice |
|
756 Main_Screen = MAIN_TOOLS_SETUP_WIFI; |
|
757 break; |
|
758 |
|
759 case 1: // Forget connection |
|
760 remove_station(_wifi_ssid); |
|
761 Main_Screen = MAIN_TOOLS_SETUP_WIFI; |
|
762 break; |
|
763 |
|
764 case 2: // Connect |
|
765 _bg = TFT_BLACK; |
|
766 TFT_fillScreen(_bg); |
|
767 TFT_setFont(DEJAVU24_FONT, NULL); |
|
768 _fg = TFT_WHITE; |
|
769 TFT_print("Momentje ..", CENTER, CENTER); |
|
770 /* |
|
771 * Disconnect old connections and wait until it's gone. |
|
772 */ |
|
773 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT); |
|
774 vTaskDelay(100 / portTICK_PERIOD_MS); |
|
775 xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY ); |
|
776 /* |
|
777 * Setup new connection. |
|
778 */ |
|
779 if ((read_station(_wifi_ssid) != -1)) { |
|
780 wifi_config_t* config = task_wifi_ConfigSTA; |
|
781 memset(config, 0x00, sizeof(wifi_config_t)); |
|
782 memcpy(config->sta.ssid, wifiStation.SSID, strlen(wifiStation.SSID)); |
|
783 memcpy(config->sta.password, wifiStation.Password, strlen(wifiStation.Password)); |
|
784 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); |
|
785 vTaskDelay(1000 / portTICK_PERIOD_MS); |
|
786 } |
|
787 Main_Screen = MAIN_TOOLS_SETUP_WIFI; |
|
788 break; |
|
789 |
|
790 default: break; |
|
791 } |
|
792 break; |
|
793 |
|
794 case MAIN_TOOLS_SETUP_WIFI_NEW: |
|
795 // All work is already done, jump to the base screen. |
|
796 Main_Screen = MAIN_TOOLS_SETUP_WIFI; |
|
797 break; |
|
798 |
|
799 default: |
|
800 break; |
|
801 } |
|
802 |
|
803 return false; |
|
804 } |
|
805 |
|
806 |