diff --git a/GpsTracker/GpsTracker.ino b/GpsTracker/GpsTracker.ino index 75589bc..64c8a8e 100644 --- a/GpsTracker/GpsTracker.ino +++ b/GpsTracker/GpsTracker.ino @@ -14,6 +14,8 @@ void setup() { rtc::setup(); hardware::sdcard::setup(); hardware::sim808::setup(); + + positions::setup(); } void loop() { diff --git a/GpsTracker/Positions.cpp b/GpsTracker/Positions.cpp index 85b2030..115ef22 100644 --- a/GpsTracker/Positions.cpp +++ b/GpsTracker/Positions.cpp @@ -29,7 +29,9 @@ namespace positions { //TODO : enable/disable based on config _backupLength = 1; _backups = new backup::PositionsBackup*[_backupLength]; + _backups[0] = new backup::sd::SdPositionsBackup(); + _backups[0]->setup(); } bool acquire(PositionEntryMetadata &metadata) { diff --git a/GpsTracker/SdCard.cpp b/GpsTracker/SdCard.cpp index 33243ad..d33185a 100644 --- a/GpsTracker/SdCard.cpp +++ b/GpsTracker/SdCard.cpp @@ -4,9 +4,10 @@ namespace hardware { namespace sdcard { SdFat filesystem; + bool available = false; void setup() { - filesystem.begin(SD_SS); + available = filesystem.begin(SD_SS); } } diff --git a/GpsTracker/SdCard.h b/GpsTracker/SdCard.h index 9596915..fde853a 100644 --- a/GpsTracker/SdCard.h +++ b/GpsTracker/SdCard.h @@ -7,6 +7,7 @@ namespace hardware { namespace sdcard { extern SdFat filesystem; + extern bool available; void setup(); } diff --git a/GpsTracker/SdPositionsBackup.cpp b/GpsTracker/SdPositionsBackup.cpp index 1ede67d..c971a20 100644 --- a/GpsTracker/SdPositionsBackup.cpp +++ b/GpsTracker/SdPositionsBackup.cpp @@ -5,6 +5,9 @@ #include "Config.h" #include "SdFat.h" #include "Positions.h" +#include "Debug.h" + +#define LOGGER_NAME "Positions::backup::sd" namespace positions { namespace backup { @@ -20,38 +23,92 @@ namespace positions { positions::count(sdConfig.lastSavedEntry) > sdConfig.saveThreshold; } - void appendPositions(const File &file, SdPositionConfig_t &sdConfig) { + void getPositionsFileName(uint16_t fileIndex, char *buffer) { + sprintf(buffer, POSITIONS_FILENAME, fileIndex); + } + + void ensurePositionsFolder() { + char positionsFolder[] = POSITIONS_FOLDER; + + hardware::sdcard::filesystem.chdir(); + if (!hardware::sdcard::filesystem.exists(positionsFolder)) { + hardware::sdcard::filesystem.mkdir(positionsFolder, true); + } + + hardware::sdcard::filesystem.chdir(positionsFolder); + } + + void selectFile(SdPositionConfig_t &sdConfig, File &file) { + char positionFileName[POSITIONS_FILENAME_LENGTH]; + + if (sdConfig.fileRecords >= sdConfig.maxRecordsPerFile) { + if (file.isOpen()) { + file.close(); + config::backup::sd::set(sdConfig); + } + + sdConfig.fileIndex++; + sdConfig.filePosition = 0; + sdConfig.fileRecords = 0; + } + + if (!file.isOpen()) { + ensurePositionsFolder(); + getPositionsFileName(sdConfig.fileIndex, positionFileName); + file.open(positionFileName, O_RDWR | O_CREAT); + } + } + + void appendPosition(File &file, SdPositionConfig_t &sdConfig, PositionEntry &entry) { + VERBOSE("appendPosition"); + + const char fieldTerminator = ','; + + file.printField(entry.metadata.batteryLevel, fieldTerminator); + file.printField(entry.metadata.batteryVoltage, fieldTerminator); + file.printField(entry.metadata.temperature, fieldTerminator); + file.printField(entry.metadata.timeToFix, fieldTerminator); + file.printField(static_cast(entry.metadata.status), fieldTerminator); + file.println(entry.position); + + sdConfig.filePosition = file.position(); + } + + void appendPositions(SdPositionConfig_t &sdConfig) { + VERBOSE("appendPositions"); + uint16_t currentEntryIndex = sdConfig.lastSavedEntry + 1; PositionEntry currentEntry; + File file; hardware::i2c::powerOn(); do { if (!positions::get(currentEntryIndex, currentEntry)) break; - - sdConfig.filePosition = file.position(); - } while (true); + selectFile(sdConfig, file); + appendPosition(file, sdConfig, currentEntry); + sdConfig.lastSavedEntry = currentEntryIndex; + } while (positions::moveNext(currentEntryIndex)); hardware::i2c::powerOff(); + if (file.isOpen()) file.close(); + config::backup::sd::set(sdConfig); } } - void SdPositionsBackup::setup() { - config::backup::sd::setup(); - } + void SdPositionsBackup::setup() { } void SdPositionsBackup::backup() { - SdPositionConfig_t sdConfig; - - if (!details::isBackupNeeded(sdConfig)) return; + VERBOSE("backup"); - char *filename; - hardware::sdcard::filesystem.chdir("positions"); - File file = hardware::sdcard::filesystem.open(filename, O_RDWR | O_CREAT); + if (!hardware::sdcard::available) { + VERBOSE_MSG("backup", "not available"); + return; + } - file.seek(sdConfig.filePosition); - file.find('\n'); + SdPositionConfig_t sdConfig; - details::appendPositions(file, sdConfig); + if (!details::isBackupNeeded(sdConfig)) return; + details::appendPositions(sdConfig); } } diff --git a/GpsTracker/SdPositionsBackup.h b/GpsTracker/SdPositionsBackup.h index de5f5ac..98ac21e 100644 --- a/GpsTracker/SdPositionsBackup.h +++ b/GpsTracker/SdPositionsBackup.h @@ -3,6 +3,11 @@ #include "PositionsBackup.h" #include "RawSdFile.h" +#define POSITIONS_FOLDER "positions" +#define POSITIONS_FILENAME "positions-%05d.csv" +#define POSITIONS_FILENAME_LENGTH 19 + + using namespace sd; namespace positions { diff --git a/GpsTracker/SdPositionsConfig.cpp b/GpsTracker/SdPositionsConfig.cpp index de40a10..6d50885 100644 --- a/GpsTracker/SdPositionsConfig.cpp +++ b/GpsTracker/SdPositionsConfig.cpp @@ -40,8 +40,6 @@ namespace config { } - void setup() { } - SdPositionConfig_t get() { if (value.seed != POSITIONS_CONFIG_SEED) details::read(); @@ -57,7 +55,8 @@ namespace config { VERBOSE("reset"); SdPositionConfig_t config = { POSITIONS_CONFIG_SEED, - POSITIONS_CONFIG_DeFAULT_SAVE_THRESHOLD, + POSITIONS_CONFIG_DEFAULT_SAVE_THRESHOLD, + POSITIONS_CONFIG_DEFAULT_MAX_RECORDS_PER_FILE, 0xFFFF, 0, 0, diff --git a/GpsTracker/SdPositionsConfig.h b/GpsTracker/SdPositionsConfig.h index 04b78d2..935448e 100644 --- a/GpsTracker/SdPositionsConfig.h +++ b/GpsTracker/SdPositionsConfig.h @@ -4,11 +4,13 @@ #define POSITIONS_CONFIG_FILENAME "positions.config" #define POSITIONS_CONFIG_SEED 45 -#define POSITIONS_CONFIG_DeFAULT_SAVE_THRESHOLD 10 +#define POSITIONS_CONFIG_DEFAULT_SAVE_THRESHOLD 10 +#define POSITIONS_CONFIG_DEFAULT_MAX_RECORDS_PER_FILE 5 struct SdPositionConfig_t { uint8_t seed; uint8_t saveThreshold; + uint8_t maxRecordsPerFile; uint16_t lastSavedEntry; uint16_t fileIndex; uint32_t filePosition;