main/task_wifi.c

changeset 0
913eb9ca40b1
child 1
86b275481021
equal deleted inserted replaced
-1:000000000000 0:913eb9ca40b1
1 /**
2 * @file task_wifi.c
3 * @brief WiFi task. Connect to the known AP with the strongest signal.
4 */
5
6
7 #include "dcf77tx.h"
8
9 #define MAX_AP_NUM 10
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 esp_netif_t *sta_netif = NULL; ///< Station interface
21
22
23 wifi_scan_config_t scan_config = { ///< WiFi scanner configuration.
24 .ssid = (uint8_t *)CONFIG_ESP_WIFI_SSID,
25 .bssid = 0,
26 .channel = 0,
27 .show_hidden = false
28 };
29
30 bool _wifi_ScanDone = false; ///< Scan ready
31 bool _wifi_BetterAP = false; ///< If better AP available.
32 int8_t _wifi_RSSI = -127; ///< Latest RSSI level.
33 uint16_t _wifi_Scanned = 0; ///< Total scanned APs.
34
35 extern char hostname[]; ///< Generated hostname
36
37
38
39 const int TASK_WIFI_REQUEST_STA_DISCONNECT = BIT0; ///< When set, means a client requested to disconnect from currently connected AP.
40 const int TASK_WIFI_REQUEST_STA_CONNECT = BIT1; ///< When set, means a client requested to connect to an access point.
41 const int TASK_WIFI_REQUEST_STA_SCAN = BIT2; ///< When set, means a client requested a AP scan.
42 const int TASK_WIFI_REQUEST_STA_STATUS = BIT3; ///< When set, means a client requested to update the connection status.
43
44 const int TASK_WIFI_HAS_IP = BIT4; ///< Indicate that we have an IP address
45 const int TASK_WIFI_STA_FAILED = BIT5; ///< Indicate that we could not get a connection to AP as station.
46 const int TASK_WIFI_STA_DISCONNECTED = BIT6; ///< Indicate that we are disconnected from an ap station.
47 const int TASK_WIFI_STA_CONNECTED = BIT7; ///< Indicate that we are connected to AP as station, flip of BIT5.
48
49
50
51 /**
52 * @brief Array with AP security names
53 */
54 const char *apsec[] = { "Open", "WEP", "WPA", "WPA2", "WPA WPA2", "Enterprise" };
55
56
57 /****************************************************************************/
58
59
60 bool ready_WiFi(void)
61 {
62 if (wifi_state->STA_connected && wifi_state->STA_online)
63 return true;
64 return false;
65 }
66
67
68
69 void status_WiFi(void)
70 {
71 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_STATUS);
72 }
73
74
75
76 void request_WiFi(void)
77 {
78 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
79 }
80
81
82 void scan_WiFi(void)
83 {
84 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_SCAN);
85 }
86
87
88 void disconnect_WiFi(void)
89 {
90 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT);
91 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
92 }
93
94
95 static void print_servers(void)
96 {
97 ESP_LOGI(TAG, "List of configured NTP servers:");
98
99 for (uint8_t i = 0; i < SNTP_MAX_SERVERS; ++i){
100 if (esp_sntp_getservername(i)){
101 ESP_LOGI(TAG, "server %d: %s", i, esp_sntp_getservername(i));
102 } else {
103 // we have either IPv4 or IPv6 address, let's print it
104 char buff[64];
105 ip_addr_t const *ip = esp_sntp_getserver(i);
106 if (ipaddr_ntoa_r(ip, buff, 64) != NULL)
107 ESP_LOGI(TAG, "server %d: %s", i, buff);
108 }
109 }
110 }
111
112
113 static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
114 {
115 switch (event_id) {
116
117 case WIFI_EVENT_SCAN_DONE:
118 {
119 /* Get the results so the memory used is freed. */
120 ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, accessp_records));
121 ESP_LOGI(TAG, "Event wifi Scane done, %d records", ap_num);
122 _wifi_BetterAP = false;
123 for (int i = 0; i < ap_num; i++) {
124 wifi_ap_record_t ap = accessp_records[i];
125 ESP_LOGI(TAG, "AP:%d bssid:%02x:%02x:%02x:%02x:%02x:%02x ssid:%s ch:%d rssi:%d",
126 i, ap.bssid[0], ap.bssid[1], ap.bssid[2], ap.bssid[3], ap.bssid[4], ap.bssid[5],
127 ap.ssid, ap.primary, ap.rssi);
128 if (ap.rssi > CONFIG_ESP_WIFI_ROAMING_LEVEL && ap.rssi > (_wifi_RSSI + 3)) {
129 _wifi_BetterAP = true;
130 ESP_LOGI(TAG, "AP:%d is a better AP", i);
131 }
132 }
133 _wifi_Scanned = ap_num;
134 _wifi_ScanDone = true;
135 if (_wifi_BetterAP) {
136 ESP_LOGI(TAG, "Disconnect current AP");
137 disconnect_WiFi();
138 }
139 break;
140 }
141
142 case WIFI_EVENT_STA_START:
143 {
144 ESP_LOGI(TAG, "Event wifi START");
145 // Set the configured hostname for the dhcp client.
146 ESP_ERROR_CHECK(esp_netif_set_hostname(sta_netif, hostname));
147 esp_wifi_connect();
148 _wifi_BetterAP = false;
149 break;
150 }
151
152 case WIFI_EVENT_STA_CONNECTED:
153 {
154 wifi_event_sta_connected_t* event = (wifi_event_sta_connected_t*) event_data;
155 wifi_ap_record_t ap_info;
156 esp_wifi_sta_get_ap_info(&ap_info);
157 ESP_LOGI(TAG, "Event STA connected, ssid:%s, bssid:" MACSTR ", channel:%d, rssi: %d, authmode:%s",
158 ap_info.ssid, MAC2STR(ap_info.bssid), event->channel, ap_info.rssi, apsec[event->authmode]);
159 if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) {
160 wifi_state->STA_connected = true;
161 wifi_state->STA_rssi = ap_info.rssi;
162 wifi_state->STA_channel = ap_info.primary;
163 sprintf(wifi_state->STA_ssid, "%s", ap_info.ssid);
164 snprintf(wifi_state->STA_bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
165 ap_info.bssid[0], ap_info.bssid[1], ap_info.bssid[2], ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]);
166 xSemaphoreGive(xSemaphoreWiFi);
167 } else {
168 ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_CONNECTED");
169 }
170 print_servers();
171 _wifi_BetterAP = false;
172 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
173 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
174 break;
175 }
176
177 case WIFI_EVENT_STA_DISCONNECTED:
178 {
179 wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data;
180
181 ESP_LOGI(TAG, "Event STA disconnected, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d",
182 disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason);
183 if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) {
184 wifi_state->STA_connected = false;
185 wifi_state->STA_online = false;
186 wifi_state->STA_rssi = 0;
187 xSemaphoreGive(xSemaphoreWiFi);
188 } else {
189 ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_DISCONNECTED");
190 }
191 _wifi_BetterAP = false;
192 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
193 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
194 break;
195 }
196
197 default:
198 ESP_LOGW(TAG, "Unknown WiFi event %ld", event_id);
199 break;
200 }
201 }
202
203
204
205 static void got_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
206 {
207 switch (event_id) {
208
209 case IP_EVENT_STA_GOT_IP:
210 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_HAS_IP);
211 ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
212 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
213 wifi_state->STA_online = true;
214 snprintf(wifi_state->STA_ip, 16, IPSTR, IP2STR(&event->ip_info.ip));
215 snprintf(wifi_state->STA_nm, 16, IPSTR, IP2STR(&event->ip_info.netmask));
216 snprintf(wifi_state->STA_gw, 16, IPSTR, IP2STR(&event->ip_info.gw));
217 xSemaphoreGive(xSemaphoreWiFi);
218 } else {
219 ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_GOT_IP");
220 }
221
222 // ESP_LOGI(TAG, "Starting SNTP");
223 // esp_netif_sntp_start();
224
225 break;
226
227 case IP_EVENT_STA_LOST_IP:
228 ESP_LOGW(TAG, "Lost IP address");
229 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_HAS_IP);
230 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
231 wifi_state->STA_ip[0] = '\0';
232 wifi_state->STA_nm[0] = '\0';
233 wifi_state->STA_gw[0] = '\0';
234 wifi_state->STA_online = false;
235 xSemaphoreGive(xSemaphoreWiFi);
236 } else {
237 ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_LOST_IP");
238 }
239 break;
240
241 case IP_EVENT_AP_STAIPASSIGNED:
242 ESP_LOGI(TAG, "IP_EVENT_AP_STAIPASSIGNED");
243 break;
244
245 default:
246 ESP_LOGW(TAG, "Unknown IP event %ld", event_id);
247 break;
248 }
249 }
250
251
252 void time_sync_notification_cb(struct timeval *tv)
253 {
254 time_t now;
255 char strftime_buf[64];
256 struct tm timeinfo;
257
258 ESP_LOGI(TAG, "Notification of a time synchronization event");
259 int rc = sntp_get_sync_status();
260
261 if (rc == SNTP_SYNC_STATUS_COMPLETED) {
262 time(&now);
263 localtime_r(&now, &timeinfo);
264 // System_TimeOk = true;
265 strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
266 ESP_LOGI(TAG, "NTP time is set: %s", strftime_buf);
267 } else {
268 ESP_LOGI(TAG, "NTP unknown time sync event rc=%d", rc);
269 }
270 }
271
272
273 void task_wifi( void * pvParameters )
274 {
275 ESP_LOGI(TAG, "Starting WiFi");
276
277 /* event handler and event group for the wifi driver */
278 xEventGroupWifi = xEventGroupCreate();
279 /* initialize the tcp stack */
280 ESP_ERROR_CHECK(esp_netif_init());
281 ESP_ERROR_CHECK(esp_event_loop_create_default());
282
283 wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
284 ESP_ERROR_CHECK(esp_wifi_init(&cfg));
285
286 sta_netif = esp_netif_create_default_wifi_sta();
287 assert(sta_netif);
288
289 /*
290 * Setup SNTP configuration
291 */
292 /**
293 * NTP server address could be acquired via DHCP,
294 * see following menuconfig options:
295 * 'LWIP_DHCP_GET_NTP_SRV' - enable STNP over DHCP
296 * 'LWIP_SNTP_DEBUG' - enable debugging messages
297 *
298 * NOTE: This call should be made BEFORE esp acquires IP address from DHCP,
299 * otherwise NTP option would be rejected by default.
300 */
301 ESP_LOGI(TAG, "Initializing SNTP");
302 esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
303 config.start = false; // start SNTP service explicitly (after connecting)
304 config.server_from_dhcp = true; // accept NTP offers from DHCP server, if any (need to enable *before* connecting)
305 config.renew_servers_after_new_IP = true; // let esp-netif update configured SNTP server(s) after receiving DHCP lease
306 config.index_of_first_server = 1; // updates from server num 1, leaving server 0 (from DHCP) intact
307 config.ip_event_to_renew = IP_EVENT_STA_GOT_IP;
308 config.sync_cb = time_sync_notification_cb; // only if we need the notification function
309 esp_netif_sntp_init(&config);
310 ESP_LOGI(TAG, "Starting SNTP");
311 esp_netif_sntp_start();
312
313
314 /*
315 * memory allocation of objects used by the task
316 */
317 accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * MAX_AP_NUM);
318 xSemaphoreWiFi = xSemaphoreCreateMutex();
319 wifi_state = malloc(sizeof(WIFI_State));
320 memset(wifi_state, 0x00, sizeof(WIFI_State));
321
322 /*
323 * init wifi as station
324 */
325 esp_event_handler_instance_t instance_any_id;
326 esp_event_handler_instance_t instance_got_ip;
327 ESP_ERROR_CHECK( esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id) );
328 ESP_ERROR_CHECK( esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, &got_ip_event_handler, NULL, &instance_got_ip) );
329
330 wifi_config_t wifi_config = {
331 .sta = {
332 .ssid = CONFIG_ESP_WIFI_SSID,
333 .password = CONFIG_ESP_WIFI_PASSWORD,
334 #if CONFIG_WIFI_ALL_CHANNEL_SCAN
335 .scan_method = WIFI_ALL_CHANNEL_SCAN,
336 #elif CONFIG_WIFI_FAST_SCAN
337 .scan_method = WIFI_FAST_SCAN,
338 #endif
339 .failure_retry_cnt = 3,
340 .sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
341 .threshold.rssi = CONFIG_ESP_FAST_SCAN_MINIMUM_SIGNAL,
342 .threshold.authmode = WIFI_AUTH_WPA2_PSK,
343 },
344 };
345 ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
346 ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
347 ESP_ERROR_CHECK(esp_wifi_start());
348
349 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
350 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
351 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
352 EventBits_t uxBits;
353
354 for(;;) {
355
356 /* actions that can trigger: request a connection, a scan, or a disconnection */
357 uxBits = xEventGroupWaitBits(xEventGroupWifi,
358 TASK_WIFI_REQUEST_STA_CONNECT | TASK_WIFI_REQUEST_STA_DISCONNECT | TASK_WIFI_REQUEST_STA_SCAN | TASK_WIFI_REQUEST_STA_STATUS,
359 pdFALSE, pdFALSE, portMAX_DELAY );
360
361 if (uxBits & TASK_WIFI_REQUEST_STA_DISCONNECT) {
362 /*
363 * user requested a disconnect, this will in effect disconnect the wifi
364 */
365 ESP_LOGI(TAG, "Request STA disconnect");
366 ESP_ERROR_CHECK(esp_wifi_disconnect());
367 xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY );
368
369 /* finally: release the scan request bit */
370 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT);
371 ESP_LOGI(TAG, "Request STA disconnect is done");
372
373 } else if (uxBits & TASK_WIFI_REQUEST_STA_CONNECT) {
374
375 ESP_LOGI(TAG, "Request STA connect");
376 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_FAILED);
377 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
378
379 ESP_LOGI(TAG, "Connecting to `%s'", CONFIG_ESP_WIFI_SSID);
380 esp_err_t wifierror = esp_wifi_connect();
381 if (wifierror != ESP_OK) {
382 ESP_LOGE(TAG, "esp_wifi_connect() `%s' rc=%04x", CONFIG_ESP_WIFI_SSID, (int)wifierror);
383 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_FAILED);
384 }
385 uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED, pdFALSE, pdFALSE, 5000 / portTICK_PERIOD_MS);
386
387 } else if (uxBits & TASK_WIFI_REQUEST_STA_STATUS) {
388 /*
389 * Request WiFi update status, refresh the rssi.
390 */
391 ESP_LOGD(TAG, "Request STA status");
392 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_STATUS);
393 wifi_ap_record_t ap_info;
394 esp_wifi_sta_get_ap_info(&ap_info);
395 ESP_LOGI(TAG, "Event STA status, ssid:%s, bssid:" MACSTR ", rssi: %d", ap_info.ssid, MAC2STR(ap_info.bssid), ap_info.rssi);
396 _wifi_RSSI = ap_info.rssi;
397 _wifi_BetterAP = false;
398 if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) {
399 wifi_state->STA_rssi = ap_info.rssi;
400 wifi_state->STA_channel = ap_info.primary;
401 snprintf(wifi_state->STA_bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
402 ap_info.bssid[0], ap_info.bssid[1], ap_info.bssid[2], ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]);
403 xSemaphoreGive(xSemaphoreWiFi);
404 } else {
405 ESP_LOGE(TAG, "lock error TASK_WIFI_REQUEST_STA_STATUS");
406 }
407
408 } else if (uxBits & TASK_WIFI_REQUEST_STA_SCAN) {
409
410 ESP_LOGI(TAG, "Request STA scan");
411 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_SCAN);
412 /* safe guard against overflow */
413 ap_num = MAX_AP_NUM;
414 _wifi_ScanDone = false;
415 _wifi_BetterAP = false;
416 ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false));
417 }
418
419 } /* for(;;) */
420 }
421
422

mercurial