Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SD card basic R/W check + folder/file presence check #2085

Merged
merged 4 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions code/components/jomjol_helper/Helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ enum SystemStatusFlag_t { // One bit per error
SYSTEM_STATUS_PSRAM_BAD = 1 << 0, // 1, Critical Error
SYSTEM_STATUS_HEAP_TOO_SMALL = 1 << 1, // 2, Critical Error
SYSTEM_STATUS_CAM_BAD = 1 << 2, // 4, Critical Error
SYSTEM_STATUS_SDCARD_CHECK_BAD = 1 << 3, // 8, Critical Error
SYSTEM_STATUS_FOLDER_CHECK_BAD = 1 << 4, // 16, Critical Error

// Second Byte
SYSTEM_STATUS_CAM_FB_BAD = 1 << (0+8), // 8, Flow still might work
Expand Down
166 changes: 166 additions & 0 deletions code/components/jomjol_helper/sdcard_check.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#include "sdcard_check.h"
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/stat.h>

#include "esp_rom_crc.h"
#include "ClassLogFile.h"

static const char *TAG = "SDCARD";

int SDCardCheckRW(void)
{
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Basic R/W check started...");
FILE* pFile = NULL;
int iCRCMessage = 0;

pFile = fopen("/sdcard/sdcheck.txt","w");
if (pFile == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E1) No able to open file to write");
return -1;
}
else {
std::string sMessage = "This message is used for a SD-Card basic check!";
iCRCMessage = esp_rom_crc16_le(0, (uint8_t*)sMessage.c_str(), sMessage.length());
if (fwrite(sMessage.c_str(), sMessage.length(), 1, pFile) == 0 ) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E2) Not able to write file");
fclose(pFile);
unlink("/sdcard/sdcheck.txt");
return -2;
}
fclose(pFile);
}

pFile = fopen("/sdcard/sdcheck.txt","r");
if (pFile == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E3) Not able to open file to read back");
unlink("/sdcard/sdcheck.txt");
return -3;
}
else {
char cReadBuf[50];
if (fgets(cReadBuf, sizeof(cReadBuf), pFile) == 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E4) Not able to read file back");
fclose(pFile);
unlink("/sdcard/sdcheck.txt");
return -4;
}
else {
if (esp_rom_crc16_le(0, (uint8_t*)cReadBuf, strlen(cReadBuf)) != iCRCMessage) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E5) Read back, but wrong CRC");
fclose(pFile);
unlink("/sdcard/sdcheck.txt");
return -5;
}
}
fclose(pFile);
}

if (unlink("/sdcard/sdcheck.txt") != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E6) Unable to delete the file");
return -6;
}

LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Basic R/W check successful");
return 0;
}


bool SDCardCheckFolderFilePresence()
{
struct stat sb;
bool bRetval = true;

LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Folder/file presence check started...");
/* check if folder exists: config */
if (stat("/sdcard/config", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: Folder /config not found");
bRetval = false;
}

/* check if folder exists: html */
if (stat("/sdcard/html", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: Folder /html not found");
bRetval = false;
}

/* check if folder exists: firmware */
if (stat("/sdcard/firmware", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: Folder /firmware not found");
bRetval = false;
}

/* check if folder exists: img_tmp */
if (stat("/sdcard/img_tmp", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: Folder /img_tmp not found");
bRetval = false;
}

/* check if folder exists: log */
if (stat("/sdcard/log", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: Folder /log not found");
bRetval = false;
}

/* check if folder exists: demo */
if (stat("/sdcard/demo", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: Folder /demo not found");
bRetval = false;
}

/* check if file exists: wlan.ini */
if (stat("/sdcard/wlan.ini", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /wlan.ini not found");
bRetval = false;
}

/* check if file exists: config.ini */
if (stat("/sdcard/config/config.ini", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /config/config.ini not found");
bRetval = false;
}

/* check if file exists: index.html */
if (stat("/sdcard/html/index.html", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /html/index.html not found");
bRetval = false;
}

/* check if file exists: ota.html */
if (stat("/sdcard/html/ota_page.html", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /html/ota.html not found");
bRetval = false;
}

/* check if file exists: log.html */
if (stat("/sdcard/html/log.html", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /html/log.html not found");
bRetval = false;
}

/* check if file exists: common.js */
if (stat("/sdcard/html/common.js", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /html/common.js not found");
bRetval = false;
}

/* check if file exists: gethost.js */
if (stat("/sdcard/html/gethost.js", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /html/gethost.js not found");
bRetval = false;
}

/* check if file exists: version.txt */
if (stat("/sdcard/html/version.txt", &sb) != 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /html/version.txt not found");
bRetval = false;
}

if (bRetval)
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Folder/file presence check successful");

return bRetval;
}
11 changes: 11 additions & 0 deletions code/components/jomjol_helper/sdcard_check.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#ifndef COMPONENTS_HELPER_SDCARD_CHECK_H
#define COMPONENTS_HELPER_SDCARD_CHECK_H

#include "../../include/defines.h"

int SDCardCheckRW(void);
bool SDCardCheckFolderFilePresence(void);

#endif /* COMPONENTS_HELPER_SDCARD_CHECK_H */
2 changes: 1 addition & 1 deletion code/components/jomjol_helper/statusled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void task_StatusLED(void *pvParameter)
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); // Set the GPIO as a push/pull output
gpio_set_level(BLINK_GPIO, 1);// LED off

for (int i=0; i<3; ) // Default: repeat 3 times
for (int i=0; i<2; ) // Default: repeat 2 times
{
if (!StatusLEDDataInt.bInfinite)
++i;
Expand Down
49 changes: 33 additions & 16 deletions code/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#endif //ENABLE_MQTT
#include "Helper.h"
#include "statusled.h"
#include "sdcard_check.h"

#include "../../include/defines.h"
//#include "server_GPIO.h"
Expand Down Expand Up @@ -205,15 +206,9 @@ extern "C" void app_main(void)
return; // No way to continue without working SD card!
}

// SD card: Create directories (if not already existing)
// SD card: Create log directories (if not already existing)
// ********************************************
bool bDirStatus = LogFile.CreateLogDirectories(); // needed for logging + image saving
bDirStatus = MakeDir("/sdcard/firmware"); // needed for firmware update
bDirStatus = MakeDir("/sdcard/img_tmp"); // needed for setting up alignment marks
bDirStatus = MakeDir("/sdcard/demo"); // needed for demo mode
if (!bDirStatus) {
StatusLED(SDCARD_CHECK, 1, false);
}
LogFile.CreateLogDirectories(); // mandatory for logging + image saving

// ********************************************
// Highlight start of logfile logging
Expand All @@ -223,33 +218,55 @@ extern "C" void app_main(void)
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Start ======================");
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");

// Migrate parameter in config.ini to new naming (firmware 14.1 and newer)
// SD card: basic R/W check
// ********************************************
int iSDCardStatus = SDCardCheckRW();
if (iSDCardStatus < 0) {
if (iSDCardStatus <= -1 && iSDCardStatus >= -2) { // write error
StatusLED(SDCARD_CHECK, 1, true);
}
else if (iSDCardStatus <= -3 && iSDCardStatus >= -5) { // read error
StatusLED(SDCARD_CHECK, 2, true);
}
else if (iSDCardStatus == -6) { // delete error
StatusLED(SDCARD_CHECK, 3, true);
}
setSystemStatusFlag(SYSTEM_STATUS_SDCARD_CHECK_BAD); // reduced web interface going to be loaded
}

// Migrate parameter in config.ini to new naming (firmware 15.0 and newer)
// ********************************************
migrateConfiguration();

// Init time (as early as possible, but SD card needs to be initialized)
// ********************************************
setupTime(); // NTP time service: Status of time synchronization will be checked after every round (server_tflite.cpp)

// SD card: basic RW check
// SD card: Create further mandatory directories (if not already existing)
// Correct creation of these folders will be checked with function "SDCardCheckFolderFilePresence"
// ********************************************
// TODO
MakeDir("/sdcard/firmware"); // mandatory for OTA firmware update
MakeDir("/sdcard/img_tmp"); // mandatory for setting up alignment marks
MakeDir("/sdcard/demo"); // mandatory for demo mode

// Check for updates
// ********************************************
CheckOTAUpdate();
CheckUpdate();

// Start SoftAP for initial remote setup
// Note: Start AP if no wlan.ini and/or config.ini available, e.g. SD empty; function does not exit anymore until reboot
// Note: Start AP if no wlan.ini and/or config.ini available, e.g. SD card empty; function does not exit anymore until reboot
// ********************************************
#ifdef ENABLE_SOFTAP
CheckStartAPMode();
#endif

// SD card: Check folder structure
// SD card: Check presence of some mandatory folders / files
// ********************************************
// TODO
if (!SDCardCheckFolderFilePresence()) {
StatusLED(SDCARD_CHECK, 4, true);
setSystemStatusFlag(SYSTEM_STATUS_FOLDER_CHECK_BAD); // reduced web interface going to be loaded
}

// Check version information
// ********************************************
Expand Down Expand Up @@ -464,12 +481,12 @@ extern "C" void app_main(void)
TFliteDoAutoStart();
}
else if (isSetSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD) || // Non critical errors occured, we try to continue...
isSetSystemStatusFlag(SYSTEM_STATUS_NTP_BAD)) {
isSetSystemStatusFlag(SYSTEM_STATUS_NTP_BAD)) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Initialization completed with errors! Starting flow task ...");
TFliteDoAutoStart();
}
else { // Any other error is critical and makes running the flow impossible. Init is going to abort.
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Flow task start aborted!");
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Flow task start aborted. Loading reduced web interface...");
}
}

Expand Down
11 changes: 7 additions & 4 deletions code/main/server_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,10 @@ esp_err_t hello_main_handler(httpd_req_t *req)

if (filetosend == "/sdcard/html/index.html") {
if (isSetSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD) || // Initialization failed with crritical errors!
isSetSystemStatusFlag(SYSTEM_STATUS_CAM_BAD)) {
isSetSystemStatusFlag(SYSTEM_STATUS_CAM_BAD) ||
isSetSystemStatusFlag(SYSTEM_STATUS_SDCARD_CHECK_BAD) ||
isSetSystemStatusFlag(SYSTEM_STATUS_FOLDER_CHECK_BAD))
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "We have a critical error, not serving main page!");

char buf[20];
Expand All @@ -228,13 +231,13 @@ esp_err_t hello_main_handler(httpd_req_t *req)
}
}

message += "<br>Please check <a href=\"https://jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes\" target=_blank>jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes</a> for more information!";
message += "<br>Please check logs with log viewer and/or <a href=\"https://jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes\" target=_blank>jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes</a> for more information!";
message += "<br><br><button onclick=\"window.location.href='/reboot';\">Reboot</button>";
message += "&nbsp;<button onclick=\"window.open('/ota_page.html');\">OTA Update</button>";
message += "&nbsp;<button onclick=\"window.open('/log.html');\">Log Viewer</button>";
message += "&nbsp;<button onclick=\"window.open('/info.html');\">Show System Info</button>";
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, message.c_str());
return ESP_FAIL;
httpd_resp_send(req, message.c_str(), message.length());
return ESP_OK;
}
else if (isSetupModusActive()) {
ESP_LOGD(TAG, "System is in setup mode --> index.html --> setup.html");
Expand Down