


#include "head.h"

#ifdef CAN_SLAVE_BOARD

struct history_rcd_file fixd_ll_file;
struct history_rcd_file rand_ll_file;
struct history_rcd_file frzd_ll_file;
struct history_rcd_file sharpd_ll_file;
struct history_rcd_file monthd_ll_file;
struct history_rcd_file eventd_ll_file;


struct ll_file_info fixd_file_info;
struct ll_file_info rand_file_info;
struct ll_file_info frzd_file_info;
struct ll_file_info sharpd_file_info;
struct ll_file_info monthd_file_info;
struct ll_file_info eventd_file_info;

DWORD us0_ll;
bool ll_file_set=0;

fileInfo fixdList;      //线损模块定时冻结
fileInfo randList;      //线损模块瞬时冻结
fileInfo frzdList;      //线损模块日冻结
fileInfo sharpdList;        //线损模块整点冻结
fileInfo monthdList;        //线损模块考核日冻结

fileInfo eventd_pnaList;    //A 相有功功率反向
fileInfo eventd_pnbList;    //B 相有功功率反向
fileInfo eventd_pncList;    //C 相有功功率反向
fileInfo eventd_flownList;  //潮流方向改变
fileInfo eventd_llclrList;  //线损模块清零
fileInfo eventd_soeclrList; //事件清零
fileInfo eventd_syntList;   //校时

fileInfo *p_eventdList[]=
{
    &eventd_pnaList,
    &eventd_pnbList,
    &eventd_pncList,
    &eventd_flownList,
    &eventd_llclrList,
    &eventd_soeclrList,
    &eventd_syntList
};


const struct ll_element FIXD_ELEMENT_ST[]=
{
    {0x6401,    "kWh",  &meter_dd[ID_EP_P].value},
    {0x6402,    "kWh",  &meter_dd[ID_EQ_P].value},
    {0x6403,    "kWh",  &meter_dd[ID_EQ_1].value},
    {0x6404,    "kWh",  &meter_dd[ID_EQ_4].value},
    {0x6405,    "kWh",  &meter_dd[ID_EP_N].value},
    {0x6406,    "kWh",  &meter_dd[ID_EQ_N].value},
    {0x6407,    "kWh",  &meter_dd[ID_EQ_2].value},
    {0x6408,    "kWh",  &meter_dd[ID_EQ_3].value},

    {0x4008,    "W",    &meter_yc[ID_PA].value},
    {0x4009,    "W",    &meter_yc[ID_PB].value},
    {0x400A,    "W",    &meter_yc[ID_PC].value},
    {0x400B,    "W",    &meter_yc[ID_P].value},
};
const int FIXD_ELEMENT_ST_NUMBER  = sizeof( FIXD_ELEMENT_ST ) / sizeof(FIXD_ELEMENT_ST[0]);


const struct ll_element RAND_ELEMENT_ST[]=
{
    {0x6401,    "kWh",  &meter_dd[ID_EP_P].value},
    {0x6402,    "kWh",  &meter_dd[ID_EQ_P].value},
    {0x6403,    "kWh",  &meter_dd[ID_EQ_1].value},
    {0x6404,    "kWh",  &meter_dd[ID_EQ_4].value},
    {0x6405,    "kWh",  &meter_dd[ID_EP_N].value},
    {0x6406,    "kWh",  &meter_dd[ID_EQ_N].value},
    {0x6407,    "kWh",  &meter_dd[ID_EQ_2].value},
    {0x6408,    "kWh",  &meter_dd[ID_EQ_3].value},

    {0x4008,    "W",    &meter_yc[ID_PA].value},
    {0x4009,    "W",    &meter_yc[ID_PB].value},
    {0x400A,    "W",    &meter_yc[ID_PC].value},
    {0x400B,    "W",    &meter_yc[ID_P].value},
};
const int RAND_ELEMENT_ST_NUMBER  = sizeof( RAND_ELEMENT_ST ) / sizeof(RAND_ELEMENT_ST[0]);


const struct ll_element FRZD_ELEMENT_ST[]=
{
    {0x6401,    "kWh",  &meter_dd[ID_EP_P].value},
    {0x6402,    "kWh",  &meter_dd[ID_EQ_P].value},
    {0x6403,    "kWh",  &meter_dd[ID_EQ_1].value},
    {0x6404,    "kWh",  &meter_dd[ID_EQ_4].value},
    {0x6405,    "kWh",  &meter_dd[ID_EP_N].value},
    {0x6406,    "kWh",  &meter_dd[ID_EQ_N].value},
    {0x6407,    "kWh",  &meter_dd[ID_EQ_2].value},
    {0x6408,    "kWh",  &meter_dd[ID_EQ_3].value},

    {0x4008,    "W",    &meter_yc[ID_PA].value},
    {0x4009,    "W",    &meter_yc[ID_PB].value},
    {0x400A,    "W",    &meter_yc[ID_PC].value},
    {0x400B,    "W",    &meter_yc[ID_P].value},
};
const int FRZD_ELEMENT_ST_NUMBER  = sizeof( FRZD_ELEMENT_ST ) / sizeof(FRZD_ELEMENT_ST[0]);


const struct ll_element SHARPD_ELEMENT_ST[]=
{
    {0x6401,    "kWh",  &meter_dd[ID_EP_P].value},
    {0x6405,    "kWh",  &meter_dd[ID_EP_N].value},
};
const int SHARPD_ELEMENT_ST_NUMBER  = sizeof( SHARPD_ELEMENT_ST ) / sizeof(SHARPD_ELEMENT_ST[0]);


const struct ll_element MONTHD_ELEMENT_ST[]=
{
    {0x6401,    "kWh",  &meter_dd[ID_EP_P].value},
    {0x6402,    "kWh",  &meter_dd[ID_EQ_P].value},
    {0x6403,    "kWh",  &meter_dd[ID_EQ_1].value},
    {0x6404,    "kWh",  &meter_dd[ID_EQ_4].value},
    {0x6405,    "kWh",  &meter_dd[ID_EP_N].value},
    {0x6406,    "kWh",  &meter_dd[ID_EQ_N].value},
    {0x6407,    "kWh",  &meter_dd[ID_EQ_2].value},
    {0x6408,    "kWh",  &meter_dd[ID_EQ_3].value},

};
const int MONTHD_ELEMENT_ST_NUMBER  = sizeof( MONTHD_ELEMENT_ST ) / sizeof(MONTHD_ELEMENT_ST[0]);









LL_FILE_ST ll_file_st[]=
{
    {"fixd",    &fixd_ll_file,      &fixd_file_info,    &fixdList,      FIXD_ELEMENT_ST,        FIXD_LL_HEAD,   LL_FIXD_101_DIR,    12, 60, false},
    {"rand",    &rand_ll_file,      &rand_file_info,    &randList,      RAND_ELEMENT_ST,        RAND_LL_HEAD,   LL_RAND_101_DIR,    12, 3,  false},
    {"frzd",    &frzd_ll_file,      &frzd_file_info,    &frzdList,      FRZD_ELEMENT_ST,        FRZD_LL_HEAD,   LL_FRZD_101_DIR,    12, 62, false},
    {"sharpd",  &sharpd_ll_file,    &sharpd_file_info,  &sharpdList,    SHARPD_ELEMENT_ST,      SHARPD_LL_HEAD, LL_SHARPD_101_DIR,  2,  264,false},
    {"monthd",  &monthd_ll_file,    &monthd_file_info,  &monthdList,    MONTHD_ELEMENT_ST,      MONTHD_LL_HEAD, LL_MONTHD_101_DIR,  8,  12, false},
    {"eventd",  &eventd_ll_file,    &eventd_file_info,  NULL,   		NULL,                   EVENTD_LL_HEAD, LL_EVENTD_101_DIR,  8,  70, false},

};


typedef struct date
{
    int year;
    int month;
    int day;
} date;

int dpm[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; /*平年每月天数*/

short month_prev[]= {12,1,2,3,4,5,6,7,8,9,10,11};
/*判断闰年1:是;0:否*/
/*闰年特点：年份是4的倍数但不是100的倍数、年份是400的倍数*/
int isLeap(int year)
{
    return(year%4==0&& year%100!=0)||(year%400==0);
}


/*日期校验*/
/*日期错误返回1，正确返回0*/
int dateIsErr(date d)
{
    if(d.year<1582&& d.month<10&& d.day<15)/*仅支持1582年10月15日之后的日期计算*/
        return 1;
    if(d.month<1|| d.month>12)/*月校验*/
        return 1;
    if(d.day<1|| d.day>31)/*日初步校验*/
        return 1;
    if(d.month!=2&& d.day>dpm[d.month])/*非2月日校验*/
        return 1;
    if(d.month==2&&isLeap(d.year)&& d.day>29)/*2月闰年日校验*/
        return 1;
    if(d.month==2&&isLeap(d.year)==0&& d.day>28)/*2月平年日校验*/
        return 1;
    return 0;
}



/*计算与日期start相差delta天的日期*/
date dateDelta(date start,int delta)
{

    date end = start;

    if(delta>=0)
    {
        /*日期start向后计算*/
        end.day = start.day+ delta;/*start日加intervalDays天*/
        while(end.day> dpm[end.month])
        {
            /*不断减去整月天数，向月、年进位，直至其不超过当前月份天数*/
            end.day-= dpm[end.month];
            if(isLeap(end.year)&& end.month==2)/*闰年2月天数-1*/
                end.day--;

            end.month++;/*月进位+1*/

            if(end.month==13)
            {
                /*满1年*/
                end.year++;/*年进位+1*/
                end.month=1;/*月归位至1月*/
            }
        }
    }
    else
    {
        /*日期start向前计算*/
        end.day=    start.day+delta;/*start日加intervalDays天*/
        while(end.day<1)
        {
            /*不断加整月天数，向月、年借位，直至其不小于1*/
            end.month--;/*月借位-1*/
            if(end.month==0)
            {
                /*向年借位*/
                end.year--;/*年借位-1*/
                end.month=12;/*月归位至12月*/
            }
            end.day+=dpm[end.month];
            if(isLeap(end.year)&& end.month==2)/*闰年2月天数+1*/
                end.day++;
        }
    }

    return end;
}

int day_sum(int y,int m,int d)
{
    unsigned char x[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
    int i,s=0;
    for(i=1; i<y; i++)
    {
        if((i%4==0 && i%100!=0) || i%400==0)
            s+=366;//闰年
        else
            s+=365;//平年
    }

    if((y%4==0 && y%100!=0) || y%400==0)
        x[2]=29;
    for(i=1; i<m; i++)
        s+=x[i];//整月的天数
    s+=d;//日的天数
    return s;//返回总天数,相对公元1年
}




int delete_ll_file(u8 file_id)
{
    LL_FILE_ST *p_file_st;
    char dir_name[64];

    if(file_id>=ID_LL_FILE_NUM)
        return -1;

    p_file_st = &ll_file_st[file_id];

    sprintf(dir_name,"%s%s%02d.msg",p_file_st->file_dir,p_file_st->file_name,tRunPara.wSWID);

    //删除保存的文件
    p_file_st->p_file->handle = rt_file_open(dir_name,O_CREAT|O_RDWR,0);

    if(IS_ERR(p_file_st->p_file->handle))
    {
        p_file_st->p_file->handle = 0;
        return -2;
    }

    rt_file_close(p_file_st->p_file->handle,0);

    if(rt_file_del(dir_name))
        return -3;


    return 0;
}


void init_ll_db_file(fileInfo *p_db,char *file_name,int sectNum,int listSize)
{
	fileInfo *p_list = p_db;
	memset((char *)p_list,0,sizeof( fileInfo));
    sprintf(p_list->fileName,file_name);
   	p_list->listMax = sectNum;
    p_list->listSize =listSize;//时标+4*12(浮点数存储)
    p_list->fileTatal=1;
    p_list->fileTableSize=0;
    initListData(p_list);
}


int init_his_ll(void)
{

	init_ll_db_file(&fixdList,"fixd.dat",ll_file_st[ID_LL_FILE_FIXD].sectNum,8+4*ll_file_st[ID_LL_FILE_FIXD].dataNum);//时标+4*12(浮点数存储)
	init_ll_db_file(&randList,"rand.dat",ll_file_st[ID_LL_FILE_RAND].sectNum,8+4*ll_file_st[ID_LL_FILE_RAND].dataNum);//时标+4*12(浮点数存储)
	init_ll_db_file(&frzdList,"frzd.dat",ll_file_st[ID_LL_FILE_FRZD].sectNum,8+4*ll_file_st[ID_LL_FILE_FRZD].dataNum);//时标+4*12(浮点数存储)
	init_ll_db_file(&sharpdList,"sharpd.dat",ll_file_st[ID_LL_FILE_SHARPD].sectNum,8+4*ll_file_st[ID_LL_FILE_SHARPD].dataNum);//时标+4*12(浮点数存储)
	init_ll_db_file(&monthdList,"monthd.dat",ll_file_st[ID_LL_FILE_MONTHD].sectNum,8+4*ll_file_st[ID_LL_FILE_MONTHD].dataNum);//时标+4*12(浮点数存储)

	init_ll_db_file(&eventd_pnaList,"eventd_pna.dat",10,1+8+4+4*8+8+4*8);//事件类型(1)+时标(8)+记录次数(4)+4*8(浮点数存储)+时标(8)+4*8(浮点数存储)
	init_ll_db_file(&eventd_pnbList,"eventd_pnb.dat",10,1+8+4+4*8+8+4*8);//事件类型(1)+时标(8)+记录次数(4)+4*8(浮点数存储)+时标(8)+4*8(浮点数存储)
	init_ll_db_file(&eventd_pncList,"eventd_pnc.dat",10,1+8+4+4*8+8+4*8);//事件类型(1)+时标(8)+记录次数(4)+4*8(浮点数存储)+时标(8)+4*8(浮点数存储)
	init_ll_db_file(&eventd_flownList,"eventd_flown.dat",10,1+8+4+4*8);//事件类型(1)+时标(8)+记录次数(4)+4*8(浮点数存储)
	init_ll_db_file(&eventd_llclrList,"eventd_llclr.dat",10,1+8+4+4*8);//事件类型(1)+时标(8)+记录次数(4)+4*8(浮点数存储)
	init_ll_db_file(&eventd_soeclrList,"eventd_soeclr.dat",10,1+8+4);//事件类型(1)+时标(8)+记录次数(4)
	init_ll_db_file(&eventd_syntList,"eventd_synt.dat",10,1+8+4);//事件类型(1)+时标(8)+记录次数(4)

    return 0;
}



/******************************************************************************
函数名称：  init_ll_file_fixd
函数版本：  01.01
创建作者：  xj
创建日期：  2016-08-09
函数说明：  上电初始化事件记录文件，读取对应目录下记录文件，
            未创建文件，则创建新的事件记录文件
参数说明：

返回值：
    0：     成功
    其它：  失败
修改记录：
*/
int init_ll_file(void)
{
    int ret=0;
    int i;


	fixd_file_info.b_first = true;
	rand_file_info.b_first = true;
	frzd_file_info.b_first = true;
	sharpd_file_info.b_first = true;
	monthd_file_info.b_first = true;
	eventd_file_info.b_first = true;

    us0_ll=ustimer_get_origin();

    init_his_ll();

      	// be modified by Jack.Liu on 2020/06/19--19:42:19  测试使用

    for(i=0; i<ID_LL_FILE_NUM; i++)
    {

        delete_ll_file(i);
        
        ret = create_ll_file(i);

    }


    return ret;

}








/******************************************************************************
函数名称：  ll_read_fixp_file
函数版本：  01.01
创建作者：  xj
创建日期：  2016-08-09
函数说明：  读取第几天的定点记录文件
参数说明：  day:第几天，p_part_id:节点索引

返回值：
    0：     成功
    其它：  失败
修改记录：
*/
int  ll_read_file(u8 file_id)
{
    int file_len;
    char * file_buf;
    loff_t pos;
    int ret=0;
    char dir_name[64] = {0};
    LL_FILE_ST *p_file_st;

    if(file_id>=ID_LL_FILE_NUM)
        return -1;

    p_file_st = &ll_file_st[file_id];

    if(p_file_st->p_file->name == NULL)
        return -1;


    sprintf(dir_name,"%s%s%02d.msg",p_file_st->file_dir,p_file_st->p_file->name,tRunPara.wSWID);

    //打开文件
    p_file_st->p_file->handle = rt_file_open(dir_name,O_CREAT|O_RDWR,0);

    if(IS_ERR(p_file_st->p_file->handle))
    {
        p_file_st->p_file->handle = 0;
        rt_printf("%s:%s open error!\r\n",__func__,p_file_st->p_file->name);
        return -2;
    }

    //得到文件长度
    rt_file_llseek(p_file_st->p_file->handle,0,SEEK_END);
    file_len= p_file_st->p_file->handle->f_pos;
    rt_file_llseek(p_file_st->p_file->handle,0,SEEK_SET);

    //文件长度为0
    if(file_len == 0)
        return -3;

    //分配内存
    file_buf = rt_malloc(file_len);
    if(file_buf == NULL)
        return -4;

    memset(file_buf,0,file_len);

    //读出文件内容
    pos=0;
    ret = rt_file_read(p_file_st->p_file->handle,file_buf, file_len,&pos);
    if(ret !=  file_len)
    {
        rt_file_close(p_file_st->p_file->handle,0);
        p_file_st->p_file->handle = 0;
        rt_printf("%s:%s read error:file_length=%d,ret=%d!\r\n",__func__,p_file_st->p_file->name,file_len,ret);

        rt_free(file_buf);
        return -5;
    }

    rt_file_close(p_file_st->p_file->handle,0);

    //节点数
    p_file_st->p_file->node_num = atoi(&file_buf[FIXD_LL_ID_OFFSET]);
    p_file_st->p_file->offset = pos;

    //释放内存
    rt_free(file_buf);

    return ret;
}



/******************************************************************************
函数名称：  create_event_rcd_file
函数版本：  01.01
创建作者：  xj
创建日期：  2016-08-09
函数说明：  创建最初事件记录或操作记录文件
参数说明：

返回值：
    0：     成功
    其它：  失败
修改记录：
*/
int create_ll_file(u8 file_id)
{
    int i,j,k;
    unsigned int file_len,head_len;
    char *p,*p_file;
    loff_t pos;
    struct rtc_time_t tm;   //时标

    LL_FILE_ST *p_file_st;
    u16 rcd_len;
    u16 event_num;

    int ret = 0;
    char dir_name[64]= {0};
    char tmp_buf[128]= {0};


	
    if(file_id>=ID_LL_FILE_NUM)
        return -1;

	

    p_file_st = &ll_file_st[file_id];
    head_len = strlen(p_file_st->file_head);
    rcd_len = p_file_st->sectNum*(strlen(LL_RCD_HEAD)+p_file_st->dataNum*strlen(LL_RCD)+1);
    file_len = head_len + rcd_len + 1;

    // 分配并初始化空间
    p_file = rt_malloc(file_len);
    if(!p_file)
        return -2;

    memset(p_file,0,file_len);
    p = p_file;

    if(file_id!=ID_LL_FILE_EVENTD)
    {
        j = sprintf(p,"%s%02d.msg,v1.0\r\n",p_file_st->file_name,tRunPara.wSWID); //文件头
        p += j;
    }

    if(set_get_fixed_arg(FIXED_SET_ID,tmp_buf, sizeof(tmp_buf)))
    {
        strcpy(tmp_buf,"XXXXXXXXXXXXXXXXXXXXXXXX");
    }

    j = sprintf(p,"%24.24s,",tmp_buf);
    p += j;

    if(file_id!=ID_LL_FILE_EVENTD)
    {
        j = sprintf(p,"%03d,",p_file_st->p_list->listNum);//节数 n
        p += j;

        j = sprintf(p,"02\r\n");//信息对象地址长度
        p += j;
    }
    /*
    else
    {
        j = sprintf(p,"%02d\r\n",p_file_st->p_list->listNum);//节数 n
        p += j;
    }
    */


    if(file_id!=ID_LL_FILE_EVENTD)
    {
        for(i=0; i<p_file_st->p_list->listNum; i++)
        {

            union
            {
                float ff;
                u8 tt[4];
            } ff;

            readListData(p_file_st->p_list,i+1,tmp_buf);

            //线损模块数据信息对象数目
            j = sprintf(p,"%d,",p_file_st->dataNum);
            p += j;

            //记录时间 YYYY-MM-DD HH:MM:SS
            memcpy(&tm,tmp_buf,8);//时标
            j = sprintf(p,"%04d-%02d-%02d %02d:%02d:%02d,",
                        tm.year+2000,
                        tm.month,
                        tm.day,
                        tm.hour,
                        tm.min,
                        tm.ms/1000);
            p += j;

            for(k=0; k<p_file_st->dataNum; k++)
            {
                struct ll_element *p_ele = (struct ll_element *)&p_file_st->p_element[k];

                j = sprintf(p,"%04x,",p_ele->ti);
                p += j;

                memcpy(&ff.tt,tmp_buf+8+4*k,4);
                if(k==p_file_st->dataNum-1)
                {
                    j = sprintf(p,"%8.2f",ff.ff);//信息元素值
                }
                else
                {
                    j = sprintf(p,"%8.2f,",ff.ff);//信息元素值
                }

                p += j;
            }

            j = sprintf(p,"\r\n");
            p += j;

        }
    }
    else  //事件记录
    {

        event_num = eventd_pnaList.listNum + eventd_pnbList.listNum + eventd_pncList.listNum + eventd_flownList.listNum
                    + eventd_llclrList.listNum + eventd_soeclrList.listNum + eventd_syntList.listNum;

        j = sprintf(p,"%02d\r\n",event_num);//节数 n
        p += j;

        for(i=0; i<7; i++)
        {
            int m;
            fileInfo  *p_list;
		
            p_list = p_eventdList[i];

            for(m=0; m<p_list->listNum; m++)
            {
                u8 type;
                u32 times;

                union
                {
                    float ff;
                    u8 tt[4];
                } ff;

                readListData(p_list,m+1,tmp_buf);
                memcpy(&type,tmp_buf,1);//事件类型

                //类型编号
                j = sprintf(p,"%02d,",type);
                p += j;

                //YYYY-MM-DD HH:mm:ss.XXX
                memcpy(&tm,tmp_buf+1,8);
                j = sprintf(p,"%04d-%02d-%02d %02d:%02d:%02d.%03d,",
                            tm.year+2000,
                            tm.month,
                            tm.day,
                            tm.hour,
                            tm.min,
                            tm.ms/1000,
                            tm.ms%1000);
                p += j;

                memcpy(&times,tmp_buf+9,4);

                if(type == 1)
                {
                    EventNumData.sADir_Num = times;
                }
                else if(type == 2)
                {
                    EventNumData.sBDir_Num = times;
                }
                else if(type == 3)
                {
                    EventNumData.sCDir_Num = times;
                }
                else if(type == 4)
                {
                    EventNumData.sDir_Num = times;
                }
                else if(type == 5)
                {
                    EventNumData.sClr_Num = times;
                }
                else if(type == 6)
                {
                    EventNumData.sSOEClr_Num = times;
                }
                else if(type == 7)
                {
                    EventNumData.sAdjustTime_Num = times;
                }
                if((type==6)||(type==7))
                {
                    //记录总次数
                    j = sprintf(p,"%08d",times);
                    p += j;
                }
                else
                {
                    //记录总次数
                    j = sprintf(p,"%08d,8,",times);
                    p += j;

                    for(k=0; k<8; k++)
                    {
                        j=sprintf(p,"%04x,",meter_dd[k].ti);
                        p += j;

						memcpy(&ff.tt,tmp_buf+13+4*k,4);
						if((type == 1)||(type == 2)||(type == 3))
						{
	                        j = sprintf(p,"%8.2f,",ff.ff);//信息元素值
	                        p += j;
						}
						else
						{
							if(k==7)
                            {
                                j = sprintf(p,"%8.2f",ff.ff);//信息元素值
                            }
                            else
                            {
                                j = sprintf(p,"%8.2f,",ff.ff);//信息元素值
                               
                            }
							 p += j;
						}

                        
                    }

        
                    if((type == 1)||(type == 2)||(type == 3))
                    {
                    	//结束时刻
                        memcpy(&tm,tmp_buf+13+4*8,8);
                        j = sprintf(p,"%04d-%02d-%02d %02d:%02d:%02d.%03d,",
                                    tm.year+2000,
                                    tm.month,
                                    tm.day,
                                    tm.hour,
                                    tm.min,
                                    tm.ms/1000,
                                    tm.ms%1000);
                        p += j;


                        for(k=0; k<8; k++)
                        {
                            j=sprintf(p,"%04x,",meter_dd[k].ti);
                            p += j;

                            memcpy(&ff.tt,tmp_buf+13+4*8+8+4*k,4);

                            if(k==7)
                            {
                                j = sprintf(p,"%8.2f",ff.ff);//信息元素值
                            }
                            else
                            {
                                j = sprintf(p,"%8.2f,",ff.ff);//信息元素值
                            }

                            p += j;
                        }
                    }

                }

                j = sprintf(p,"\r\n");
                p += j;

            }
        }
    }

    j = sprintf(p,"\r");//文件结束符
    p += j;


    file_len = p-p_file;

    sprintf(dir_name,"%s%s%02d.msg",p_file_st->file_dir,p_file_st->file_name,tRunPara.wSWID);

    p_file_st->p_file->handle = rt_file_open(dir_name,O_CREAT|O_RDWR,0);

    if(IS_ERR(p_file_st->p_file->handle))
    {
        p_file_st->p_file->handle = 0;
        rt_printf("%s:%s open error!\r\n",__func__,p_file_st->p_file->name);
        rt_free(p_file);
        return -3;
    }

    pos = 0;
    if(rt_file_write(p_file_st->p_file->handle,p_file,file_len,&pos) != file_len)
    {
        rt_free(p_file);
        return -4;
    }

    rt_file_close(p_file_st->p_file->handle,0);

    //释放内存
    rt_free(p_file);

    return ret;

}

//定时冻结
void refresh_fixd_file(void)
{
    int i,ret1,ret2;
    struct timespec ts;
    static struct rtc_time_t time;  //时标

    char rcd_buf[64]= {0};

    //获取当前时间
    clk_time_get(&ts);
    timespec_to_rtc(ts,&time,0);

    if(fixd_file_info.b_first)
    {
        fixd_file_info.time_bk = time;
        fixd_file_info.b_first = 0;
    }
    else if((tRunPara.wZDJG!=0)&&((time.min%tRunPara.wDDJG) == 0)
            &&(time.min!=fixd_file_info.time_bk.min)&&(time.year!=8))
    {

        fixd_file_info.time_bk = time;

        memcpy(rcd_buf,&time,8);

        for(i=0; i<FIXD_ELEMENT_ST_NUMBER; i++)
        {
            memcpy(&rcd_buf[8+4*i],FIXD_ELEMENT_ST[i].p_val,4);

        }
        writeListData(&fixdList,rcd_buf);

        ret1 = delete_ll_file(ID_LL_FILE_FIXD);
        ret2 = create_ll_file(ID_LL_FILE_FIXD);
#ifdef METERING_ENERGY
        energy_curve_refresh(ENERGY_CURVE_RT);
		metering_freeze_refresh(ENERGY_SET_DATA,&time);
#endif



        rt_printf_time("%s:listNum=%d,ret1=%d,ret2=%d\r\n",__func__,fixdList.listNum,ret1,ret2);

    }

}

//瞬时冻结
void refresh_rand_file(void)
{

    int i,ret1,ret2;
    struct timespec ts;
    static struct rtc_time_t time;  //时标
    char rcd_buf[64]= {0};

    if(rand_file_info.b_frz)
    {
        rand_file_info.b_frz = false;

        //获取当前时间
        clk_time_get(&ts);
        timespec_to_rtc(ts,&time,0);

        memcpy(rcd_buf,&time,8);

        for(i=0; i<RAND_ELEMENT_ST_NUMBER; i++)
        {
            memcpy(&rcd_buf[8+4*i],RAND_ELEMENT_ST[i].p_val,4);
        }
        writeListData(&randList,rcd_buf);


        ret1 = delete_ll_file(ID_LL_FILE_RAND);
        ret2 = create_ll_file(ID_LL_FILE_RAND);

        rt_printf_time("%s:listNum=%d,ret1=%d,ret2=%d\r\n",__func__,randList.listNum,ret1,ret2);

    }
}


//日冻结
void refresh_frzd_file(void)
{
    int i,ret1,ret2;
    struct timespec ts;
    static struct rtc_time_t time,tm;   //时标
    char rcd_buf[64]= {0};
    int day_pre,day_now;
    date date_pre,date_now;
    int days;

    struct rtc_time_t tm_end;   //时标
    int day_diff=0;

    //获取当前时间
    clk_time_get(&ts);
    timespec_to_rtc(ts,&time,0);

    day_now = day_sum(time.year,time.month, time.day);
    day_pre = day_sum(frzd_file_info.time_bk.year,frzd_file_info.time_bk.month,frzd_file_info.time_bk.day);

    if(frzd_file_info.b_first)
    {
        frzd_file_info.time_bk = time;
        frzd_file_info.b_first = 0;

        //读最后一条记录
        readListData(&frzdList,frzdList.listNum,rcd_buf);
        memcpy(&tm_end,rcd_buf,8);//时标
        date_now.year = time.year;
		date_now.month = time.month;
		date_now.day = time.day;


        if(frzdList.listNum)
        {
            day_diff =  day_now - day_sum(tm_end.year,tm_end.month,tm_end.day);
        }

        if(day_diff>0)
        {
            days = (day_diff>=7)?7:day_diff;

            for(i=0; i<FRZD_ELEMENT_ST_NUMBER; i++)
            {
                if(i<8)//只更新正向有功电能、正向无功电能...三象限无功电能,功率等因为停电，填0
                {
                    memcpy(&rcd_buf[8+4*i],&tRunPara.sysData.fwDD[i],4);
                }
            }

            for(i=0; i<days; i++)
            {
                date_pre = dateDelta(date_now,i-days+1);
                tm.year = date_pre.year;
                tm.month = date_pre.month;
                tm.day = date_pre.day;
                tm.hour = 0;
                tm.min = 0;
                tm.ms = 0;
                memcpy(rcd_buf,&tm,8);
                

                writeListData(&frzdList,rcd_buf);

                ret1 = delete_ll_file(ID_LL_FILE_FRZD);
                ret2 = create_ll_file(ID_LL_FILE_FRZD);
#ifdef METERING_ENERGY
                energy_curve_refresh(ENERGY_CURVE_DAY);
				metering_freeze_refresh(ENERGY_SET_DATA,&time);
#endif
                rt_printf_time("%s:listNum=%d,ret1=%d,ret2=%d\r\n",__func__,frzdList.listNum,ret1,ret2);

            }
        }

    }
    else if((day_now > day_pre)&&(time.year!=8))//装置未对时前的时间为2008年，不记录线损文件
    {
        if(day_now == (day_pre+1))
        {
            memcpy(rcd_buf,&time,8);

            for(i=0; i<FRZD_ELEMENT_ST_NUMBER; i++)
            {
                memcpy(&rcd_buf[8+4*i],FRZD_ELEMENT_ST[i].p_val,4);
            }
            writeListData(&frzdList,rcd_buf);
            frzd_file_info.time_bk = time;

            ret1 = delete_ll_file(ID_LL_FILE_FRZD);
            ret2 = create_ll_file(ID_LL_FILE_FRZD);
#ifdef METERING_ENERGY
            energy_curve_refresh(ENERGY_CURVE_DAY);
			metering_freeze_refresh(ENERGY_DAY_DATA,&time);
#endif
            rt_printf_time("%s:listNum=%d,ret1=%d,ret2=%d\r\n",__func__,frzdList.listNum,ret1,ret2);
        }
        else
        {
            frzd_file_info.b_first = 1;

        }

    }

}

//整点冻结
void refresh_sharpd_file(void)
{
    int i,ret1,ret2;
    struct timespec ts;
    static struct rtc_time_t time;  //时标
    char rcd_buf[64]= {0};

    //获取当前时间
    clk_time_get(&ts);
    timespec_to_rtc(ts,&time,0);

    if(sharpd_file_info.b_first)
    {
        sharpd_file_info.time_bk = time;
        sharpd_file_info.b_first = 0;
    }
    else if(((time.hour!=sharpd_file_info.time_bk.hour)
             &&(time.min == 0)&&(time.year!=8)))
    {
        sharpd_file_info.time_bk = time;

        memcpy(rcd_buf,&time,8);

        for(i=0; i<SHARPD_ELEMENT_ST_NUMBER; i++)
        {
            memcpy(&rcd_buf[8+4*i],SHARPD_ELEMENT_ST[i].p_val,4);
        }
        writeListData(&sharpdList,rcd_buf);


        ret1 = delete_ll_file(ID_LL_FILE_SHARPD);
        ret2 = create_ll_file(ID_LL_FILE_SHARPD);

        rt_printf_time("%s:listNum=%d,ret1=%d,ret2=%d\r\n",__func__,sharpdList.listNum,ret1,ret2);
    }

}


//考核日冻结
void refresh_monthd_file(void)
{
    int i,ret1,ret2;
    bool b_fill=false;
    struct timespec ts;
    static struct rtc_time_t time;  //时标
    int day_pre,day_now;
    char rcd_buf[64]= {0};

    struct rtc_time_t tm_end;   //时标

    //获取当前时间
    clk_time_get(&ts);
    timespec_to_rtc(ts,&time,0);

    day_now = day_sum(time.year,time.month, time.day);
    day_pre = day_sum(monthd_file_info.time_bk.year,monthd_file_info.time_bk.month,monthd_file_info.time_bk.day);

    if(monthd_file_info.b_first)
    {
        monthd_file_info.time_bk = time;
        monthd_file_info.b_first = 0;

		
        readListData(&monthdList,monthdList.listNum,rcd_buf);
        memcpy(&tm_end,rcd_buf,8);//时标

        while(monthdList.listNum)
        {

            if((tm_end.year*12 + tm_end.month)<(time.year*12 + time.month))
            {
                if(tm_end.month>=12)
                {
                    tm_end.year += 1;
                    tm_end.month = 1;
                }
                else
                {
                    tm_end.month += 1;
                }

                tm_end.day = tRunPara.wMonday;
                tm_end.hour=tRunPara.wMonhour;
                tm_end.min=0;
                tm_end.ms=0;
                memcpy(rcd_buf,&tm_end,8);
                for(i=0; i<MONTHD_ELEMENT_ST_NUMBER; i++)
                {
                    memcpy(&rcd_buf[8+4*i],&tRunPara.sysData.fwDD[i],4);
                }
                writeListData(&monthdList,rcd_buf);
                b_fill = true;

            }
            else
            {
                break;
            }

        }

        if(b_fill)
        {
            ret1 = delete_ll_file(ID_LL_FILE_MONTHD);
            ret2 = create_ll_file(ID_LL_FILE_MONTHD);
            rt_printf_time("%s:listNum=%d,ret1=%d,ret2=%d\r\n",__func__,monthdList.listNum,ret1,ret2);
        }

    }
    else
    {
    	if(day_pre > day_now)
    	{
    		monthd_file_info.time_bk = time;
    	}
        if((tRunPara.wMonday == time.day)
           &&(tRunPara.wMonhour == time.hour)
           &&(day_now > day_pre)
           &&(time.year!=8))
        {
            //只往前跨度一个月
            if((time.month + time.year*12) == (monthd_file_info.time_bk.month + monthd_file_info.time_bk.year*12 + 1))
            {

                monthd_file_info.time_bk = time;

                memcpy(rcd_buf,&time,8);

                for(i=0; i<MONTHD_ELEMENT_ST_NUMBER; i++)
                {
                    memcpy(&rcd_buf[8+4*i],MONTHD_ELEMENT_ST[i].p_val,4);
                }
                writeListData(&monthdList,rcd_buf);

                ret1 = delete_ll_file(ID_LL_FILE_MONTHD);
                ret2 = create_ll_file(ID_LL_FILE_MONTHD);
                rt_printf_time("%s:listNum=%d,ret1=%d,ret2=%d\r\n",__func__,monthdList.listNum,ret1,ret2);

            }
            else
            {
                monthd_file_info.b_first = 1;
            }

        }
    }

}

//月冻结
void refresh_month_file(void)
{
#ifndef CAN_DISABLE
    int i;
#endif
    static int first = 1;
    struct timespec ts;
    static struct rtc_time_t time;  //时标
    static struct rtc_time_t month_time;    //时标

    //获取当前时间
    clk_time_get(&ts);
    timespec_to_rtc(ts,&time,0);

    if(first)
    {
#ifdef METERING_ENERGY
	#ifndef CAN_DISABLE
        for(i=0; i<CAN_BOARD_NUM; i++)
	#endif
        {
		#ifndef CAN_DISABLE
            if(is_can_slot_valid(i))
		#endif
            {
                first = 0;
                month_time = time;
                //      energy_curve_refresh(ENERGY_CURVE_DAY);
                //      energy_curve_refresh(ENERGY_CURVE_MON);
            }
        }
#endif
    }
    else
    {
        if(time.month != month_time.month)
        {
            month_time = time;
#ifdef METERING_ENERGY
            energy_curve_refresh(ENERGY_CURVE_MON);
#endif
        }
    }
}


//更新事件有效数据    opt：0-》功率方向开始            1-》功率方向结束        2-》其他事件
int fresh_eventd_file(struct eventd_format_st *p,BYTE opt)
{
    int i;
    u8 type;
    char rcd_buf[100]= {0};
    //事件类型(1)+时标(8)+记录次数(4)+4*8(浮点数存储)+时标(8)+4*8(浮点数存储)

  
    if(opt==2)
    {
        type = p->type;
        memcpy(rcd_buf,&p->type,1);     //事件类型
        memcpy(rcd_buf+1,&p->start.tm,8);   //起始时间
        memcpy(rcd_buf+9,&p->times,4);//记录次数

        for(i=0; i<8; i++)
        {
            memcpy(rcd_buf+13+i*4,&p->start.ele[i].val,4);
        }

        memcpy(rcd_buf+13+8*4,&p->end.tm,8);    //结束时间

        for(i=0; i<8; i++)
        {
            memcpy(rcd_buf+21+8*4+i*4,&p->end.ele[i].val,4);
        }

        if((type>=1)&&(type<=7))
        {
            
            writeListData(p_eventdList[type-1],rcd_buf);
        }
        else
            return 0;

        //rt_printf("tyfx\r\n");
        return 1;    //总次数累加
    }
    else if(opt==0)     //功率反向开始
    {

        type = p->type;
        memcpy(rcd_buf,&p->type,1);     //事件类型
        memcpy(rcd_buf+1,&p->start.tm,8);   //起始时间
        memcpy(rcd_buf+9,&p->times,4);//记录次数

        if((type<1)||(type>3))    //功率方向才会进行此项
        {
            return 0;   //错误
        }

        for(i=0; i<8; i++)
        {
            memcpy(rcd_buf+13+i*4,&p->start.ele[i].val,4);
        }

        memset(rcd_buf+13+8*4,0,8);    //结束时间    数据填0
        
        for(i=0; i<8; i++)
        {
            memset(rcd_buf+21+8*4+i*4,0,4);
        }

        if((type>=1)&&(type<=7))
        {
            writeListData(p_eventdList[type-1],rcd_buf);
        }
        else
            return 0;
        //rt_printf("glfxs\r\n");
        return 1;     //总次数累加
    }
    else if(opt==1)    //功率反向结束
    {
        BYTE flag=0;
        int count,tmp;
        char buf[100]= {0};
        fileInfo* pList;
        
        if(p->type==1)
        {
          pList=&eventd_pnaList;
        }
        else if(p->type==2)
        {
          pList=&eventd_pnbList;
        }
        else if(p->type==3)
        {
          pList=&eventd_pncList;
        }
        else
            return 0;

        for(count=0; count<pList->listNum; count++)
        {

            readListData(pList,pList->listNum-count,buf);
            if(buf[0]==p->type)   //找到最近写入的同个类型的数据
            {
                if((buf[45]==0)&&(buf[46]==0)&&(buf[47]==0)&&
                   (buf[48]==0)&&(buf[49]==0)&&(buf[50]==0))   //判断结束时间为0
                {
                    flag=1;
                    tmp=pList->listNum-count;   //记录搜索到的序号

                    //rt_printf("find_replace_place=%d\r\n",tmp);
                    break;
                }
            }

            //rt_printf("find_replace_place_pro=%d\r\n",eventdList.listNum-count);
        }
        if(flag==0)
        {
#ifndef ADD_POWER_REVERSE_EVENT_FULL_FUN        
            type = p->type;
            memcpy(rcd_buf,&p->type,1);     //事件类型
            memset(rcd_buf+1,0,8);  //起始时间
            memcpy(rcd_buf+9,&p->times,4);//记录次数

            for(i=0; i<8; i++)
            {
                memset(rcd_buf+13+i*4,0,4);
            }

            memcpy(rcd_buf+13+8*4,&p->end.tm,8);    //结束时间
            for(i=0; i<8; i++)
            {
                memcpy(rcd_buf+21+8*4+i*4,&p->end.ele[i].val,4);
            }

           
            writeListData(p_eventdList[type-1],rcd_buf);
            //rt_printf("glfxew\r\n");
            return 1;        //总次数累加
#else
            return 0;        //总次数不累加 若找不到对应的开始时间则不写入事件
#endif
        }
        else
        {
            type = p->type;
            memcpy(rcd_buf,buf,100);                //获取开始的数据
            memcpy(rcd_buf+13+8*4,&p->end.tm,8);    //结束时间
            for(i=0; i<8; i++)
            {
                memcpy(rcd_buf+21+8*4+i*4,&p->end.ele[i].val,4);
            }

           
            ReplaceListData(p_eventdList[type-1],tmp,rcd_buf);       //覆盖某一条数据
            //rt_printf("glfxer\r\n");
            return 0;                                      //总次数不累加
        }
    }

    return -1;
}


void ll_file_app(void)
{
    int i;
    int ret1,ret2;
    if(tRunPara.bTT_LLFile)
    {
        refresh_rand_file();
        if(ustimer_get_duration(us0_ll) > USTIMER_SEC)
        {
            us0_ll=ustimer_get_origin();
            refresh_fixd_file();
            refresh_frzd_file();
            refresh_sharpd_file();
            refresh_monthd_file();
            refresh_month_file();

            if(eventd_file_info.b_new)
            {
            	DWORD event_num;
                eventd_file_info.b_new = false;
                ret1 = delete_ll_file(ID_LL_FILE_EVENTD);
                ret2 = create_ll_file(ID_LL_FILE_EVENTD);
				event_num = eventd_pnaList.listNum + eventd_pnbList.listNum + eventd_pncList.listNum + eventd_flownList.listNum
                    + eventd_llclrList.listNum + eventd_soeclrList.listNum + eventd_syntList.listNum;
                rt_printf_time("%s:listNum=%d,ret1=%d,ret2=%d\r\n",__func__,event_num,ret1,ret2);
            }


            for(i=0; i<8; i++)
            {
                tRunPara.sysData.fwDD[i] = *FIXD_ELEMENT_ST[i].p_val;
            }

        }
    }
    else
    {
        us0_ll=ustimer_get_origin();
    }

}


#endif


