1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 // Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1b, Real-time extensions
24 // (IEEE Std 1003.1b-1993) specification
26 // For this specific file, see use of clock_gettime,
27 // Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
28 // and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
29 #ifndef _POSIX_C_SOURCE
30 #define _POSIX_C_SOURCE 200809L
33 #include "iotivity_config.h"
35 // Pull in _POSIX_TIMERS feature test macro to check for
36 // clock_gettime() support.
41 #ifdef HAVE_ARDUINO_TIME_H
47 #ifdef HAVE_SYS_TIME_H
56 #include "logger_types.h"
59 LogLevel g_level = DEBUG;
61 bool g_hidePrivateLogEntries = false;
64 static oc_log_ctx_t *logCtx = 0;
68 #define LINE_BUFFER_SIZE (16 * 2) + 16 + 1 // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination
69 #define S_LINE_BUFFER_SIZE (50 * 2) + 50 + 1 // Show 50 bytes, 2 chars/byte, spaces between bytes, null termination
71 static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 + 1; // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination
72 static const uint16_t S_LINE_BUFFER_SIZE = (50 * 2) + 50 + 1; // Show 50 bytes, 2 chars/byte, spaces between bytes, null termination
73 #endif //defined(_MSC_VER)
75 #if defined(__ANDROID__) || defined(__TIZEN__)
76 #elif defined __linux__ || defined __APPLE__ || defined _WIN32 || defined(__TIZENRT__)
77 static oc_log_level LEVEL_XTABLE[] = {OC_LOG_DEBUG, OC_LOG_INFO,
78 OC_LOG_WARNING, OC_LOG_ERROR, OC_LOG_FATAL};
81 // Convert LogLevel to platform-specific severity level. Store in PROGMEM on Arduino
84 static const char *LEVEL[] =
85 {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
88 static android_LogPriority LEVEL[] =
89 {ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
91 #elif defined(__linux__) || defined(__APPLE__) || defined(__msys_nt__)|| defined(__TIZENRT__)
92 static const char * LEVEL[] __attribute__ ((unused)) = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
93 #elif defined(_MSC_VER)
94 static const char * LEVEL[] = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
98 #include "oic_string.h"
100 PROGMEM const char level0[] = "DEBUG";
101 PROGMEM const char level1[] = "INFO";
102 PROGMEM const char level2[] = "WARNING";
103 PROGMEM const char level3[] = "ERROR";
104 PROGMEM const char level4[] = "FATAL";
106 PROGMEM const char * const LEVEL[] = {level0, level1, level2, level3, level4};
108 static void OCLogString(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr);
109 #ifdef ARDUINO_ARCH_AVR
110 //Mega2560 and other 8-bit AVR microcontrollers
111 #define GET_PROGMEM_BUFFER(buffer, addr) { OICStrcpy(buffer, sizeof(buffer), (char*)pgm_read_word(addr));}
112 #elif defined ARDUINO_ARCH_SAM
113 //Arduino Due and other 32-bit ARM micro-controllers
114 #define GET_PROGMEM_BUFFER(buffer, addr) { OICStrcpy(buffer, sizeof(buffer), (char*)pgm_read_dword(addr));}
116 #define GET_PROGMEM_BUFFER(buffer, addr) { buffer[0] = '\0';}
118 #else // !defined(__ANDROID__) && !defined(ARDUINO)
119 static const char *LEVEL[] __attribute__ ((unused)) =
120 {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
126 * Output the contents of the specified buffer (in hex) with the specified priority level.
128 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
129 * @param tag - Module name
130 * @param buffer - pointer to buffer of bytes
131 * @param bufferSize - max number of byte in buffer
133 void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize)
135 if (!buffer || !tag || (bufferSize == 0))
140 // No idea why the static initialization won't work here, it seems the compiler is convinced
141 // that this is a variable-sized object.
142 char lineBuffer[LINE_BUFFER_SIZE];
143 memset(lineBuffer, 0, sizeof lineBuffer);
146 for (i = 0; i < bufferSize; i++)
148 // Format the buffer data into a line
149 snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]);
151 // Output 16 values per line
154 OCLogv(level, tag, "%s", lineBuffer);
155 memset(lineBuffer, 0, sizeof lineBuffer);
159 // Output last values in the line, if any
162 OCLogv(level, tag, "%s", lineBuffer);
166 void OCPrintCALogBuffer(LogLevel level, const char *tag, const uint8_t *buffer,
167 uint16_t bufferSize, uint8_t isHeader)
169 if (!buffer || !tag || (bufferSize == 0))
174 // No idea why the static initialization won't work here, it seems the compiler is convinced
175 // that this is a variable-sized object.
176 char lineBuffer[S_LINE_BUFFER_SIZE];
179 for (i = 0; i < bufferSize; i++)
181 // Format the buffer data into a line
182 snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]);
184 // Output 50 values per line
189 OCLogv(level, tag, "| Analyzer(Header) | %s", lineBuffer);
193 OCLogv(level, tag, "| Analyzer(Body) | %s", lineBuffer);
195 memset(lineBuffer, 0, sizeof lineBuffer);
204 OCLogv(level, tag, "| Analyzer(Header) | %s", lineBuffer);
208 OCLogv(level, tag, "| Analyzer(Body) | %s", lineBuffer);
213 void OCSetLogLevel(LogLevel level, bool hidePrivateLogEntries)
216 g_hidePrivateLogEntries = hidePrivateLogEntries;
219 bool OCGetPrivateLogLevel()
221 return g_hidePrivateLogEntries;
225 void OCLogConfig(oc_log_ctx_t *ctx)
237 #if defined(__linux__) || defined(__APPLE__) || defined(_WIN32)|| defined(__TIZENRT__)
238 if (logCtx && logCtx->destroy)
240 logCtx->destroy(logCtx);
246 * Output a variable argument list log string with the specified priority level.
247 * Only defined for Linux and Android
249 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
250 * @param tag - Module name
251 * @param format - variadic log string
253 void OCLogv(LogLevel level, const char * tag, const char * format, ...)
255 if (!format || !tag) {
259 if (g_level > level && ERROR != level && WARNING != level && FATAL != level)
264 if (true == g_hidePrivateLogEntries && INFO_PRIVATE == level)
269 char buffer[MAX_LOG_V_BUFFER_SIZE] = {0};
271 va_start(args, format);
272 vsnprintf(buffer, sizeof buffer - 1, format, args);
274 OCLog(level, tag, buffer);
278 * Output a log string with the specified priority level.
279 * Only defined for Linux and Android
281 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
282 * @param tag - Module name
283 * @param logStr - log string
285 void OCLog(LogLevel level, const char * tag, const char * logStr)
292 if (g_level > level && ERROR != level && WARNING != level && FATAL != level)
297 if (true == g_hidePrivateLogEntries && INFO_PRIVATE == level)
320 printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
322 __android_log_write(LEVEL[level], tag, logStr);
326 if (logCtx && logCtx->write_level)
328 logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr);
336 #if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
337 struct timespec when = { .tv_sec = 0, .tv_nsec = 0 };
338 clockid_t clk = CLOCK_REALTIME;
339 #ifdef CLOCK_REALTIME_COARSE
340 clk = CLOCK_REALTIME_COARSE;
342 if (!clock_gettime(clk, &when))
344 min = (when.tv_sec / 60) % 60;
345 sec = when.tv_sec % 60;
346 ms = when.tv_nsec / 1000000;
348 #elif defined(_WIN32)
349 SYSTEMTIME systemTime = {0};
350 GetLocalTime(&systemTime);
351 min = (int)systemTime.wMinute;
352 sec = (int)systemTime.wSecond;
353 ms = (int)systemTime.wMilliseconds;
356 if (!gettimeofday(&now, NULL))
358 min = (now.tv_sec / 60) % 60;
359 sec = now.tv_sec % 60;
360 ms = now.tv_usec * 1000;
363 printf("%02d:%02d.%03d %s: %s: %s\n", min, sec, ms, LEVEL[level], tag, logStr);
371 * Initialize the serial logger for Arduino
372 * Only defined for Arduino
376 Serial.begin(115200);
380 * Output a log string with the specified priority level.
381 * Only defined for Arduino. Only uses PROGMEM strings
382 * for the tag parameter
384 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
385 * @param tag - Module name
386 * @param logStr - log string
388 void OCLogString(LogLevel level, PROGMEM const char * tag, const char * logStr)
395 char buffer[LINE_BUFFER_SIZE];
397 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
398 Serial.print(buffer);
401 Serial.print(F(": "));
402 while ((c = pgm_read_byte(tag)))
407 Serial.print(F(": "));
409 Serial.println(logStr);
413 * Output the contents of the specified buffer (in hex) with the specified
416 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
417 * @param tag - Module name
418 * @param buffer - pointer to buffer of bytes
419 * @param bufferSize - max number of byte in buffer
421 void OCLogBuffer(LogLevel level, PROGMEM const char * tag,
422 const uint8_t * buffer, size_t bufferSize)
424 if (!buffer || !tag || (bufferSize == 0))
429 char lineBuffer[LINE_BUFFER_SIZE] = {0};
430 uint8_t lineIndex = 0;
431 for (uint8_t i = 0; i < bufferSize; i++)
433 // Format the buffer data into a line
434 snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]);
436 // Output 16 values per line
439 OCLogString(level, tag, lineBuffer);
440 memset(lineBuffer, 0, sizeof lineBuffer);
444 // Output last values in the line, if any
447 OCLogString(level, tag, lineBuffer);
452 * Output a log string with the specified priority level.
453 * Only defined for Arduino. Uses PROGMEM strings
455 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
456 * @param tag - Module name
457 * @param logStr - log string
459 void OCLog(LogLevel level, PROGMEM const char *tag, const int lineNum,
460 PROGMEM const char *logStr)
466 char buffer[LINE_BUFFER_SIZE] = {0};
467 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
468 Serial.print(buffer);
470 Serial.print(F(": "));
471 while ((c = pgm_read_byte(tag)))
476 Serial.print(F(": "));
477 Serial.print(lineNum);
478 Serial.print(F(": "));
479 while ((c = pgm_read_byte(logStr)))
488 * Output a variable argument list log string with the specified priority level.
489 * Only defined for Arduino as depicted below.
491 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
492 * @param tag - Module name
493 * @param format - variadic log string
495 void OCLogv(LogLevel level, PROGMEM const char *tag, const int lineNum,
496 PROGMEM const char *format, ...)
498 char buffer[LINE_BUFFER_SIZE];
500 va_start(ap, format);
501 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
502 Serial.print(buffer);
505 Serial.print(F(": "));
506 while ((c = pgm_read_byte(tag)))
511 Serial.print(F(": "));
512 Serial.print(lineNum);
513 Serial.print(F(": "));
516 vsnprintf_P(buffer, sizeof(buffer), format, ap);
518 vsnprintf(buffer, sizeof(buffer), format, ap);
520 for (char *p = &buffer[0]; *p; p++)
522 // emulate cooked mode for newlines
533 * Output a variable argument list log string with the specified priority level.
534 * Only defined for Arduino as depicted below.
536 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
537 * @param tag - Module name
538 * @param format - variadic log string
540 void OCLogv(LogLevel level, const char *tag, const __FlashStringHelper *format, ...)
542 char buffer[LINE_BUFFER_SIZE];
544 va_start(ap, format);
545 // strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
546 // Serial.print(buffer);
548 Serial.print(LEVEL[level]);
550 Serial.print(F(": "));
552 /*while ((c = pgm_read_byte(tag))) {
557 Serial.print(F(": "));
560 vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR
562 vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world
564 for (char *p = &buffer[0]; *p; p++)
566 // emulate cooked mode for newlines
569 // Serial.write('\r');