diff --git a/examples/platformio-basic/src/main.cpp b/examples/platformio-basic/src/main.cpp index 0a87923..b4e6338 100644 --- a/examples/platformio-basic/src/main.cpp +++ b/examples/platformio-basic/src/main.cpp @@ -23,13 +23,13 @@ String stringValue1 = "this is a string"; float floatValue; double doubleValue; -void printTimestamp(Print *_logOutput) { +void printTimestamp(Print *_logOutput, int) { char c[12]; int m = sprintf(c, "%10lu ", millis()); _logOutput->print(c); } -void printCarret(Print *_logOutput) { _logOutput->print('>'); } +void printCarret(Print *_logOutput, int) { _logOutput->print('>'); } void setup() { // Set up serial port and wait until connected diff --git a/src/ArduinoLog.cpp b/src/ArduinoLog.cpp index d2f27a0..fccf09a 100644 --- a/src/ArduinoLog.cpp +++ b/src/ArduinoLog.cpp @@ -13,7 +13,7 @@ Logging::Logging() #ifndef DISABLE_LOGGING - : _level(LOG_LEVEL_SILENT), + : _level(ArduinoLogLevel::LogLevelSilent), _showLevel(true), _showColors(false), _handlerCount(0) @@ -26,7 +26,17 @@ Logging::Logging() {} #endif -void Logging::begin(int level, Print* logOutput, bool showLevel, bool showColors) { +// Static helper function to constrain int values to valid enum range +ArduinoLogLevel Logging::constrainLevel(int level) { + if (level < static_cast(ArduinoLogLevel::LogLevelSilent)) { + return ArduinoLogLevel::LogLevelSilent; + } else if (level > static_cast(ArduinoLogLevel::LogLevelVerbose)) { + return ArduinoLogLevel::LogLevelVerbose; + } + return static_cast(level); +} + +void Logging::begin(ArduinoLogLevel level, Print* logOutput, bool showLevel, bool showColors) { #ifndef DISABLE_LOGGING setLevel(level); setShowLevel(showLevel); @@ -45,15 +55,34 @@ void Logging::begin(int level, Print* logOutput, bool showLevel, bool showColors #endif } +// Backward compatibility: int overload +void Logging::begin(int level, Print *logOutput, bool showLevel, bool showColors) { + begin(constrainLevel(level), logOutput, showLevel, showColors); +} + +void Logging::setLevel(ArduinoLogLevel level) { +#ifndef DISABLE_LOGGING + _level = level; +#endif +} + +// Backward compatibility: int overload void Logging::setLevel(int level) { + setLevel(constrainLevel(level)); +} + +ArduinoLogLevel Logging::getLogLevel() const { #ifndef DISABLE_LOGGING - _level = constrain(level, LOG_LEVEL_SILENT, LOG_LEVEL_VERBOSE); + return _level; +#else + return ArduinoLogLevel::LogLevelSilent; #endif } +// Backward compatibility: return level as int int Logging::getLevel() const { #ifndef DISABLE_LOGGING - return _level; + return static_cast(_level); #else return 0; #endif @@ -279,16 +308,6 @@ void Logging::printFormat(const char format, va_list *args) { #endif } -#ifndef DISABLE_LOGGING -template void Logging::writeLog(Args... args) { - for (int i = 0; i < _handlerCount; i++) { - if (_logOutputs[i]) { - _logOutputs[i]->print(args...); - } - } -} -#endif - #ifndef __DO_NOT_INSTANTIATE__ Logging Log = Logging(); #endif diff --git a/src/ArduinoLog.h b/src/ArduinoLog.h index 71b82e1..3af509b 100644 --- a/src/ArduinoLog.h +++ b/src/ArduinoLog.h @@ -46,14 +46,61 @@ typedef void (*printfunction)(Print*, int); // ************************************************************************ //#define DISABLE_LOGGING -#define LOG_LEVEL_SILENT 0 -#define LOG_LEVEL_FATAL 1 -#define LOG_LEVEL_ERROR 2 -#define LOG_LEVEL_WARNING 3 -#define LOG_LEVEL_INFO 4 -#define LOG_LEVEL_NOTICE 4 -#define LOG_LEVEL_TRACE 5 -#define LOG_LEVEL_VERBOSE 6 +enum class ArduinoLogLevel : unsigned char { + LogLevelSilent = 0, + LogLevelFatal = 1, + LogLevelError = 2, + LogLevelWarning = 3, + LogLevelInfo = 4, + LogLevelNotice = 4, // Same as INFO, kept for backward compatibility + LogLevelTrace = 5, + LogLevelVerbose = 6 +}; + +// Save existing macro definitions if they exist, then undefine them temporarily +// This allows us to use our own LOG_LEVEL_* constants while preserving any +// previously defined macros from other libraries (e.g. NimBLE) +#ifdef LOG_LEVEL_SILENT +#define ARDUINOLOG_SAVED_LOG_LEVEL_SILENT LOG_LEVEL_SILENT +#undef LOG_LEVEL_SILENT +#endif +#ifdef LOG_LEVEL_FATAL +#define ARDUINOLOG_SAVED_LOG_LEVEL_FATAL LOG_LEVEL_FATAL +#undef LOG_LEVEL_FATAL +#endif +#ifdef LOG_LEVEL_ERROR +#define ARDUINOLOG_SAVED_LOG_LEVEL_ERROR LOG_LEVEL_ERROR +#undef LOG_LEVEL_ERROR +#endif +#ifdef LOG_LEVEL_WARNING +#define ARDUINOLOG_SAVED_LOG_LEVEL_WARNING LOG_LEVEL_WARNING +#undef LOG_LEVEL_WARNING +#endif +#ifdef LOG_LEVEL_INFO +#define ARDUINOLOG_SAVED_LOG_LEVEL_INFO LOG_LEVEL_INFO +#undef LOG_LEVEL_INFO +#endif +#ifdef LOG_LEVEL_NOTICE +#define ARDUINOLOG_SAVED_LOG_LEVEL_NOTICE LOG_LEVEL_NOTICE +#undef LOG_LEVEL_NOTICE +#endif +#ifdef LOG_LEVEL_TRACE +#define ARDUINOLOG_SAVED_LOG_LEVEL_TRACE LOG_LEVEL_TRACE +#undef LOG_LEVEL_TRACE +#endif +#ifdef LOG_LEVEL_VERBOSE +#define ARDUINOLOG_SAVED_LOG_LEVEL_VERBOSE LOG_LEVEL_VERBOSE +#undef LOG_LEVEL_VERBOSE +#endif + +// ArduinoLog maintains these names for backward compatibility +constexpr ArduinoLogLevel LOG_LEVEL_FATAL = ArduinoLogLevel::LogLevelFatal; +constexpr ArduinoLogLevel LOG_LEVEL_ERROR = ArduinoLogLevel::LogLevelError; +constexpr ArduinoLogLevel LOG_LEVEL_WARNING = ArduinoLogLevel::LogLevelWarning; +constexpr ArduinoLogLevel LOG_LEVEL_INFO = ArduinoLogLevel::LogLevelInfo; +constexpr ArduinoLogLevel LOG_LEVEL_NOTICE = ArduinoLogLevel::LogLevelNotice; +constexpr ArduinoLogLevel LOG_LEVEL_TRACE = ArduinoLogLevel::LogLevelTrace; +constexpr ArduinoLogLevel LOG_LEVEL_VERBOSE = ArduinoLogLevel::LogLevelVerbose; #define LOG_COLOR_BOLD_RED F("\033[1;31m") #define LOG_COLOR_BOLD_WHITE F("\033[1;37m") @@ -120,6 +167,18 @@ class Logging { * \return void * */ + void begin(ArduinoLogLevel level, Print *output, bool showLevel = true, + bool showColors = false); + + /** + * Backward compatibility: Initializing with int level + * + * \param level - logging levels <= this will be logged (as integer). + * \param output - place that logging output will be sent to. + * \param showLevel - if true, the level will be shown in the output. + * \param showColors - if true, the color will be shown in the output. + * \return void + */ void begin(int level, Print *output, bool showLevel = true, bool showColors = false); /** @@ -128,6 +187,14 @@ class Logging { * \param level - The new log level. * \return void */ + void setLevel(ArduinoLogLevel level); + + /** + * Backward compatibility: Set the log level with int + * + * \param level - The new log level (as integer). + * \return void + */ void setLevel(int level); /** @@ -135,6 +202,13 @@ class Logging { * * \return The current log level. */ + ArduinoLogLevel getLogLevel() const; + + /** + * Backward compatibility: Get the log level as int + * + * \return The current log level as integer. + */ int getLevel() const; /** @@ -224,13 +298,13 @@ class Logging { */ template void fatal(T msg, Args... args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_FATAL, false, msg, args...); + printLevel(ArduinoLogLevel::LogLevelFatal, false, msg, args...); #endif } template void fatalln(T msg, Args... args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_FATAL, true, msg, args...); + printLevel(ArduinoLogLevel::LogLevelFatal, true, msg, args...); #endif } @@ -246,13 +320,13 @@ class Logging { */ template void error(T msg, Args... args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_ERROR, false, msg, args...); + printLevel(ArduinoLogLevel::LogLevelError, false, msg, args...); #endif } template void errorln(T msg, Args... args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_ERROR, true, msg, args...); + printLevel(ArduinoLogLevel::LogLevelError, true, msg, args...); #endif } @@ -268,13 +342,13 @@ class Logging { */ template void warning(T msg, Args...args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_WARNING, false, msg, args...); + printLevel(ArduinoLogLevel::LogLevelWarning, false, msg, args...); #endif } template void warningln(T msg, Args...args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_WARNING, true, msg, args...); + printLevel(ArduinoLogLevel::LogLevelWarning, true, msg, args...); #endif } @@ -290,25 +364,25 @@ class Logging { */ template void notice(T msg, Args...args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_NOTICE, false, msg, args...); + printLevel(ArduinoLogLevel::LogLevelNotice, false, msg, args...); #endif } template void noticeln(T msg, Args...args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_NOTICE, true, msg, args...); + printLevel(ArduinoLogLevel::LogLevelNotice, true, msg, args...); #endif } template void info(T msg, Args...args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_INFO, false, msg, args...); + printLevel(ArduinoLogLevel::LogLevelInfo, false, msg, args...); #endif } template void infoln(T msg, Args...args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_INFO, true, msg, args...); + printLevel(ArduinoLogLevel::LogLevelInfo, true, msg, args...); #endif } @@ -324,13 +398,13 @@ class Logging { */ template void trace(T msg, Args... args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_TRACE, false, msg, args...); + printLevel(ArduinoLogLevel::LogLevelTrace, false, msg, args...); #endif } template void traceln(T msg, Args... args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_TRACE, true, msg, args...); + printLevel(ArduinoLogLevel::LogLevelTrace, true, msg, args...); #endif } @@ -346,17 +420,20 @@ class Logging { */ template void verbose(T msg, Args... args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_VERBOSE, false, msg, args...); + printLevel(ArduinoLogLevel::LogLevelVerbose, false, msg, args...); #endif } template void verboseln(T msg, Args... args) { #ifndef DISABLE_LOGGING - printLevel(LOG_LEVEL_VERBOSE, true, msg, args...); + printLevel(ArduinoLogLevel::LogLevelVerbose, true, msg, args...); #endif } -private: + private: + // Static helper function to constrain int values to valid enum range + static ArduinoLogLevel constrainLevel(int level); + void print(const char *format, va_list args); void print(const __FlashStringHelper *format, va_list args); @@ -373,13 +450,13 @@ class Logging { void printFormat(const char format, va_list *args); - template void printLevel(int level, bool cr, T msg, ...) { + template void printLevel(ArduinoLogLevel level, bool cr, T msg, ...) { #ifndef DISABLE_LOGGING if (level > _level) { return; } - if (level < LOG_LEVEL_SILENT) { - level = LOG_LEVEL_SILENT; + if (level < ArduinoLogLevel::LogLevelSilent) { + level = ArduinoLogLevel::LogLevelSilent; } #ifdef ESP32 @@ -387,13 +464,13 @@ class Logging { #endif if (_showColors) { switch (level) { - case LOG_LEVEL_FATAL: + case ArduinoLogLevel::LogLevelFatal: writeLog(LOG_COLOR_BOLD_RED); break; - case LOG_LEVEL_ERROR: + case ArduinoLogLevel::LogLevelError: writeLog(LOG_COLOR_RED); break; - case LOG_LEVEL_WARNING: + case ArduinoLogLevel::LogLevelWarning: writeLog(LOG_COLOR_YELLOW); break; default: @@ -404,14 +481,14 @@ class Logging { if (_prefix != NULL && _showLevel) { for (int i = 0; i < _handlerCount; i++) { if (_logOutputs[i]) { - _prefix(_logOutputs[i], level); + _prefix(_logOutputs[i], static_cast(level)); } } } if (_showLevel) { static const char levels[] = "FEWITV"; - writeLog(levels[level - 1]); + writeLog(levels[static_cast(level) - 1]); writeLog(": "); } @@ -422,7 +499,7 @@ class Logging { if (_suffix != NULL && _showLevel) { for (int i = 0; i < _handlerCount; i++) { if (_logOutputs[i]) { - _suffix(_logOutputs[i], level); + _suffix(_logOutputs[i], static_cast(level)); } } } @@ -444,13 +521,21 @@ class Logging { } #ifndef DISABLE_LOGGING - int _level; + ArduinoLogLevel _level; bool _showLevel; bool _showColors; Print* _logOutputs[LOG_MAX_HANDLERS]; int _handlerCount; - template void writeLog(Args... args); +#ifndef DISABLE_LOGGING + template void writeLog(Args... args) { + for (int i = 0; i < _handlerCount; i++) { + if (_logOutputs[i]) { + _logOutputs[i]->print(args...); + } + } + } +#endif #ifdef ESP32 SemaphoreHandle_t _semaphore; #endif @@ -463,4 +548,39 @@ class Logging { #ifndef __DO_NOT_INSTANTIATE__ extern Logging Log; #endif + +// Restore previously defined macros if they existed +#ifdef ARDUINOLOG_SAVED_LOG_LEVEL_SILENT +#define LOG_LEVEL_SILENT ARDUINOLOG_SAVED_LOG_LEVEL_SILENT +#undef ARDUINOLOG_SAVED_LOG_LEVEL_SILENT +#endif +#ifdef ARDUINOLOG_SAVED_LOG_LEVEL_FATAL +#define LOG_LEVEL_FATAL ARDUINOLOG_SAVED_LOG_LEVEL_FATAL +#undef ARDUINOLOG_SAVED_LOG_LEVEL_FATAL +#endif +#ifdef ARDUINOLOG_SAVED_LOG_LEVEL_ERROR +#define LOG_LEVEL_ERROR ARDUINOLOG_SAVED_LOG_LEVEL_ERROR +#undef ARDUINOLOG_SAVED_LOG_LEVEL_ERROR +#endif +#ifdef ARDUINOLOG_SAVED_LOG_LEVEL_WARNING +#define LOG_LEVEL_WARNING ARDUINOLOG_SAVED_LOG_LEVEL_WARNING +#undef ARDUINOLOG_SAVED_LOG_LEVEL_WARNING +#endif +#ifdef ARDUINOLOG_SAVED_LOG_LEVEL_INFO +#define LOG_LEVEL_INFO ARDUINOLOG_SAVED_LOG_LEVEL_INFO +#undef ARDUINOLOG_SAVED_LOG_LEVEL_INFO +#endif +#ifdef ARDUINOLOG_SAVED_LOG_LEVEL_NOTICE +#define LOG_LEVEL_NOTICE ARDUINOLOG_SAVED_LOG_LEVEL_NOTICE +#undef ARDUINOLOG_SAVED_LOG_LEVEL_NOTICE +#endif +#ifdef ARDUINOLOG_SAVED_LOG_LEVEL_TRACE +#define LOG_LEVEL_TRACE ARDUINOLOG_SAVED_LOG_LEVEL_TRACE +#undef ARDUINOLOG_SAVED_LOG_LEVEL_TRACE +#endif +#ifdef ARDUINOLOG_SAVED_LOG_LEVEL_VERBOSE +#define LOG_LEVEL_VERBOSE ARDUINOLOG_SAVED_LOG_LEVEL_VERBOSE +#undef ARDUINOLOG_SAVED_LOG_LEVEL_VERBOSE +#endif + #endif \ No newline at end of file