Initial commit: project docs and ignore rules

This commit is contained in:
Dr Jones
2026-05-03 23:20:16 -07:00
commit 8c372c3cb0
8 changed files with 1177 additions and 0 deletions

302
error_handler.cpp Normal file
View 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;
}