sd card support enhancements
This commit is contained in:
parent
8674098b65
commit
71781723f4
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "src/pmu.h"
|
||||
|
||||
|
||||
/* Data exchange connectors */
|
||||
#if FEATURE_CHASEMAPPER
|
||||
#include "src/conn-chasemapper.h"
|
||||
|
|
@ -287,7 +288,7 @@ void setupChannelList() {
|
|||
file.close();
|
||||
}
|
||||
|
||||
const char *HTMLHEAD = "<html><head> <meta charset=\"UTF-8\"> <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">";
|
||||
const char *HTMLHEAD = "<!DOCTYPE html><html><head> <meta charset=\"UTF-8\"> <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">";
|
||||
void HTMLBODY(char *ptr, const char *which) {
|
||||
strcat(ptr, "<body><form class=\"wrapper\" action=\"");
|
||||
strcat(ptr, which);
|
||||
|
|
@ -657,7 +658,15 @@ struct st_configitems config_list[] = {
|
|||
{"mqtt.password", 63, &sonde.config.mqtt.password},
|
||||
{"mqtt.prefix", 63, &sonde.config.mqtt.prefix},
|
||||
#endif
|
||||
|
||||
#if FEATURE_SDCARD
|
||||
/* SD-Card settings */
|
||||
{"sd.cs", 0, &sonde.config.sd.cs},
|
||||
{"sd.miso", 0, &sonde.config.sd.miso},
|
||||
{"sd.mosi", 0, &sonde.config.sd.mosi},
|
||||
{"sd.clk", 0, &sonde.config.sd.clk},
|
||||
{"sd.sync", 0, &sonde.config.sd.sync},
|
||||
{"sd.name", 0, &sonde.config.sd.name},
|
||||
#endif
|
||||
/* Hardware dependeing settings */
|
||||
{"disptype", 0, &sonde.config.disptype},
|
||||
{"norx_timeout", 0, &sonde.config.norx_timeout},
|
||||
|
|
@ -1038,7 +1047,7 @@ const char *handleEditPost(AsyncWebServerRequest * request) {
|
|||
// will be removed. its now in data/upd.html (for GET; POST to update.html still handled here)
|
||||
const char *createUpdateForm(boolean run) {
|
||||
char *ptr = message;
|
||||
strcpy(ptr, "<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body><form action=\"update.html\" method=\"post\">");
|
||||
strcpy(ptr, "<!DOCTYPE html><html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body><form action=\"update.html\" method=\"post\">");
|
||||
if (run) {
|
||||
strcat(ptr, "<p>Doing update, wait until reboot</p>");
|
||||
} else {
|
||||
|
|
@ -1230,16 +1239,38 @@ void SetupAsyncServer() {
|
|||
}
|
||||
request->send(SPIFFS, filename, "text/plain");
|
||||
});
|
||||
|
||||
server.on("/file", HTTP_POST, [](AsyncWebServerRequest * request) {
|
||||
request->send(200);
|
||||
}, handleUpload);
|
||||
#if FEATURE_SDCARD
|
||||
server.on("/sd/data.csv", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
Serial.println("Opening SD card file\n");
|
||||
const File SDFile = SD.open("/data.csv", FILE_READ);
|
||||
if(SDFile) { Serial.printf("SD file opened\n"); }
|
||||
else { Serial.printf("SD file does not exist"); request->send(404); return; }
|
||||
AsyncWebServerResponse *response = request->beginChunkedResponse("text/plain", [SDFile](uint8_t *buf, size_t maxLen, size_t index) -> size_t {
|
||||
File SDLambdaFile = SDFile;
|
||||
// if(maxLen>1024) maxLen=1024;
|
||||
Serial.printf("[HTTP]\t[%d]\tINDEX [%d]\tBUFFER_MAX_LENGHT [%d]\r\n", index, SDLambdaFile.size(), maxLen);
|
||||
return SDLambdaFile.read(buf, maxLen);
|
||||
});
|
||||
request->send(response);
|
||||
});
|
||||
server.serveStatic("/sd/", SD, "/");
|
||||
#endif
|
||||
|
||||
server.on("/edit.html", HTTP_GET, [](AsyncWebServerRequest * request) {
|
||||
// new version:
|
||||
// Open file
|
||||
// store file object in request->_tempObject
|
||||
//request->send(200, "text/html", createEditForm(request->getParam(0)->value()));
|
||||
const String filename = request->getParam(0)->value();
|
||||
AsyncWebParameter *param = request->getParam(0);
|
||||
if(!param) {
|
||||
request->send(404);
|
||||
return;
|
||||
}
|
||||
const String filename = param->value();
|
||||
File file = SPIFFS.open("/" + filename, "r");
|
||||
int state = 0;
|
||||
request->send("text/html", 0, [state, file, filename](uint8_t *buffer, size_t maxLen, size_t index) mutable -> size_t {
|
||||
|
|
@ -1252,9 +1283,13 @@ void SetupAsyncServer() {
|
|||
if (ret == NULL)
|
||||
request->send(200, "text/html", "<html><head>ERROR</head><body><p>Something went wrong (probably ESP32 out of memory). Uploaded file is empty.</p></body></hhtml>");
|
||||
else {
|
||||
String f = request->getParam(0)->value();
|
||||
AsyncWebParameter *param = request->getParam(0);
|
||||
if(!param) {
|
||||
request->send(404);
|
||||
return;
|
||||
}
|
||||
String f = param->value();
|
||||
request->redirect("/edit.html?file=" + f);
|
||||
//request->send(200, "text/html", createEditForm(request->getParam(0)->value()));
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
|
|
@ -1265,8 +1300,12 @@ void SetupAsyncServer() {
|
|||
// Route to load style.css file
|
||||
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest * request) {
|
||||
AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/style.css", "text/css");
|
||||
response->addHeader("Cache-Control", "max-age=86400");
|
||||
request->send(response);
|
||||
if(response) {
|
||||
response->addHeader("Cache-Control", "max-age=86400");
|
||||
request->send(response);
|
||||
} else {
|
||||
request->send(404);
|
||||
}
|
||||
});
|
||||
|
||||
server.on("/live.kml", HTTP_GET, [](AsyncWebServerRequest * request) {
|
||||
|
|
@ -1296,7 +1335,10 @@ void SetupAsyncServer() {
|
|||
// This happens with concurrent requests, notably if a browser fetches rdz.js and cfg.js concurrently for config.html
|
||||
// With the cache, rdz.js is likely already in the cache...0
|
||||
Serial.printf("URL is %s\n", url.c_str());
|
||||
AsyncWebServerResponse *response = request->beginResponse(SPIFFS, url, "text/html");
|
||||
const char *type = "text/html";
|
||||
if(url.endsWith(".js")) type="text/javascript";
|
||||
Serial.printf("Responding with type %si (url %s)\n", type, url.c_str());
|
||||
AsyncWebServerResponse *response = request->beginResponse(SPIFFS, url, type);
|
||||
if(response) {
|
||||
response->addHeader("Cache-Control", "max-age=900");
|
||||
request->send(response);
|
||||
|
|
@ -1693,14 +1735,13 @@ void setup()
|
|||
char buf[12];
|
||||
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(/*921600 */115200);
|
||||
Serial.begin(115200);
|
||||
for (int i = 0; i < 39; i++) {
|
||||
int v = gpio_get_level((gpio_num_t)i);
|
||||
Serial.printf("%d:%d ", i, v);
|
||||
}
|
||||
|
||||
//NimBLEDevice::init("NimBLE-Arduino");
|
||||
//NimBLEServer* pServer = NimBLEDevice::createServer();;
|
||||
#ifndef REMOVE_ALL_FOR_TESTING
|
||||
|
||||
Serial.println("");
|
||||
#ifdef ESP_MEM_DEBUG
|
||||
|
|
@ -1810,10 +1851,8 @@ void setup()
|
|||
|
||||
setupWifiList();
|
||||
Serial.printf("before disp.initFromFile... layouts is %p\n", disp.layouts);
|
||||
Serial.printf("test\n");
|
||||
|
||||
disp.initFromFile(sonde.config.screenfile);
|
||||
Serial.printf("disp.initFromFile... layouts is %p", disp.layouts);
|
||||
Serial.printf("disp.initFromFile... layouts is %p\n", disp.layouts);
|
||||
|
||||
|
||||
// == show initial values from config.txt ========================= //
|
||||
|
|
@ -1929,9 +1968,25 @@ void setup()
|
|||
#if FEATURE_APRS
|
||||
connAPRS.init();
|
||||
#endif
|
||||
#if FEATURE_SDCARD
|
||||
connSDCard.init();
|
||||
#endif
|
||||
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
getKeyPress(); // clear key buffer
|
||||
|
||||
#else
|
||||
/// DEBUG ONLY
|
||||
WiFi.begin("Dinosauro", "03071975");
|
||||
while(!WiFi.isConnected()) { delay(500); Serial.print(":"); }
|
||||
Serial.println("... WiFi is connected!\n");
|
||||
SetupAsyncServer();
|
||||
sonde.config.sd.cs = 13;
|
||||
sonde.config.sd.clk = 14;
|
||||
sonde.config.sd.miso = 2;
|
||||
sonde.config.sd.mosi = 15;
|
||||
connSDCard.init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void enterMode(int mode) {
|
||||
|
|
@ -2882,6 +2937,8 @@ int fetchHTTPheader(int *validType) {
|
|||
void loop() {
|
||||
Serial.printf("\nMAIN: Running loop in state %d [currentDisp:%d, lastDisp:%d]. free heap: %d, unused stack: %d\n",
|
||||
mainState, currentDisplay, lastDisplay, ESP.getFreeHeap(), uxTaskGetStackHighWaterMark(0));
|
||||
|
||||
#ifndef REMOVE_ALL_FOR_TESTING
|
||||
switch (mainState) {
|
||||
case ST_DECODER:
|
||||
#ifndef DISABLE_MAINRX
|
||||
|
|
@ -2911,7 +2968,9 @@ void loop() {
|
|||
sonde.updateDisplay();
|
||||
lastDisplay = currentDisplay;
|
||||
}
|
||||
|
||||
#else
|
||||
delay(1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,13 @@ var cfgs = [
|
|||
[ "sondehub.fiinterval", "Import frequency (minutes, ≥ 5)" ],
|
||||
[ "sondehub.fimaxdist", "Import maximum distance (km, ≤ 700)" ],
|
||||
[ "sondehub.fimaxage", "Import maximum age (hours, ≤ 48)" ],
|
||||
[ "", "SD card logger configuration", "https://github.com/dl9rdz/rdz_ttgo_sonde/wiki/SDcard-configuration"],
|
||||
[ "cs", "SD card CS" ],
|
||||
[ "miso", "SD card MISO/DI" ],
|
||||
[ "mosi", "SD card MOSI/DO" ],
|
||||
[ "clk", "SD card CLK" ],
|
||||
[ "sync", "SD card sync interval [s]" ],
|
||||
[ "name", "SD card naming (0=by sondeid, 1=by day)" ],
|
||||
[ "", "Hardware configuration (requires reboot)", "https://github.com/dl9rdz/rdz_ttgo_sonde/wiki/Hardware-configuration"],
|
||||
[ "disptype", "Display type (0=OLED/SSD1306, 1=ILI9225, 2=OLED/SH1106, 3=ILI9341, 4=ILI9342, 5=ST7789)"],
|
||||
[ "oled_sda", "OLED SDA/TFT SDA"],
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
// Safeboot image is a minimalistic version that only includes WiFi / OTA functionality
|
||||
#define FEATURE_SONDEHUB 0
|
||||
#define FEATURE_MQTT 0
|
||||
#define FEATURE_SDARD 0
|
||||
#define FEATURE_SDCARD 0
|
||||
#define FEATURE_APRS 0
|
||||
#define LEGACY_FONTS_IN_CODEBIN 0
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -106,6 +106,10 @@ void Sonde::defaultConfig() {
|
|||
config.sx1278_sck = SCK;
|
||||
// config.oled_rst = 16;
|
||||
config.oled_rst = -1; // GPIO16 is Flash CS on Lora32 v1.6
|
||||
config.sd.cs = -1;
|
||||
config.sd.miso = -1;
|
||||
config.sd.mosi = -1;
|
||||
config.sd.clk = -1;
|
||||
config.disptype = 0;
|
||||
config.dispcontrast = -1;
|
||||
config.tft_orient = 1;
|
||||
|
|
@ -225,6 +229,10 @@ void Sonde::defaultConfig() {
|
|||
config.button2_pin = 14 + 128; // GPIO14 / T6
|
||||
config.led_pout = 25;
|
||||
config.batt_adc = 35;
|
||||
config.sd.cs = 13;
|
||||
config.sd.miso = 2;
|
||||
config.sd.mosi = 15;
|
||||
config.sd.clk = 14;
|
||||
}
|
||||
}
|
||||
//
|
||||
|
|
|
|||
|
|
@ -229,6 +229,15 @@ struct st_sondehub {
|
|||
double fimaxage;
|
||||
};
|
||||
|
||||
struct st_sdcard {
|
||||
int cs;
|
||||
int miso;
|
||||
int mosi;
|
||||
int clk;
|
||||
int sync;
|
||||
int name;
|
||||
};
|
||||
|
||||
// to be extended
|
||||
enum { TYPE_TTGO, TYPE_M5_CORE2 };
|
||||
|
||||
|
|
@ -297,6 +306,7 @@ typedef struct st_rdzconfig {
|
|||
struct st_mqtt mqtt;
|
||||
struct st_sondehub sondehub;
|
||||
struct st_cm cm;
|
||||
struct st_sdcard sd;
|
||||
} RDZConfig;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,45 +4,84 @@
|
|||
|
||||
#include "conn-sdcard.h"
|
||||
|
||||
// TODO: Move into config
|
||||
#define CS 13
|
||||
#define SYNC_INTERVAL 10
|
||||
static SPIClass sdspi(HSPI);
|
||||
|
||||
void ConnSDCard::init() {
|
||||
/* Initialize SD card */
|
||||
initok = SD.begin(CS);
|
||||
Serial.printf("SD card init: %s\n", initok?"OK":"Failed");
|
||||
if(sonde.config.sd.clk==-1)
|
||||
return;
|
||||
/* Initialize SD card */
|
||||
// SPI (==VSPI) is used by SX127x.
|
||||
// On LoRa32, SD-Card is on different pins, so cannot share VSPI
|
||||
// Use HSPI (if using a TFT with SPI, you have to make sure that the same pins are used for both (MISO/MOSI/CLK)
|
||||
sdspi.begin(sonde.config.sd.clk, sonde.config.sd.miso, sonde.config.sd.mosi, sonde.config.sd.cs);
|
||||
initok = SD.begin(sonde.config.sd.cs, sdspi);
|
||||
Serial.printf("SD card init: %s\n", initok ? "OK" : "Failed");
|
||||
uint8_t cardType = SD.cardType();
|
||||
|
||||
if (cardType == CARD_NONE) {
|
||||
Serial.println("No SD card attached");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("SD Card Type: ");
|
||||
if (cardType == CARD_MMC) {
|
||||
Serial.println("MMC");
|
||||
} else if (cardType == CARD_SD) {
|
||||
Serial.println("SDSC");
|
||||
} else if (cardType == CARD_SDHC) {
|
||||
Serial.println("SDHC");
|
||||
} else {
|
||||
Serial.println("UNKNOWN");
|
||||
}
|
||||
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
|
||||
Serial.printf("SD Card Size: %luMB\n", cardSize);
|
||||
uint64_t usedSize = SD.usedBytes() / (1024 * 1024);
|
||||
//uint64_t totalSize = SD.totalBytes() / (1024 * 1024);
|
||||
uint64_t totalSize = SD.totalBytes();
|
||||
Serial.printf("SD Card used/total: %lu/%lu MB\n", usedSize, totalSize);
|
||||
|
||||
file = SD.open("/data.csv", FILE_APPEND);
|
||||
if (!file) {
|
||||
Serial.println("Cannot open file");
|
||||
return;
|
||||
}
|
||||
file.printf("Hello word... test\n");
|
||||
file.close();
|
||||
|
||||
//sdf = SD.open("/data.csv", FILE_READ);
|
||||
}
|
||||
|
||||
void ConnSDCard::netsetup() {
|
||||
/* empty function, we don't use any network here */
|
||||
/* empty function, we don't use any network here */
|
||||
}
|
||||
|
||||
String ConnSDCard::getStatus() {
|
||||
return String("");
|
||||
return String("");
|
||||
}
|
||||
|
||||
// Rotation by time or by id.
|
||||
|
||||
void ConnSDCard::updateSonde( SondeInfo *si ) {
|
||||
if (!initok) return;
|
||||
if (!file) {
|
||||
file = SD.open("/data.csv", FILE_APPEND);
|
||||
}
|
||||
if (!file) {
|
||||
Serial.println("Error opening file");
|
||||
return;
|
||||
}
|
||||
SondeData *sd = &si->d;
|
||||
file.printf("%d,%s,%s,%d,"
|
||||
"%f,%f,%f,%f,%f,%f,%d,%d,"
|
||||
"%d,%d,%d,%d\n",
|
||||
sd->validID, sd->ser, sd->typestr, sd->subtype,
|
||||
sd->lat, sd->lon, sd->alt, sd->vs, sd->hs, sd->dir, sd->sats, sd->validPos,
|
||||
sd->time, sd->frame, sd->vframe, sd->validTime);
|
||||
wcount++;
|
||||
if(wcount >= SYNC_INTERVAL) {
|
||||
file.flush();
|
||||
wcount = 0;
|
||||
}
|
||||
if (!initok) return;
|
||||
if (!file) {
|
||||
file = SD.open("/data.csv", FILE_APPEND);
|
||||
}
|
||||
if (!file) {
|
||||
Serial.println("Error opening file");
|
||||
return;
|
||||
}
|
||||
SondeData *sd = &si->d;
|
||||
file.printf("%d,%s,%s,%d,"
|
||||
"%f,%f,%f,%f,%f,%f,%d,%d,"
|
||||
"%d,%d,%d,%d\n",
|
||||
sd->validID, sd->ser, sd->typestr, sd->subtype,
|
||||
sd->lat, sd->lon, sd->alt, sd->vs, sd->hs, sd->dir, sd->sats, sd->validPos,
|
||||
sd->time, sd->frame, sd->vframe, sd->validTime);
|
||||
wcount++;
|
||||
if (wcount >= sonde.config.sd.sync) {
|
||||
file.flush();
|
||||
wcount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,5 +39,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
extern ConnSDCard connSDCard;
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue