#include "SD_Card.h" #include "DPC_Timeout.h" #include "string.h" #include "stdlib.h" #include "stdio.h" #include "rtc.h" volatile ff_search_struct FileSearchStruct; void SD_Card_Var_Init(SD_CARD_Global_Struct* SD_Struct){ HTTP_DATA_Struct* HTTP_DATA; HTTP_DATA=&SD_Struct->CSV_DATA; SD_Struct->DATA0 = &SD_Struct->DATA0_ch[0]; SD_Struct->Header = "serial_number;" "started_at;" "ended_at;" "status_indication;" "energy_sum;" "battery_level_at_start;" "battery_level_at_end;" "battery_voltage_at_start;" "battery_voltage_at_end;" "battery_temperature_at_end;" "latitude;" "longitude;" "maximum_load_current;" "maximum_charge_current;" "internal_resistance;" "is_moderated;" "event_time;" "battery_condition_id\r"; SD_Struct->FileName = &SD_Struct->Filename_ch[0]; SD_Struct->Path = &SD_Struct->Path_ch[0]; HTTP_DATA->Serial_Number = &HTTP_DATA->Serial_Number_var[0]; HTTP_DATA->Battery_Condition_ID = &HTTP_DATA->Battery_Condition_ID_var[0]; HTTP_DATA->Event_time = &HTTP_DATA->Event_time_var[0]; HTTP_DATA->Started_At_Time = &HTTP_DATA->Started_At_Time_var[0]; HTTP_DATA->Ended_At_Time = &HTTP_DATA->Ended_At_Time_var[0]; HTTP_DATA->Status_Indication = &HTTP_DATA->Status_Indication_var[0]; HTTP_DATA->Energy_Sum = &HTTP_DATA->Energy_Sum_var[0]; HTTP_DATA->Battery_Level_At_Start = &HTTP_DATA->Battery_Level_At_Start_var[0]; HTTP_DATA->Battery_Level_At_End = &HTTP_DATA->Battery_Level_At_End_var[0]; HTTP_DATA->Battery_Voltage_At_Start = &HTTP_DATA->Battery_Voltage_At_Start_var[0]; HTTP_DATA->Battery_Voltage_At_End = &HTTP_DATA->Battery_Voltage_At_End_var[0]; HTTP_DATA->Battery_Temperature_At_End = &HTTP_DATA->Battery_Temperature_At_End_var[0]; HTTP_DATA->Latitude = &HTTP_DATA->Latitude_var[0]; HTTP_DATA->Longitude = &HTTP_DATA->Longitude_var[0]; HTTP_DATA->Maximum_Load_Current = &HTTP_DATA->Maximum_Load_Current_var[0]; HTTP_DATA->Maximum_Charge_Current = &HTTP_DATA->Maximum_Charge_Current_var[0]; HTTP_DATA->Internal_Resistance = &HTTP_DATA->Internal_Resistance_var[0]; HTTP_DATA->Moderated = &HTTP_DATA->Moderated_var[0]; HTTP_DATA->Current_time = &HTTP_DATA->Current_time_var[0]; } uint8_t SD_Received_LOOKFOR(char* answ, char* LOOKFOR){ uint8_t result=0; char *istr='\0'; istr=strstr(answ, LOOKFOR); if (istr=='\0') { result=0; //nothing found } else { result=1; //found } return result; } SD_Card_states SD_Set_Command(SD_CARD_Global_Struct* SD_Struct, SD_Op_Commands CMD, uint32_t Timeout){ if (SD_Struct->SD_State_to_return == SD_READY){ //Battery_Data_to_String_Converter(Sim_Struct); SD_Struct->SD_Active_Command = CMD; SD_Struct->SD_State_to_return = SD_BUSY; DPC_TO_Set(TO_SD_Card,Timeout); //CSV_Data_Compilation(SD_Struct); return SD_COMMAND_SET; } else return SD_COMMAND_NOT_SET; } void SD_Card_Processing(SD_CARD_Global_Struct* SD_Struct){ SD_Stages* Active_Stage; SD_Op_Commands* CMD; Time_Struct rtc_time; char Filename_ch[20]; char* Filename = &Filename_ch[0]; char Path_ch[100]; char* Path=&Path_ch[0]; FileSearchStruct.filename=&FileSearchStruct.filename_ch[0]; FileSearchStruct.fullpath=&FileSearchStruct.fullpath_ch[0]; strcpy(Path,""); strcpy(Filename,""); CMD = &SD_Struct->SD_Active_Command; Active_Stage = &SD_Struct->SD_Stages_list; SD_Struct->SD_CARD_ChipDetect = HAL_GPIO_ReadPin(SD_CD_GPIO_Port, SD_CD_Pin); if (DPC_TO_Check(TO_SD_Card)==TO_OUT_TOOK){ if (*Active_Stage != SD_IDLE) { SD_Struct->SD_Stages_list = SD_UMOUNT; } } switch (*Active_Stage){ case SD_IDLE: if (SD_Struct->Mount_Flag){ if (*CMD == SD_OP_WRITE_STATUS){ CSV_Status_Data_Compilation(SD_Struct); *Active_Stage = SD_OPEN_DIR; } else if (*CMD == SD_OP_WRITE_PARAM){ CSV_Param_Data_Compilation(SD_Struct); *Active_Stage = SD_OPEN_DIR; } else if(*CMD == SD_OP_WRITE_HEADER){ *Active_Stage = SD_OPEN_DIR; } else if (*CMD == SD_OP_DELETEOLD){ RTC_Get_Values(&rtc_time); if (rtc_time.year>20){ *Active_Stage = SD_DELETE_OLD_FILES; } else *Active_Stage = SD_IDLE; } } if (*CMD == SD_OP_MOUNT){ *Active_Stage = SD_MOUNT; } else if (*CMD == SD_OP_UMOUNT){ *Active_Stage = SD_UMOUNT; } break; case SD_MOUNT: fres = f_mount(&FatFs, "", 1); //1=mount now if (fres != FR_OK) { SD_Struct->Fat_result=fres; } else if(fres==FR_OK){ SD_Struct->Mount_Flag = 1; *Active_Stage = SD_CHECK_FREE_SPACE; } break; case SD_CHECK_FREE_SPACE: fres = f_getfree("", &free_clusters, &getFreeFs); if (fres == FR_OK) { total_sectors = (getFreeFs->n_fatent - 2) * getFreeFs->csize; free_sectors = free_clusters * getFreeFs->csize; #if _MAX_SS != _MIN_SS free_space=free_sectors*getFreeFs->ssize; #else free_space = free_sectors * 512; #endif if (free_space < __MIN_FREE_SPACE_REQUIRED){ *Active_Stage = SD_DELETE_OLD_FILES; } else { SD_Struct->Mount_Flag = 1; *Active_Stage = SD_IDLE; } } break; case SD_DELETE_OLD_FILES: FileSearchStruct.Oldest_FN_Month=99; FileSearchStruct.Oldest_FN_Year=99; FileSearchStruct.Oldest_FN_Value=0; Search_for_Oldest(&FileSearchStruct, Path, SD_Struct->Battery_Serial); strcat(FileSearchStruct.fullpath,"/"); strcat(FileSearchStruct.fullpath,FileSearchStruct.filename); if (FileSearchStruct.isDir==1){ fres = delete_node(FileSearchStruct.fullpath, sizeof(FileSearchStruct.fullpath_ch), &flinf); } else{ fres=f_unlink(FileSearchStruct.fullpath); } if (fres==FR_OK){ *Active_Stage = SD_CHECK_FREE_SPACE; } else *Active_Stage = SD_CHECK_FREE_SPACE; break; case SD_OPEN_DIR: //strcpy(Path,"/"); //itoa(SD_Struct->Battery_Serial,Path+1,sizeof(SD_Struct->Battery_Serial)+6); SD_Update_Path(SD_Struct); fres = f_opendir(&dir, SD_Struct->Path); if (fres == FR_OK) { *Active_Stage = SD_OPEN_FILE; } else if (fres == FR_NO_PATH){ fres = f_mkdir(SD_Struct->Path); *Active_Stage = SD_OPEN_DIR; } else *Active_Stage = SD_OPEN_DIR; break; case SD_OPEN_FILE: strcat(SD_Struct->Path,"/"); strcat(SD_Struct->Path,SD_Struct->FileName); if (f_open(&fil, SD_Struct->Path, FA_READ | FA_WRITE | FA_OPEN_ALWAYS )==FR_OK){ if (fil.fsize==0){ *Active_Stage = SD_WRITE_HEADER; } else { *Active_Stage = SD_READ; } } //fres = f_open(&fil, "1221.csv" /* SD_Struct->FileName*/, FA_READ | FA_WRITE | FA_OPEN_ALWAYS | FA_CREATE_ALWAYS); break; case SD_READ: fres = f_read(&fil, &readbuff[0], strlen(SD_Struct->Header), &nRead); //f_gets(&readbuff[0], sizeof(SD_Struct->Header),&fil); //if (fres == FR_OK){ if(SD_Received_LOOKFOR(&readbuff[0], SD_Struct->Header)){ *Active_Stage = SD_WRITE; } else *Active_Stage = SD_WRITE_HEADER; //} break; case SD_WRITE_HEADER: f_puts(SD_Struct->Header, &fil); *Active_Stage = SD_WRITE; break; case SD_WRITE: fres = f_lseek(&fil, f_size(&fil)); fres = f_write(&fil, SD_Struct->DATA0, strlen(SD_Struct->DATA0), &BytesWr); //f_puts(SD_Struct->DATA0, &fil); *Active_Stage = SD_CLOSE; break; case SD_CLOSE: if(f_close(&fil) == FR_OK){ if (f_closedir(&dir)==FR_OK){ *Active_Stage = SD_IDLE; } } break; case SD_UMOUNT: if(f_mount(NULL, "", 1) == FR_OK){ *Active_Stage = SD_IDLE; SD_Struct->Mount_Flag = 0; } break; } if (*Active_Stage == SD_IDLE) { SD_Struct->SD_Active_Command = SD_OP_DONOTHING; SD_Struct->SD_State_to_return = SD_READY; } else SD_Struct->SD_State_to_return = SD_BUSY; } void SD_Update_Path(SD_CARD_Global_Struct* source){ uint64_t Raw; char* part1="/"; char* stringptr=&source->Raw_var[0]; Raw=source->Battery_Serial; itoa(Raw,stringptr,sizeof(Raw)+2); strcpy(source->Path,part1); strcat(source->Path,stringptr); //strcat(source->Path,part1); } void Search_for_Oldest(volatile ff_search_struct* sourceStruct,char* Path, uint64_t ActualSerial){ uint32_t Raw; uint64_t Raw64; char Path2_ch[100]; char* Path2=&Path2_ch[0]; char Filename_ch[20]; char* Filename = &Filename_ch[0]; // Oldest_FN_Year = 99; // Oldest_FN_Month = 99; // Oldest_FN_Value = 0; fres = f_opendir(&dir,Path); if (fres == FR_OK) { //i = strlen(Path); for (;;) { fres = f_readdir(&dir, &flinf); /* Read a directory item */ if (fres != FR_OK || flinf.fname[0] == 0) break; /* Break on error or end of dir */ if (flinf.fname[0] == '.') continue; /* Ignore dot entry */ #if _USE_LFN Filename = *flinf.lfname ? fno.lfname : fno.fname; #else Filename = flinf.fname; #endif if ((flinf.fattrib & AM_DIR) && !(flinf.fattrib & AM_SYS) && !(flinf.fattrib & AM_HID) ){ Raw64=atol(Filename); if (Raw64 != ActualSerial){ strcpy(sourceStruct->fullpath,Path); strcpy(sourceStruct->filename,Filename); sourceStruct->isDir=1; break; } else { strcpy(Path2,Path); strcat(Path2,"/"); strcat(Path2,Filename); Search_for_Oldest(sourceStruct,Path2,ActualSerial); } // if (sourceStruct->value!=0){ // sourceStruct->Lastfound_FN_Month=(uint8_t)(sourceStruct->value/100); // Raw=sourceStruct->Lastfound_FN_Month*100; // sourceStruct->Lastfound_FN_Year=(uint8_t)(sourceStruct->value-Raw); // } } else if ( !(flinf.fattrib & AM_DIR) && !(flinf.fattrib & AM_SYS) && !(flinf.fattrib & AM_HID) ) { sourceStruct->isDir=0; sourceStruct->value = Filename_to_Value(Filename); if (sourceStruct->value!=0){ sourceStruct->Lastfound_FN_Month=(uint8_t)(sourceStruct->value/100); Raw=sourceStruct->Lastfound_FN_Month*100; sourceStruct->Lastfound_FN_Year=(uint8_t)(sourceStruct->value-Raw); // if (Lastfound_FN_Month<=Oldest_FN_Month && Lastfound_FN_Year<=Oldest_FN_Year){ // Oldest_FN_Year = Lastfound_FN_Year; // Oldest_FN_Month = Lastfound_FN_Month; // Oldest_FN_Value = FN_Value; // } } } if (sourceStruct->Lastfound_FN_Month!=0 || sourceStruct->Lastfound_FN_Year!=0){ if (sourceStruct->Lastfound_FN_Month<=sourceStruct->Oldest_FN_Month && sourceStruct->Lastfound_FN_Year<=sourceStruct->Oldest_FN_Year){ sourceStruct->Oldest_FN_Year = sourceStruct->Lastfound_FN_Year; sourceStruct->Oldest_FN_Month = sourceStruct->Lastfound_FN_Month; //sourceStruct->Oldest_FN_Value = sourceStruct->value; strcpy(sourceStruct->fullpath,Path); strcpy(sourceStruct->filename,Filename); } } // if (flinf.fattrib & AM_DIR) { /* It is a directory */ // //res = scan_files(path); // //if (res != FR_OK) break; // //path[i] = 0; // } else { /* It is a file. */ // // //printf("%s/%s\n", path, fn); // } } // if (Oldest_FN_Value!=0){ // Configure_Path_to_delete(Path, Oldest_FN_Value); // } //fres = f_unlink() } } void Battery_Data_to_CSV_Converter(SD_CARD_Global_Struct* Sd_Struct, HTTP_DATA_Struct* DST){ Battery_Data_Struct* Bat_data; HTTP_DATA_Struct CSV_Data_DST; CSV_Data_DST = *DST; char* Raw = &Sd_Struct->Raw_var[0]; int Size; Bat_data = &Sd_Struct->BATTERY_DATA; itoa(Bat_data->Serial,Raw,sizeof(Bat_data->Serial)+2); strcpy(Sd_Struct->CSV_DATA.Serial_Number, Raw); itoa(Bat_data->Battery_cond_ID,Raw,10); strcpy(Sd_Struct->CSV_DATA.Battery_Condition_ID, Raw); SIM800_Time_To_String(&Bat_data->Event_time,CSV_Data_DST.Event_time); SIM800_Time_To_String(&Bat_data->Started_At_Time,CSV_Data_DST.Started_At_Time); SIM800_Time_To_String(&Bat_data->Ended_At_Time,CSV_Data_DST.Ended_At_Time); itoa(Bat_data->Status_Indication,Raw,10); strcpy(CSV_Data_DST.Status_Indication, Raw); itoa(Bat_data->Energy_Sum,Raw,10); strcpy(CSV_Data_DST.Energy_Sum, Raw); itoa(Bat_data->Battery_Level_At_Start,Raw,10); strcpy(CSV_Data_DST.Battery_Level_At_Start, Raw); itoa(Bat_data->Battery_Level_At_End,Raw,10); strcpy(CSV_Data_DST.Battery_Level_At_End, Raw); sprintf(Raw, "%f", Bat_data->Battery_Voltage_At_Start); //ftoa(Bat_data->Battery_Voltage_At_Start,Raw,sizeof(Bat_data->Battery_Voltage_At_Start)); strcpy(CSV_Data_DST.Battery_Voltage_At_Start, Raw); sprintf(Raw, "%f", Bat_data->Battery_Voltage_At_End); //ftoa(Bat_data->Battery_Voltage_At_End,Raw,sizeof(Bat_data->Battery_Voltage_At_End)); strcpy(CSV_Data_DST.Battery_Voltage_At_End, Raw); itoa(Bat_data->Battery_Temperature_At_End,Raw,10); strcpy(CSV_Data_DST.Battery_Temperature_At_End, Raw); itoa(Bat_data->Maximum_Load_Current,Raw,10); strcpy(CSV_Data_DST.Maximum_Load_Current, Raw); itoa(Bat_data->Maximum_Charge_Current,Raw,10); strcpy(CSV_Data_DST.Maximum_Charge_Current, Raw); sprintf(Raw, "%f", Bat_data->Internal_Resistance); //ftoa(Bat_data->Internal_Resistance,Raw,sizeof(Bat_data->Internal_Resistance)); strcpy(CSV_Data_DST.Internal_Resistance, Raw); if (Bat_data->Moderated){ strcpy(CSV_Data_DST.Moderated,"true"); } else strcpy(CSV_Data_DST.Moderated,"false"); //memcpy(DST,&CSV_Data_DST, sizeof(CSV_Data_DST)); memset(Raw,0,100); } uint64_t Filename_to_Value(char* FN){ Time_Struct rtc_time; uint32_t Raw; uint32_t FN_month; char* istr="/0"; //char* test1_ptr=&test1[0]; istr=strstr(FN,".CSV"); if (istr=='\0') { Raw=0; //nothing found } else { Raw=atoi(istr-4); //found } return Raw; } uint8_t Configure_Path_to_delete(char* path, uint32_t Value){ char service[10]; char* csv=".CSV"; char* service_ptr=&service[0]; itoa(Value,service_ptr,sizeof(Value)+6); strcat(path,service_ptr); strcat(path,csv); } void CSV_Status_Data_Compilation(SD_CARD_Global_Struct* Sd_Struct){ char* Delimeter=";"; char* EndOfString = "\r"; strcpy(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Serial_Number); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Event_time); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Battery_Condition_ID); //strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,EndOfString); } void CSV_Param_Data_Compilation(SD_CARD_Global_Struct* Sd_Struct){ char* Delimeter=";"; char* EndOfString = "\n"; strcpy(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Serial_Number); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Started_At_Time); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Ended_At_Time); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Status_Indication); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Energy_Sum); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Battery_Level_At_Start); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Battery_Level_At_End); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Battery_Voltage_At_Start); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Battery_Voltage_At_End); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Battery_Temperature_At_End); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Latitude); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Longitude); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Maximum_Load_Current); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Maximum_Charge_Current); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Internal_Resistance); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,Sd_Struct->CSV_DATA.Moderated); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,""); //strcat(Sd_Struct->DATA0,Delimeter); strcat(Sd_Struct->DATA0,EndOfString); }