#include "error_handler.h" #include #ifdef ARDUINO #include #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 #include #include #include #define SERIAL_PRINT(x) printf("%s", (x)) #define SERIAL_PRINTLN(x) printf("%s\n", (x)) #define GET_MILLIS() (static_cast(std::chrono::duration_cast(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(code)); Serial.print(", Severity: "); Serial.print(static_cast(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(code), static_cast(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(entry.code)); Serial.print(", Severity: "); Serial.print(static_cast(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(entry.code), static_cast(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(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(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; }