Image for T-Beam is in good working shape, restructuring the Perl data importer to deal with the 44 columns using hashes rather than positions
This commit is contained in:
parent
e28ebe5b17
commit
d3043533ce
9 changed files with 174 additions and 41 deletions
|
|
@ -38,6 +38,10 @@
|
|||
#define GPS_TX_PIN 8
|
||||
#endif
|
||||
|
||||
#ifndef BUTTON_PIN
|
||||
#define BUTTON_PIN 0
|
||||
#endif
|
||||
|
||||
#ifndef FW_BUILD_UTC
|
||||
#define FW_BUILD_UTC unknown
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void DisplayManager::showError(const char* line1, const char* line2) {
|
|||
drawLines(kExerciseName, "ERROR", line1, line2);
|
||||
}
|
||||
|
||||
void DisplayManager::showSample(const GnssSample& sample, const RunStats& stats) {
|
||||
void DisplayManager::showSample(const GnssSample& sample, const RunStats& stats, bool recording) {
|
||||
char l1[24];
|
||||
char l2[20];
|
||||
char l3[20];
|
||||
|
|
@ -56,7 +56,7 @@ void DisplayManager::showSample(const GnssSample& sample, const RunStats& stats)
|
|||
char l5[20];
|
||||
char l6[20];
|
||||
|
||||
snprintf(l1, sizeof(l1), "%s %.5s", __DATE__, __TIME__);
|
||||
snprintf(l1, sizeof(l1), "%s", recording ? "*RECORDING" : "Halted");
|
||||
snprintf(l2, sizeof(l2), "FIX: %s", fixTypeToString(sample.fixType));
|
||||
snprintf(l3, sizeof(l3), "USED: %d/%d", sample.satsUsed < 0 ? 0 : sample.satsUsed, sample.satsInView < 0 ? 0 : sample.satsInView);
|
||||
if (sample.validHdop) {
|
||||
|
|
@ -70,4 +70,3 @@ void DisplayManager::showSample(const GnssSample& sample, const RunStats& stats)
|
|||
}
|
||||
|
||||
} // namespace field_qa
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class DisplayManager {
|
|||
void begin();
|
||||
void showBoot(const char* line2, const char* line3 = nullptr);
|
||||
void showError(const char* line1, const char* line2 = nullptr);
|
||||
void showSample(const GnssSample& sample, const RunStats& stats);
|
||||
void showSample(const GnssSample& sample, const RunStats& stats, bool recording);
|
||||
|
||||
private:
|
||||
void drawLines(const char* l1,
|
||||
|
|
@ -26,4 +26,3 @@ class DisplayManager {
|
|||
};
|
||||
|
||||
} // namespace field_qa
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ bool StorageManager::startLog(const char* runId, const char* bootTimestampUtc) {
|
|||
m_ready = false;
|
||||
m_lastError = "";
|
||||
m_path = makeFilePath(runId);
|
||||
m_newFile = !SD.exists(m_path.c_str());
|
||||
if (!ensureDir() || !openFile()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -148,10 +149,24 @@ bool StorageManager::ensureDir() {
|
|||
}
|
||||
|
||||
String StorageManager::makeFilePath(const char* runId) const {
|
||||
char path[96];
|
||||
char basePath[96];
|
||||
char candidatePath[112];
|
||||
const char* rid = (runId && runId[0] != '\0') ? runId : "run";
|
||||
snprintf(path, sizeof(path), "%s/%s.csv", kLogDir, rid);
|
||||
return String(path);
|
||||
snprintf(basePath, sizeof(basePath), "%s/%s", kLogDir, rid);
|
||||
snprintf(candidatePath, sizeof(candidatePath), "%s.csv", basePath);
|
||||
if (!SD.exists(candidatePath)) {
|
||||
return String(candidatePath);
|
||||
}
|
||||
|
||||
for (uint16_t suffix = 2; suffix < 1000; ++suffix) {
|
||||
snprintf(candidatePath, sizeof(candidatePath), "%s_%02u.csv", basePath, (unsigned)suffix);
|
||||
if (!SD.exists(candidatePath)) {
|
||||
return String(candidatePath);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(candidatePath, sizeof(candidatePath), "%s_overflow.csv", basePath);
|
||||
return String(candidatePath);
|
||||
}
|
||||
|
||||
bool StorageManager::openFile() {
|
||||
|
|
@ -164,7 +179,7 @@ bool StorageManager::openFile() {
|
|||
}
|
||||
|
||||
void StorageManager::writeHeader(const char* runId, const char* bootTimestampUtc) {
|
||||
if (!m_file || m_file.size() > 0) {
|
||||
if (!m_file || !m_newFile) {
|
||||
return;
|
||||
}
|
||||
m_file.printf("# exercise: %s\n", kExerciseName);
|
||||
|
|
@ -179,6 +194,7 @@ void StorageManager::writeHeader(const char* runId, const char* bootTimestampUtc
|
|||
m_file.printf("# created_by: ChatGPT/Codex handoff\n");
|
||||
m_file.print("record_type,timestamp_utc,sample_seq,ms_since_run_start,board_id,gnss_chip,firmware_exercise_name,firmware_version,boot_timestamp_utc,run_id,fix_type,fix_dimension,sats_in_view,sat_seen,sats_used,hdop,vdop,pdop,latitude,longitude,altitude_m,speed_mps,course_deg,pps_seen,quality_class,gps_count,galileo_count,glonass_count,beidou_count,navic_count,qzss_count,sbas_count,mean_cn0,max_cn0,age_of_fix_ms,ttff_ms,longest_no_fix_ms,sat_talker,sat_constellation,sat_prn,sat_elevation_deg,sat_azimuth_deg,sat_snr,sat_used_in_solution\n");
|
||||
m_file.flush();
|
||||
m_newFile = false;
|
||||
}
|
||||
|
||||
bool StorageManager::writePendingBuffer() {
|
||||
|
|
@ -241,14 +257,12 @@ bool StorageManager::appendBytes(const char* data, size_t len) {
|
|||
}
|
||||
|
||||
bool StorageManager::appendLine(const String& line) {
|
||||
if (!appendBytes(line.c_str(), line.length())) {
|
||||
return false;
|
||||
if (line.endsWith("\n")) {
|
||||
return appendBytes(line.c_str(), line.length());
|
||||
}
|
||||
if (!line.endsWith("\n")) {
|
||||
static const char newline = '\n';
|
||||
return appendBytes(&newline, 1);
|
||||
}
|
||||
return true;
|
||||
String record = line;
|
||||
record += '\n';
|
||||
return appendBytes(record.c_str(), record.length());
|
||||
}
|
||||
|
||||
void StorageManager::appendSampleCsv(const GnssSample& sample,
|
||||
|
|
@ -468,6 +482,7 @@ void StorageManager::close() {
|
|||
m_file.close();
|
||||
}
|
||||
m_ready = false;
|
||||
m_newFile = false;
|
||||
}
|
||||
|
||||
bool StorageManager::normalizePath(const char* input, String& normalized) const {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class StorageManager {
|
|||
void eraseLogsRecursive(File& dir);
|
||||
|
||||
bool m_ready = false;
|
||||
bool m_newFile = false;
|
||||
String m_path;
|
||||
String m_lastError;
|
||||
File m_file;
|
||||
|
|
|
|||
|
|
@ -118,6 +118,25 @@ bool StartupSdManager::consumeRemovedEvent() {
|
|||
return out;
|
||||
}
|
||||
|
||||
bool StartupSdManager::forceRemount() {
|
||||
logf("Watcher: manual rescan requested");
|
||||
presentVotes_ = 0;
|
||||
absentVotes_ = 0;
|
||||
lastPollMs_ = 0;
|
||||
lastFullScanMs_ = millis();
|
||||
|
||||
cycleSdRail(cfg_.recoveryRailOffMs, cfg_.recoveryRailOnSettleMs);
|
||||
delay(cfg_.startupWarmupMs);
|
||||
|
||||
if (mountCardFullScan()) {
|
||||
setStateMounted();
|
||||
return true;
|
||||
}
|
||||
|
||||
setStateAbsent();
|
||||
return false;
|
||||
}
|
||||
|
||||
void StartupSdManager::logf(const char* fmt, ...) {
|
||||
char msg[196];
|
||||
va_list args;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class StartupSdManager {
|
|||
|
||||
bool consumeMountedEvent();
|
||||
bool consumeRemovedEvent();
|
||||
bool forceRemount();
|
||||
|
||||
void printCardInfo();
|
||||
bool ensureDirRecursive(const char* path);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue