Config on SD card

This commit is contained in:
Sassa NF
2024-10-08 21:26:58 +01:00
parent 672ab951b2
commit 1011d8bf13
4 changed files with 274 additions and 12 deletions
+196
View File
@@ -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);
}
+32
View File
@@ -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
+27 -1
View File
@@ -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
View File
@@ -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