
#include "head.h"

#ifndef CAN_DISABLE
#ifdef CAN_SLAVE_BOARD

/*
struct frz_rcd_t 	rcd_fixd;
struct frz_rcd_t 	rcd_rand;
struct frz_rcd_t 	rcd_frzd;
struct frz_rcd_t 	rcd_sharpd;
struct frz_rcd_t 	rcd_monthd;
*/

METER_RUN_PARA tMeterRunPara;
METER_DATA tMeterData;
extern u32 g_start_sec;

u8 calib_wait = 0;
u8 calib_step = 0;

float freeze_dd[FREEZE_NUM];
u8 can_metering_set[2];
u8 can_metering_busy;
static unsigned char jxfs = 255;
static unsigned char wgfs = 255;

uint32_t swnd_us[4] = {0};
u8 metering_can_busy;


METER_YX_ST meter_yx[ID_YX_NUM] = 
{
	{0x0001, 0},
	{0x0002, 0},
	{0x0003, 0},
	{0x0004, 0},	
};


METER_YC_ST meter_yc[ID_YC_NUM] = 
{
	{0x4001,	0},
	{0x4002,	0},
	{0x4003,	0},
	{0x4004,	0},
	
	{0x4005,	0},
	{0x4006,	0},
	{0x4007,	0},

	{0x4008,	0},
	{0x4009,	0},
	{0x400A,	0},
	{0x400B,	0},


	{0x400C,	0},
	{0x400D,	0},
	{0x400E,	0},
	{0x400F, 	0},

	{0x4010, 	0},
	{0x4011, 	0},
	{0x4012, 	0},
	{0x4013, 	0},

	{0x4014, 	0},
	{0x4015, 	0},
	{0x4016, 	0},
	{0x4017, 	0},

	{0x4018, 	0},
	{0x4019, 	0},
	{0x401A, 	0},

};



METER_DD_ST meter_dd[ID_DD_NUM] = 
{
	{0x6401, 	0},
	{0x6402, 	0},
	{0x6403, 	0},
	{0x6404, 	0},
	
	{0x6405, 	0},
	{0x6406, 	0},
	{0x6407, 	0},
	{0x6408, 	0},

	{0x6409, 	0},
	{0x640A, 	0},
	{0x640B, 	0},
	{0x640C, 	0},
	{0x640D,	0},
	{0x640E,	0},

	{0x640F, 	0},
	{0x6410,	0},
	{0x6411,	0},
	{0x6412,	0},
	{0x6413,	0},

};

#if 0
const XS_CAN_SET_ST xs_can_set[]=
{
	{0x8021, 	1,	UTINY_R,	"考核日冻结日",							(void*)&tRunPara.frz_day 		},
	{0x8022, 	1,	UTINY_R,	"考核日冻结小时",							(void*)&tRunPara.frz_hour 		},
	{0x8023, 	1,	FLOAT_R,	"功率反向事件有功功率触发下限", 					(void*)&tRunPara.dRevLimtPW		},
	{0x8024, 	1,	USHORT_R,	"功率反向事件判定延时",						(void*)&tRunPara.dTRevLimtPW 	},
	{0x8025, 	1,	FLOAT_R,	"潮流方向改变事件有功功率触发下限",	(void*)&tRunPara.				dRevLimtTD 		},
	{0x8026, 	1,	USHORT_R,	"潮流方向改变事件判定延时" ,					(void*)&tRunPara.dTRevLimtTD	},
};
#endif



METER_YK_ST meter_yk[ID_YK_NUM] = 
{
	{0x6001, 	0},
	{0x6002, 	0},
	{0x6003, 	0},
};

/*
void metering_freeze_copy(int owner,int index)
{
	if(index == SW_DD_NOW1) 		//正向有功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EP_P].value;
	else if(index == SW_DD_NOW2) 	//正向无功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EQ_P].value;
	else if(index == SW_DD_NOW3) 	//日冻结，一象限无功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EQ_1].value;
	else if(index == SW_DD_NOW4) 	//日冻结，四象限无功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EQ_4].value;	

	if((index == SW_DD_DAY1) || (index == SW_DD_NOW1))			//冻结正向有功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EP_P].value;
	else if((index == SW_DD_DAY2) || (index == SW_DD_NOW2)) 	//冻结正向无功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EQ_P].value;
	else if((index == SW_DD_DAY3) || (index == SW_DD_NOW3)) 	//冻结一象限无功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EQ_1].value;
	else if((index == SW_DD_DAY4) || (index == SW_DD_NOW4))		//冻结四象限无功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EQ_4].value;

	else if((index == SW_DD_DAY5) || (index == SW_DD_NOW5)) 	//冻结反向有功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EP_N].value;
	else if((index == SW_DD_DAY6) || (index == SW_DD_NOW6)) 	//冻结反向无功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EQ_N].value;
	else if((index == SW_DD_DAY7) || (index == SW_DD_NOW7)) 	//冻结二象限无功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EQ_2].value;
	else if((index == SW_DD_DAY8) || (index == SW_DD_NOW8)) 	//冻结三象限无功功电能
		g_sw[owner].dd[index].fv = meter_dd[ID_EQ_3].value;
}
*/

#ifdef METERING_ENERGY
void metering_freeze_refresh(u8 data_type,struct rtc_time_t *p_time)
{
	int sw = 0;
	int i=0;

	if(data_type == ENERGY_CURVE_RT)
	{
		g_sw[sw].dd[SW_DD_NOW1].fv = meter_dd[ID_EP_P].value;  //更新到测量结构体中
		g_sw[sw].dd[SW_DD_NOW2].fv = meter_dd[ID_EQ_P].value;
		g_sw[sw].dd[SW_DD_NOW3].fv = meter_dd[ID_EQ_1].value;
		g_sw[sw].dd[SW_DD_NOW4].fv = meter_dd[ID_EQ_4].value;
		g_sw[sw].dd[SW_DD_NOW5].fv = meter_dd[ID_EP_N].value;
		g_sw[sw].dd[SW_DD_NOW6].fv = meter_dd[ID_EQ_N].value;
		g_sw[sw].dd[SW_DD_NOW7].fv = meter_dd[ID_EQ_2].value;
		g_sw[sw].dd[SW_DD_NOW8].fv = meter_dd[ID_EQ_3].value;

		g_sw[sw].dd[SW_DD_EPAP].fv = meter_dd[ID_EPA_P].value;
		g_sw[sw].dd[SW_DD_EPBP].fv = meter_dd[ID_EPB_P].value;
		g_sw[sw].dd[SW_DD_EPCP].fv = meter_dd[ID_EPC_P].value;
		g_sw[sw].dd[SW_DD_EPAN].fv = meter_dd[ID_EPA_N].value;
		g_sw[sw].dd[SW_DD_EPBN].fv = meter_dd[ID_EPB_N].value;
		g_sw[sw].dd[SW_DD_EPCN].fv = meter_dd[ID_EPC_N].value;

		g_sw[sw].dd[SW_DD_EPA].fv = meter_dd[ID_EPA].value;
		g_sw[sw].dd[SW_DD_EPB].fv = meter_dd[ID_EPB].value;
		g_sw[sw].dd[SW_DD_EPC].fv = meter_dd[ID_EPC].value;

		g_sw[sw].dd[SW_DD_EP].fv = meter_dd[ID_EP].value;
		g_sw[sw].dd[SW_DD_EQ].fv = meter_dd[ID_EQ].value;

	}
	else if(data_type == ENERGY_DAY_DATA)
	{
		g_sw[sw].dd[SW_DD_DAY1].fv = g_sw[sw].dd[SW_DD_NOW1].fv;  //更新到日冻结中
		g_sw[sw].dd[SW_DD_DAY2].fv = g_sw[sw].dd[SW_DD_NOW2].fv;
		g_sw[sw].dd[SW_DD_DAY3].fv = g_sw[sw].dd[SW_DD_NOW3].fv;
		g_sw[sw].dd[SW_DD_DAY4].fv = g_sw[sw].dd[SW_DD_NOW4].fv;
		g_sw[sw].dd[SW_DD_DAY5].fv = g_sw[sw].dd[SW_DD_NOW5].fv;
		g_sw[sw].dd[SW_DD_DAY6].fv = g_sw[sw].dd[SW_DD_NOW6].fv;
		g_sw[sw].dd[SW_DD_DAY7].fv = g_sw[sw].dd[SW_DD_NOW7].fv;
		g_sw[sw].dd[SW_DD_DAY8].fv = g_sw[sw].dd[SW_DD_NOW8].fv;
		for(i=SW_DD_DAY1;i<=SW_DD_DAY8;i++)
		{
#ifdef M_IT_TC
			int j;			
		
			for(j=0;j<CFG_UART_NUM_MAX;j++)
			{
				g_sw[sw].dd[i].bsend101[j] = true;
			}

			for(j=0;j<CFG_ETH_MAX_LOGIC;j++)
			{
				g_sw[sw].dd[i].bsend104[j] = true;
			}
#endif
			if(p_time)
			{
				g_sw[sw].dd[i].ct=*p_time;
				g_sw[sw].dd[i].bchanged=true;
			}
		}
	}
	else if(data_type == ENERGY_SET_DATA)
	{
		g_sw[sw].dd[SW_DD_15M1].fv = g_sw[sw].dd[SW_DD_NOW1].fv;  //更新到15分钟冻结中
		g_sw[sw].dd[SW_DD_15M2].fv = g_sw[sw].dd[SW_DD_NOW2].fv;
		g_sw[sw].dd[SW_DD_15M3].fv = g_sw[sw].dd[SW_DD_NOW3].fv;
		g_sw[sw].dd[SW_DD_15M4].fv = g_sw[sw].dd[SW_DD_NOW4].fv;
		g_sw[sw].dd[SW_DD_15M5].fv = g_sw[sw].dd[SW_DD_NOW5].fv;
		g_sw[sw].dd[SW_DD_15M6].fv = g_sw[sw].dd[SW_DD_NOW6].fv;
		g_sw[sw].dd[SW_DD_15M7].fv = g_sw[sw].dd[SW_DD_NOW7].fv;
		g_sw[sw].dd[SW_DD_15M8].fv = g_sw[sw].dd[SW_DD_NOW8].fv;
		for(i=SW_DD_15M1;i<=SW_DD_15M8;i++)
		{
#ifdef M_IT_TC
			int j;			
			
			for(j=0;j<CFG_UART_NUM_MAX;j++)
			{
				g_sw[sw].dd[i].bsend101[j] = true;
			}

			for(j=0;j<CFG_ETH_MAX_LOGIC;j++)
			{
				g_sw[sw].dd[i].bsend104[j] = true;
			}
#endif
			if(p_time)
			{
				g_sw[sw].dd[i].ct=*p_time;
				g_sw[sw].dd[i].bchanged=true;
			}
		}
	}
}

void metering_yc_refresh(void)
{
	int sw = 0;

	g_sw[sw].ac_in[SW_AC_IN_XS_UAB] = meter_yc[ID_UAB].value*Q16_BASE;  //更新到遥测结构体中
	g_sw[sw].ac_in[SW_AC_IN_XS_UBC] = meter_yc[ID_UBC].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_UCA] = meter_yc[ID_UCA].value*Q16_BASE;

	g_sw[sw].ac_in[SW_AC_IN_XS_UA] = meter_yc[ID_UA].value*Q16_BASE;  //更新到遥测结构体中
	g_sw[sw].ac_in[SW_AC_IN_XS_UB] = meter_yc[ID_UB].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_UC] = meter_yc[ID_UC].value*Q16_BASE;

	
	g_sw[sw].ac_in[SW_AC_IN_XS_IA] = meter_yc[ID_IA].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_IB] = meter_yc[ID_IB].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_IC] = meter_yc[ID_IC].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_P]  = meter_yc[ID_P].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_PA] = meter_yc[ID_PA].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_PB] = meter_yc[ID_PB].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_PC] = meter_yc[ID_PC].value*Q16_BASE;
	
	g_sw[sw].ac_in[SW_AC_IN_XS_Q]  = meter_yc[ID_Q].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_QA] = meter_yc[ID_QA].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_QB] = meter_yc[ID_QB].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_QC] = meter_yc[ID_QC].value*Q16_BASE;

	g_sw[sw].ac_in[SW_AC_IN_XS_S]    = meter_yc[ID_S].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_SA]   = meter_yc[ID_SA].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_SB]   = meter_yc[ID_SB].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_SC]   = meter_yc[ID_SC].value*Q16_BASE;
	
	g_sw[sw].ac_in[SW_AC_IN_XS_COS]  = meter_yc[ID_COS].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_COSA] = meter_yc[ID_COSA].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_COSB] = meter_yc[ID_COSB].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_COSC] = meter_yc[ID_COSC].value*Q16_BASE;
	g_sw[sw].ac_in[SW_AC_IN_XS_FREQ] = meter_yc[ID_FREQ].value*Q16_BASE;
}
#endif

u8 metering_dir_change(u8 id)
{
	return meter_yx[id].value;
}

u8 can_metering_calib(char* buf)
{
	u8 i;

	for(i=0; i<CAN_BOARD_NUM; i++)
	{
		if(is_can_slot_valid(i))
			break;
	}
	if(i > CAN_BOARD_NUM)
	{
		rt_printf("\r\n没有找到计量板卡...");
		return 0;
	}
	if((buf[0] == 's') || (buf[0] == 'S'))
	{
		if(calib_step == 0)
		{
			calib_wait = 0;
			calib_step = 1;
			rt_printf("\r\n1、标准源输出三相电压电流");
			rt_printf("\r\n   电压电流角度（0°，-120°，120°）");
			rt_printf("\r\n   标准源稳定后按回车键，开始校准");
		}
		else
		{
			rt_printf("\r\n 校准出错退出");
			calib_wait = 0;
			calib_step = 0;
		}
	}
	else if(buf[0] ==  0x0d)
	{
		if(calib_step)
		{
			if(calib_wait)
			{
				rt_printf("\r\n退出校准...");
				calib_wait = 0;
				calib_step = 0;
			}
			else
			{
				if(calib_step == 1)
				{
					can_metering_calib_step1(0, get_can_slot(i));
					calib_wait = 1;
					calib_step = 2;
					rt_printf("\r\n发送校准1");
				}
				else if(calib_step == 2)
				{
					calib_wait = 1;
					rt_printf("\r\n发送校准2");					
					can_metering_calib_step2(0, get_can_slot(i));
				}
				else
				{
					rt_printf("\r\n 校准出错退出");
					calib_wait = 0;
					calib_step = 0;					
				}
			}
		}
	}
	
	return calib_step;
}


int can_metering_send(u8 cmd, u8 *src, u8 data_len)
{
	u8 tx_buf[256];
	
	tx_buf[0]= cmd;
	tx_buf[1]= 1;
	tx_buf[2]= 0;
	tx_buf[3]= data_len;
	
	memcpy(&tx_buf[4],src,data_len);
	tx_buf[4+data_len] = can_app_checksum(tx_buf,data_len+4);
	
	if(can_send(0,tx_buf) != 0)
	{
		return -1;
	}
	return 0;
}

void can_app_metering_yx_recv(u8* buf)
{
	int i;
	u16 ti;

	for(i=0;i<ID_YX_NUM;i++)
	{
		ti = (u16)buf[i*3] | ((u16)buf[i*3 + 1] <<8 );
		if(meter_yx[i].ti == ti)
		{
			memcpy(&meter_yx[i].value, &buf[i*3+2], sizeof(u8));
		//	rt_printf("\r\nRecv: meter_yx[%d].value=%d\r\n", i, meter_yx[i].value);	
		}
	}	
}

void can_app_metering_yc_recv(u8* buf)
{
	int i;
	u16 ti;
	u8 *pbuf;
	
	for(i=0;i<ID_YC_NUM;i++)
	{
		ti = (u16)buf[i*6] | ((u16)buf[i*6 + 1] <<8 );
		if(meter_yc[i].ti == ti)
		{
			pbuf = (u8*)(&meter_yc[i].value);
			pbuf[0] = buf[i*6+5];
			pbuf[1] = buf[i*6+4];
			pbuf[2] = buf[i*6+3];
			pbuf[3] = buf[i*6+2];
		//	rt_printf("\r\nRecv: meter_yc[%d].value=%f\r\n", i, meter_yc[i].value);	
		}
	}
#ifdef METERING_ENERGY
	metering_yc_refresh();
#endif
}

void can_app_metering_dd_recv(u8* buf)
{
	int i;
	u16 ti;
	u8 *pbuf;
	
	for(i=0;i<ID_DD_NUM;i++)
	{
		ti = (u16)buf[i*6] | ((u16)buf[i*6 + 1] <<8 );
		if(meter_dd[i].ti == ti)
		{
			pbuf = (u8*)(&meter_dd[i].value);
			pbuf[0] = buf[i*6+5];
			pbuf[1] = buf[i*6+4];
			pbuf[2] = buf[i*6+3];
			pbuf[3] = buf[i*6+2];
			//rt_printf("\r\nRecv: meter_dd[%d].value=%f\r\n", i, meter_dd[i].value);	
		}
	}
}

void can_dd_clear_recv(u8* buf)
{
    u16 value;

    value = (u16)buf[0] | ((u16)buf[1] <<8 );
    if(value == 0x6001)
    {
        if(buf[2] == 0)
        {
            g_print_to_net = 1;
            rt_printf("电能成功清除\r\n");
        #ifdef METERING_ENERGY
            soft_dd_val_clr();   // be modified by Jack.Liu on 2020/06/17--19:8:16
        #endif
        }
    }
}

int can_app_get_metering_yx(u8 no, u8 slot)
{
	u8 buf[5];
	
	buf[0] = CAN_FRAME_TYPE_LL_YX;
	buf[1] = slot;
	buf[2] = 0;
	buf[3] = 1;
	buf[4] = can_app_checksum(buf,buf[3]+3); //校验和
	//rt_printf("获取计量板遥信\r\n");
	// 发送
	can_send(no, buf);
	
	return 0;
}


int can_app_get_metering_yc(u8 no, u8 slot)
{
	u8 buf[5];
	
	buf[0] = CAN_FRAME_TYPE_LL_YC;
	buf[1] = slot;
	buf[2] = 0;
	buf[3] = 1;
	buf[4] = can_app_checksum(buf,buf[3]+3); //校验和
	//rt_printf("获取计量板遥测\r\n");
	// 发送
	can_send(no, buf);
	
	return 0;
}

int can_app_energy_clear(u8 no, u8 slot)
{
	u8 buf[8];
	
	buf[0] = CAN_FRAME_TYPE_LL_SET;
	buf[1] = slot;
	buf[2] = 0;
	buf[3] = 3;
	buf[4] = 0x01;
	buf[5] = 0x60;
	buf[6] = can_app_checksum(buf,buf[3]+3); //校验和
	//rt_printf("计量电能清除\r\n");
	// 发送
	can_send(no, buf);
	
	return 0;	
}


int can_app_get_metering_dd(u8 no, u8 slot)
{
	u8 buf[5];
	
	buf[0] = CAN_FRAME_TYPE_LL_DD;
	buf[1] = slot;
	buf[2] = 0;
	buf[3] = 1;
	buf[4] = can_app_checksum(buf,buf[3]+3); //校验和
	//rt_printf("获取计量板电度\r\n");
	// 发送
	can_send(no, buf);
	
	return 0;
}


int can_app_set_metering_jxfs(u8 no, u8 slot, u8 data)
{
	u8 buf[8];
	
	buf[0] = CAN_FRAME_TYPE_LL_SET;
	buf[1] = slot;
	buf[2] = 0;
	buf[3] = 4;
	buf[4] = 0x03;
	buf[5] = 0x60;
	buf[6] = data;
	buf[7] = can_app_checksum(buf,buf[3]+3); //校验和
	rt_printf("设置计量接线方式\r\n");
	jxfs = pRunSet->wJLJX;
	// 发送
	can_send(no, buf);
	
	return 0;	

}

void can_dd_jxfs_recv(u8* buf)
{
	u16 value;
	
	value = (u16)buf[0] | ((u16)buf[1] <<8 );
	if(value == 0x6003)
	{
		can_metering_set[0] = 0;
		rt_printf("设置接线方式返回\r\n");
	}
}


int can_app_set_metering_wgfs(u8 no, u8 slot, u8 data)
{
	u8 buf[8];
	
	buf[0] = CAN_FRAME_TYPE_LL_SET;
	buf[1] = slot;
	buf[2] = 0;
	buf[3] = 4;
	buf[4] = 0x04;
	buf[5] = 0x60;
	buf[6] = data;
	buf[7] = can_app_checksum(buf,buf[3]+3); //校验和
	rt_printf("设置无功计算方式\r\n");
	// 发送
	can_send(no, buf);
	
	return 0;	

}

void can_dd_wgfs_recv(u8* buf)
{
	u16 value;
	
	value = (u16)buf[0] | ((u16)buf[1] <<8 );
	if(value == 0x6004)
	{
		can_metering_set[1] = 0;
		wgfs = pRunSet->wWGFS;
		rt_printf("设置无功电能计算方式返回\r\n");
	}
}



void can_metering_calib_step1(u8 no, u8 slot)
{
	u8 buf[5];
	
	buf[0] = CAN_FRAME_TYPE_LL_CALIB1;
	buf[1] = slot;
	buf[2] = 0;
	buf[3] = 1;
	buf[4] = can_app_checksum(buf,buf[3]+3); //校验和

	// 发送
	can_send(no, buf);	
}

void can_metering_calib_step2(u8 no, u8 slot)
{
	u8 buf[5];
	
	buf[0] = CAN_FRAME_TYPE_LL_CALIB2;
	buf[1] = slot;
	buf[2] = 0;
	buf[3] = 1;
	buf[4] = can_app_checksum(buf,buf[3]+3); //校验和

	// 发送
	can_send(no, buf);	
}

void can_metering_calib_error(u8 data)
{
	rt_printf("\r\n\r\n校准失败...\r\n");
	if(data & 0x40)
	{
		rt_printf("\r\n校准精度不够...\r\n");
	}
	if(data & 0x20)
	{
		rt_printf("\r\nC相电流源输入有误...\r\n");
	}
	if(data & 0x10)
	{
		rt_printf("\r\nB相电流源输入有误...\r\n");
	}
	if(data & 0x08)
	{
		rt_printf("\r\nA相电流源输入有误...\r\n");
	}
	if(data & 0x04)
	{
		rt_printf("\r\nC相电压源输入有误...\r\n");
	}
	if(data & 0x02)
	{
		rt_printf("\r\nB相电压源输入有误...\r\n");
	}
	if(data & 0x01)
	{
		rt_printf("\r\nA相电压源输入有误...\r\n");
	}

}

/******************************************************************************
函数名称：	can_metering_recv_app
函数版本：	01.01
创建作者：	
创建日期：	
函数说明：	主要处理终端向线损模块写参数命令:
				考核日冻结日，（1~28）
				考核日冻结小时，（0~23）
				功率反向事件有功功率触发下限，(推荐为额定功率的0.05~5%，设置为0表示不启动)
				功率反向事件判断延时，（1~99s）
				潮流方向改变事件有功功率触发下限，(推荐为额定功率的0.05~5%，设置为0表示不启动)
				潮流方向改变事件判断延时，（1~99s）

			控制类命令：
				电能总召唤，
				瞬时冻结命令，
				线损模块清零，
				事件清零，
				校时
			
参数说明：	
返回值：  	
修改记录：	
*/
int can_metering_recv_app(u8 *buf)
{
	u8 cmd;
	u8 len, crc,crc_check;
	
	if(buf == NULL)
	{
		return -1;
	}
	#if 0
	if(buf[1] != g_sys_info.slot)
	{
		return -2;
	}
	#endif
	len = buf[3];
	crc = buf[len+3];
	crc_check = can_app_checksum(buf,len+3);
	if(crc != crc_check)
	{
#if 0
		rt_printf("can校验和错误\r\n");
#endif
		return -3;
	}

	cmd = buf[0];
	len = buf[3];
	switch(cmd)
	{
		case CAN_FRAME_TYPE_LL_YX:	
			metering_can_busy = 0;
			can_app_metering_yx_recv(&buf[4]);
			break;
			
		case CAN_FRAME_TYPE_LL_YC:
			metering_can_busy = 0;
			can_app_metering_yc_recv(&buf[4]);
			break;

			
		case CAN_FRAME_TYPE_LL_SET:
			metering_can_busy = 0;
			can_dd_clear_recv(&buf[4]);	
			can_dd_jxfs_recv(&buf[4]);
			can_dd_wgfs_recv(&buf[4]);
			break;

		case CAN_FRAME_TYPE_LL_DD:
			metering_can_busy = 0;
			can_app_metering_dd_recv(&buf[4]);
			break;
		case CAN_FRAME_TYPE_LL_CALIB1:
			if(buf[4] == 0)
			{
				rt_printf("\r\n\r\n第一步校准完成...\r\n");
				rt_printf("\r\n2、标准源输出0.5L功率因数");
				rt_printf("\r\n   按回车键，开始校准");
			}
			else
			{
				can_metering_calib_error(buf[4]);
			}
			calib_wait = 0;
			break;
		case CAN_FRAME_TYPE_LL_CALIB2:
			if(buf[4] == 0)
			{
				rt_printf("\r\n\r\n计量板校准完成...\r\n");
			}
			else
				can_metering_calib_error(buf[4]);
			calib_wait = 0;
			calib_step = 0;
			break;		
		case CAN_FRAME_TYPE_LL_SET_TIME:
			
			//memcpy(&ts.tv_sec,buf+4,sizeof(long)); //注意大小端问题
			//ts.tv_sec = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; 
			//ts.tv_nsec = 0;
			
			//gps_time_set(&ts);

			// 系统启动时间
			//if(g_start_sec == 0)
			//{
			//	g_start_sec = (u32)ts.tv_sec;
			//}
			
			break;

	}

	return 0;
	
}

void can_clear_send_timer(void)
{
	swnd_us[0] = ustimer_get_origin();
	swnd_us[1] = ustimer_get_origin();
	swnd_us[2] = ustimer_get_origin();
	swnd_us[3] = ustimer_get_origin();
}

void can_metering_send_app(void)
{
	static uint32_t wait_us[2] = {0};
	static unsigned char send_count[2] = {0};
	u8 i;

	if(swnd_us[0] == 0)
		swnd_us[0] = ustimer_get_origin();
	if(swnd_us[1] == 0)
		swnd_us[1] = ustimer_get_origin();
	if(swnd_us[2] == 0)
		swnd_us[2] = ustimer_get_origin();

	for(i=0; i<CAN_BOARD_NUM; i++)
	{
		if(is_can_slot_valid(i))
		{
					//下发接线方式
			if(jxfs != pRunSet->wJLJX)
			{
//				can_app_set_metering_jxfs(0, get_can_slot(i), jxfs);
				if(!can_metering_set[0])
				{
					send_count[0] = 0;
					jxfs = pRunSet->wJLJX;
					can_metering_set[0] = 1;
					wait_us[0] 	  = ustimer_get_origin();
				}
			}
			//下发无功计算方式
			if(wgfs != pRunSet->wWGFS)
			{
//				can_app_set_metering_wgfs(0, get_can_slot(i), wgfs);
				if(!can_metering_set[1])
				{
					send_count[1] 		= 0;
					can_metering_set[1] = 1;
					wgfs = pRunSet->wWGFS;
					wait_us[1] = ustimer_get_origin();
				}
			}
#if 1		
			if(can_metering_set[0])
			{
				if(ustimer_delay_origin2(&wait_us[0], 3*USTIMER_SEC))
				{
					send_count[0]++;
					if(send_count[0] > 1)
					{
						can_metering_set[0] = 0;
						jxfs = pRunSet->wJLJX;
					}
					else
					{
						jxfs = 255;
						can_app_set_metering_jxfs(0, get_can_slot(i),  pRunSet->wJLJX);
						wait_us[0] = ustimer_get_origin();
					}
				}
				continue;
			}
			else if(can_metering_set[1])
			{
				if(ustimer_delay_origin2(&wait_us[1], 3*USTIMER_SEC))
				{
					send_count[1]++;
					if(send_count[1] > 1)
					{
						can_metering_set[1] = 0;
						wgfs = pRunSet->wWGFS;
					}
					else
					{
						wgfs = 255;
						can_app_set_metering_wgfs(0, get_can_slot(i), pRunSet->wWGFS);
						wait_us[1] = ustimer_get_origin();
					}
				}
				continue;
			}
						
			if(ustimer_delay_origin2(&swnd_us[0], 3*USTIMER_SEC) && !metering_can_busy)
			{
				swnd_us[0] = ustimer_get_origin();
				metering_can_busy = 1;
				can_app_get_metering_yx(0, get_can_slot(i));
			}
			if(ustimer_delay_origin2(&swnd_us[1], 7*USTIMER_SEC) && !metering_can_busy)
			{
				swnd_us[1] = ustimer_get_origin();
				metering_can_busy = 1;
				can_app_get_metering_yc(0, get_can_slot(i));
			}
			if(ustimer_delay_origin2(&swnd_us[2], 14*USTIMER_SEC) && !metering_can_busy)
			{
				swnd_us[2] =ustimer_get_origin();
				metering_can_busy = 1;
				can_app_get_metering_dd(0, get_can_slot(i));
			}
				//对时报文发送
			if(ustimer_delay_origin2(&swnd_us[3], 5*USTIMER_SEC))
			{
				swnd_us[3] = ustimer_get_origin();
				can_app_timing();
			}
#endif


		}
	}

}	

void can_app_busy(void)
{
	static long busy_us;
	
	if(metering_can_busy)
	{
		if(ustimer_delay_origin2(&busy_us, 5*USTIMER_SEC))
		{
			metering_can_busy = 0;
		}
	}
	else
	{
		busy_us = ustimer_get_origin();
	}
}
#endif

#if 0
int can_ll_energy(struct timespec time,u8 cmd)
{
	char buf[128]={0};
	float ll_dd[ID_DD_NUM];
	u32 dd_time;
	int i;
	int ret;
	
	union
	{
		float ff;
		u8 tt[4];
	}ff;
	

	if(dt7308_spi_dd(ll_dd))
	{
		dd_time = (u32)(((time.tv_sec&0xff)<<24) | (time.tv_nsec>>8));

		buf[0] = (unsigned char)(dd_time>>24);
		buf[1] = (unsigned char)(dd_time>>16);
		buf[2] = (unsigned char)(dd_time>>8);
		buf[3] = (unsigned char)(dd_time);
	
		for(i=0;i<ID_DD_NUM;i++)
		{
			ff.ff = ll_dd[i];
			buf[4+i*6]=(u8)xs_can_dd[i].ti;
			buf[5+i*6]=(u8)(xs_can_dd[i].ti>>8);
			buf[6+i*6]=ff.tt[0];
			buf[7+i*6]=ff.tt[1];
			buf[8+i*6]=ff.tt[2];
			buf[9+i*6]=ff.tt[3];
		}
		can_ll_send(cmd,4+6*ID_DD_NUM,buf);
	}
	

}
#endif

#if 0
void can_ll_msg_app(void)
{
	struct timespec ts;
	struct rtc_time_t tm;
	int i;
	u32 dd_time;
	static int first = 1;

	//获取当前时间
//	gps_time_get(&ts);
//	timespec_to_rtc(&ts,&tm);

	if(first)
	{
		rcd_fixd.time_bk = tm;
		rcd_rand.time_bk = tm;
		rcd_frzd.time_bk = tm;
		rcd_sharpd.time_bk = tm;
		rcd_sharpd.time_bk = tm;
		rcd_monthd.time_bk = tm;
		first = 0;
	}


	//线损模块定时冻结
	if((((u16)tm.hour*60+(u16)tm.min)>((u16)rcd_fixd.time_bk.hour*60+(u16)rcd_fixd.time_bk.min))
			&&(tRunPara.wZDJG!=0)&&((tm.min%tRunPara.wZDJG) == 0))
	{
		rcd_fixd.time_bk = tm;

		can_ll_energy(ts,CAN_FRAME_TYPE_LL_FIXD);
	
	}


	//线损模块日冻结：每日0 点自动冻结当前时间电能量和有功功率值
	if(tm.day!=rcd_frzd.time_bk.day)
	{
		rcd_frzd.time_bk = tm;
		can_ll_energy(ts,CAN_FRAME_TYPE_LL_FRZD);
	}

	//线损模块整点冻结
	if(tm.hour!=rcd_sharpd.time_bk.hour)
	{
		rcd_sharpd.time_bk = tm;
		can_ll_energy(ts,CAN_FRAME_TYPE_LL_SHARPD);
	}	


	//线损模块考核日冻结
	if((tm.day!=rcd_monthd.time_bk.day)&&(tm.day == tRunPara.frz_day))
	{
		rcd_monthd.time_bk =  tm;
		can_ll_energy(ts,CAN_FRAME_TYPE_LL_MONTHD);
	}



	
}
#endif
#endif

