test_log.h (1824B)
1 #pragma once 2 // Test-mode CSV logger — a minimal append-only log over LittleFS, used by TEST 3 // MODE (toggled in the OPTIONS menu) to capture diagnostics for later analysis. 4 // Each instance owns one file: it appends one preformatted CSV line per sample 5 // (flushed immediately by closing, so a brownout can't eat the tail), writes its 6 // header lazily on the first line, caps the file by byte size (a safety valve so 7 // a forgotten test badge can't fill flash), and can dump itself to a Stream. The 8 // sampling CADENCE lives in the caller — this is just persistence + retrieval. 9 // Adding a new metric = a new TestLog instance; that's the whole "room for more". 10 #include <Arduino.h> 11 #include <LittleFS.h> 12 #include "config.h" 13 14 #ifndef TEST_LOG_MAX_BYTES 15 #define TEST_LOG_MAX_BYTES 65536 16 #endif 17 18 class TestLog { 19 public: 20 TestLog(const char* path, const char* header) : _path(path), _header(header) {} 21 22 // Append a CSV line (no trailing newline needed). Lazily writes the header to a 23 // new/empty file; stops silently once the byte cap is reached. 24 void append(const char* line) { 25 File f = LittleFS.open(_path, "a"); 26 if (!f) return; 27 if (f.size() == 0) f.println(_header); 28 if (f.size() < TEST_LOG_MAX_BYTES) f.println(line); 29 f.close(); 30 } 31 32 // Dump the whole file to `out` — the retrieval path: plug in USB, read serial. 33 void dump(Stream& out) const { 34 out.print("==== "); out.print(_path); out.println(" ===="); 35 File f = LittleFS.open(_path, "r"); 36 if (!f) { out.println("(none)"); return; } 37 while (f.available()) out.write(f.read()); 38 f.close(); 39 out.println("==== end ===="); 40 } 41 42 // Start a fresh capture (called when test mode is enabled). 43 void reset() { LittleFS.remove(_path); } 44 45 private: 46 const char* _path; 47 const char* _header; 48 };