v1.2: Settings toggles, flight logbook, local time, WiFi auto-reconnect, metric units

This commit is contained in:
Eiswolf-BG
2026-08-03 04:16:08 +02:00
parent 0de99ef1c5
commit b913ca2f44
22 changed files with 817 additions and 229 deletions

View File

@@ -1,25 +1,30 @@
#include "wifi_manager.h"
#include "config.h"
#include "sd_storage.h"
#include <WiFi.h>
#include <Preferences.h>
#include <SD.h>
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <cstring>
namespace WifiMgr {
namespace {
Preferences prefs;
struct NetworkEntry {
char ssid[33] = {0};
char pass[64] = {0};
};
NetworkEntry networks[Config::MAX_WIFI_NETWORKS];
uint8_t networkCountVal = 0;
State state = State::Idle;
uint32_t connectStartMs = 0;
constexpr uint32_t CONNECT_TIMEOUT_MS = 15000; // bounded, same fix as the Kinect sketch
constexpr uint32_t CONNECT_TIMEOUT_MS = 15000;
char ipStr[16] = {0};
// Schuetzt 'state': der Netzwerk-Task (Core 0) schreibt es in
// beginConnect()/update(), der Render-Loop (Core 1) liest es ueber
// getState(). ipStr wird nur einmal beim Verbinden geschrieben und danach
// nur gelesen, daher hier ohne eigenen Lock.
uint32_t lastReconnectAttemptMs = 0;
constexpr uint32_t RECONNECT_RETRY_MS = 10000;
SemaphoreHandle_t mutex = nullptr;
void setState(State s) {
@@ -27,50 +32,136 @@ namespace {
state = s;
xSemaphoreGive(mutex);
}
void loadFromSd() {
networkCountVal = 0;
if (!SdStorage::isMounted()) return;
if (!SD.exists(Config::SD_WIFI_CREDENTIALS_FILE)) return;
File f = SD.open(Config::SD_WIFI_CREDENTIALS_FILE, FILE_READ);
if (!f) return;
while (networkCountVal < Config::MAX_WIFI_NETWORKS && f.available()) {
String ssid = f.readStringUntil('\n');
String pass = f.readStringUntil('\n');
ssid.trim();
pass.trim();
if (ssid.length() == 0) break;
strncpy(networks[networkCountVal].ssid, ssid.c_str(), sizeof(networks[networkCountVal].ssid) - 1);
strncpy(networks[networkCountVal].pass, pass.c_str(), sizeof(networks[networkCountVal].pass) - 1);
networkCountVal++;
}
f.close();
}
void saveToSd() {
if (!SdStorage::isMounted()) return;
File f = SD.open(Config::SD_WIFI_CREDENTIALS_FILE, FILE_WRITE);
if (!f) return;
for (uint8_t i = 0; i < networkCountVal; i++) {
f.println(networks[i].ssid);
f.println(networks[i].pass);
}
f.close();
}
}
void init() {
if (mutex == nullptr) mutex = xSemaphoreCreateMutex();
prefs.begin("adsb_radar", /*readOnly=*/false);
setState(hasStoredCredentials() ? State::Idle : State::NoCredentials);
loadFromSd();
setState(networkCountVal > 0 ? State::Idle : State::NoCredentials);
}
bool hasStoredCredentials() {
String ssid = prefs.getString("ssid", "");
return ssid.length() > 0;
uint8_t networkCount() { return networkCountVal; }
String networkSsid(uint8_t index) {
if (index >= networkCountVal) return String();
return String(networks[index].ssid);
}
void saveCredentials(const char* ssid, const char* password) {
prefs.putString("ssid", ssid);
prefs.putString("pass", password);
bool addNetwork(const char* ssid, const char* password) {
if (networkCountVal >= Config::MAX_WIFI_NETWORKS) return false;
strncpy(networks[networkCountVal].ssid, ssid, sizeof(networks[networkCountVal].ssid) - 1);
strncpy(networks[networkCountVal].pass, password, sizeof(networks[networkCountVal].pass) - 1);
networkCountVal++;
saveToSd();
return true;
}
void beginConnect() {
if (!hasStoredCredentials()) {
setState(State::NoCredentials);
return;
void removeNetwork(uint8_t index) {
if (index >= networkCountVal) return;
for (uint8_t i = index; i < networkCountVal - 1; i++) {
networks[i] = networks[i + 1];
}
String ssid = prefs.getString("ssid", "");
String pass = prefs.getString("pass", "");
networkCountVal--;
networks[networkCountVal] = NetworkEntry{};
saveToSd();
}
void connectTo(const char* ssid, const char* password) {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), pass.c_str());
WiFi.begin(ssid, password);
connectStartMs = millis();
setState(State::Connecting);
}
void update() {
if (getState() != State::Connecting) return;
if (WiFi.status() == WL_CONNECTED) {
strncpy(ipStr, WiFi.localIP().toString().c_str(), sizeof(ipStr) - 1);
setState(State::Connected);
void beginConnect() {
if (networkCountVal == 0) {
setState(State::NoCredentials);
return;
}
if (millis() - connectStartMs > CONNECT_TIMEOUT_MS) {
WiFi.disconnect(true);
int visibleCount = WiFi.scanNetworks(/*async=*/false);
int8_t chosen = -1;
for (uint8_t i = 0; i < networkCountVal && chosen < 0; i++) {
for (int j = 0; j < visibleCount; j++) {
if (WiFi.SSID(j) == networks[i].ssid) {
chosen = (int8_t)i;
break;
}
}
}
if (chosen < 0) {
setState(State::Failed);
return;
}
connectTo(networks[chosen].ssid, networks[chosen].pass);
}
void update() {
State s = getState();
if (s == State::Connecting) {
if (WiFi.status() == WL_CONNECTED) {
strncpy(ipStr, WiFi.localIP().toString().c_str(), sizeof(ipStr) - 1);
setState(State::Connected);
return;
}
if (millis() - connectStartMs > CONNECT_TIMEOUT_MS) {
WiFi.disconnect(true);
setState(State::Failed);
}
return;
}
if (s == State::Connected && WiFi.status() != WL_CONNECTED) {
Serial.println("[WifiMgr] Verbindung verloren, versuche automatisch neu zu verbinden...");
setState(State::Idle);
lastReconnectAttemptMs = millis() - RECONNECT_RETRY_MS;
return;
}
if ((s == State::Idle || s == State::Failed) && networkCountVal > 0) {
if (millis() - lastReconnectAttemptMs >= RECONNECT_RETRY_MS) {
lastReconnectAttemptMs = millis();
beginConnect();
}
}
}
@@ -104,37 +195,4 @@ int32_t getScanResultRSSI(int index) {
const char* getIP() { return ipStr; }
bool loadCredentialsFromSd() {
if (!SdStorage::isMounted()) return false;
if (!SD.exists(Config::SD_WIFI_CREDENTIALS_FILE)) return false;
File f = SD.open(Config::SD_WIFI_CREDENTIALS_FILE, FILE_READ);
if (!f) return false;
String ssid = f.readStringUntil('\n');
String pass = f.readStringUntil('\n');
f.close();
ssid.trim();
pass.trim();
if (ssid.length() == 0) return false;
saveCredentials(ssid.c_str(), pass.c_str());
return true;
}
void saveCredentialsToSdIfMounted() {
if (!SdStorage::isMounted()) return;
String ssid = prefs.getString("ssid", "");
String pass = prefs.getString("pass", "");
if (ssid.length() == 0) return;
File f = SD.open(Config::SD_WIFI_CREDENTIALS_FILE, FILE_WRITE);
if (!f) return;
f.println(ssid);
f.println(pass);
f.close();
}
}