This commit is contained in:
2025-10-06 18:27:50 +02:00
commit 3e191a4f60
213 changed files with 22261 additions and 0 deletions
+149
View File
@@ -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;
+68
View File
@@ -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__); }