ENTS-tock
Environmental NeTworked Sensor firmware on Tock OS
Loading...
Searching...
No Matches
wifi.c
Go to the documentation of this file.
1#include "wifi.h"
2
3#include <stdbool.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <stm32_systime.h>
7
8// #include "adc.h"
9// #include "ads.h"
10#include "app_lorawan.h"
11// #include "bme280_sensor.h"
12#include "../user_config.h"
13#include "board.h"
15#include "dma.h"
16#include "fifo.h"
17#include "payload.h"
18#include "sensors.h"
19
24static UTIL_TIMER_Object_t UploadTimer = {};
25
29const unsigned int max_retries = 5;
30
34const unsigned int retry_delay = 1000;
35
41void UploadEvent(void* context);
42
48void Upload(void);
49
57bool Connect(void);
58
64bool Disconnect(void);
65
71bool TimeSync(void);
72
78bool Check(void);
79
85void StartUploads(void);
86
90void StopUploads(void);
91
95void ResumeUploads(void);
96
102void ErrorHandler(void);
103
111bool Esp32Init(void);
112
113void WiFiInit(void) {
114 APP_LOG(TS_OFF, VLEVEL_M, "WiFi app starting\r\n");
115
116 // loop until sucessful connection
117 while (!Esp32Init()) {
118 Disconnect();
119 }
120
121 // start timers for uploading
122 StartUploads();
123}
124
125void UploadEvent(void* context) {
126 // lower priority (higher value) than measure task
127 UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_WiFiUpload), CFG_SEQ_Prio_1);
128}
129
130void Upload(void) {
131 const size_t buffer_size = 256;
132 size_t buffer_len = 0;
133 uint8_t buffer[buffer_size];
134
135 // get payload (pegged at 512)
136 PayloadStatus payload_status = PAYLOAD_OK;
137 payload_status = FormatPayload(buffer, buffer_size, &buffer_len);
138 if (payload_status == PAYLOAD_ERROR) {
139 APP_LOG(TS_OFF, VLEVEL_M, "Error formatting payload\r\n");
140 return;
141 } else if (payload_status == PAYLOAD_NO_DATA) {
142 APP_LOG(TS_OFF, VLEVEL_M, "No data to send\r\n");
143 return;
144 }
145
146 // print buffer
147 APP_LOG(TS_ON, VLEVEL_M, "Payload[%d]: ", buffer_len);
148 for (int i = 0; i < buffer_len; i++) {
149 APP_LOG(TS_OFF, VLEVEL_M, "%02X ", buffer[i]);
150 }
151 APP_LOG(TS_OFF, VLEVEL_M, "\r\n");
152
153 // posts data to website
154 APP_LOG(TS_ON, VLEVEL_M, "Uploading data.");
155 if (!ControllerWiFiPost(buffer, buffer_len)) {
156 APP_LOG(TS_OFF, VLEVEL_M, "Error! Could not communicate with esp32!\r\n");
157 }
158
159 for (unsigned int retries = 0;; retries++) {
160 HAL_Delay(retry_delay);
161 APP_LOG(TS_OFF, VLEVEL_M, ".");
162
164 APP_LOG(TS_OFF, VLEVEL_M, "(%d) \r\n", resp.http_code);
165
166 if (resp.http_code == 200) {
167 break;
168 } else {
169 // check category of error
170 if (resp.http_code == 0) {
171 APP_LOG(TS_OFF, VLEVEL_M,
172 "Error when posting data! Likely error with WiFi or response "
173 "timeout.\r\n");
174 } else {
175 APP_LOG(TS_OFF, VLEVEL_M,
176 "Error with HTTP code! Likely error with measurement format or "
177 "backend.\r\n");
178 }
179
180 // give up after max retries and tirgger error handler
181 if (retries >= max_retries) {
182 APP_LOG(TS_ON, VLEVEL_M, "Max retries reached! Stopping upload.\r\n");
183 ErrorHandler();
184 return;
185 }
186 }
187 }
188
189 if (FramBufferLen() > 0) {
190 APP_LOG(TS_ON, VLEVEL_M, "Buffer not empty, starting another upload\r\n");
191 UploadEvent(NULL);
192 }
193
194 StatusLedOff();
195}
196
197void StartUploads(void) {
198 // start sensor measurements
199 APP_LOG(TS_ON, VLEVEL_M, "Starting sensor measurements...\t");
200 SensorsStart();
201 APP_LOG(TS_OFF, VLEVEL_M, "Started!\r\n");
202
203 // get upload period from user config
204 const UserConfiguration* cfg = UserConfigGet();
205 UTIL_TIMER_Time_t UploadPeriod = cfg->Upload_interval * 1000;
206
207 // setup upload task
208 APP_LOG(TS_ON, VLEVEL_M, "Starting upload task...\t")
209 UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_WiFiUpload), UTIL_SEQ_RFU, Upload);
210 UploadEvent(NULL);
211 UTIL_TIMER_Create(&UploadTimer, UploadPeriod, UTIL_TIMER_PERIODIC,
212 UploadEvent, NULL);
213 UTIL_TIMER_Start(&UploadTimer);
214 APP_LOG(TS_OFF, VLEVEL_M, "Started!\r\n");
215}
216
217void StopUploads(void) {
218 // stop upload timer
219 APP_LOG(TS_ON, VLEVEL_M, "Stopping upload task...\t");
220 UTIL_TIMER_Stop(&UploadTimer);
221 APP_LOG(TS_OFF, VLEVEL_M, "Stopped!\r\n");
222}
223
224void ResumeUploads(void) {
225 // stop upload timer
226 APP_LOG(TS_ON, VLEVEL_M, "Starting upload task...\t")
227 UTIL_TIMER_Start(&UploadTimer);
228 APP_LOG(TS_OFF, VLEVEL_M, "Started!\r\n");
229}
230
231void ErrorHandler(void) {
232 // turn on status LED
233 StatusLedOn();
234
235 StopUploads();
236
237 // first disconnect, then retry until connected to wifi
238 do {
239 Disconnect();
240 } while (!Esp32Init());
241
243}
244
245bool Connect(void) {
246 // load configurations
247 const UserConfiguration* cfg = UserConfigGet();
248
249 const char* ssid = cfg->WiFi_SSID;
250 const char* passwd = cfg->WiFi_Password;
251
252 APP_LOG(TS_ON, VLEVEL_M, "Connecting to %s.", ssid);
253 if (!ControllerWiFiConnect(ssid, passwd)) {
254 APP_LOG(TS_OFF, VLEVEL_M, "Error! Could not communicate with esp32!\r\n");
255 return false;
256 }
257
258 for (unsigned int retries = 0;; retries++) {
259 HAL_Delay(retry_delay);
260 APP_LOG(TS_OFF, VLEVEL_M, ".")
261
263 if (status == CONTROLLER_WIFI_CONNECTED) {
264 break;
265 } else {
266 if (retries >= max_retries) {
267 APP_LOG(TS_OFF, VLEVEL_M, "Error! Timeout after %d retries!\r\n",
268 retries);
269 return false;
270 } else {
271 if (status == CONTROLLER_WIFI_DISCONNECTED) {
272 continue;
273 } else if (status == CONTROLLER_WIFI_NO_SSID_AVAIL) {
274 APP_LOG(TS_OFF, VLEVEL_M, "Error! No SSID available!\r\n");
275 return false;
276 } else if (status == CONTROLLER_WIFI_CONNECT_FAILED) {
277 APP_LOG(TS_OFF, VLEVEL_M, "Error! Connect failed!\r\n");
278 return false;
279 }
280 }
281 }
282 }
283
284 APP_LOG(TS_OFF, VLEVEL_M, "Connected!\r\n");
285
286 return true;
287}
288
289bool Disconnect(void) {
290 APP_LOG(TS_ON, VLEVEL_M, "Disconnecting from WiFi.");
292 APP_LOG(TS_OFF, VLEVEL_M, "Error! Could not communicate with esp32!\r\n");
293 return false;
294 }
295
296 for (unsigned int retries = 0;; retries++) {
297 HAL_Delay(retry_delay);
298 APP_LOG(TS_OFF, VLEVEL_M, ".")
299
301 if (status == CONTROLLER_WIFI_IDLE_STATUS) {
302 break;
303 } else if (status == CONTROLLER_WIFI_DISCONNECTED) {
304 break;
305 } else {
306 if (retries >= max_retries) {
307 APP_LOG(TS_OFF, VLEVEL_M, "Error! Timeout after %d retries!\r\n",
308 retries);
309 return false;
310 }
311 }
312 }
313 APP_LOG(TS_OFF, VLEVEL_M, "Done!\r\n");
314
315 return true;
316}
317
318bool TimeSync(void) {
319 SysTime_t ts = {.Seconds = -1, .SubSeconds = 0};
320
321 APP_LOG(TS_OFF, VLEVEL_M, "Syncing time.");
322 if (!ControllerWiFiNtpSync()) {
323 APP_LOG(TS_OFF, VLEVEL_M, "Error! Could not communicate with esp32!\r\n");
324 return false;
325 }
326
327 for (unsigned int retries = 0;; retries++) {
328 HAL_Delay(retry_delay);
329 APP_LOG(TS_OFF, VLEVEL_M, ".");
330
331 ts.Seconds = ControllerWiFiTime();
332
333 // check for errors
334 if (ts.Seconds != 0) {
335 break;
336 } else {
337 if (retries >= max_retries) {
338 APP_LOG(TS_OFF, VLEVEL_M, "Error! Timeout after %d retries!\r\n",
339 retries);
340 return false;
341 }
342 }
343 }
344
345 SysTimeSet(ts);
346
347 APP_LOG(TS_OFF, VLEVEL_M, "Done!\r\n");
348 APP_LOG(TS_OFF, VLEVEL_M, "Current timestamp is %d\r\n", ts.Seconds);
349
350 return true;
351}
352
353bool Check(void) {
354 const UserConfiguration* cfg = UserConfigGet();
355
356 // const char url[] = "dirtviz.jlab.ucsc.edu";
357 // const uint32_t port = 80;
358
359 const char* url = cfg->API_Endpoint_URL;
360
361 APP_LOG(TS_OFF, VLEVEL_M, "Checking API health.");
362 if (!ControllerWiFiCheckApi(url)) {
363 APP_LOG(TS_OFF, VLEVEL_M, "Error! Could not communicate with esp32!\r\n");
364 return false;
365 }
366
367 for (unsigned int retries = 0;; retries++) {
368 APP_LOG(TS_OFF, VLEVEL_M, ".");
369
371 APP_LOG(TS_OFF, VLEVEL_M, "(%d) \r\n", resp.http_code);
372
373 if (resp.http_code == 200) {
374 break;
375 } else {
376 // check category of error
377 if (resp.http_code == 0) {
378 APP_LOG(TS_OFF, VLEVEL_M,
379 "Error when posting data! Likely error with WiFi or response "
380 "timeout.\r\n");
381 } else {
382 APP_LOG(TS_OFF, VLEVEL_M,
383 "Error with HTTP code! Likely error with measurement format or "
384 "backend.\r\n");
385 }
386
387 // give up after max retries and tirgger error handler
388 if (retries >= max_retries) {
389 APP_LOG(TS_ON, VLEVEL_M, "Max retries reached! Stopping upload.\r\n");
390 return false;
391 }
392 }
393
394 HAL_Delay(retry_delay);
395 }
396
397 return true;
398}
399
400bool Esp32Init(void) {
401 // Start WiFi connection
402 if (!Connect()) {
403 return false;
404 }
405
406 // Check WiFi connection and API health
407 if (!Check()) {
408 return false;
409 }
410
411 // sync with NTP server
412 if (!TimeSync()) {
413 return false;
414 }
415
416 // Stop webserver if running (timeout of 60 seconds)
417 UserConfigSetupStop(60);
418
419 return true;
420}
Controller module for stm32.
const char ssid[]
uint8_t buffer[32]
uint8_t i
Circular buffer as FIFO data structure for buffering measurements.
bool ControllerWiFiConnect(const char *ssid, const char *passwd)
Initialize WiFi settings on the esp32.
Definition wifi.c:40
ControllerWiFiStatus ControllerWiFiCheckWiFi(void)
Checks the current status of WiFi.
Definition wifi.c:69
bool ControllerWiFiCheckApi(const char *url)
Queries the API endpoint to check if it is reachable.
Definition wifi.c:104
bool ControllerWiFiDisconnect(void)
Disconnects from the WiFi network.
Definition wifi.c:56
bool ControllerWiFiNtpSync(void)
Triggers a NTP sync with the server.
Definition wifi.c:80
ControllerWiFiStatus
WiFi status.
Definition wifi.h:57
uint32_t ControllerWiFiTime(void)
Get the current time from the NTP server.
Definition wifi.c:93
bool ControllerWiFiPost(const uint8_t *data, size_t data_len)
Post data to the configured endpoint.
Definition wifi.c:118
ControllerWiFiResponse ControllerWiFiCheckRequest(void)
Checks the status of the most recent HTTP request.
Definition wifi.c:135
@ CONTROLLER_WIFI_CONNECTED
Definition wifi.h:62
@ CONTROLLER_WIFI_IDLE_STATUS
Definition wifi.h:59
@ CONTROLLER_WIFI_CONNECT_FAILED
Definition wifi.h:63
@ CONTROLLER_WIFI_DISCONNECTED
Definition wifi.h:65
@ CONTROLLER_WIFI_NO_SSID_AVAIL
Definition wifi.h:60
const UserConfiguration * UserConfigGet(void)
Gets a reference to the loaded user configuration data in RAM.
bool Disconnect(void)
Disconnect from WiFi.
Definition wifi.c:289
void StopUploads(void)
Stop upload timer.
Definition wifi.c:217
bool TimeSync(void)
Timesync with NTP server.
Definition wifi.c:318
const unsigned int retry_delay
Delay in milliseconds between retries.
Definition wifi.c:34
void StartUploads(void)
Setup upload timer.
Definition wifi.c:197
void Upload(void)
Upload data to hub.
Definition wifi.c:130
void WiFiInit(void)
Initialize WiFi uploading method.
Definition wifi.c:113
bool Esp32Init(void)
Call initialization functions for ESP32.
Definition wifi.c:400
void ResumeUploads(void)
Resumes upload timer.
Definition wifi.c:224
bool Check(void)
Check API health.
Definition wifi.c:353
void ErrorHandler(void)
Error handler.
Definition wifi.c:231
const unsigned int max_retries
Maximum number of retries for any event.
Definition wifi.c:29
bool Connect(void)
Connect to WiFi.
Definition wifi.c:245
void UploadEvent(void *context)
Function call for upload event.
Definition wifi.c:125
WiFi response.
Definition wifi.h:75
unsigned int http_code
Definition wifi.h:77