main/task_wifi.c

changeset 0
88d965579617
child 23
58a328e91881
equal deleted inserted replaced
-1:000000000000 0:88d965579617
1 /**
2 * @file task_wifi.c
3 * @brief WiFi task. Connect to the known AP with the strongest signal.
4 */
5
6
7 #include "config.h"
8
9
10 static const char *TAG = "task_wifi";
11
12
13 SemaphoreHandle_t xSemaphoreWiFi = NULL; ///< Semaphore WiFi task.
14 EventGroupHandle_t xEventGroupWifi; ///< Events WiFi task.
15 uint16_t ap_num = MAX_AP_NUM; ///< Scan counter.
16 wifi_ap_record_t *accessp_records; ///< [MAX_AP_NUM] records array with scan results.
17 wifi_config_t *task_wifi_ConfigSTA = NULL; ///< Current STA configuration.
18 WIFI_State *wifi_state = NULL; ///< Public state for other tasks.
19
20 wifi_scan_config_t scan_config = { ///< WiFi scanner configuration.
21 .ssid = 0,
22 .bssid = 0,
23 .channel = 0,
24 .show_hidden = false,
25 .scan_time.passive = 130 ///< Beacons are usually sent every 100 mSec.
26 };
27
28 uint8_t _wifi_ssid[33]; ///< Current SSID
29 bool _wifi_ScanAPs = false; ///< Scanning
30 bool _wifi_ScanDone = false; ///< Scan ready
31 uint16_t _wifi_Scanned = 0; ///< Total scanned APs.
32
33 extern uint32_t TimeSpent; ///< Counter that is increased each second.
34 extern bool System_TimeOk;
35 extern time_t now;
36 extern char strftime_buf[64];
37 extern struct tm timeinfo;
38
39 const int TASK_WIFI_REQUEST_WIFI_SCAN = BIT0; ///< When set, means a client requested to scan wireless networks.
40 const int TASK_WIFI_REQUEST_STA_DISCONNECT = BIT1; ///< When set, means a client requested to disconnect from currently connected AP.
41 const int TASK_WIFI_REQUEST_STA_CONNECT = BIT2; ///< When set, means a client requested to connect to an access point.
42
43 const int TASK_WIFI_HAS_IP = BIT3; ///< Indicate that we have an IP address
44 const int TASK_WIFI_STA_FAILED = BIT4; ///< Indicate that we could not get a connection to AP as station.
45 const int TASK_WIFI_STA_DISCONNECTED = BIT5; ///< Indicate that we are disconnected from an ap station.
46 const int TASK_WIFI_STA_CONNECTED = BIT6; ///< Indicate that we are connected to AP as station, flip of BIT6.
47
48 const int TASK_WIFI_REQUEST_SYSTEM = BIT8; ///< The system needs a connection
49 const int TASK_WIFI_REQUEST_USER = BIT9; ///< The user needs a connection
50
51
52 /**
53 * @brief local callback function. Is called when the timesync is valid
54 * from a timeserver. Sets the global boolean System_TimeOk value.
55 * @param tv is the received time. Not used.
56 */
57 void time_sync_notification_cb(struct timeval *tv);
58
59 /**
60 * @brief Array with AP security names
61 */
62 const char *apsec[] = { "Open", "WEP", "WPA", "WPA2", "WPA WPA2", "Enterprise" };
63
64
65 /****************************************************************************/
66
67
68
69 void requestWiFi_system(bool state)
70 {
71 if (state)
72 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_SYSTEM);
73 else
74 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_SYSTEM);
75
76 if (xEventGroupGetBits(xEventGroupWifi) & (TASK_WIFI_REQUEST_SYSTEM | TASK_WIFI_REQUEST_USER))
77 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
78 else
79 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT);
80 }
81
82
83
84 void requestWiFi_user(bool state)
85 {
86 if (state)
87 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_USER);
88 else
89 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_USER);
90
91 if (xEventGroupGetBits(xEventGroupWifi) & (TASK_WIFI_REQUEST_SYSTEM | TASK_WIFI_REQUEST_USER))
92 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT);
93 else
94 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT);
95 }
96
97
98
99 bool ready_WiFi(void)
100 {
101 if (wifi_state->STA_connected && wifi_state->STA_online)
102 return true;
103 return false;
104 }
105
106
107
108 static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
109 {
110 switch (event_id) {
111
112 case WIFI_EVENT_SCAN_DONE:
113 // Get the results so the memory used is freed.
114 ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, accessp_records));
115 _wifi_Scanned = ap_num;
116 _wifi_ScanDone = true;
117 break;
118
119 case WIFI_EVENT_STA_START:
120 ESP_LOGI(TAG, "Event wifi START");
121 // Set the configured hostname for the dhcp client.
122 ESP_ERROR_CHECK(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, config.hostname));
123 esp_wifi_connect();
124 break;
125
126 case WIFI_EVENT_STA_CONNECTED:
127 {
128 wifi_event_sta_connected_t* event = (wifi_event_sta_connected_t*) event_data;
129 wifi_ap_record_t ap_info;
130 esp_wifi_sta_get_ap_info(&ap_info);
131 ESP_LOGI(TAG, "Event STA connected, ssid:%s, bssid:" MACSTR ", channel:%d, rssi: %d, authmode:%s",
132 ap_info.ssid, MAC2STR(ap_info.bssid), event->channel, ap_info.rssi, apsec[event->authmode]);
133 if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
134 wifi_state->STA_connected = true;
135 wifi_state->STA_rssi = ap_info.rssi;
136 sprintf(wifi_state->STA_ssid, "%s", ap_info.ssid);
137 xSemaphoreGive(xSemaphoreWiFi);
138 }
139 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
140 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
141 break;
142 }
143
144 case WIFI_EVENT_STA_DISCONNECTED:
145 {
146 wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data;
147
148 ESP_LOGI(TAG, "Event STA disconnected, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d",
149 disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason);
150 if (xSemaphoreTake(xSemaphoreWiFi, 10) == pdTRUE) {
151 wifi_state->STA_connected = false;
152 wifi_state->STA_online = false;
153 wifi_state->STA_rssi = 0;
154 xSemaphoreGive(xSemaphoreWiFi);
155 }
156 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
157 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
158 break;
159 }
160
161 default:
162 ESP_LOGI(TAG, "Unknown WiFi event %d", event_id);
163 break;
164 }
165 }
166
167
168
169 static void got_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
170 {
171 switch (event_id) {
172
173 case IP_EVENT_STA_GOT_IP:
174 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_HAS_IP);
175 ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
176 if (xSemaphoreTake(xSemaphoreWiFi, 10) == pdTRUE) {
177 wifi_state->STA_online = true;
178 snprintf(wifi_state->STA_ip, 16, "%s", ip4addr_ntoa(&event->ip_info.ip));
179 snprintf(wifi_state->STA_nm, 16, "%s", ip4addr_ntoa(&event->ip_info.netmask));
180 snprintf(wifi_state->STA_gw, 16, "%s", ip4addr_ntoa(&event->ip_info.gw));
181 xSemaphoreGive(xSemaphoreWiFi);
182 }
183 break;
184
185 case IP_EVENT_STA_LOST_IP:
186 ESP_LOGW(TAG, "Lost IP address");
187 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_HAS_IP);
188 if (xSemaphoreTake(xSemaphoreWiFi, 10) == pdTRUE) {
189 wifi_state->STA_ip[0] = '\0';
190 wifi_state->STA_nm[0] = '\0';
191 wifi_state->STA_gw[0] = '\0';
192 wifi_state->STA_online = false;
193 xSemaphoreGive(xSemaphoreWiFi);
194 }
195 break;
196
197 default:
198 ESP_LOGI(TAG, "Unknown IP event %d", event_id);
199 break;
200 }
201 }
202
203
204
205 void task_wifi( void * pvParameters )
206 {
207 ESP_LOGI(TAG, "Starting WiFi");
208
209 /* event handler and event group for the wifi driver */
210 xEventGroupWifi = xEventGroupCreate();
211 /* initialize the tcp stack */
212 tcpip_adapter_init();
213 ESP_ERROR_CHECK(esp_event_loop_create_default());
214
215 /*
216 * memory allocation of objects used by the task
217 */
218 accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * MAX_AP_NUM);
219 task_wifi_ConfigSTA = (wifi_config_t*)malloc(sizeof(wifi_config_t));
220 memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t));
221
222 xSemaphoreWiFi = xSemaphoreCreateMutex();
223 wifi_state = malloc(sizeof(WIFI_State));
224 wifi_state->STA_connected = false;
225 wifi_state->STA_online = false;
226 wifi_state->STA_rssi = 0;
227
228 /* stop dhcp server and start dhcp client */
229 ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP));
230 ESP_ERROR_CHECK(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA));
231
232 /*
233 * init wifi as station
234 */
235 wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
236 ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
237
238 ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL) );
239 ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &got_ip_event_handler, NULL) );
240
241 ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
242 ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
243 ESP_ERROR_CHECK(esp_wifi_start());
244
245 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
246 EventBits_t uxBits;
247
248 for(;;) {
249
250 /* actions that can trigger: request a connection, a scan, or a disconnection */
251 uxBits = xEventGroupWaitBits(xEventGroupWifi,
252 TASK_WIFI_REQUEST_STA_CONNECT | TASK_WIFI_REQUEST_WIFI_SCAN | TASK_WIFI_REQUEST_STA_DISCONNECT,
253 pdFALSE, pdFALSE, portMAX_DELAY );
254
255 if (uxBits & TASK_WIFI_REQUEST_STA_DISCONNECT) {
256 /*
257 * user requested a disconnect, this will in effect disconnect the wifi
258 */
259 ESP_LOGI(TAG, "Request STA disconnect");
260 ESP_ERROR_CHECK(esp_wifi_disconnect());
261 xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY );
262
263 /* finally: release the scan request bit */
264 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT);
265
266 } else if (uxBits & TASK_WIFI_REQUEST_STA_CONNECT) {
267
268 ESP_LOGI(TAG, "Request STA connect");
269 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_FAILED);
270 _wifi_ScanAPs = true;
271 _wifi_ScanDone = false;
272 ap_num = MAX_AP_NUM;
273 ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false));
274 while (_wifi_ScanDone == false) {
275 vTaskDelay(10 / portTICK_PERIOD_MS);
276 }
277 ESP_LOGI(TAG, "Scan done %d APs", _wifi_Scanned);
278 bool found = false;
279
280 // Available Access Points.
281 for (int i = 0; i < _wifi_Scanned; i++) {
282 wifi_ap_record_t ap = accessp_records[i];
283 // Check if we know this AP in the database.
284 // ESP_LOGI(TAG, "%d %-20s ch: %2d rssi: %d %s", i, ap.ssid, ap.primary, ap.rssi, apsec[ap.authmode]);
285 if ((read_station(ap.ssid) >= 0)) {
286 /* ssid */
287 size_t sz = sizeof(task_wifi_ConfigSTA->sta.ssid);
288 memcpy(task_wifi_ConfigSTA->sta.ssid, wifiStation.SSID, sz);
289 /* password */
290 sz = sizeof(task_wifi_ConfigSTA->sta.password);
291 memcpy(task_wifi_ConfigSTA->sta.password, wifiStation.Password, sz);
292 found = true;
293 break;
294 }
295 }
296 if (found) {
297 /*
298 * Now connect to the known SSID
299 */
300 // ESP_LOGI(TAG, "Connecting to `%s'", task_wifi_ConfigSTA->sta.ssid);
301 ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, task_wifi_ConfigSTA));
302 esp_err_t wifierror = esp_wifi_connect();
303 if (wifierror != ESP_OK) {
304 ESP_LOGE(TAG, "esp_wifi_connect() `%s' rc=%04x", task_wifi_ConfigSTA->sta.ssid, (int)wifierror);
305 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_FAILED);
306 }
307 uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED, pdFALSE, pdFALSE, 5000 / portTICK_PERIOD_MS);
308 if (uxBits & TASK_WIFI_STA_CONNECTED)
309 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); // Only clear when connected.
310 } else {
311 ESP_LOGI(TAG, "No known AP found, scan again");
312 vTaskDelay(3000 / portTICK_PERIOD_MS);
313 }
314 }
315
316 } /* for(;;) */
317 vTaskDelay(10 / portTICK_PERIOD_MS);
318 }
319
320

mercurial