File manager
FileManager.cpp
- Committer:
- nsrwsurasak
- Date:
- 2016-09-20
- Revision:
- 38:e2799f75940f
- Parent:
- 36:09e662a69c50
File content as of revision 38:e2799f75940f:
/** ****************************************************************************** * @file FileManager.cpp * @author Narut T * @version V1 * @date 19/05/2016 * @brief File Manager for managing file system in SD Card ******************************************************************************/ #include "main.h" char m_StrGpsInterval[XMLTEXT_SIZE]; // GPS Interval char m_StrDataInterval[XMLTEXT_SIZE]; // Data Interval uint32_t m_GpsInterval; uint32_t m_DataInterval; Variable_Data_TypeDef m_varList[MAX_VAR]; // Variable List unsigned int m_amountVarList = 0; // Amount of variable list bool m_SdCardHasDisconnected = false; // flag to indicate sd card has disconnected char m_varListFileName[MAX_FILE_NAME_SIZE]; // Variable File Name bool m_sdCardIsPresent; // Flag to indicate sd card is present uint32_t m_TxID; // Transmit ID uint32_t m_RxID; // Receive ID #if UART_FILE_ACCESS char m_bufFileName[MAX_FILE_NAME_SIZE]; // buffer for storing File Name #endif /** Connect pin for SD Card LED */ #ifdef LED_SDCARD DigitalOut ledStatus(LED_SDCARD); #else DigitalOut ledStatus(NC); #endif #if CAPTURE_TIME Timer t; #endif /* ############### Static function prototype ################## */ static void FILEMANAGER_RemoveSpaces(char* s , int size); static void FILEMANAGER_GetXmlText(char *str, char *ret); static void FILEMANAGER_GenerateFileNameWithTime(time_t timestamp, char * file_name); static void FILEMANAGER_SetLedStatus(bool on); /** * @brief Utility function to Remove space charector from given char array * @note * @param char array to process remove spaces * @param size of char array * @retval space removed char array */ static void FILEMANAGER_RemoveSpaces(char* s , int size) { char* cpy = s; // an alias to iterate through s without moving s char* temp = s; for (int i = 0 ; i < size ; i++) { if (*cpy != ' ') *temp++ = *cpy; cpy++; } *temp = 0; return; } /** * @brief Utility function to get XML tag * @note Only First tag will be returned * @param char array to get XML Text * @param char array to be populate XML text * @retval XML text */ static void FILEMANAGER_GetXmlText(char *str, char *ret) { int size = strlen(str); int i; bool begin_text = false; char * ret_addr = ret; /* initialized our return value */ memset (ret,' ',XMLTEXT_SIZE); /* Loop to check XML tag symbols */ for(i = 0; i < size ; i++) { if (*str == '>') { /* Found begining of the tag */ begin_text = true; } else if (begin_text && *str == '<') { /* Reach the end of text message */ begin_text = false; break; } else if (begin_text && *str != ' ') { /* Populate the return value */ *ret = *str; ret++; } /* Move to next char */ str++; } /* Remove space from return value */ FILEMANAGER_RemoveSpaces(ret_addr, XMLTEXT_SIZE); } /** * @brief Utility function to get File Name with Date * @note Format file will be YYYY-MM-DD.filename * @param timestamp - time structure to get Date * @param file_name - char array to file name * @retval renamed file name */ static void FILEMANAGER_GenerateFileNameWithTime(time_t timestamp, char * file_name) { char str[RENAME_FILE_BUFFER_SIZE]; struct tm * ptm; /* Convert timestamp to readable format */ ptm = localtime ( ×tamp ); /* Replacing YYYY to the converted year */ sprintf(str,"%04d", ptm->tm_year + YEAR_4DIGITS_OFFSET); memcpy(&file_name[TIMESTAMP_YEAR_OFFSET], str, TIMESTAMP_YEAR_SIZE); /* Replacing MM to converted month */ sprintf(str,"%02d", ptm->tm_mon+1); memcpy(&file_name[TIMESTAMP_MONTH_OFFSET], str, TIMESTAMP_MONTH_SIZE); /* Replacing DD to converted date */ sprintf(str,"%02d", ptm->tm_mday); memcpy(&file_name[TIMESTAMP_DATE_OFFSET], str,TIMESTAMP_DATE_SIZE); } /** * @brief Function to perform read setup file * @note filename must be defined in FileManager.h, GPS/ Data interval will be stored in dedicated variable * @param None * @retval None */ void FILEMANAGER_ReadSetupFile() { /* Open file in reading mode */ FILE *fp = fopen(SETUP_FILE_NAME, "r"); if (fp == NULL) { /* In case of error, print the message */ printf("\nError! Unable to open file! %s \n", SETUP_FILE_NAME); /* Indicate LED Status (OFF)*/ FILEMANAGER_SetLedStatus(false); } else { /* Initialized state */ ReadingFileState state = STATE_FINDING; /* Allocate buffer for reading file */ char buf[READ_FILE_BUFFER_SIZE]; /* Indicate LED Status (ON)*/ FILEMANAGER_SetLedStatus(true); /* Read line from the file */ while (fgets(buf, sizeof(buf), fp) != NULL) { /* Check the TAG */ if (strstr (buf,DATA_TAG)) { /* Found the DATA TAG */ state = STATE_FOUND_DATA; } else if (strstr (buf,GPS_TAG)) { /* Found GPS TAG */ state = STATE_FOUND_GPS; } else if (strstr (buf,UPDATE_INTERVAL_TAG)) { /* Found Interval TAG */ if (state == STATE_FOUND_GPS) { /* Get XML text for GPS Interval */ FILEMANAGER_GetXmlText(buf, m_StrGpsInterval); m_GpsInterval = atoi(m_StrGpsInterval); #if DEBUG printf("\r\n-found GPS interval %s ", m_StrGpsInterval); #endif /* Set state to indicate that we are finding */ state = STATE_FINDING; } else if(state == STATE_FOUND_DATA) { /* Get XML text for Data Interval */ FILEMANAGER_GetXmlText(buf, m_StrDataInterval); m_DataInterval = atoi(m_StrDataInterval); #if DEBUG printf("\r\n-found Data interval %s ", m_StrDataInterval); #endif /* Set state to indicate that we are finding */ state = STATE_FINDING; } } else if (strstr (buf,VAR_LIST_FILE_TAG)) { /* Get XML text for Variable File Name */ char bufFileName[MAX_FILE_NAME_SIZE]; FILEMANAGER_GetXmlText(buf, bufFileName); /* Get Copy to dedicated variable */ memcpy(m_varListFileName,PREFIX_FILE_NAME,strlen(PREFIX_FILE_NAME)); memcpy(&m_varListFileName[strlen(PREFIX_FILE_NAME)],bufFileName,strlen(bufFileName)); } else if (strstr (buf,RMS_DEVICE_TAG)) { /* Get XML text for RMS device TAG */ char bufDevice[XMLTEXT_SIZE]; FILEMANAGER_GetXmlText(buf, bufDevice); m_TxID = atoi(bufDevice); } else if (strstr (buf,RMS_KEY_TAG)) { /* Get XML text for RMS Key TAG */ char bufKey[XMLTEXT_SIZE]; FILEMANAGER_GetXmlText(buf, bufKey); m_RxID = atoi(bufKey); } } /* Ensure file is closed */ fclose(fp); #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler free(fp); #endif } } /** * @brief Function to log GPS Data * @note * @param timestamp - time structure to get Date * @param lat - char array for lattitude * @param longti - char array for longtitude * @retval None */ void FILEMANAGER_LogGPSData(time_t timestamp ,char lat[], char longti[]) { if (!m_sdCardIsPresent) { /** Turn off LED */ FILEMANAGER_SetLedStatus(false); printf("Error! SD Card is not connected \n"); /** Return as nothing to be done */ return; } /* Get File name */ char file_name[] = GPS_LOG_FILE_NAME; /* Generate file name with time stamp */ FILEMANAGER_GenerateFileNameWithTime(timestamp,file_name); /* Open file with "APPEND" mode */ FILE *fp = fopen(file_name, "a"); if (fp == NULL) { /* if it can't open the file then print error message */ printf("Error! Unable to open file %s!\n",file_name); /* Indicate LED Status (OFF)*/ FILEMANAGER_SetLedStatus(false); } else { #if CAPTURE_TIME t.reset(); t.start(); #endif /* Indicate LED Status (ON)*/ FILEMANAGER_SetLedStatus(true); #if DEBUG /* Print some message for information */ printf("\r\n Writing to Gps Log File (%s)....",file_name); #endif /* Write the line with lattitude and longtitude */ fprintf(fp, "%d,%s,%s\n",timestamp,lat,longti); #if DEBUG printf("Done"); #endif /* Close file once it done */ fclose(fp); #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler free(fp); #endif #if CAPTURE_TIME t.stop(); printf("\r\nThe GPS Write Log time taken was %d millsecond\n", t.read_ms()); #endif } } /** * @brief Function to log RMS Data * @note sequence must be in the same order with variableList * @param timestamp - time structure to get Date * @param var - float array to be log in the file * @param size - size of the float array * @param p_headerRequired - pointer to flag for log header * @param msec - time in millisecond * @retval None */ void FILEMANAGER_LogRMSData(time_t timestamp ,float * var, int size, bool * p_headerRequired, uint32_t msec) { if (!m_sdCardIsPresent) { /** Turn off LED */ FILEMANAGER_SetLedStatus(false); printf("Error! SD Card is not connected \n"); /** Return as nothing to be done */ return; } /* Get File name */ char file_name[] = RTL_LOG_FILE_NAME; /* Generate File name with timestamp */ FILEMANAGER_GenerateFileNameWithTime(timestamp,file_name); #if DEBUG printf("\r\n File name is generated \n"); #endif #if DEBUG printf("\r\n Going to Open RMS File For write \n"); #endif /* Open file with "APPEND" mode */ FILE *fp = fopen(file_name, "a"); if (*p_headerRequired || !FILEMANAGER_IsFileExist(file_name)) { /* If file is not exist, log the header */ FILEMANAGER_LogRMSHeader(fp, timestamp, file_name); /* Clear flag once header has been written */ *p_headerRequired = false; } if (fp == NULL) { /* In case of error, print the error message */ printf("Error! Unable to open file %s!\n",file_name); /* Indicate LED Status (OFF)*/ FILEMANAGER_SetLedStatus(false); } else { /* Indicate LED Status (ON)*/ FILEMANAGER_SetLedStatus(true); #if CAPTURE_TIME t.reset(); t.start(); #endif #if DEBUG /* Print some message for information */ printf("\r\n Writing to Log File (%s)....",file_name); #endif /* Write timestamp */ fprintf(fp, "%d,%d",timestamp,msec); /* Write variable data */ for(int i = 0; i < size; i++) { fprintf(fp, ",%g",var[i]); } /* Write new line as we done */ fprintf(fp, "\n"); #if DEBUG printf("Done"); #endif /* Close the file */ fclose(fp); #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler free(fp); #endif #if CAPTURE_TIME t.stop(); printf("\r\n The RMS Write log time taken was %d milliseconds\n", t.read_ms()); #endif } } /** * @brief Function to log RMS Header * @note sequence must be in the same order with variableList * @param timestamp - time structure to get Date * @retval None */ void FILEMANAGER_LogRMSHeader(FILE *fp, time_t timestamp, char file_name[]) { #if DEBUG /* opened file so can write */ printf("\r\n Writing Header to Log File (%s)....",file_name); #endif fprintf(fp, "%s,%s",RMS_HEADER_TIME,RMS_HEADER_MSECOND); for(int i = 0; i < m_amountVarList; i++) { fprintf(fp, ",%s",m_varList[i].varName); } /* Write new line as done */ fprintf(fp, "\n-,-"); /* Write the unit of variables to the file */ for(int i = 0; i < m_amountVarList; i++) { fprintf(fp, ",%s",m_varList[i].varUnit); } /* Write new line as done */ fprintf(fp, "\n"); #if DEBUG printf("Done"); #endif } /** * @brief Function to log Mini RMS System Data * @note this file is only for debug * @param gps_interval - gps interval * @param rms_interval - rms interval * @param isResetCausedByWdg - flag to indicate system restart by watchdog * @retval None */ void FILEMANAGER_LogSystemData(float gps_interval,float rms_interval, bool isResetCausedByWdg) { /* Open the file in append mode */ FILE *fp = fopen(MINIRMS_LOG_FILE_NAME, "a"); if (fp == NULL) { /* In case of error, print the msg */ printf("Error! Unable to open file!\n"); /* Indicate LED Status (OFF)*/ FILEMANAGER_SetLedStatus(false); } else { /* Indicate LED Status (ON)*/ FILEMANAGER_SetLedStatus(true); /* get Timestamp */ time_t seconds = INTERNALRTC_GetEpoch(); /* Write some message, which is TBD */ fprintf(fp, "\nStart Mini-RMS System with At UTC Time %s , Gps Interval = %f second, RMS Interval = %f second, Variable = %d variable(s) ",ctime(&seconds),gps_interval,rms_interval,m_amountVarList); if (isResetCausedByWdg) { fprintf(fp, " **** Restart by Watchdog"); } fclose(fp); // ensure you close the file after writing #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler free(fp); #endif } } /** * @brief Utility to delete file * @note * @param filename - file name to be deleted * @retval None */ void FILEMANAGER_Deletefile(char filename[]) { #if UART_FILE_ACCESS FILEMANAGER_AddPrefixFilename(filename, m_bufFileName); #endif #if UART_FILE_ACCESS FILE *fp = fopen(m_bufFileName, "r"); // try and open file #else FILE *fp = fopen(filename, "r"); // try and open file #endif if (fp != NULL) { // if it does open... fclose(fp); // close it #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler free(fp); #endif #if UART_FILE_ACCESS remove(m_bufFileName); // and then delete #else remove(filename); // and then delete #endif } // if we can't open it, it doesn't exist and so we can't delete it } /** * @brief Utility to check file available * @note * @param filename - file name to be checked * @retval true - file is exist , false - file is not exist */ bool FILEMANAGER_IsFileExist(char filename[]) { bool exist = false; FILE *fp = fopen(filename, "r"); // try and open file if (fp != NULL) { // if it does open... fclose(fp); // close it #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler free(fp); #endif exist = true; } return exist; } /** * @brief Utility to get GPS Interval * @note must be called after read the setup file * @param None * @retval GPS interval */ int FILEMANAGER_GPSInterval() { /* Return interval in int */ return ( m_GpsInterval ); } /** * @brief Utility to get Data Interval * @note must be called after read the setup file * @param None * @retval Data interval */ int FILEMANAGER_DataInterval() { /* Return interval in int */ return ( m_DataInterval ); } /** * @brief Function to read the variable list file * @note Recommended to call this function at initilization phase * @param None * @retval pointer to variable list */ Variable_Data_TypeDef * FILEMANAGER_ReadVarFile() { /* Open the file with reading mode */ FILE *fp = fopen(m_varListFileName, "r"); if (fp == NULL) { /* if it can't open the file then print error message */ printf("\nError! Unable to open file! %s \n", m_varListFileName); /* Indicate LED Status (OFF)*/ FILEMANAGER_SetLedStatus(false); return NULL; } else { /* Indicate LED Status (ON)*/ FILEMANAGER_SetLedStatus(true); /* Allocate buffer for reading */ char buf[READ_FILE_BUFFER_SIZE]; int index = 0; /* Initialize return value */ memset(m_varList, ' ', sizeof(m_varList)); /* Read line from the file */ while (fgets(buf, sizeof(buf), fp) != NULL) { /* Check the TAG */ if (strstr (buf,VAR_NAME_TAG)) { /* Found variable TAG, populate it*/ FILEMANAGER_GetXmlText(buf , m_varList[index].varName); } else if (strstr (buf,VAR_ADDR_TAG)) { /* Found variable address TAG, populate it*/ FILEMANAGER_GetXmlText(buf , m_varList[index].varAddress); } else if (strstr (buf,VAR_TYPE_TAG)) { /* Found variable type TAG, populate it*/ FILEMANAGER_GetXmlText(buf , m_varList[index].varType); } else if (strstr (buf,VAR_LSB1_TAG)) { /* Found variable LSB1 TAG, populate it*/ FILEMANAGER_GetXmlText(buf , m_varList[index].varLSB1); } else if (strstr (buf,VAR_LSB2_TAG)) { /* Found variable LSB2 TAG, populate it*/ FILEMANAGER_GetXmlText(buf , m_varList[index].varLSB2); } else if (strstr (buf,VAR_BITMASK_TAG)) { /* Found variable BitMask TAG, populate it*/ FILEMANAGER_GetXmlText(buf , m_varList[index].varBitMask); } else if (strstr (buf,VAR_UNIT_TAG)) { /* Found variable unit TAG, populate it*/ FILEMANAGER_GetXmlText(buf , m_varList[index].varUnit); index++; } } /* Close File */ fclose(fp); #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler free(fp); #endif /* Populate amount */ m_amountVarList = index; /* Return variable list */ return m_varList; } } /** * @brief Function to amount of variable for data logging * @note Must be called after readVarFile * @param None * @retval amount of variable list */ int FILEMANAGER_GetAmountVarList() { return m_amountVarList; } /** * @brief Function to get variable list * @note Must be called after readVarFile * @param None * @retval pointer to variable list */ Variable_Data_TypeDef * FILEMANAGER_GetVarList() { return m_varList; } /** * @brief Function to get Receieve ID * @note Must be called after readSetupFile * @param None * @retval Receieve ID */ uint32_t FILEMANAGER_GetRxID() { return m_RxID; } /** * @brief Function to get Transmit ID * @note Must be called after readSetupFile * @param None * @retval Transmit ID */ uint32_t FILEMANAGER_GetTxID() { return m_TxID; } /** * @brief Utility to play with LED status * @note Libary user need to assign proper PinName to LED_SDCARD * @param on - True for turning LED ON, otherwise LED off * @retval None */ static void FILEMANAGER_SetLedStatus(bool on) { /* Check LED Connection */ if (ledStatus.is_connected()) { /* Set LED regarding to given argment */ if (m_sdCardIsPresent) { ledStatus = on; } else { ledStatus = false; } } #if DEBUG else { printf("\r\nSDCard LED is not connected !!"); } #endif } #if UART_FILE_ACCESS /** * @brief Utility to show list of file in SD Card * @param serial - pointer to serial to be display as output * @retval None */ void FILEMANAGER_listDir(Serial* serial) { DIR *d; struct dirent *p; d = opendir("/sd"); if (d != NULL) { while ((p = readdir(d)) != NULL) { if (serial != NULL) { serial->printf("\n\r%s", p->d_name); } else { printf("\n\r%s", p->d_name); } } } else { printf("Could not open directory!\n"); } closedir(d); } /** * @brief Utility to display content of specific file * @param serial - pointer to serial to be display as output * @param filename - filename to be read * @retval None */ void FILEMANAGER_DisplayFile(Serial* serial, char* filename) { FILEMANAGER_AddPrefixFilename(filename, m_bufFileName); /* Open the file with reading mode */ FILE *fp = fopen(m_bufFileName, "r"); if (fp == NULL) { /* if it can't open the file then print error message */ if (serial != NULL) { serial->printf("\nError! Unable to open file! %s \n", filename); } else { printf("\nError! Unable to open file! %s \n", filename); } } else { /* Allocate buffer for reading file */ char buf[READ_FILE_BUFFER_SIZE]; /* Read line from the file */ while (fgets(buf, sizeof(buf), fp) != NULL) { if (serial != NULL) { serial->printf("\n%s", buf); } else { printf("\n%s", buf); } #if WATCHDOG_ENABLE /** restart Watchdog */ wd.Service(); #endif } /* Close File */ fclose(fp); #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler free(fp); #endif } } /** * @brief Utility to replace content of specific file * @param serial - pointer to serial to be display as output * @param filename - filename to be replace * @retval None */ WritingFileStatus FILEMANAGER_WriteFile(Serial* serial, char* filename, char* input) { WritingFileStatus status = FILE_OK; FILEMANAGER_AddPrefixFilename(filename, m_bufFileName); FILE *fp = fopen(m_bufFileName, "a"); if (fp == NULL) { /* if it can't open the file then print error message */ if (serial != NULL) { serial->printf("\nError! Unable to open file! %s \n", filename); } else { printf("\nError! Unable to open file! %s \n", filename); } status = FILE_ERROR; } else { fprintf(fp, "%s",input); fclose(fp); #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler free(fp); #endif } return status; } void FILEMANAGER_AddPrefixFilename(char* in, char* out) { sprintf(out,"%s%s", PREFIX_FILE_NAME, in); } #endif