Skip to content

Commit

Permalink
SD logger example
Browse files Browse the repository at this point in the history
  • Loading branch information
cotestatnt committed Mar 15, 2024
1 parent 1da0c8d commit 4a708c8
Show file tree
Hide file tree
Showing 9 changed files with 1,056 additions and 20 deletions.
155 changes: 155 additions & 0 deletions examples/csvLoggerSdFat/csvLoggerSdFat.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#include <SD.h>
#include <AsyncFsWebServer.h>

// Timezone definition to get properly time from NTP server
#define MYTZ "CET-1CEST,M3.5.0,M10.5.0/3"
#include <time.h>

#define PIN_CS 14
#define PIN_SCK 13
#define PIN_MOSI 12
#define PIN_MISO 11


AsyncFsWebServer server(80, SD, "myServer");
struct tm ntpTime;
const char* basePath = "/csv";

//////////////////////////////// NTP Time /////////////////////////////////////////
void getUpdatedtime(const uint32_t timeout) {
uint32_t start = millis();
do {
time_t now = time(nullptr);
ntpTime = *localtime(&now);
delay(1);
} while (millis() - start < timeout && ntpTime.tm_year <= (1970 - 1900));
}


//////////////////////////////// Filesystem /////////////////////////////////////////
bool startFilesystem(){
if (SD.begin(PIN_CS)){
server.printFileList(SD, "/", 2);
return true;
}
else {
Serial.println("ERROR on mounting filesystem. It will be formmatted!");
ESP.restart();
}
return false;
}

//////////////////////////// Append a row to csv file ///////////////////////////////////
bool appenRow() {
getUpdatedtime(10);

char filename[24];
snprintf(filename, sizeof(filename),
"%s/%04d_%02d_%02d.csv",
basePath,
ntpTime.tm_year + 1900,
ntpTime.tm_mon + 1,
ntpTime.tm_mday
);

File file;
if (SD.exists(filename)) {
file = SD.open(filename, "a"); // Append to existing file
}
else {
file = SD.open(filename, "w"); // Create a new file
file.println("timestamp, free heap, largest free block, connected, wifi strength");
}

if (file) {
char timestamp[25];
strftime(timestamp, sizeof(timestamp), "%c", &ntpTime);

char row[64];
#ifdef ESP32
snprintf(row, sizeof(row), "%s, %d, %d, %s, %d",
timestamp,
heap_caps_get_free_size(0),
heap_caps_get_largest_free_block(0),
(WiFi.status() == WL_CONNECTED) ? "true" : "false",
WiFi.RSSI()
);
#elif defined(ESP8266)
uint32_t free;
uint16_t max;
ESP.getHeapStats(&free, &max, nullptr);
snprintf(row, sizeof(row),
"%s, %d, %d, %s, %d",
timestamp, free, max,
(WiFi.status() == WL_CONNECTED) ? "true" : "false",
WiFi.RSSI()
);
#endif
Serial.println(row);
file.println(row);
file.close();
return true;
}

return false;
}


void setup() {
SPI.begin(PIN_SCK, PIN_MISO, PIN_MOSI, PIN_CS);
Serial.begin(115200);

delay(1000);
startFilesystem();

// Create csv logs folder if not exists
if (!SD.exists(basePath)) {
SD.mkdir(basePath);
}

server.setAP("ESP32_CSVLOGGER", "123456789");
IPAddress myIP = server.startWiFi(15000);

// Enable ACE FS file web editor and add FS info callback fucntion
server.enableFsCodeEditor();
#ifdef ESP32
server.setFsInfoCallback([](fsInfo_t* fsInfo) {
fsInfo->totalBytes = SD.totalBytes();
fsInfo->usedBytes = SD.usedBytes();
fsInfo->fsName = "SD";
});
#endif

// Start server
server.init();
Serial.print(F("\nAsync ESP Web Server started on IP Address: "));
Serial.println(myIP);
Serial.println(F(
"This is \"scvLoggerSdFat.ino\" example.\n"
"Open /setup page to configure optional parameters.\n"
"Open /edit page to view, edit or upload example or your custom webserver source files."
));

// Set NTP servers
#ifdef ESP8266
configTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
#elif defined(ESP32)
configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
#endif

// Wait for NTP sync (with timeout)
getUpdatedtime(5000);

appenRow();
}

void loop() {
if (server.getCaptivePortal())
server.updateDNS();

static uint32_t updateTime;
if (millis()- updateTime > 30000) {
updateTime = millis();
appenRow();
}
}
189 changes: 189 additions & 0 deletions examples/csvLoggerSdFat/data/assets/css/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/* Misc */
html, body {
font-family: "Helvetica","Arial",sans-serif;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
body {
margin: 0;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
text-align: left;
background-color: #fff;
}

h1 {
margin: 5px;
text-align: center;
}

p {
font-size: 0.9rem;
margin: 0.5rem 0 1.5rem 0;
}

a,
a:visited {
color: #08C;
text-decoration: none;
}

a:hover,
a:focus {
color: #69c773;
cursor: pointer;
}

a.delete-file,
a.delete-file:visited {
color: #CC0000;
margin-left: 0.5rem;
vertical-align: middle;
}

button {
display: inline-block;
border-radius: 3px;
border: none;
font-size: 0.9rem;
padding: 0.5rem 1em;
background: #86b32d;
border-bottom: 1px solid #5d7d1f;
color: white;
margin: 5px 0;
text-align: center;
}

button:hover {
opacity: 0.75;
cursor: pointer;
}

#page-wrapper {
width: 95%;
background: #FFF;
padding: 1.25rem;
margin: 1rem auto;
min-height: 800px;
border-top: 5px solid #69c773;
box-shadow: 0 2px 10px rgba(0,0,0,0.8);
}

#content {
width: 85%;
overflow: auto;
height: 86vh;
}

#files {
width: 15%;
}

#files ul {
margin: 20px 0;
padding: 0.5rem 1rem;
overflow-y: auto;
list-style: square;
background: #F7F7F7;
border: 1px solid #D9D9D9;
border-radius: 5px;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
max-height: 75vh;
}

#files li {
margin-left: 8px;
font-size: 14px;
display: flex;
justify-content: space-between;
align-items: center;
}

.container {
display: flex;
flex-direction: row;
align-content: flex-start;
justify-content: space-between;
align-items: flex-start;
column-gap: 10px;
height: 86vh;
}

.delete {
font-size: 24px;
transition: 0.3s;
margin-top:5px;
}

.delete-all{
color: #f44336;
font-size: 12px;
background-color: transparent;
background-repeat: no-repeat;
border: none;
cursor: pointer;
overflow: hidden;
}

/* Tables */
.table-holder {
margin-top: 20px;
border: 1px solid lightgray;
border-radius: 5px;
border-bottom: 0px;
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
}

.tables {
margin-bottom: 50px;
}

table {
width: 100%;
border-bottom: 0px;
}

table, th, td {
border: 1px solid lightgrey;
border-collapse: collapse;
padding-left: 5px;
}

table tr:nth-child(even) {
background-color: white;
}

table tr:nth-child(odd) {
background-color: #f2f2f2;
}

table th {
background-color: #e1e1e1;
color: black;
}

/* Sections */

.section {
box-shadow: 10px 10px 10px 10px;
background-color: #e5e5e5;
padding: 10px;
padding-top: 20px;
font-size: 18px;
}

.section-lightgrey {
background-color: #f9f9f9;
}

/* 100% Image Width on Smaller Screens */
@media only screen and (max-width: 700px){
.modal-content {
width: 100%;
}
}
Loading

0 comments on commit 4a708c8

Please sign in to comment.