v1.2: Settings toggles, flight logbook, local time, WiFi auto-reconnect, metric units
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user