-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathwifi_logger.c
359 lines (317 loc) · 8.81 KB
/
wifi_logger.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#include "wifi_logger.h"
static const char* tag_wifi_logger = "wifi_logger";
static QueueHandle_t wifi_logger_queue;
/**
* @brief Initialises message queue
*
* @return esp_err_t ESP_OK - if queue init sucessfully, ESP_FAIL - if queue init failed
**/
esp_err_t init_queue(void)
{
wifi_logger_queue = xQueueCreate(MESSAGE_QUEUE_SIZE, sizeof(char*));
if (wifi_logger_queue == NULL)
{
ESP_LOGE(tag_wifi_logger, "%s", "Queue creation failed");
return ESP_FAIL;
}
else
{
ESP_LOGI(tag_wifi_logger, "%s", "Queue created");
return ESP_OK;
}
}
/**
* @brief Initialises and connects to wifi
**/
void init_wifi(void)
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(example_connect());
}
/**
* @brief Sends log message to message queue
*
* @param log_message log message to be sent to the queue
* @return esp_err_t ESP_OK - if queue init sucessfully, ESP_FAIL - if queue init failed
**/
esp_err_t send_to_queue(char* log_message)
{
BaseType_t qerror = xQueueSendToBack(wifi_logger_queue, (void*)&log_message, (TickType_t) 0/portTICK_PERIOD_MS);
if(qerror == pdPASS)
{
ESP_LOGD(tag_wifi_logger, "%s", "Data sent to Queue");
return ESP_OK;
}
else if(qerror == errQUEUE_FULL)
{
ESP_LOGE(tag_wifi_logger, "%s", "Data not sent to Queue, Queue full");
return ESP_FAIL;
}
else
{
ESP_LOGE(tag_wifi_logger, "%s", "Unknown error");
return ESP_FAIL;
}
}
/**
* @brief Receive data from queue. Timeout is set to portMAX_DELAY, which is around 50 days (confirm from esp32 specs)
*
* @return char* - returns log message received from the queue, returns NULL if error
**/
char* receive_from_queue(void)
{
char* data;
// ************************* IMPORTANT *******************************************************************
// Timeout period is set to portMAX_DELAY, so if it doesnot receive a log message for ~50 days, config assert will fail and program will crash
//
BaseType_t qerror = xQueueReceive(wifi_logger_queue, &data, (TickType_t) portMAX_DELAY);
configASSERT(qerror);
//
// *******************************************************************************************************
if(qerror == pdPASS)
{
ESP_LOGD(tag_wifi_logger, "%s", "Data received from Queue");
}
else if(qerror == pdFALSE)
{
ESP_LOGW(tag_wifi_logger, "%s", "Data not received from Queue");
data = NULL;
}
else
{
free((void*)data);
ESP_LOGE(tag_wifi_logger, "%s", "Unknown error");
data = NULL;
}
return data;
}
/**
* @brief generates log message, of the format generated by ESP_LOG function
*
* @param level set ESP LOG level {E, W, I, D, V}
* @param TAG Tag for the log message
* @param line line
* @param func func
* @param fmt fmt
*/
void generate_log_message(esp_log_level_t level, const char *TAG, int line, const char *func, const char *fmt, ...)
{
char log_print_buffer[BUFFER_SIZE];
memset(log_print_buffer, '\0', BUFFER_SIZE);
snprintf(log_print_buffer, BUFFER_SIZE, "%s (%s:%d) ", TAG, func, line);
va_list args;
va_start(args, fmt);
int len = strlen(log_print_buffer);
if (BUFFER_SIZE - len > 1)
{
vsnprintf(&log_print_buffer[len], (BUFFER_SIZE - len), fmt, args);
}
else
{
memset(log_print_buffer, '\0', BUFFER_SIZE);
sprintf(log_print_buffer, "%s", "Buffer overflowed, increase buffer size");
}
va_end(args);
uint log_level_opt = 2;
switch (level)
{
case ESP_LOG_ERROR:
log_level_opt = 0;
break;
case ESP_LOG_WARN:
log_level_opt = 1;
break;
case ESP_LOG_INFO:
log_level_opt = 2;
break;
case ESP_LOG_DEBUG:
log_level_opt = 3;
break;
case ESP_LOG_VERBOSE:
log_level_opt = 4;
break;
default:
log_level_opt = 2;
break;
}
// ************************* IMPORTANT *******************************************************************
// I am mallocing a char* inside generate_log_timestamp() function situated inside util.cpp, log_print_buffer is not being pushed to queue
// The function returns the malloc'd char* and is passed to the queue
//
send_to_queue(generate_log_message_timestamp(log_level_opt, esp_log_timestamp(), log_print_buffer));
//
//********************************************************************************************************
}
/**
* @brief route log messages generated by ESP_LOGX to the wifi logger
*
* @param fmt logger string format
* @param tag arguments
* @return int return value of vprintf
*/
int system_log_message_route(const char* fmt, va_list tag)
{
char *log_print_buffer = (char*) malloc(sizeof(char) * BUFFER_SIZE);
vsprintf(log_print_buffer, fmt, tag);
send_to_queue(log_print_buffer);
return vprintf(fmt, tag);
}
/**
* @brief wrapper function to start wifi logger
*
*/
void start_wifi_logger(void)
{
init_wifi();
ESP_ERROR_CHECK(init_queue());
#ifdef CONFIG_ROUTE_ESP_IDF_API_LOGS_TO_WIFI
esp_log_set_vprintf(system_log_message_route);
#endif
xTaskCreatePinnedToCore(&wifi_logger, "wifi_logger", 4096, NULL, 2, NULL, 1);
ESP_LOGI(tag_wifi_logger, "WiFi logger initialised");
}
/*
* @brief A common wrapper function to check connection status for all interfaces
*
* @param handle_t Interface handle
* @return bool True if connected
*/
bool is_connected(void* handle_t)
{
bool ret = false;
#ifdef CONFIG_TRANSPORT_PROTOCOL_WEBSOCKET
ret = esp_websocket_client_is_connected((esp_websocket_client_handle_t) handle_t);
#endif
#ifdef CONFIG_TRANSPORT_PROTOCOL_TCP
/* Technically ENOTCONN indicates socket is not connected but I think there is a bug
* Check out https://github.com/espressif/esp-idf/issues/6092 to follow the issue ticket raised
* Till then keeping the following check instead of just 0 == errno
**/
if (0 == errno || ENOTCONN == errno)
{
ret = true;
}
#endif
#ifdef CONFIG_TRANSPORT_PROTOCOL_UDP
ret = true;
#endif
return ret;
}
/**
* @brief function which handles sending of log messages to server by UDP
*
*/
#ifdef CONFIG_TRANSPORT_PROTOCOL_UDP
void wifi_logger()
{
struct network_data* handle = malloc(sizeof(struct network_data));
network_manager(handle);
while (true)
{
char* log_message = receive_from_queue();
if (log_message != NULL)
{
int len = send_data(handle, log_message);
ESP_LOGD(tag_wifi_logger, "%d %s", len, "bytes of data sent");
free((void*)log_message);
}
else
{
log_message = "Unknown error - receiving log message";
int len = send_data(handle, log_message);
ESP_LOGE(tag_wifi_logger, "%d %s", len, "Unknown error");
}
}
close_network_manager(handle);
}
#endif
/**
* @brief function which handles sending of log messages to server by TCP
*
*/
#ifdef CONFIG_TRANSPORT_PROTOCOL_TCP
void wifi_logger()
{
char* log_message;
while(1) // To keep trying over and over
{
while(1) // Try creating and connecting to socket
{
struct tcp_network_data* handle = malloc(sizeof(struct network_data));
if (false == tcp_network_manager(handle))
{
// Slow down while retrying.
vTaskDelay(2000 / portTICK_PERIOD_MS);
break;
}
while (is_connected(handle))
{
log_message = receive_from_queue();
if (log_message != NULL)
{
int len = tcp_send_data(handle, log_message);
if(len < 0)
{
/* Trying to push it back to queue if sending fails, but might lose some logs if frequency is high
* Might see garbage at first when reconnected.
*/
xQueueSendToFront(wifi_logger_queue, (void*)log_message, (TickType_t) portMAX_DELAY);
break;
}
ESP_LOGD(tag_wifi_logger, "%d %s", len, "bytes of data sent");
}
else
{
log_message = "Unknown error - receiving log message";
int len = tcp_send_data(handle, log_message);
ESP_LOGE(tag_wifi_logger, "%d %s", len, "Unknown error");
}
//Checkout following link to understand why we need this delay if want watchdog running.
//https://github.com/espressif/esp-idf/issues/1646#issuecomment-367507724
vTaskDelay(10 / portTICK_PERIOD_MS);
}
if (handle->sock != -1)
{
tcp_close_network_manager(handle);
}
}
}
}
#endif
#ifdef CONFIG_TRANSPORT_PROTOCOL_WEBSOCKET
void wifi_logger()
{
esp_websocket_client_handle_t handle = websocket_network_manager();
while (true)
{
if(is_connected(handle))
{
char* log_message = receive_from_queue();
if (log_message != NULL)
{
int len = websocket_send_data(handle, log_message);
if(len > 0)
{
ESP_LOGD(tag_wifi_logger, "%d %s", len, "bytes of data sent");
}
free((void*)log_message);
}
else
{
log_message = "Unknown error - log message corrupt";
int len = websocket_send_data(handle, log_message);
ESP_LOGE(tag_wifi_logger, "%d %s", len, "Unknown error");
}
}
else
{
//Checkout following link to understand why we need this delay if want watchdog running.
//https://github.com/espressif/esp-idf/issues/1646#issuecomment-367507724
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
websocket_close_network_manager(handle);
}
#endif