diff --git a/ESP32_PrusaConnectCam/ESP32_PrusaConnectCam.ino b/ESP32_PrusaConnectCam/ESP32_PrusaConnectCam.ino index 4ac76ab..3b3b834 100644 --- a/ESP32_PrusaConnectCam/ESP32_PrusaConnectCam.ino +++ b/ESP32_PrusaConnectCam/ESP32_PrusaConnectCam.ino @@ -115,14 +115,14 @@ void setup() { /* init 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_TaskCaptureAndSendPhoto, "CaptureAndSendPhoto", 4700, 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_TaskMain, "SystemNtpOtaUpdate", 6200, NULL, 1, &Task_SystemMain, 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", 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_TaskSerialCfg, "CheckSerialConfiguration", 3300, 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_TaskSysLed, "SystemLed", 2900, 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_TaskSerialCfg, "CheckSerialConfiguration", 2600, NULL, 5, &Task_SerialCfg, 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", 2100, NULL, 7, &Task_SysLed, 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*/ /* init wdg */ diff --git a/ESP32_PrusaConnectCam/WebPage.h b/ESP32_PrusaConnectCam/WebPage.h index 829a98a..04c3784 100644 --- a/ESP32_PrusaConnectCam/WebPage.h +++ b/ESP32_PrusaConnectCam/WebPage.h @@ -72,6 +72,7 @@ const char index_html[] PROGMEM = R"rawliteral(






+

diff --git a/ESP32_PrusaConnectCam/connect.cpp b/ESP32_PrusaConnectCam/connect.cpp index 270c8eb..d0e283f 100644 --- a/ESP32_PrusaConnectCam/connect.cpp +++ b/ESP32_PrusaConnectCam/connect.cpp @@ -130,7 +130,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i size_t fbLen = camera->GetPhotoFb()->len; /* sending exif data */ - if (camera->GetPhotoExifData()->header != NULL) { + if ((camera->GetPhotoExifData()->header != NULL) && (camera->GetStreamStatus() == false)) { SendWithExif = true; sendet_data += client.write(camera->GetPhotoExifData()->header, camera->GetPhotoExifData()->len); 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.flush(); /* log message */ if (SendWithExif) { @@ -164,15 +163,24 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i } else if (SendInfo == i_data_type) { log->AddEvent(LogLevel_Verbose, F("Sending info")); sendet_data = client.print(*i_data); - client.flush(); } + client.flush(); 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 */ String response = ""; String fullResponse = ""; + delay(10); // wait for response log->AddEvent(LogLevel_Verbose, F("Response:")); while (client.connected()) { if (client.available()) { @@ -225,7 +233,7 @@ void PrusaConnect::SendPhotoToBackend() { String Photo = ""; 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; } else { total_len = camera->GetPhotoFb()->len; @@ -294,7 +302,9 @@ void PrusaConnect::TakePictureAndSendToBackend() { 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 */ void PrusaConnect::SavePhotoToSdCard() { + /* check if time laps photo save is enabled */ if (EnableTimelapsPhotoSave == true) { 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)) { log->AddEvent(LogLevel_Info, F("Create folder for TimeLaps photos")); log->CreateDir(SD_MMC, TIMELAPS_PHOTO_FOLDER); } + /* create file name */ String FileName = String(TIMELAPS_PHOTO_FOLDER) + "/" + String(TIMELAPS_PHOTO_PREFIX) + "_"; FileName += log->GetSystemTime(); FileName += TIMELAPS_PHOTO_SUFFIX; log->AddEvent(LogLevel_Verbose, F("Saving file: "), FileName); + /* save photo to SD card */ 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) { log->AddEvent(LogLevel_Info, F("Photo saved to SD card. EXIF")); diff --git a/ESP32_PrusaConnectCam/log.cpp b/ESP32_PrusaConnectCam/log.cpp index adcd98d..563032f 100644 --- a/ESP32_PrusaConnectCam/log.cpp +++ b/ESP32_PrusaConnectCam/log.cpp @@ -24,6 +24,7 @@ Logs::Logs() { FileMaxSize = 1024; NtpTimeSynced = false; LogMsg = ""; + LogMutex = xSemaphoreCreateMutex(); } /** @@ -39,6 +40,7 @@ Logs::Logs(String i_FilePath, String i_FileName) { FileMaxSize = 1024; NtpTimeSynced = false; LogMsg = ""; + LogMutex = xSemaphoreCreateMutex(); } /** @@ -55,6 +57,7 @@ Logs::Logs(LogLevel_enum i_LogLevel, String i_FilePath, String i_FileName) { FileMaxSize = 1024; NtpTimeSynced = false; LogMsg = ""; + LogMutex = xSemaphoreCreateMutex(); } /** @@ -71,6 +74,7 @@ Logs::Logs(String i_FilePath, String i_FileName, uint16_t i_FileSize) { FileMaxSize = i_FileSize; NtpTimeSynced = false; LogMsg = ""; + LogMutex = xSemaphoreCreateMutex(); } /** @@ -88,6 +92,7 @@ Logs::Logs(LogLevel_enum i_LogLevel, String i_FilePath, String i_FileName, uint1 FileMaxSize = i_FileSize; NtpTimeSynced = false; LogMsg = ""; + LogMutex = xSemaphoreCreateMutex(); } /** @@ -103,6 +108,7 @@ void Logs::Init() { /* init micro SD card */ InitSdCard(); + LogFileOpened = OpenFile(&LogFile, FilePath + FileName); if (true == GetCardDetectedStatus()) { /* check maximum log file size */ @@ -121,13 +127,37 @@ void Logs::Init() { LogMsg += F("Log level: "); LogMsg += String(LogLevel); LogMsg += "\n"; - AppendFile(SD_MMC, FilePath + FileName, LogMsg); + AppendFile(&LogFile, &LogMsg); } else { 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 @param LogLevel_enum - log level @@ -146,9 +176,13 @@ void Logs::SetLogLevel(LogLevel_enum level) { @return none */ 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) { - LogMsg = ""; + /* create log message */ + LogMsg = ""; if (true == date) { LogMsg += GetSystemTime(); LogMsg += " - "; @@ -158,14 +192,27 @@ void Logs::AddEvent(LogLevel_enum level, String msg, bool newLine, bool date) { LogMsg += "\n"; } - AppendFile(SD_MMC, FilePath + FileName, LogMsg); + /* print log message to console */ 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) else { Serial.println(msg); } #endif + xSemaphoreGive(LogMutex); } /** @@ -178,9 +225,14 @@ void Logs::AddEvent(LogLevel_enum level, String msg, bool newLine, bool date) { @return none */ void Logs::AddEvent(LogLevel_enum level, const __FlashStringHelper *msg, String parameters, bool newLine, bool date) { - if (LogLevel >= level) { - LogMsg = ""; + /* mutex for log */ + xSemaphoreTake(LogMutex, portMAX_DELAY); + /* check log level */ + if (LogLevel >= level) { + + /* create log message */ + LogMsg = ""; if (true == date) { LogMsg += GetSystemTime(); LogMsg += " - "; @@ -191,14 +243,29 @@ void Logs::AddEvent(LogLevel_enum level, const __FlashStringHelper *msg, String LogMsg += "\n"; } - AppendFile(SD_MMC, FilePath + FileName, LogMsg); + /* print log message to console */ 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) else { Serial.println(msg); } #endif + + /* release mutex */ + xSemaphoreGive(LogMutex); } /** @@ -281,13 +348,14 @@ bool Logs::GetNtpTimeSynced() { */ void Logs::CheckMaxLogFileSize() { 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) { uint16_t file_count = FileCount(SD_MMC, FilePath, FileName); AddEvent(LogLevel_Info, F("Maximum log file size. File count: "), String(file_count)); + LogCloseFile(); 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"); } +/** + @info Get log file opened + @param none + @return bool - log file opened +*/ +bool Logs::GetLogFileOpened() { + return LogFileOpened; +} + /** @info Get system time @param none diff --git a/ESP32_PrusaConnectCam/log.h b/ESP32_PrusaConnectCam/log.h index edc95ea..159e98a 100644 --- a/ESP32_PrusaConnectCam/log.h +++ b/ESP32_PrusaConnectCam/log.h @@ -27,12 +27,15 @@ enum LogLevel_enum { class Logs : public MicroSd { private: - LogLevel_enum LogLevel; ///< LogLevel - String FileName; ///< log File name - String FilePath; ///< log file patch - uint16_t FileMaxSize; ///< log file max size - bool NtpTimeSynced; ///< status NTP time sync - String LogMsg; ///< log message + LogLevel_enum LogLevel; ///< LogLevel + String FileName; ///< log File name + String FilePath; ///< log file patch + uint16_t FileMaxSize; ///< log file max size + bool NtpTimeSynced; ///< status NTP time sync + String LogMsg; ///< log message + File LogFile; ///< log file object + bool LogFileOpened; ///< log file opened status + SemaphoreHandle_t LogMutex; ///< log mutex public: Logs(); @@ -43,6 +46,9 @@ public: ~Logs(){}; void Init(); + void LogOpenFile(); + void LogCloseFile(); + void LogCheckOpenedFile(); void AddEvent(LogLevel_enum, String, bool = true, bool = true); void AddEvent(LogLevel_enum, const __FlashStringHelper*, String, bool = true, bool = true); void SetLogLevel(LogLevel_enum); @@ -57,6 +63,7 @@ public: bool GetNtpTimeSynced(); void CheckMaxLogFileSize(); void CheckCardSpace(); + bool GetLogFileOpened(); String GetSystemTime(); }; diff --git a/ESP32_PrusaConnectCam/mcu_cfg.h b/ESP32_PrusaConnectCam/mcu_cfg.h index a473cf3..caa484c 100644 --- a/ESP32_PrusaConnectCam/mcu_cfg.h +++ b/ESP32_PrusaConnectCam/mcu_cfg.h @@ -14,7 +14,7 @@ #define _MCU_CFG_H_ /* ---------------- 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 CONSOLE_VERBOSE_DEBUG false ///< enable/disable verbose debug log level for console #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] /* ------------------- TASKS --------------------*/ -#define TASK_SYSTEM 2000 ///< system task interval [ms] -#define TASK_SDCARD 30000 ///< sd card task interval [ms] -#define TASK_WIFI 30000 ///< wifi reconnect interval. Checking when is signal lost [ms] -#define TASK_SERIAL_CFG 2000 ///< serial cfg task interval [ms] +#define TASK_SYSTEM 1000 ///< system task interval [ms] +#define TASK_SDCARD 25000 ///< sd card task interval [ms] +#define TASK_WIFI 28000 ///< wifi reconnect interval. Checking when is signal lost [ms] +#define TASK_SERIAL_CFG 1000 ///< serial cfg 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_PHOTO_SEND 1000 ///< photo send task interval [ms] @@ -57,7 +57,7 @@ #define WEB_SERVER_PORT 80 ///< WEB server port #define SERIAL_PORT_SPEED 115200 ///< baud rate #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 WIFI_CLIENT_WAIT_CON false ///< wait for connecting to WiFi network #define WEB_CACHE_INTERVAL 86400 ///< cache interval for browser [s] 86400s = 24h @@ -75,7 +75,7 @@ /* ---------------- MicroSD Logs ----------------*/ #define LOGS_FILE_NAME "SysLog.log" ///< syslog file name #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 /* ---------------- AP MODE CFG ----------------*/ diff --git a/ESP32_PrusaConnectCam/micro_sd.cpp b/ESP32_PrusaConnectCam/micro_sd.cpp index 07464c1..d01edf1 100644 --- a/ESP32_PrusaConnectCam/micro_sd.cpp +++ b/ESP32_PrusaConnectCam/micro_sd.cpp @@ -19,6 +19,7 @@ MicroSd::MicroSd() { CardDetected = false; DetectAfterBoot = false; + sdCardMutex = xSemaphoreCreateMutex(); } /** @@ -35,6 +36,73 @@ void MicroSd::ReinitCard() { 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 @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. */ /* https://github.com/espressif/arduino-esp32/blob/master/libraries/SD_MMC/src/SD_MMC.h */ + if (!SD_MMC.begin("/sdcard", true)) { Serial.println(F("SD Card Mount Failed")); CardDetected = false; CardSizeMB = 0; - //DetectAfterBoot = false; return; } @@ -60,20 +128,19 @@ void MicroSd::InitSdCard() { Serial.println(F("No SD_MMC card attached")); CardDetected = false; CardSizeMB = 0; - //DetectAfterBoot = false; return; } /* print card type */ Serial.print(F("Found card. Card Type: ")); if (cardType == CARD_MMC) { - Serial.print(F("MMC")); + Serial.println(F("MMC")); } else if (cardType == CARD_SD) { - Serial.print(F("SDSC")); + Serial.println(F("SDSC")); } else if (cardType == CARD_SDHC) { - Serial.print(F("SDHC")); + Serial.println(F("SDHC")); } else { - Serial.print(F("UNKNOWN")); + Serial.println(F("UNKNOWN")); } CardDetected = true; @@ -281,6 +348,70 @@ bool MicroSd::AppendFile(fs::FS &fs, String path, String message) { 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 @param fs::FS - card @@ -465,6 +596,51 @@ void MicroSd::CheckCardUsedStatus() { #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 @param fs::FS - card diff --git a/ESP32_PrusaConnectCam/micro_sd.h b/ESP32_PrusaConnectCam/micro_sd.h index 49aad4d..d39940d 100644 --- a/ESP32_PrusaConnectCam/micro_sd.h +++ b/ESP32_PrusaConnectCam/micro_sd.h @@ -33,15 +33,16 @@ class MicroSd { private: - bool CardDetected; ///< Card detected status - bool DetectAfterBoot; ///< Card detect after boot - uint32_t CardSizeMB; ///< Card size - uint32_t CardTotalMB; ///< Card total size - uint32_t CardUsedMB; ///< Card used size - uint32_t CardFreeMB; ///< Card free size - uint8_t FreeSpacePercent; ///< Free space in percent - uint8_t UsedSpacePercent; ///< Used space in percent - File file; ///< File object + bool CardDetected; ///< Card detected status + bool DetectAfterBoot; ///< Card detect after boot + uint32_t CardSizeMB; ///< Card size + uint32_t CardTotalMB; ///< Card total size + uint32_t CardUsedMB; ///< Card used size + uint32_t CardFreeMB; ///< Card free size + uint8_t FreeSpacePercent; ///< Free space in percent + uint8_t UsedSpacePercent; ///< Used space in percent + File file; ///< File object + SemaphoreHandle_t sdCardMutex; ///< Mutex for SD card public: MicroSd(); @@ -49,6 +50,9 @@ public: void InitSdCard(); void ReinitCard(); + bool OpenFile(File*, String); + void CloseFile(File*); + bool CheckOpenFile(File*); void ListDir(fs::FS &, String, uint8_t); bool CheckDir(fs::FS &, String); @@ -57,6 +61,7 @@ public: void ReadFileConsole(fs::FS &, String); bool WriteFile(fs::FS &, String, String); bool AppendFile(fs::FS &, String, String); + bool AppendFile(File*, String*); bool RenameFile(fs::FS &, String, String); bool DeleteFile(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); void CheckCardUsedStatus(); + bool isCardCorrupted(); bool GetCardDetectedStatus(); bool GetCardDetectAfterBoot(); diff --git a/ESP32_PrusaConnectCam/server.cpp b/ESP32_PrusaConnectCam/server.cpp index 78e4cf1..c8b9129 100644 --- a/ESP32_PrusaConnectCam/server.cpp +++ b/ESP32_PrusaConnectCam/server.cpp @@ -252,6 +252,7 @@ void Server_InitWebServer_WebPages() { if (true == SystemLog.GetCardDetectedStatus()) { request->send(SD_MMC, SystemLog.GetFilePath() + SystemLog.GetFileName(), "text/plain"); + //SystemLog.LogOpenFile(); } else { request->send_P(404, "text/plain", "Micro SD card not found with FAT32 partition!"); } diff --git a/ESP32_PrusaConnectCam/stream.cpp b/ESP32_PrusaConnectCam/stream.cpp index 44f14c2..994bb0c 100644 --- a/ESP32_PrusaConnectCam/stream.cpp +++ b/ESP32_PrusaConnectCam/stream.cpp @@ -226,7 +226,7 @@ size_t AsyncJpegStreamResponse::_content(uint8_t *buffer, size_t maxLen, size_t char buf[50] = { '\0' }; camera->StreamSetFrameSize(_frame.fb->len / 1024); 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); Serial.println(buf); lastAsyncRequest = end; diff --git a/ESP32_PrusaConnectCam/system.cpp b/ESP32_PrusaConnectCam/system.cpp index 1c79f2d..839e915 100644 --- a/ESP32_PrusaConnectCam/system.cpp +++ b/ESP32_PrusaConnectCam/system.cpp @@ -542,7 +542,9 @@ void System_TaskSdCardCheck(void *pvParameters) { esp_task_wdt_reset(); /* check micro SD card */ if ((true == SystemLog.GetCardDetectAfterBoot()) && (false == SystemLog.GetCardDetectedStatus())) { + SystemLog.LogCloseFile(); SystemLog.ReinitCard(); + SystemLog.LogOpenFile(); SystemLog.AddEvent(LogLevel_Warning, F("Reinit micro SD card done!")); } @@ -558,6 +560,16 @@ void System_TaskSdCardCheck(void *pvParameters) { 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"); /* reset wdg */