Files
CuboBmsFirmware/firmware/Core/Src/SD_Card.c
2023-03-29 20:05:42 +03:00

573 lines
17 KiB
C

#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);
}