Initial commit: project docs and ignore rules
This commit is contained in:
302
error_handler.cpp
Normal file
302
error_handler.cpp
Normal file
@@ -0,0 +1,302 @@
|
||||
#include "error_handler.h"
|
||||
#include <cstring>
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <Arduino.h>
|
||||
#define SERIAL_PRINT(x) Serial.print(x)
|
||||
#define SERIAL_PRINTLN(x) Serial.println(x)
|
||||
#define GET_MILLIS() millis()
|
||||
#define DELAY_MS(x) delay(x)
|
||||
#else
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#define SERIAL_PRINT(x) printf("%s", (x))
|
||||
#define SERIAL_PRINTLN(x) printf("%s\n", (x))
|
||||
#define GET_MILLIS() (static_cast<unsigned long>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count()))
|
||||
#define DELAY_MS(x) std::this_thread::sleep_for(std::chrono::milliseconds(x))
|
||||
#endif
|
||||
|
||||
// Global error handler instance
|
||||
ErrorHandler errorHandler;
|
||||
|
||||
ErrorHandler::ErrorHandler() : error_index(0), logging_enabled(true) {
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
memset(error_history, 0, sizeof(error_history));
|
||||
}
|
||||
|
||||
void ErrorHandler::reportError(ErrorCode code, ErrorSeverity severity, const char* description) {
|
||||
// Update statistics
|
||||
stats.total_errors++;
|
||||
stats.last_error_time = GET_MILLIS();
|
||||
stats.last_error_code = code;
|
||||
|
||||
if (severity == SEVERITY_CRITICAL) {
|
||||
stats.critical_errors++;
|
||||
}
|
||||
|
||||
// Categorize errors
|
||||
switch (code) {
|
||||
case ERR_NFC_INIT_FAILED:
|
||||
case ERR_NFC_READ_FAILED:
|
||||
stats.nfc_errors++;
|
||||
break;
|
||||
case ERR_COMMUNICATION_TIMEOUT:
|
||||
case ERR_PAIRING_FAILED:
|
||||
case ERR_INVALID_MESSAGE:
|
||||
stats.communication_errors++;
|
||||
break;
|
||||
case ERR_SD_INIT_FAILED:
|
||||
case ERR_SD_WRITE_FAILED:
|
||||
stats.sd_errors++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Store in history
|
||||
ErrorEntry& entry = error_history[error_index];
|
||||
entry.code = code;
|
||||
entry.severity = severity;
|
||||
entry.timestamp = GET_MILLIS();
|
||||
|
||||
if (description) {
|
||||
strncpy(entry.description, description, sizeof(entry.description) - 1);
|
||||
entry.description[sizeof(entry.description) - 1] = '\0';
|
||||
} else {
|
||||
entry.description[0] = '\0';
|
||||
}
|
||||
|
||||
error_index = (error_index + 1) % MAX_ERROR_HISTORY;
|
||||
|
||||
// Log the error
|
||||
if (logging_enabled) {
|
||||
#ifdef ARDUINO
|
||||
Serial.print("[ERROR] Code: ");
|
||||
Serial.print(static_cast<int>(code));
|
||||
Serial.print(", Severity: ");
|
||||
Serial.print(static_cast<int>(severity));
|
||||
Serial.print(", Time: ");
|
||||
Serial.print(entry.timestamp);
|
||||
if (description) {
|
||||
Serial.print(", Desc: ");
|
||||
Serial.print(description);
|
||||
}
|
||||
Serial.println();
|
||||
#else
|
||||
printf("[ERROR] Code: %d, Severity: %d, Time: %lu",
|
||||
static_cast<int>(code), static_cast<int>(severity), entry.timestamp);
|
||||
if (description) {
|
||||
printf(", Desc: %s", description);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Attempt recovery for non-critical errors
|
||||
if (severity < SEVERITY_CRITICAL) {
|
||||
handleError(code);
|
||||
}
|
||||
}
|
||||
|
||||
void ErrorHandler::reportNFCError(const char* description) {
|
||||
reportError(ERR_NFC_READ_FAILED, SEVERITY_ERROR, description);
|
||||
}
|
||||
|
||||
void ErrorHandler::reportCommunicationError(const char* description) {
|
||||
reportError(ERR_COMMUNICATION_TIMEOUT, SEVERITY_WARNING, description);
|
||||
}
|
||||
|
||||
void ErrorHandler::reportSDError(const char* description) {
|
||||
reportError(ERR_SD_WRITE_FAILED, SEVERITY_WARNING, description);
|
||||
}
|
||||
|
||||
bool ErrorHandler::handleError(ErrorCode code) {
|
||||
switch (code) {
|
||||
case ERR_NFC_READ_FAILED:
|
||||
return attemptNFCRecovery();
|
||||
case ERR_COMMUNICATION_TIMEOUT:
|
||||
case ERR_PAIRING_FAILED:
|
||||
return attemptCommunicationRecovery();
|
||||
case ERR_SD_WRITE_FAILED:
|
||||
return attemptSDRecovery();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ErrorHandler::attemptNFCRecovery() {
|
||||
if (logging_enabled) {
|
||||
#ifdef ARDUINO
|
||||
Serial.println("[RECOVERY] Attempting NFC recovery...");
|
||||
#else
|
||||
printf("[RECOVERY] Attempting NFC recovery...\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
DELAY_MS(100);
|
||||
|
||||
// TODO: Implement actual NFC recovery logic
|
||||
return true; // Assume success for now
|
||||
}
|
||||
|
||||
bool ErrorHandler::attemptCommunicationRecovery() {
|
||||
if (logging_enabled) {
|
||||
#ifdef ARDUINO
|
||||
Serial.println("[RECOVERY] Attempting communication recovery...");
|
||||
#else
|
||||
printf("[RECOVERY] Attempting communication recovery...\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
DELAY_MS(500);
|
||||
|
||||
return true; // Assume success for now
|
||||
}
|
||||
|
||||
bool ErrorHandler::attemptSDRecovery() {
|
||||
if (logging_enabled) {
|
||||
#ifdef ARDUINO
|
||||
Serial.println("[RECOVERY] Attempting SD card recovery...");
|
||||
#else
|
||||
printf("[RECOVERY] Attempting SD card recovery...\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
DELAY_MS(200);
|
||||
|
||||
return true; // Assume success for now
|
||||
}
|
||||
|
||||
void ErrorHandler::clearErrors() {
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
memset(error_history, 0, sizeof(error_history));
|
||||
error_index = 0;
|
||||
|
||||
if (logging_enabled) {
|
||||
#ifdef ARDUINO
|
||||
Serial.println("[INFO] Error history cleared");
|
||||
#else
|
||||
printf("[INFO] Error history cleared\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ErrorStats ErrorHandler::getStats() const {
|
||||
return stats;
|
||||
}
|
||||
|
||||
bool ErrorHandler::hasRecentErrors(unsigned long time_window_ms) const {
|
||||
unsigned long current_time = GET_MILLIS();
|
||||
return (current_time - stats.last_error_time) < time_window_ms;
|
||||
}
|
||||
|
||||
bool ErrorHandler::hasCriticalErrors() const {
|
||||
return stats.critical_errors > 0;
|
||||
}
|
||||
|
||||
void ErrorHandler::printErrorHistory() const {
|
||||
if (!logging_enabled) return;
|
||||
|
||||
#ifdef ARDUINO
|
||||
Serial.println("=== Error History ===");
|
||||
for (int i = 0; i < MAX_ERROR_HISTORY; i++) {
|
||||
int idx = (error_index + i) % MAX_ERROR_HISTORY;
|
||||
const ErrorEntry& entry = error_history[idx];
|
||||
|
||||
if (entry.timestamp == 0) continue; // Empty entry
|
||||
|
||||
Serial.print("[");
|
||||
Serial.print(i + 1);
|
||||
Serial.print("] Code: ");
|
||||
Serial.print(static_cast<int>(entry.code));
|
||||
Serial.print(", Severity: ");
|
||||
Serial.print(static_cast<int>(entry.severity));
|
||||
Serial.print(", Time: ");
|
||||
Serial.print(entry.timestamp);
|
||||
if (entry.description[0] != '\0') {
|
||||
Serial.print(", Desc: ");
|
||||
Serial.print(entry.description);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println("===================");
|
||||
#else
|
||||
printf("=== Error History ===\n");
|
||||
for (int i = 0; i < MAX_ERROR_HISTORY; i++) {
|
||||
int idx = (error_index + i) % MAX_ERROR_HISTORY;
|
||||
const ErrorEntry& entry = error_history[idx];
|
||||
|
||||
if (entry.timestamp == 0) continue; // Empty entry
|
||||
|
||||
printf("[%d] Code: %d, Severity: %d, Time: %lu",
|
||||
i + 1, static_cast<int>(entry.code), static_cast<int>(entry.severity), entry.timestamp);
|
||||
if (entry.description[0] != '\0') {
|
||||
printf(", Desc: %s", entry.description);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("===================\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ErrorHandler::printStats() const {
|
||||
if (!logging_enabled) return;
|
||||
|
||||
#ifdef ARDUINO
|
||||
Serial.println("=== Error Statistics ===");
|
||||
Serial.print("Total Errors: ");
|
||||
Serial.println(stats.total_errors);
|
||||
Serial.print("Critical Errors: ");
|
||||
Serial.println(stats.critical_errors);
|
||||
Serial.print("NFC Errors: ");
|
||||
Serial.println(stats.nfc_errors);
|
||||
Serial.print("Communication Errors: ");
|
||||
Serial.println(stats.communication_errors);
|
||||
Serial.print("SD Errors: ");
|
||||
Serial.println(stats.sd_errors);
|
||||
Serial.print("Last Error Time: ");
|
||||
Serial.println(stats.last_error_time);
|
||||
Serial.print("Last Error Code: ");
|
||||
Serial.println(static_cast<int>(stats.last_error_code));
|
||||
Serial.println("========================");
|
||||
#else
|
||||
printf("=== Error Statistics ===\n");
|
||||
printf("Total Errors: %u\n", stats.total_errors);
|
||||
printf("Critical Errors: %u\n", stats.critical_errors);
|
||||
printf("NFC Errors: %u\n", stats.nfc_errors);
|
||||
printf("Communication Errors: %u\n", stats.communication_errors);
|
||||
printf("SD Errors: %u\n", stats.sd_errors);
|
||||
printf("Last Error Time: %u\n", stats.last_error_time);
|
||||
printf("Last Error Code: %d\n", static_cast<int>(stats.last_error_code));
|
||||
printf("========================\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ErrorHandler::enableLogging(bool enable) {
|
||||
logging_enabled = enable;
|
||||
}
|
||||
|
||||
void ErrorHandler::feedWatchdog() {
|
||||
// TODO: Implement watchdog feeding logic
|
||||
}
|
||||
|
||||
bool ErrorHandler::isSystemHealthy() const {
|
||||
// Check for critical errors
|
||||
if (hasCriticalErrors()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for recent errors (within 30 seconds)
|
||||
if (hasRecentErrors(30000)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check total error count threshold
|
||||
if (stats.total_errors > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user