Files
flyradar/src/location_presets.cpp
2026-08-16 14:33:27 +02:00

140 lines
3.9 KiB
C++

#include "location_presets.h"
#include "config.h"
#include "sd_mutex.h"
#include "sd_storage.h"
#include <SD.h>
#include <cstring>
namespace LocationPresets {
namespace {
constexpr const char* PRESETS_FILE = "/Flightradar_cyd/locations.txt";
struct Preset {
double lat = 0;
double lon = 0;
// Optional user-assigned name (e.g. "Home") or taken from the nearest
// airport - empty if none was set. 16 characters + null terminator
// are sufficient for a well-readable line in the preset list.
char name[17] = {0};
};
Preset presets[MAX_PRESETS];
uint8_t presetCount = 0;
int8_t activeIdx = -1;
void saveToSd() {
if (!SdStorage::isMounted()) return;
SdMutex::Guard guard;
File f = SD.open(PRESETS_FILE, FILE_WRITE);
if (!f) return;
f.printf("active=%d\n", (int)activeIdx);
for (uint8_t i = 0; i < presetCount; i++) {
f.printf("%.6f,%.6f,%s\n", presets[i].lat, presets[i].lon, presets[i].name);
}
f.close();
}
void loadFromSd() {
presetCount = 0;
activeIdx = -1;
if (!SdStorage::isMounted()) return;
SdMutex::Guard guard;
if (!SD.exists(PRESETS_FILE)) return;
File f = SD.open(PRESETS_FILE, FILE_READ);
if (!f) return;
bool firstLine = true;
while (f.available()) {
String line = f.readStringUntil('\n');
line.trim();
if (line.length() == 0) continue;
if (firstLine) {
firstLine = false;
if (line.startsWith("active=")) {
activeIdx = (int8_t)line.substring(7).toInt();
continue;
}
}
int comma1 = line.indexOf(',');
if (comma1 < 0) continue;
if (presetCount >= MAX_PRESETS) break;
// The name is an optional third field - older,
// saved presets (before this feature) only have
// "lat,lon" without a second comma, then the name stays empty.
int comma2 = line.indexOf(',', comma1 + 1);
presets[presetCount].lat = line.substring(0, comma1).toDouble();
if (comma2 < 0) {
presets[presetCount].lon = line.substring(comma1 + 1).toDouble();
presets[presetCount].name[0] = 0;
} else {
presets[presetCount].lon = line.substring(comma1 + 1, comma2).toDouble();
String nm = line.substring(comma2 + 1);
strncpy(presets[presetCount].name, nm.c_str(), sizeof(presets[presetCount].name) - 1);
}
presetCount++;
}
f.close();
if (activeIdx >= (int8_t)presetCount) activeIdx = -1;
}
}
void init() {
loadFromSd();
}
uint8_t count() { return presetCount; }
void getLatLon(uint8_t index, double& lat, double& lon) {
if (index >= presetCount) return;
lat = presets[index].lat;
lon = presets[index].lon;
}
String getName(uint8_t index) {
if (index >= presetCount) return String();
return String(presets[index].name);
}
bool addPreset(double lat, double lon, const String& name) {
if (presetCount >= MAX_PRESETS) return false;
presets[presetCount].lat = lat;
presets[presetCount].lon = lon;
strncpy(presets[presetCount].name, name.c_str(), sizeof(presets[presetCount].name) - 1);
presetCount++;
saveToSd();
return true;
}
void removePreset(uint8_t index) {
if (index >= presetCount) return;
for (uint8_t i = index; i < presetCount - 1; i++) {
presets[i] = presets[i + 1];
}
presetCount--;
presets[presetCount] = Preset{};
if (activeIdx == (int8_t)index) {
activeIdx = -1;
} else if (activeIdx > (int8_t)index) {
activeIdx--;
}
saveToSd();
}
int8_t activeIndex() { return activeIdx; }
void setActiveIndex(int8_t index) {
if (index >= (int8_t)presetCount) return;
activeIdx = index;
saveToSd();
}
}