mirror of
https://github.com/Genaker/LoraSA.git
synced 2026-05-14 13:25:58 +02:00
Config on SD card
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
#include "config.h"
|
||||
|
||||
void listDir(fs::FS &fs, const char *dirname, uint8_t levels)
|
||||
{
|
||||
Serial.printf("Listing directory: %s\n", dirname);
|
||||
|
||||
File root = fs.open(dirname);
|
||||
if (!root)
|
||||
{
|
||||
Serial.println("Failed to open directory");
|
||||
return;
|
||||
}
|
||||
if (!root.isDirectory())
|
||||
{
|
||||
Serial.println("Not a directory");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while (file)
|
||||
{
|
||||
if (file.isDirectory())
|
||||
{
|
||||
Serial.print(" DIR : ");
|
||||
Serial.println(file.name());
|
||||
if (levels)
|
||||
{
|
||||
listDir(fs, file.path(), levels - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(" FILE: ");
|
||||
Serial.print(file.name());
|
||||
Serial.print(" SIZE: ");
|
||||
Serial.println(file.size());
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
#define LORA_CONFIG "/lora_config.txt"
|
||||
Config Config::init()
|
||||
{
|
||||
if (SD.cardType() == sdcard_type_t::CARD_NONE)
|
||||
{
|
||||
Serial.println("No SD card found, will assume defaults");
|
||||
return Config();
|
||||
}
|
||||
|
||||
File f = SD.open(LORA_CONFIG, FILE_READ);
|
||||
if (!f)
|
||||
{
|
||||
Serial.println("Listing root directory:");
|
||||
listDir(SD, "/", 0);
|
||||
Serial.println("Config file " LORA_CONFIG " not found, will assume defaults");
|
||||
Config cfg;
|
||||
|
||||
if (cfg.create_missing_config)
|
||||
{
|
||||
cfg.write_config(LORA_CONFIG);
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
Config c = Config();
|
||||
|
||||
while (f.available() > 0)
|
||||
{
|
||||
String ln = f.readStringUntil('\n');
|
||||
ParseResult r = parse_config_line(ln);
|
||||
|
||||
if (r.error.length() > 0)
|
||||
{
|
||||
Serial.printf("%s in '%s', will assume defaults\n", r.error, ln);
|
||||
return Config();
|
||||
}
|
||||
|
||||
if (r.key.length() == 0)
|
||||
{
|
||||
// blank line or comment - skip
|
||||
continue;
|
||||
}
|
||||
|
||||
// do something with known keys and values
|
||||
|
||||
if (r.key.equalsIgnoreCase("print_profile_time"))
|
||||
{
|
||||
String v = r.value;
|
||||
bool p = v.equalsIgnoreCase("true");
|
||||
if (!p && !v.equalsIgnoreCase("false"))
|
||||
{
|
||||
Serial.printf("Expected bool for '%s', found '%s' - ignoring\n",
|
||||
r.key.c_str(), r.value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
c.print_profile_time = p;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r.key.equalsIgnoreCase("log_data_json_interval"))
|
||||
{
|
||||
c.log_data_json_interval = r.value.toInt();
|
||||
}
|
||||
|
||||
Serial.printf("Unknown key '%s' will be ignored\n", r.key);
|
||||
}
|
||||
|
||||
f.close();
|
||||
return c;
|
||||
}
|
||||
|
||||
bool Config::write_config(const char *path)
|
||||
{
|
||||
File f = SD.open(path, FILE_WRITE, /*create = */ true);
|
||||
if (!f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
f.println("print_profile_time = " + String(print_profile_time ? "true" : "false"));
|
||||
f.println("log_data_json_interval = " + String(log_data_json_interval));
|
||||
|
||||
f.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
ParseResult parse_config_line(String ln)
|
||||
{
|
||||
ln.trim();
|
||||
if (ln.length() == 0 || ln.charAt(0) == '#')
|
||||
{
|
||||
// blank line or comment - skip
|
||||
return ParseResult(String(), String());
|
||||
}
|
||||
|
||||
int i = ln.indexOf("="); // ok, this must exist
|
||||
if (i < 0)
|
||||
{
|
||||
return ParseResult(String("Broken config: expected '='"));
|
||||
}
|
||||
|
||||
String k = ln.substring(0, i);
|
||||
k.trim();
|
||||
|
||||
String v = ln.substring(i + 1);
|
||||
v.trim();
|
||||
|
||||
if (v.length() == 0 || v.charAt(0) == '#')
|
||||
{
|
||||
return ParseResult(String("Broken config: expected non-empty value"));
|
||||
}
|
||||
|
||||
if (v.charAt(0) == '"')
|
||||
{
|
||||
// quoted strings get special treatment
|
||||
int i = v.indexOf('"', 1);
|
||||
while (i > 0)
|
||||
{
|
||||
if (v.length() == i + 1 || v.charAt(i + 1) != '"')
|
||||
break;
|
||||
|
||||
v = v.substring(0, i + 1) + v.substring(i + 2);
|
||||
i = v.indexOf('"', i + 1);
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
return ParseResult(String("Broken config: expected closing quotes"));
|
||||
}
|
||||
|
||||
String c = v.substring(i + 1);
|
||||
c.trim();
|
||||
if (c.length() > 0 && c.charAt(0) != '#')
|
||||
{
|
||||
return ParseResult(
|
||||
String("Broken config: expected nothing but whitespace and "
|
||||
"comments after value"));
|
||||
}
|
||||
|
||||
v = v.substring(1, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = v.indexOf('#');
|
||||
if (i > 0)
|
||||
{
|
||||
v = v.substring(0, i);
|
||||
v.trim();
|
||||
}
|
||||
}
|
||||
|
||||
return ParseResult(k, v);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef _LORA_CONFIG_H
|
||||
#define _LORA_CONFIG_H
|
||||
|
||||
#include <SD.h>
|
||||
|
||||
#define CREATE_MISSING_CONFIG true
|
||||
struct Config
|
||||
{
|
||||
bool create_missing_config;
|
||||
bool print_profile_time;
|
||||
int log_data_json_interval;
|
||||
|
||||
Config()
|
||||
: create_missing_config(CREATE_MISSING_CONFIG), print_profile_time(false),
|
||||
log_data_json_interval(1000) {};
|
||||
bool write_config(const char *path);
|
||||
|
||||
static Config init();
|
||||
};
|
||||
|
||||
struct ParseResult
|
||||
{
|
||||
String key;
|
||||
String value;
|
||||
String error;
|
||||
|
||||
ParseResult(String e) : key(String()), value(String()), error(e) {};
|
||||
ParseResult(String k, String v) : key(k), value(v), error(String()) {};
|
||||
};
|
||||
|
||||
ParseResult parse_config_line(String ln);
|
||||
#endif
|
||||
@@ -705,7 +705,33 @@ void setupBoards(bool disable_u8g2)
|
||||
|
||||
beginPower();
|
||||
|
||||
beginSDCard();
|
||||
bool sdReady;
|
||||
for (int i = 0; i < 5 && !(sdReady = beginSDCard()); i++)
|
||||
{
|
||||
Serial.println("SD card failed or not found");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
if (sdReady)
|
||||
{
|
||||
char *card_type = "UNKNOWN";
|
||||
sdcard_type_t t = SD.cardType();
|
||||
|
||||
if (t == sdcard_type_t::CARD_MMC)
|
||||
{
|
||||
card_type = "MMC";
|
||||
}
|
||||
else if (t == sdcard_type_t::CARD_SD)
|
||||
{
|
||||
card_type = "SD";
|
||||
}
|
||||
else if (t == sdcard_type_t::CARD_SDHC)
|
||||
{
|
||||
card_type = "SDHC";
|
||||
}
|
||||
|
||||
Serial.printf("SD card %s is ready.\n", card_type);
|
||||
}
|
||||
|
||||
if (!disable_u8g2)
|
||||
{
|
||||
|
||||
+19
-11
@@ -42,6 +42,7 @@
|
||||
#define RADIOLIB_GODMODE (1)
|
||||
|
||||
#include <charts.h>
|
||||
#include <config.h>
|
||||
#include <events.h>
|
||||
#include <scan.h>
|
||||
|
||||
@@ -204,8 +205,8 @@ uint64_t drone_detected_frequency_end = 0;
|
||||
bool single_page_scan = false;
|
||||
|
||||
// #define PRINT_DEBUG
|
||||
#define PRINT_PROFILE_TIME
|
||||
|
||||
#define PRINT_PROFILE_TIME
|
||||
#ifdef PRINT_PROFILE_TIME
|
||||
uint64_t loop_start = 0;
|
||||
uint64_t loop_time = 0;
|
||||
@@ -215,7 +216,6 @@ uint64_t scan_start_time = 0;
|
||||
|
||||
// log data via serial console, JSON format:
|
||||
// #define LOG_DATA_JSON true
|
||||
int LOG_DATA_JSON_INTERVAL = 1000; // Log at least every second
|
||||
|
||||
uint64_t x, y, range_item, w = WATERFALL_START, i = 0;
|
||||
int osd_x = 1, osd_y = 2, col = 0, max_bin = 32;
|
||||
@@ -360,6 +360,8 @@ void osdProcess()
|
||||
}
|
||||
#endif
|
||||
|
||||
Config config;
|
||||
|
||||
struct RadioScan : Scan
|
||||
{
|
||||
float getRSSI() override;
|
||||
@@ -514,7 +516,7 @@ void logToSerialTask(void *parameter)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ulTaskNotifyTake(true, pdMS_TO_TICKS(LOG_DATA_JSON_INTERVAL));
|
||||
ulTaskNotifyTake(true, pdMS_TO_TICKS(config.log_data_json_interval));
|
||||
if (frequency_scan_result.begin != frequency_scan_result.end ||
|
||||
frequency_scan_result.last_epoch != last_epoch)
|
||||
{
|
||||
@@ -551,7 +553,7 @@ void setup(void)
|
||||
#ifdef LILYGO
|
||||
setupBoards(); // true for disable U8g2 display library
|
||||
delay(500);
|
||||
Serial.println("Setup LiLyGO board is done");
|
||||
Serial.println("Setup LiLybeginSDCardGO board is done");
|
||||
#endif
|
||||
|
||||
// LED brightness
|
||||
@@ -576,6 +578,8 @@ void setup(void)
|
||||
bt_start = millis();
|
||||
wf_start = millis();
|
||||
|
||||
config = Config::init();
|
||||
|
||||
pinMode(LED, OUTPUT);
|
||||
pinMode(BUZZER_PIN, OUTPUT);
|
||||
pinMode(REB_PIN, OUTPUT);
|
||||
@@ -938,11 +942,12 @@ void loop(void)
|
||||
drone_detected_frequency_start = 0;
|
||||
ranges_count = 0;
|
||||
|
||||
// reset scan time
|
||||
#ifdef PRINT_PROFILE_TIME
|
||||
scan_time = 0;
|
||||
loop_start = millis();
|
||||
#endif
|
||||
// reset scan time
|
||||
if (config.print_profile_time)
|
||||
{
|
||||
scan_time = 0;
|
||||
loop_start = millis();
|
||||
}
|
||||
r.epoch++;
|
||||
|
||||
if (!ANIMATED_RELOAD || !single_page_scan)
|
||||
@@ -1337,10 +1342,13 @@ void loop(void)
|
||||
|
||||
joy_btn_clicked = false;
|
||||
|
||||
if (config.print_profile_time)
|
||||
{
|
||||
#ifdef PRINT_PROFILE_TIME
|
||||
loop_time = millis() - loop_start;
|
||||
Serial.printf("LOOP: %lld ms; SCAN: %lld ms;\n ", loop_time, scan_time);
|
||||
loop_time = millis() - loop_start;
|
||||
Serial.printf("LOOP: %lld ms; SCAN: %lld ms;\n ", loop_time, scan_time);
|
||||
#endif
|
||||
}
|
||||
// No WiFi and BT Scan Without OSD
|
||||
#ifdef OSD_ENABLED
|
||||
#ifdef WIFI_SCANNING_ENABLED
|
||||
|
||||
Reference in New Issue
Block a user