init
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
#include "logger.hpp"
|
||||
#include <Arduino.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h> // For va_list, vsnprintf
|
||||
#include <sys/time.h>
|
||||
|
||||
Logger::Logger()
|
||||
: logCount(0), logIndex(0), currentLogLevel(LOG_INFO),
|
||||
logCallback(nullptr), logQueue(nullptr), logTaskHandle(nullptr) {}
|
||||
|
||||
Logger::~Logger() {
|
||||
// Clean up FreeRTOS objects
|
||||
if (logTaskHandle) vTaskDelete(logTaskHandle);
|
||||
if (logQueue) vQueueDelete(logQueue);
|
||||
}
|
||||
|
||||
void Logger::begin(UBaseType_t taskPriority, uint32_t taskStackSize) {
|
||||
// Create a queue that can hold up to 10 LogEntry items.
|
||||
logQueue = xQueueCreate(10, sizeof(LogEntry));
|
||||
|
||||
if (logQueue == nullptr) {
|
||||
Serial.println("FATAL: Failed to create logger queue!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the background task. It passes 'this' so the static function
|
||||
// can access the instance's members.
|
||||
xTaskCreate(
|
||||
logProcessingTask,
|
||||
"LoggerTask",
|
||||
taskStackSize,
|
||||
this, // Pass the current object instance to the task
|
||||
taskPriority,
|
||||
&logTaskHandle
|
||||
);
|
||||
|
||||
if (logTaskHandle == nullptr) {
|
||||
Serial.println("FATAL: Failed to create logger task!");
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::addLog(LogLevel level, const char* format, va_list args) {
|
||||
if (level < currentLogLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
LogEntry entry;
|
||||
entry.level = level;
|
||||
|
||||
// Verwende Systemzeit statt millis()
|
||||
struct timeval tv;
|
||||
if (gettimeofday(&tv, nullptr) != 0) {
|
||||
LOG_ERROR("Failed to get system time for log entry");
|
||||
entry.timestamp = 0; // Fallback-Wert
|
||||
} else {
|
||||
entry.timestamp = tv.tv_sec; // Unix-Timestamp in Sekunden
|
||||
}
|
||||
|
||||
vsnprintf(entry.message, sizeof(entry.message), format, args);
|
||||
|
||||
// Add to internal circular buffer for history
|
||||
logs[logIndex] = entry;
|
||||
logIndex = (logIndex + 1) % MAX_LOGS;
|
||||
if (logCount < MAX_LOGS) {
|
||||
logCount++;
|
||||
}
|
||||
|
||||
if (logQueue != nullptr) {
|
||||
xQueueSend(logQueue, &entry, pdMS_TO_TICKS(10));
|
||||
}
|
||||
}
|
||||
|
||||
// This is the function that runs in its own task.
|
||||
void Logger::logProcessingTask(void* instance) {
|
||||
// The instance pointer is the 'this' we passed in xTaskCreate.
|
||||
Logger* loggerInstance = static_cast<Logger*>(instance);
|
||||
LogEntry entryToProcess;
|
||||
|
||||
while (true) {
|
||||
if (xQueueReceive(loggerInstance->logQueue, &entryToProcess, portMAX_DELAY) == pdPASS) {
|
||||
if (loggerInstance->logCallback) {
|
||||
loggerInstance->logCallback(entryToProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::setLogLevel(LogLevel level) {
|
||||
currentLogLevel = level;
|
||||
}
|
||||
|
||||
LogLevel Logger::getLogLevel() const {
|
||||
return currentLogLevel;
|
||||
}
|
||||
|
||||
void Logger::setLogCallback(std::function<void(const LogEntry& entry)> callback) {
|
||||
logCallback = callback;
|
||||
}
|
||||
|
||||
// --- NEW: Public methods now handle the variable arguments ---
|
||||
void Logger::debug(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
addLog(LOG_DEBUG, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::info(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
addLog(LOG_INFO, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::warn(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
addLog(LOG_WARN, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::error(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
addLog(LOG_ERROR, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
const LogEntry* Logger::getLogs(int& count) const {
|
||||
count = logCount;
|
||||
return logs;
|
||||
}
|
||||
|
||||
void Logger::clear() {
|
||||
logCount = 0;
|
||||
logIndex = 0;
|
||||
}
|
||||
|
||||
const char* Logger::levelToString(LogLevel level) const {
|
||||
switch (level) {
|
||||
case LOG_DEBUG: return "D";
|
||||
case LOG_INFO: return "I";
|
||||
case LOG_WARN: return "W";
|
||||
case LOG_ERROR: return "E";
|
||||
default: return "U";
|
||||
}
|
||||
}
|
||||
|
||||
Logger logger;
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <functional> // For std::function
|
||||
#include <cstdarg>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
|
||||
enum LogLevel {
|
||||
LOG_DEBUG,
|
||||
LOG_INFO,
|
||||
LOG_WARN,
|
||||
LOG_ERROR
|
||||
};
|
||||
|
||||
struct LogEntry {
|
||||
LogLevel level;
|
||||
time_t timestamp;
|
||||
char message[128];
|
||||
};
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
Logger();
|
||||
~Logger();
|
||||
|
||||
void begin(UBaseType_t taskPriority = 1, uint32_t taskStackSize = 2048);
|
||||
|
||||
void setLogLevel(LogLevel level);
|
||||
LogLevel getLogLevel() const;
|
||||
|
||||
// Use the more flexible std::function for callbacks
|
||||
void setLogCallback(std::function<void(const LogEntry& entry)> callback);
|
||||
|
||||
// --- NEW: Variadic functions for printf-style formatting ---
|
||||
void debug(const char* format, ...);
|
||||
void info(const char* format, ...);
|
||||
void warn(const char* format, ...);
|
||||
void error(const char* format, ...);
|
||||
|
||||
const LogEntry* getLogs(int& count) const;
|
||||
void clear();
|
||||
const char* levelToString(LogLevel level) const;
|
||||
|
||||
private:
|
||||
static const int MAX_LOGS = 20;
|
||||
LogEntry logs[MAX_LOGS];
|
||||
int logCount;
|
||||
int logIndex;
|
||||
LogLevel currentLogLevel;
|
||||
|
||||
std::function<void(const LogEntry& entry)> logCallback;
|
||||
|
||||
QueueHandle_t logQueue;
|
||||
TaskHandle_t logTaskHandle;
|
||||
static void logProcessingTask(void* instance);
|
||||
void addLog(LogLevel level, const char* format, va_list args);
|
||||
};
|
||||
|
||||
extern Logger logger;
|
||||
|
||||
// --- OPTIONAL: Performance-enhancing macros ---
|
||||
#define LOG_DEBUG(format, ...) if(logger.getLogLevel() <= LOG_DEBUG) { logger.debug(format, ##__VA_ARGS__); }
|
||||
#define LOG_INFO(format, ...) if(logger.getLogLevel() <= LOG_INFO) { logger.info(format, ##__VA_ARGS__); }
|
||||
#define LOG_WARN(format, ...) if(logger.getLogLevel() <= LOG_WARN) { logger.warn(format, ##__VA_ARGS__); }
|
||||
#define LOG_ERROR(format, ...) if(logger.getLogLevel() <= LOG_ERROR) { logger.error(format, ##__VA_ARGS__); }
|
||||
Reference in New Issue
Block a user