updated library for logging

pull/21/merge
Miroslav Pivovarsky 2024-05-31 22:44:12 +02:00
parent b639de0dd7
commit 4243473169
11 changed files with 351 additions and 50 deletions

View File

@ -115,14 +115,14 @@ void setup() {
/* init tasks */ /* init tasks */
SystemLog.AddEvent(LogLevel_Info, F("Start tasks")); SystemLog.AddEvent(LogLevel_Info, F("Start tasks"));
xTaskCreatePinnedToCore(System_TaskMain, "SystemNtpOtaUpdate", 6500, NULL, 1, &Task_SystemMain, 0); /*function, description, stack size, parameters, priority, task handle, core*/ xTaskCreatePinnedToCore(System_TaskMain, "SystemNtpOtaUpdate", 6200, NULL, 1, &Task_SystemMain, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskCaptureAndSendPhoto, "CaptureAndSendPhoto", 4700, NULL, 2, &Task_CapturePhotoAndSend, 0); /*function, description, stack size, parameters, priority, task handle, core*/ xTaskCreatePinnedToCore(System_TaskCaptureAndSendPhoto, "CaptureAndSendPhoto", 4400, NULL, 2, &Task_CapturePhotoAndSend, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskWifiManagement, "WiFiManagement", 3300, NULL, 3, &Task_WiFiManagement, 0); /*function, description, stack size, parameters, priority, task handle, core*/ xTaskCreatePinnedToCore(System_TaskWifiManagement, "WiFiManagement", 2800, NULL, 3, &Task_WiFiManagement, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskSdCardCheck, "CheckMicroSdCard", 3000, NULL, 4, &Task_SdCardCheck, 0); /*function, description, stack size, parameters, priority, task handle, core*/ xTaskCreatePinnedToCore(System_TaskSdCardCheck, "CheckMicroSdCard", 3000, NULL, 4, &Task_SdCardCheck, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskSerialCfg, "CheckSerialConfiguration", 3300, NULL, 5, &Task_SerialCfg, 0); /*function, description, stack size, parameters, priority, task handle, core*/ xTaskCreatePinnedToCore(System_TaskSerialCfg, "CheckSerialConfiguration", 2600, NULL, 5, &Task_SerialCfg, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskStreamTelemetry, "PrintStreamTelemetry", 3000, NULL, 6, &Task_StreamTelemetry, 0); /*function, description, stack size, parameters, priority, task handle, core*/ xTaskCreatePinnedToCore(System_TaskStreamTelemetry, "PrintStreamTelemetry", 2200, NULL, 6, &Task_StreamTelemetry, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskSysLed, "SystemLed", 2900, NULL, 7, &Task_SysLed, 0); /*function, description, stack size, parameters, priority, task handle, core*/ xTaskCreatePinnedToCore(System_TaskSysLed, "SystemLed", 2100, NULL, 7, &Task_SysLed, 0); /*function, description, stack size, parameters, priority, task handle, core*/
xTaskCreatePinnedToCore(System_TaskWiFiWatchdog, "WiFiWatchdog", 3000, NULL, 8, &Task_WiFiWatchdog, 0); /*function, description, stack size, parameters, priority, task handle, core*/ xTaskCreatePinnedToCore(System_TaskWiFiWatchdog, "WiFiWatchdog", 2200, NULL, 8, &Task_WiFiWatchdog, 0); /*function, description, stack size, parameters, priority, task handle, core*/
//xTaskCreatePinnedToCore(System_TaskSdCardRemove, "SdCardRemove", 3000, NULL, 9, &Task_SdCardFileRemove, 0); /*function, description, stack size, parameters, priority, task handle, core*/ //xTaskCreatePinnedToCore(System_TaskSdCardRemove, "SdCardRemove", 3000, NULL, 9, &Task_SdCardFileRemove, 0); /*function, description, stack size, parameters, priority, task handle, core*/
/* init wdg */ /* init wdg */

View File

@ -72,6 +72,7 @@ const char index_html[] PROGMEM = R"rawliteral(
<button class="btn" onclick="actionButton('/action_capture',true,'')">Refresh Snapshot</button> <br><br> <button class="btn" onclick="actionButton('/action_capture',true,'')">Refresh Snapshot</button> <br><br>
<button class="btn" onclick="actionButton('/action_send',false,'')">Send snapshot</button><br><br><br> <button class="btn" onclick="actionButton('/action_send',false,'')">Send snapshot</button><br><br><br>
<button class="btn" onclick="window.open('saved-photo.jpg')">Download snapshot</button><br><br> <button class="btn" onclick="window.open('saved-photo.jpg')">Download snapshot</button><br><br>
<button class="btn" onclick="window.open('stream.mjpg')">Start stream</button><br><br>
</article> </article>
</div> </div>
</section> </section>

View File

@ -130,7 +130,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
size_t fbLen = camera->GetPhotoFb()->len; size_t fbLen = camera->GetPhotoFb()->len;
/* sending exif data */ /* sending exif data */
if (camera->GetPhotoExifData()->header != NULL) { if ((camera->GetPhotoExifData()->header != NULL) && (camera->GetStreamStatus() == false)) {
SendWithExif = true; SendWithExif = true;
sendet_data += client.write(camera->GetPhotoExifData()->header, camera->GetPhotoExifData()->len); sendet_data += client.write(camera->GetPhotoExifData()->header, camera->GetPhotoExifData()->len);
fbBuf += camera->GetPhotoExifData()->offset; fbBuf += camera->GetPhotoExifData()->offset;
@ -151,7 +151,6 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
} }
} }
client.println("\r\n"); client.println("\r\n");
client.flush();
/* log message */ /* log message */
if (SendWithExif) { if (SendWithExif) {
@ -164,15 +163,24 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
} else if (SendInfo == i_data_type) { } else if (SendInfo == i_data_type) {
log->AddEvent(LogLevel_Verbose, F("Sending info")); log->AddEvent(LogLevel_Verbose, F("Sending info"));
sendet_data = client.print(*i_data); sendet_data = client.print(*i_data);
client.flush();
} }
client.flush();
log->AddEvent(LogLevel_Info, "Send done: " + String(i_data_length) + "/" + String(sendet_data) + " bytes"); log->AddEvent(LogLevel_Info, "Send done: " + String(i_data_length) + "/" + String(sendet_data) + " bytes");
esp_task_wdt_reset();
/* check if all data was sent */
if (i_data_length != sendet_data) {
BackendReceivedStatus = F("INCOMPLETE DATA SEND TO SERVER!");
log->AddEvent(LogLevel_Error, F("ERROR SEND DATA TO SERVER! INCORRECT DATA LENGTH!"));
client.stop();
return false;
}
//esp_task_wdt_reset();
/* read response from server */ /* read response from server */
String response = ""; String response = "";
String fullResponse = ""; String fullResponse = "";
delay(10); // wait for response
log->AddEvent(LogLevel_Verbose, F("Response:")); log->AddEvent(LogLevel_Verbose, F("Response:"));
while (client.connected()) { while (client.connected()) {
if (client.available()) { if (client.available()) {
@ -225,7 +233,7 @@ void PrusaConnect::SendPhotoToBackend() {
String Photo = ""; String Photo = "";
size_t total_len = 0; size_t total_len = 0;
if (camera->GetPhotoExifData()->header != NULL) { if ((camera->GetPhotoExifData()->header != NULL) && (camera->GetStreamStatus() == false)) {
total_len = camera->GetPhotoExifData()->len + camera->GetPhotoFb()->len - camera->GetPhotoExifData()->offset; total_len = camera->GetPhotoExifData()->len + camera->GetPhotoFb()->len - camera->GetPhotoExifData()->offset;
} else { } else {
total_len = camera->GetPhotoFb()->len; total_len = camera->GetPhotoFb()->len;
@ -294,7 +302,9 @@ void PrusaConnect::TakePictureAndSendToBackend() {
log->AddEvent(LogLevel_Error, F("Error capturing photo. Stop sending to backend!")); log->AddEvent(LogLevel_Error, F("Error capturing photo. Stop sending to backend!"));
} }
camera->CaptureReturnFrameBuffer(); if (camera->GetStreamStatus() == false) {
camera->CaptureReturnFrameBuffer();
}
} }
/** /**
@ -459,18 +469,29 @@ void PrusaConnect::SetTimeLapsPhotoSaveStatus(bool i_data) {
@return none @return none
*/ */
void PrusaConnect::SavePhotoToSdCard() { void PrusaConnect::SavePhotoToSdCard() {
/* check if time laps photo save is enabled */
if (EnableTimelapsPhotoSave == true) { if (EnableTimelapsPhotoSave == true) {
log->AddEvent(LogLevel_Info, F("Save TimeLaps photo to SD card")); log->AddEvent(LogLevel_Info, F("Save TimeLaps photo to SD card"));
/* check if SD card is detected */
if (log->GetCardDetectedStatus() == false) {
log->AddEvent(LogLevel_Error, F("SD card not detected!"));
return;
}
/* check if folder for time laps photos exists */
if (false == log->CheckDir(SD_MMC, TIMELAPS_PHOTO_FOLDER)) { if (false == log->CheckDir(SD_MMC, TIMELAPS_PHOTO_FOLDER)) {
log->AddEvent(LogLevel_Info, F("Create folder for TimeLaps photos")); log->AddEvent(LogLevel_Info, F("Create folder for TimeLaps photos"));
log->CreateDir(SD_MMC, TIMELAPS_PHOTO_FOLDER); log->CreateDir(SD_MMC, TIMELAPS_PHOTO_FOLDER);
} }
/* create file name */
String FileName = String(TIMELAPS_PHOTO_FOLDER) + "/" + String(TIMELAPS_PHOTO_PREFIX) + "_"; String FileName = String(TIMELAPS_PHOTO_FOLDER) + "/" + String(TIMELAPS_PHOTO_PREFIX) + "_";
FileName += log->GetSystemTime(); FileName += log->GetSystemTime();
FileName += TIMELAPS_PHOTO_SUFFIX; FileName += TIMELAPS_PHOTO_SUFFIX;
log->AddEvent(LogLevel_Verbose, F("Saving file: "), FileName); log->AddEvent(LogLevel_Verbose, F("Saving file: "), FileName);
/* save photo to SD card */
if (camera->GetPhotoExifData()->header != NULL) { if (camera->GetPhotoExifData()->header != NULL) {
if (log->WritePicture(FileName, camera->GetPhotoFb()->buf + camera->GetPhotoExifData()->offset, camera->GetPhotoFb()->len - camera->GetPhotoExifData()->offset, camera->GetPhotoExifData()->header, camera->GetPhotoExifData()->len) == true) { if (log->WritePicture(FileName, camera->GetPhotoFb()->buf + camera->GetPhotoExifData()->offset, camera->GetPhotoFb()->len - camera->GetPhotoExifData()->offset, camera->GetPhotoExifData()->header, camera->GetPhotoExifData()->len) == true) {
log->AddEvent(LogLevel_Info, F("Photo saved to SD card. EXIF")); log->AddEvent(LogLevel_Info, F("Photo saved to SD card. EXIF"));

View File

@ -24,6 +24,7 @@ Logs::Logs() {
FileMaxSize = 1024; FileMaxSize = 1024;
NtpTimeSynced = false; NtpTimeSynced = false;
LogMsg = ""; LogMsg = "";
LogMutex = xSemaphoreCreateMutex();
} }
/** /**
@ -39,6 +40,7 @@ Logs::Logs(String i_FilePath, String i_FileName) {
FileMaxSize = 1024; FileMaxSize = 1024;
NtpTimeSynced = false; NtpTimeSynced = false;
LogMsg = ""; LogMsg = "";
LogMutex = xSemaphoreCreateMutex();
} }
/** /**
@ -55,6 +57,7 @@ Logs::Logs(LogLevel_enum i_LogLevel, String i_FilePath, String i_FileName) {
FileMaxSize = 1024; FileMaxSize = 1024;
NtpTimeSynced = false; NtpTimeSynced = false;
LogMsg = ""; LogMsg = "";
LogMutex = xSemaphoreCreateMutex();
} }
/** /**
@ -71,6 +74,7 @@ Logs::Logs(String i_FilePath, String i_FileName, uint16_t i_FileSize) {
FileMaxSize = i_FileSize; FileMaxSize = i_FileSize;
NtpTimeSynced = false; NtpTimeSynced = false;
LogMsg = ""; LogMsg = "";
LogMutex = xSemaphoreCreateMutex();
} }
/** /**
@ -88,6 +92,7 @@ Logs::Logs(LogLevel_enum i_LogLevel, String i_FilePath, String i_FileName, uint1
FileMaxSize = i_FileSize; FileMaxSize = i_FileSize;
NtpTimeSynced = false; NtpTimeSynced = false;
LogMsg = ""; LogMsg = "";
LogMutex = xSemaphoreCreateMutex();
} }
/** /**
@ -103,6 +108,7 @@ void Logs::Init() {
/* init micro SD card */ /* init micro SD card */
InitSdCard(); InitSdCard();
LogFileOpened = OpenFile(&LogFile, FilePath + FileName);
if (true == GetCardDetectedStatus()) { if (true == GetCardDetectedStatus()) {
/* check maximum log file size */ /* check maximum log file size */
@ -121,13 +127,37 @@ void Logs::Init() {
LogMsg += F("Log level: "); LogMsg += F("Log level: ");
LogMsg += String(LogLevel); LogMsg += String(LogLevel);
LogMsg += "\n"; LogMsg += "\n";
AppendFile(SD_MMC, FilePath + FileName, LogMsg); AppendFile(&LogFile, &LogMsg);
} else { } else {
Serial.println(F("Micro-SD card not found! Disable logs")); Serial.println(F("Micro-SD card not found! Disable logs"));
} }
} }
/**
* @brief Open log file
*
*/
void Logs::LogOpenFile() {
LogFileOpened = OpenFile(&LogFile, FilePath + FileName);
}
/**
* @brief Close log file
*
*/
void Logs::LogCloseFile() {
CloseFile(&LogFile);
}
/**
* @brief Function for check opened log file
*
*/
void Logs::LogCheckOpenedFile() {
LogFileOpened = CheckOpenFile(&LogFile);
}
/** /**
@info set log level @info set log level
@param LogLevel_enum - log level @param LogLevel_enum - log level
@ -146,9 +176,13 @@ void Logs::SetLogLevel(LogLevel_enum level) {
@return none @return none
*/ */
void Logs::AddEvent(LogLevel_enum level, String msg, bool newLine, bool date) { void Logs::AddEvent(LogLevel_enum level, String msg, bool newLine, bool date) {
/* mutex for log */
xSemaphoreTake(LogMutex, portMAX_DELAY);
/* check log level */
if (LogLevel >= level) { if (LogLevel >= level) {
LogMsg = "";
/* create log message */
LogMsg = "";
if (true == date) { if (true == date) {
LogMsg += GetSystemTime(); LogMsg += GetSystemTime();
LogMsg += " - "; LogMsg += " - ";
@ -158,14 +192,27 @@ void Logs::AddEvent(LogLevel_enum level, String msg, bool newLine, bool date) {
LogMsg += "\n"; LogMsg += "\n";
} }
AppendFile(SD_MMC, FilePath + FileName, LogMsg); /* print log message to console */
Serial.print(LogMsg); Serial.print(LogMsg);
/* append log message to log file */
if (true == LogFileOpened) {
LogFileOpened = AppendFile(&LogFile, &LogMsg);
if ((false == LogFileOpened) && (true == GetCardDetectedStatus())){
LogCloseFile();
LogOpenFile();
if (true == LogFileOpened) {
LogFileOpened = AppendFile(&LogFile, &LogMsg);
}
}
}
} }
#if (true == CONSOLE_VERBOSE_DEBUG) #if (true == CONSOLE_VERBOSE_DEBUG)
else { else {
Serial.println(msg); Serial.println(msg);
} }
#endif #endif
xSemaphoreGive(LogMutex);
} }
/** /**
@ -178,9 +225,14 @@ void Logs::AddEvent(LogLevel_enum level, String msg, bool newLine, bool date) {
@return none @return none
*/ */
void Logs::AddEvent(LogLevel_enum level, const __FlashStringHelper *msg, String parameters, bool newLine, bool date) { void Logs::AddEvent(LogLevel_enum level, const __FlashStringHelper *msg, String parameters, bool newLine, bool date) {
if (LogLevel >= level) { /* mutex for log */
LogMsg = ""; xSemaphoreTake(LogMutex, portMAX_DELAY);
/* check log level */
if (LogLevel >= level) {
/* create log message */
LogMsg = "";
if (true == date) { if (true == date) {
LogMsg += GetSystemTime(); LogMsg += GetSystemTime();
LogMsg += " - "; LogMsg += " - ";
@ -191,14 +243,29 @@ void Logs::AddEvent(LogLevel_enum level, const __FlashStringHelper *msg, String
LogMsg += "\n"; LogMsg += "\n";
} }
AppendFile(SD_MMC, FilePath + FileName, LogMsg); /* print log message to console */
Serial.print(LogMsg); Serial.print(LogMsg);
/* append log message to log file */
if (true == LogFileOpened) {
LogFileOpened = AppendFile(&LogFile, &LogMsg);
if ((false == LogFileOpened) && (true == GetCardDetectedStatus())){
LogCloseFile();
LogOpenFile();
if (true == LogFileOpened) {
AppendFile(&LogFile, &LogMsg);
}
}
}
} }
#if (true == CONSOLE_VERBOSE_DEBUG) #if (true == CONSOLE_VERBOSE_DEBUG)
else { else {
Serial.println(msg); Serial.println(msg);
} }
#endif #endif
/* release mutex */
xSemaphoreGive(LogMutex);
} }
/** /**
@ -281,13 +348,14 @@ bool Logs::GetNtpTimeSynced() {
*/ */
void Logs::CheckMaxLogFileSize() { void Logs::CheckMaxLogFileSize() {
uint32_t FileSize = GetFileSize(SD_MMC, FilePath + FileName); uint32_t FileSize = GetFileSize(SD_MMC, FilePath + FileName);
AddEvent(LogLevel_Verbose, F("Log file size: "), String(FileSize) + " bytes"); AddEvent(LogLevel_Verbose, F("Log file size: "), String(FileSize) + "/" + String(LOGS_FILE_MAX_SIZE) + " B");
if (FileSize >= LOGS_FILE_MAX_SIZE) { if (FileSize >= LOGS_FILE_MAX_SIZE) {
uint16_t file_count = FileCount(SD_MMC, FilePath, FileName); uint16_t file_count = FileCount(SD_MMC, FilePath, FileName);
AddEvent(LogLevel_Info, F("Maximum log file size. File count: "), String(file_count)); AddEvent(LogLevel_Info, F("Maximum log file size. File count: "), String(file_count));
LogCloseFile();
RenameFile(SD_MMC, FilePath + FileName, FilePath + FileName + String(file_count)); RenameFile(SD_MMC, FilePath + FileName, FilePath + FileName + String(file_count));
LogOpenFile();
} }
} }
@ -296,6 +364,15 @@ void Logs::CheckCardSpace() {
AddEvent(LogLevel_Verbose, "Card size: " + String(GetCardSizeMB()), + " MB, Used: " + String(GetCardUsedMB()) + " MB, Free: " + String(GetCardUsedMB()) + " MB"); AddEvent(LogLevel_Verbose, "Card size: " + String(GetCardSizeMB()), + " MB, Used: " + String(GetCardUsedMB()) + " MB, Free: " + String(GetCardUsedMB()) + " MB");
} }
/**
@info Get log file opened
@param none
@return bool - log file opened
*/
bool Logs::GetLogFileOpened() {
return LogFileOpened;
}
/** /**
@info Get system time @info Get system time
@param none @param none

View File

@ -27,12 +27,15 @@ enum LogLevel_enum {
class Logs : public MicroSd { class Logs : public MicroSd {
private: private:
LogLevel_enum LogLevel; ///< LogLevel LogLevel_enum LogLevel; ///< LogLevel
String FileName; ///< log File name String FileName; ///< log File name
String FilePath; ///< log file patch String FilePath; ///< log file patch
uint16_t FileMaxSize; ///< log file max size uint16_t FileMaxSize; ///< log file max size
bool NtpTimeSynced; ///< status NTP time sync bool NtpTimeSynced; ///< status NTP time sync
String LogMsg; ///< log message String LogMsg; ///< log message
File LogFile; ///< log file object
bool LogFileOpened; ///< log file opened status
SemaphoreHandle_t LogMutex; ///< log mutex
public: public:
Logs(); Logs();
@ -43,6 +46,9 @@ public:
~Logs(){}; ~Logs(){};
void Init(); void Init();
void LogOpenFile();
void LogCloseFile();
void LogCheckOpenedFile();
void AddEvent(LogLevel_enum, String, bool = true, bool = true); void AddEvent(LogLevel_enum, String, bool = true, bool = true);
void AddEvent(LogLevel_enum, const __FlashStringHelper*, String, bool = true, bool = true); void AddEvent(LogLevel_enum, const __FlashStringHelper*, String, bool = true, bool = true);
void SetLogLevel(LogLevel_enum); void SetLogLevel(LogLevel_enum);
@ -57,6 +63,7 @@ public:
bool GetNtpTimeSynced(); bool GetNtpTimeSynced();
void CheckMaxLogFileSize(); void CheckMaxLogFileSize();
void CheckCardSpace(); void CheckCardSpace();
bool GetLogFileOpened();
String GetSystemTime(); String GetSystemTime();
}; };

View File

@ -14,7 +14,7 @@
#define _MCU_CFG_H_ #define _MCU_CFG_H_
/* ---------------- BASIC MCU CFG --------------*/ /* ---------------- BASIC MCU CFG --------------*/
#define SW_VERSION "1.0.3-rc1" ///< SW version #define SW_VERSION "1.0.3-rc2" ///< SW version
#define SW_BUILD __DATE__ " " __TIME__ ///< build number #define SW_BUILD __DATE__ " " __TIME__ ///< build number
#define CONSOLE_VERBOSE_DEBUG false ///< enable/disable verbose debug log level for console #define CONSOLE_VERBOSE_DEBUG false ///< enable/disable verbose debug log level for console
#define DEVICE_HOSTNAME "Prusa-ESP32cam" ///< device hostname #define DEVICE_HOSTNAME "Prusa-ESP32cam" ///< device hostname
@ -44,10 +44,10 @@
#define STATUS_LED_ERROR 100 ///< time for blink status LED when is module in the error state [ms] #define STATUS_LED_ERROR 100 ///< time for blink status LED when is module in the error state [ms]
/* ------------------- TASKS --------------------*/ /* ------------------- TASKS --------------------*/
#define TASK_SYSTEM 2000 ///< system task interval [ms] #define TASK_SYSTEM 1000 ///< system task interval [ms]
#define TASK_SDCARD 30000 ///< sd card task interval [ms] #define TASK_SDCARD 25000 ///< sd card task interval [ms]
#define TASK_WIFI 30000 ///< wifi reconnect interval. Checking when is signal lost [ms] #define TASK_WIFI 28000 ///< wifi reconnect interval. Checking when is signal lost [ms]
#define TASK_SERIAL_CFG 2000 ///< serial cfg task interval [ms] #define TASK_SERIAL_CFG 1000 ///< serial cfg task interval [ms]
#define TASK_STREAM_TELEMETRY 30000 ///< stream telemetry task interval [ms] #define TASK_STREAM_TELEMETRY 30000 ///< stream telemetry task interval [ms]
#define TASK_WIFI_WATCHDOG 20000 ///< wifi watchdog task interval [ms] #define TASK_WIFI_WATCHDOG 20000 ///< wifi watchdog task interval [ms]
#define TASK_PHOTO_SEND 1000 ///< photo send task interval [ms] #define TASK_PHOTO_SEND 1000 ///< photo send task interval [ms]
@ -57,7 +57,7 @@
#define WEB_SERVER_PORT 80 ///< WEB server port #define WEB_SERVER_PORT 80 ///< WEB server port
#define SERIAL_PORT_SPEED 115200 ///< baud rate #define SERIAL_PORT_SPEED 115200 ///< baud rate
#define WDG_TIMEOUT 40 ///< wdg timeout [second] #define WDG_TIMEOUT 40 ///< wdg timeout [second]
#define PHOTO_FRAGMENT_SIZE 5120 ///< photo fragmentation size [bytes] #define PHOTO_FRAGMENT_SIZE 5120 ///< photo fragmentation size [bytes]
#define LOOP_DELAY 100 ///< loop delay [ms] #define LOOP_DELAY 100 ///< loop delay [ms]
#define WIFI_CLIENT_WAIT_CON false ///< wait for connecting to WiFi network #define WIFI_CLIENT_WAIT_CON false ///< wait for connecting to WiFi network
#define WEB_CACHE_INTERVAL 86400 ///< cache interval for browser [s] 86400s = 24h #define WEB_CACHE_INTERVAL 86400 ///< cache interval for browser [s] 86400s = 24h
@ -75,7 +75,7 @@
/* ---------------- MicroSD Logs ----------------*/ /* ---------------- MicroSD Logs ----------------*/
#define LOGS_FILE_NAME "SysLog.log" ///< syslog file name #define LOGS_FILE_NAME "SysLog.log" ///< syslog file name
#define LOGS_FILE_PATH "/" ///< directory for log files #define LOGS_FILE_PATH "/" ///< directory for log files
#define LOGS_FILE_MAX_SIZE 512 ///< maximum file size in the [kb] #define LOGS_FILE_MAX_SIZE 1024 ///< maximum file size in the [kb]
#define FILE_REMOVE_MAX_COUNT 5 ///< maximum count for remove files from sd card #define FILE_REMOVE_MAX_COUNT 5 ///< maximum count for remove files from sd card
/* ---------------- AP MODE CFG ----------------*/ /* ---------------- AP MODE CFG ----------------*/

View File

@ -19,6 +19,7 @@
MicroSd::MicroSd() { MicroSd::MicroSd() {
CardDetected = false; CardDetected = false;
DetectAfterBoot = false; DetectAfterBoot = false;
sdCardMutex = xSemaphoreCreateMutex();
} }
/** /**
@ -35,6 +36,73 @@ void MicroSd::ReinitCard() {
InitSdCard(); InitSdCard();
} }
/**
* @brief Open file
*
* @param i_file - file
* @param i_path - path and file name
* @return true
* @return false
*/
bool MicroSd::OpenFile(File *i_file, String i_path) {
bool status = false;
if (true == CardDetected) {
#if (true == CONSOLE_VERBOSE_DEBUG)
Serial.println("Opening file: " + i_path);
#endif
if (SD_MMC.cardType() == CARD_NONE) {
Serial.println("No SD card detected");
CardDetected = false;
} else {
*i_file = SD_MMC.open(i_path.c_str(), FILE_APPEND);
if (!*i_file) {
#if (true == CONSOLE_VERBOSE_DEBUG)
Serial.println("Failed to open file");
#endif
CardDetected = false;
} else {
status = true;
#if (true == CONSOLE_VERBOSE_DEBUG)
Serial.println("File opened");
#endif
}
}
}
return status;
}
/**
* @brief Close file
*
* @param i_file - file
*/
void MicroSd::CloseFile(File *i_file) {
if (*i_file) {
i_file->close();
}
}
/**
* @brief Check if file is opened
*
* @param i_file - file
* @return true
* @return false
*/
bool MicroSd::CheckOpenFile(File *i_file) {
if (!*i_file) {
#if (true == CONSOLE_VERBOSE_DEBUG)
Serial.println(F("File not opened!"));
#endif
return false;
} else {
return true;
}
}
/** /**
@brief Init SD card. And check, if is SD card inserted @brief Init SD card. And check, if is SD card inserted
@param none @param none
@ -46,11 +114,11 @@ void MicroSd::InitSdCard() {
/* set SD card to 1-line/1-bit mode. GPIO 4 is used for LED and for microSD card. But communication is slower. */ /* set SD card to 1-line/1-bit mode. GPIO 4 is used for LED and for microSD card. But communication is slower. */
/* https://github.com/espressif/arduino-esp32/blob/master/libraries/SD_MMC/src/SD_MMC.h */ /* https://github.com/espressif/arduino-esp32/blob/master/libraries/SD_MMC/src/SD_MMC.h */
if (!SD_MMC.begin("/sdcard", true)) { if (!SD_MMC.begin("/sdcard", true)) {
Serial.println(F("SD Card Mount Failed")); Serial.println(F("SD Card Mount Failed"));
CardDetected = false; CardDetected = false;
CardSizeMB = 0; CardSizeMB = 0;
//DetectAfterBoot = false;
return; return;
} }
@ -60,20 +128,19 @@ void MicroSd::InitSdCard() {
Serial.println(F("No SD_MMC card attached")); Serial.println(F("No SD_MMC card attached"));
CardDetected = false; CardDetected = false;
CardSizeMB = 0; CardSizeMB = 0;
//DetectAfterBoot = false;
return; return;
} }
/* print card type */ /* print card type */
Serial.print(F("Found card. Card Type: ")); Serial.print(F("Found card. Card Type: "));
if (cardType == CARD_MMC) { if (cardType == CARD_MMC) {
Serial.print(F("MMC")); Serial.println(F("MMC"));
} else if (cardType == CARD_SD) { } else if (cardType == CARD_SD) {
Serial.print(F("SDSC")); Serial.println(F("SDSC"));
} else if (cardType == CARD_SDHC) { } else if (cardType == CARD_SDHC) {
Serial.print(F("SDHC")); Serial.println(F("SDHC"));
} else { } else {
Serial.print(F("UNKNOWN")); Serial.println(F("UNKNOWN"));
} }
CardDetected = true; CardDetected = true;
@ -281,6 +348,70 @@ bool MicroSd::AppendFile(fs::FS &fs, String path, String message) {
return status; return status;
} }
/**
@brief Added text to end of file
@param File - file
@param String - message
@return bool - status
*/
bool MicroSd::AppendFile(File *i_file, String *i_msg) {
/* take mutex */
xSemaphoreTake(sdCardMutex, portMAX_DELAY);
bool status = false;
/* check if card is corrupted */
if (false == isCardCorrupted()) {
xSemaphoreGive(sdCardMutex);
return false;
}
/* check if card is detected */
if (true == CardDetected) {
#if (true == CONSOLE_VERBOSE_DEBUG)
Serial.printf("Appending to file:");
#endif
/* check if file is opened */
if (!*i_file) {
Serial.println("File not opened");
CardDetected = false;
} else {
/* write to file */
if (i_file->print(i_msg->c_str())) {
if (*i_file) {
i_file->flush();
/* check if write was OK */
if (!i_file->getWriteError()) {
#if (true == CONSOLE_VERBOSE_DEBUG)
Serial.println("Write OK");
#endif
status = true;
} else {
Serial.println(F("Failed write to file"));
}
} else {
Serial.println(F("File not opened!"));
}
} else {
Serial.println(F("Failed write to file!"));
}
#if (true == CONSOLE_VERBOSE_DEBUG)
Serial.println((status == true) ? "Message appended" : "Append Failed");
#endif
}
}
/* give mutex */
xSemaphoreGive(sdCardMutex);
return status;
}
/** /**
@brief Rename file on the SD card @brief Rename file on the SD card
@param fs::FS - card @param fs::FS - card
@ -465,6 +596,51 @@ void MicroSd::CheckCardUsedStatus() {
#endif #endif
} }
/**
* @brief Function to check if card is corrupted
*
* @return true
* @return false
*/
bool MicroSd::isCardCorrupted() {
bool ret = true;
if (true == CardDetected) {
#if (true == CONSOLE_VERBOSE_DEBUG)
//Serial.println(F("Checking card..."));
#endif
/* check card size */
uint64_t use = SD_MMC.usedBytes();
uint64_t size = 0;
if (use != 0) {
size = SD_MMC.cardSize();
}
#if (true == CONSOLE_VERBOSE_DEBUG)
Serial.printf("Card size: %llu, Used: %llu\n", size, use);
#endif
/* check space on the card */
if (size == use) {
Serial.println(F("No space left on device!"));
CardDetected = false;
ret = false;
}
/* check another error */
if ((size <= 0 ) || (size == 0) || (use <= 0) || (use == 0)) {
Serial.println(F("No card detected!"));
CardDetected = false;
ret = false;
}
} else {
ret = false;
}
return ret;
}
/** /**
@brief Write picture to the SD card @brief Write picture to the SD card
@param fs::FS - card @param fs::FS - card

View File

@ -33,15 +33,16 @@
class MicroSd { class MicroSd {
private: private:
bool CardDetected; ///< Card detected status bool CardDetected; ///< Card detected status
bool DetectAfterBoot; ///< Card detect after boot bool DetectAfterBoot; ///< Card detect after boot
uint32_t CardSizeMB; ///< Card size uint32_t CardSizeMB; ///< Card size
uint32_t CardTotalMB; ///< Card total size uint32_t CardTotalMB; ///< Card total size
uint32_t CardUsedMB; ///< Card used size uint32_t CardUsedMB; ///< Card used size
uint32_t CardFreeMB; ///< Card free size uint32_t CardFreeMB; ///< Card free size
uint8_t FreeSpacePercent; ///< Free space in percent uint8_t FreeSpacePercent; ///< Free space in percent
uint8_t UsedSpacePercent; ///< Used space in percent uint8_t UsedSpacePercent; ///< Used space in percent
File file; ///< File object File file; ///< File object
SemaphoreHandle_t sdCardMutex; ///< Mutex for SD card
public: public:
MicroSd(); MicroSd();
@ -49,6 +50,9 @@ public:
void InitSdCard(); void InitSdCard();
void ReinitCard(); void ReinitCard();
bool OpenFile(File*, String);
void CloseFile(File*);
bool CheckOpenFile(File*);
void ListDir(fs::FS &, String, uint8_t); void ListDir(fs::FS &, String, uint8_t);
bool CheckDir(fs::FS &, String); bool CheckDir(fs::FS &, String);
@ -57,6 +61,7 @@ public:
void ReadFileConsole(fs::FS &, String); void ReadFileConsole(fs::FS &, String);
bool WriteFile(fs::FS &, String, String); bool WriteFile(fs::FS &, String, String);
bool AppendFile(fs::FS &, String, String); bool AppendFile(fs::FS &, String, String);
bool AppendFile(File*, String*);
bool RenameFile(fs::FS &, String, String); bool RenameFile(fs::FS &, String, String);
bool DeleteFile(fs::FS &, String); bool DeleteFile(fs::FS &, String);
uint32_t GetFileSize(fs::FS &, String); uint32_t GetFileSize(fs::FS &, String);
@ -68,6 +73,7 @@ public:
bool WritePicture(String, uint8_t *, size_t, const uint8_t *, size_t); bool WritePicture(String, uint8_t *, size_t, const uint8_t *, size_t);
void CheckCardUsedStatus(); void CheckCardUsedStatus();
bool isCardCorrupted();
bool GetCardDetectedStatus(); bool GetCardDetectedStatus();
bool GetCardDetectAfterBoot(); bool GetCardDetectAfterBoot();

View File

@ -252,6 +252,7 @@ void Server_InitWebServer_WebPages() {
if (true == SystemLog.GetCardDetectedStatus()) { if (true == SystemLog.GetCardDetectedStatus()) {
request->send(SD_MMC, SystemLog.GetFilePath() + SystemLog.GetFileName(), "text/plain"); request->send(SD_MMC, SystemLog.GetFilePath() + SystemLog.GetFileName(), "text/plain");
//SystemLog.LogOpenFile();
} else { } else {
request->send_P(404, "text/plain", "Micro SD card not found with FAT32 partition!"); request->send_P(404, "text/plain", "Micro SD card not found with FAT32 partition!");
} }

View File

@ -226,7 +226,7 @@ size_t AsyncJpegStreamResponse::_content(uint8_t *buffer, size_t maxLen, size_t
char buf[50] = { '\0' }; char buf[50] = { '\0' };
camera->StreamSetFrameSize(_frame.fb->len / 1024); camera->StreamSetFrameSize(_frame.fb->len / 1024);
camera->StreamSetFrameFps(fps); camera->StreamSetFrameFps(fps);
//sprintf(buf, "Size: %uKB, Time: %ums (%.1f fps)", _frame.fb->len / 1024, fp, fps); ////sprintf(buf, "Size: %uKB, Time: %ums (%.1f fps)", _frame.fb->len / 1024, fp, fps);
sprintf(buf, "Size: %uKB, FPS: %.1f", _frame.fb->len / 1024, fps); sprintf(buf, "Size: %uKB, FPS: %.1f", _frame.fb->len / 1024, fps);
Serial.println(buf); Serial.println(buf);
lastAsyncRequest = end; lastAsyncRequest = end;

View File

@ -542,7 +542,9 @@ void System_TaskSdCardCheck(void *pvParameters) {
esp_task_wdt_reset(); esp_task_wdt_reset();
/* check micro SD card */ /* check micro SD card */
if ((true == SystemLog.GetCardDetectAfterBoot()) && (false == SystemLog.GetCardDetectedStatus())) { if ((true == SystemLog.GetCardDetectAfterBoot()) && (false == SystemLog.GetCardDetectedStatus())) {
SystemLog.LogCloseFile();
SystemLog.ReinitCard(); SystemLog.ReinitCard();
SystemLog.LogOpenFile();
SystemLog.AddEvent(LogLevel_Warning, F("Reinit micro SD card done!")); SystemLog.AddEvent(LogLevel_Warning, F("Reinit micro SD card done!"));
} }
@ -558,6 +560,16 @@ void System_TaskSdCardCheck(void *pvParameters) {
SystemLog.CheckMaxLogFileSize(); SystemLog.CheckMaxLogFileSize();
} }
/* check if log file is opened */
if (true == SystemLog.GetCardDetectedStatus()) {
SystemLog.LogCheckOpenedFile();
if (false == SystemLog.GetLogFileOpened()) {
SystemLog.LogOpenFile();
SystemLog.AddEvent(LogLevel_Warning, F("Log file is not opened!"));
}
}
SystemLog.AddEvent(LogLevel_Info, "CardStatus: " + String(SystemLog.GetCardDetectedStatus()) + " FileStatus: " + String(SystemLog.GetLogFileOpened()));
SystemLog.AddEvent(LogLevel_Verbose, F("MicroSdCard task. Stack free size: "), String(uxTaskGetStackHighWaterMark(NULL)) + "B"); SystemLog.AddEvent(LogLevel_Verbose, F("MicroSdCard task. Stack free size: "), String(uxTaskGetStackHighWaterMark(NULL)) + "B");
/* reset wdg */ /* reset wdg */