850 lines
30 KiB
C
850 lines
30 KiB
C
#include "UWater_frame_app.h"
|
||
#include "UWater_rtcc_app.h"
|
||
#include "UWater_lcd_app.h"
|
||
#include "UWater_gp22_app.h"
|
||
#include "UWater_pt_app.h"
|
||
#include "UWater_frame_func_ReplyWT.h"
|
||
#include "UWater_encryption_driver.h"
|
||
#include "UWater_DataTools_App.h"
|
||
#include "UWater_uart_driver.h"
|
||
#include "UWater_eeprom_driver.h"
|
||
|
||
|
||
static u8 broad_addr[7] = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA};
|
||
static u8 task_complete_mbus = PTL_PACK_BUSY;
|
||
static STRUCT_FLAG s_frame_flag_MBUS; //规约标志
|
||
static STRUCT_FRAME_MBUS frame_struct_MBUS; //规约信息
|
||
static u8 *new_message_data_rev_mbus;
|
||
static u16 g_frame_temp_len_mbus;
|
||
static u8 g_frame_temp_send_buf_mbus[UP_BUF_SIZE]; //数据部分缓冲区
|
||
static u8 s_eep_complete_mbus;
|
||
static u8 up_deal_stat_mbus=UP_DEAL_S0;
|
||
//static u8 frame_temp_data_buf[256];//发送数据帧组帧缓存
|
||
//读通讯地址
|
||
static void frame_func_reply_WT_ReadAddr(void)
|
||
{
|
||
g_frame_temp_len_mbus = 0;
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
|
||
/*MBus规约 读温度系数*/
|
||
static void frame_func_reply_WT_ReadTemperatureCoefficient(void)
|
||
{
|
||
UNION_4U8TOU32 temp_4U8toU32_data;
|
||
g_frame_temp_len_mbus = 0;
|
||
temp_4U8toU32_data.datas = FrameCheckParaApp(FramePara_Tc0);
|
||
for(int i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = temp_4U8toU32_data.data_buf[i];
|
||
}
|
||
temp_4U8toU32_data.datas = FrameCheckParaApp(FramePara_Tc1);
|
||
for(int i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = temp_4U8toU32_data.data_buf[i];
|
||
}
|
||
g_frame_temp_len_mbus = 8;
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
|
||
/*读取物理地址*/
|
||
static void frame_func_reply_WT_ReadMac(void)
|
||
{
|
||
g_frame_temp_len_mbus = 0;
|
||
for(int i=0;i<7;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0x00;//返回给水台子固定MAC地址0x00
|
||
}
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
|
||
/*设为检定状态*/
|
||
static void frame_func_reply_WT_SetVerificationState(void)
|
||
{
|
||
g_frame_temp_len_mbus = 0;
|
||
if (0 == Sys_data_object.P1.enable_verification_function)
|
||
{
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
return;
|
||
}
|
||
FrameSetMsgApp(SetVerificationMsg);
|
||
FrameClearMsgApp(MsgCaliberate);//清零 单程时间校准校准标志
|
||
//Gp30TestFlowInit(); //设置为检定状态,GP30应用数据初始化(改善模组驱动不需要)
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0;
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
|
||
//读出厂序列号
|
||
static void frame_func_reply_WT_ReadSerialNum(void)
|
||
{
|
||
g_frame_temp_len_mbus = 0;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = Sys_data_object.P1.last_key_num;
|
||
for(int i=0;i<7;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0x00;//返回给水台子固定序列号0x00
|
||
}
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0x5A;
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
|
||
//退出检定状态
|
||
static void frame_func_reply_WT_OutVerificationState(void)
|
||
{
|
||
g_frame_temp_len_mbus = 0;
|
||
if(01 == LcdCheckStateApp())
|
||
{
|
||
FrameSetMsgApp(OutVerificationMsg);//s_struct_msg.MsgStruct.out_verification_msg = 1;
|
||
}
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
//读流量系数
|
||
static void frame_func_reply_WT_ReadFlowCoefficient(void)
|
||
{
|
||
int i;
|
||
g_frame_temp_len_mbus = 0;
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = Sys_data_object.P1.flow_coefficient_small.data_buf[i];
|
||
}
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = Sys_data_object.P1.flow_coefficient_middle0.data_buf[i];
|
||
}
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = Sys_data_object.P1.flow_coefficient_middle1.data_buf[i];
|
||
}
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = Sys_data_object.P1.flow_coefficient_middle2.data_buf[i];
|
||
}
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = Sys_data_object.P1.flow_coefficient_middle3.data_buf[i];
|
||
}
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = Sys_data_object.P1.flow_coefficient_large.data_buf[i];
|
||
}
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
//读检定数据
|
||
static void frame_func_reply_WT_ReadVerificationData(void)
|
||
{
|
||
int i;
|
||
DateTime tmp_time_buf;
|
||
UNION_4U8TOU32 tmp_datas_buf;
|
||
UNION_FLOAT_STORAGE tmp_float_datas_buf;
|
||
float tempTempratureFlag;
|
||
MET_STATE temp_met_state;
|
||
g_frame_temp_len_mbus = 0;
|
||
|
||
if(01 != LcdCheckStateApp()) //非检定状态
|
||
{
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
return;
|
||
}
|
||
//温度
|
||
if(TRUE==Check_Start_STOP_Filter_Flag())
|
||
{
|
||
Clear_Start_STOP_Filter_Flag();
|
||
tempTempratureFlag = Check_Temperature_Parameter();//传递滤波的反算温度数据
|
||
}
|
||
else
|
||
{
|
||
tempTempratureFlag = TempCheckValueApp();
|
||
}
|
||
|
||
if(tempTempratureFlag < 0)
|
||
{
|
||
tempTempratureFlag = -tempTempratureFlag;
|
||
tmp_datas_buf.datas = HexToBcd32((u32)(tempTempratureFlag*100));
|
||
tmp_datas_buf.datas|= 0x800000;
|
||
}
|
||
else
|
||
{
|
||
tmp_datas_buf.datas = HexToBcd32((u32)(tempTempratureFlag*100));
|
||
tmp_datas_buf.datas &= 0x7FFFFF;
|
||
}
|
||
for(i=0;i<3;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.data_buf[i];
|
||
}
|
||
//累计流量
|
||
tmp_float_datas_buf.float_storage_format.datas = Gp30CheckTestDataApp(GP30_APP_TOTAL_FLOW); //累计流量//BCD
|
||
tmp_datas_buf.datas = (u32) (tmp_float_datas_buf.float_datas);
|
||
tmp_datas_buf.datas = HexToBcd32(tmp_datas_buf.datas);
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.data_buf[i];
|
||
}
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0x2C; //m?
|
||
//瞬时流量
|
||
tmp_datas_buf.datas = Gp30CheckTestDataApp(GP30_APP_INS_FLOW); //瞬时流量(四位小数,放大100000倍)//BCD
|
||
tmp_datas_buf.datas = Gp30DataToBcd(tmp_datas_buf.datas, 100);//与NB区别
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.data_buf[i];
|
||
}
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0x35; //m?/h
|
||
//up单程时间
|
||
tmp_datas_buf.datas = Gp30CheckTestDataApp(GP30_APP_TOF);//
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.data_buf[i];
|
||
}
|
||
//Magnify 100000 times(m3/h):Real-time instantaneous flow
|
||
tmp_datas_buf.datas = Gp30CheckTestDataApp(GP30_APP_INS_FLOW_LCD);
|
||
tmp_datas_buf.datas = Gp30DataToBcd(tmp_datas_buf.datas, 100);
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.data_buf[i];
|
||
}
|
||
//tof
|
||
tmp_datas_buf.datas = Gp30CheckTestDataApp(GP30_APP_DIFF); //时间差
|
||
for(i=0;i<4;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.data_buf[i];
|
||
}
|
||
//累计工作时间//BCD
|
||
tmp_datas_buf.datas = RtccGetWorkHourApp();
|
||
tmp_datas_buf.datas = HexToBcd32(tmp_datas_buf.datas);
|
||
for(i=0;i<3;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.data_buf[i];
|
||
}
|
||
//实时时间
|
||
RtccGetDateTime(&tmp_time_buf);
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0x20;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_time_buf.s.year;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_time_buf.s.month;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_time_buf.s.day;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_time_buf.s.hour;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_time_buf.s.minute;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_time_buf.s.second;
|
||
//状态字
|
||
temp_met_state = FrameGetByte();
|
||
/**添加规约,用来配合水台子测流量**/
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = temp_met_state.stat1;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = temp_met_state.stat3;
|
||
//************************新增数据:15字节***********************/
|
||
//温度T0-T2(T2):3字节
|
||
#if WENDU_FANSUAN_OPEN
|
||
tempTempratureFlag= TempCheckValueApp();//传递实时的反算温度数据
|
||
|
||
if(tempTempratureFlag < 0)
|
||
{
|
||
tempTempratureFlag = -tempTempratureFlag;
|
||
tmp_datas_buf.datas = HexToBcd32((u32)(tempTempratureFlag*100));
|
||
tmp_datas_buf.datas|= 0x800000;
|
||
}
|
||
else
|
||
{
|
||
tmp_datas_buf.datas = HexToBcd32((u32)(tempTempratureFlag*100));
|
||
tmp_datas_buf.datas &= 0x7FFFFF;
|
||
}
|
||
for(i=0;i<3;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.data_buf[i];
|
||
}
|
||
tmp_datas_buf.datas = Gp30CheckDataApp(11); //TOF_UP补偿系数
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data0;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data1;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data2;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data3;
|
||
|
||
tmp_datas_buf.datas = Gp30CheckDataApp(12);//TOF_DOWN补偿系数
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data0;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data1;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data2;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data3;
|
||
#else//常规程序反算温度默认写0
|
||
for(i=0;i<3;i++)
|
||
{
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0;
|
||
}
|
||
//up amplitude(V1):4字节
|
||
tmp_datas_buf.datas = Gp30CheckTestDataApp(GP30_APP_PEAK_UP);
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data0;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data1;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data2;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data3;
|
||
//down amplitude(V2):4字节
|
||
tmp_datas_buf.datas = Gp30CheckTestDataApp(GP30_APP_PEAK_DOWN);
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data0;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data1;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data2;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data3;
|
||
#endif
|
||
//down 的单程时间
|
||
tmp_datas_buf.datas = Gp30CheckTestDataApp(GP30_APP_DOWN);
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data0;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data1;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data2;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = tmp_datas_buf.datas_map.data3;
|
||
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
|
||
//启动\停止测试
|
||
static void frame_func_reply_WT_StartOrStopTest(void)
|
||
{
|
||
g_frame_temp_len_mbus = 0;
|
||
if(01 != LcdCheckStateApp())
|
||
{
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
return;
|
||
}
|
||
if(0x01 == *(new_message_data_rev_mbus)) //start
|
||
{
|
||
Gp30StartMeasureApp(1);
|
||
}
|
||
else if(0x00 == *(new_message_data_rev_mbus)) //stop
|
||
{
|
||
Gp30StartMeasureApp(0);
|
||
}
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = *(new_message_data_rev_mbus);
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0;
|
||
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
|
||
//模组/水台子规约:读多项式系数
|
||
static void frame_func_reply_WT_ReadPolyNomialcoefficient(void)
|
||
{
|
||
g_frame_temp_len_mbus=0;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = FM_METER_TYPE;
|
||
memcpy(&g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus], &(cal_coefficient[0].value[0]),sizeof (cal_coefficient));
|
||
g_frame_temp_len_mbus = (sizeof (cal_coefficient)+1);
|
||
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
//写温度系数
|
||
static void frame_func_s3_WT_SetTempratureConefficient(void)
|
||
{
|
||
switch(up_deal_stat_mbus)
|
||
{
|
||
case UP_DEAL_S0:
|
||
{
|
||
if(TASK_IDLE == EepIfIdle())//存储温度系数到EEPROM完成
|
||
{
|
||
g_frame_temp_len_mbus=0;
|
||
if (0x01 == Sys_data_object.P1.start_using_flg) //出厂启用
|
||
{
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
return;
|
||
}
|
||
|
||
fram_tools_writeU32ByBuf(Sys_data_object.P1.temperature_coefficient0.data_buf, new_message_data_rev_mbus, 0);
|
||
fram_tools_writeU32ByBuf(Sys_data_object.P1.temperature_coefficient1.data_buf, (new_message_data_rev_mbus + 4), 0);
|
||
|
||
#if WENDU_FANSUAN_OPEN
|
||
UNION_2U8TOU16 temp_caliber_value;
|
||
temp_caliber_value.datas_map.data0 =*(new_message_data_rev_mbus + 8);//获取温度数据低字节
|
||
temp_caliber_value.datas_map.data1 =*(new_message_data_rev_mbus + 9);//获取温度数据高字节
|
||
|
||
SetCaliberateTemperature(temp_caliber_value.datas);//当前温度数据
|
||
|
||
if(Get_Temperature_Caliberate()!=0)/*1、表计在校准时下发清零温度系数,活塞台子会下发非零校准温度值 2、表计在校准时下发写温度系数,-活塞台子下发的校准温度值为0*/
|
||
{
|
||
FrameSetMsgApp(MsgCaliberate); //置1 单程时间校准校准MSG----只有在校准温度不是零的情况下才允许校准单程时间
|
||
RtccSetTimer(RTCC_TOF_CALIBERATE_TIME, RTCC_TOF_CALIBERATE_TIME_OUT);//设置超时防护 超时防护----实际测试
|
||
}
|
||
#endif
|
||
EepWrite(&Sys_data_object.P1.temperature_coefficient0.datas_map.data0, EEP_FRAME_TEMPERATURE_COEFFICIENT_ADDR, 8, &s_eep_complete_mbus);
|
||
Frame_Para_Init();
|
||
|
||
if((0==Sys_data_object.P1.temperature_coefficient0.datas)&&(0==Sys_data_object.P1.temperature_coefficient1.datas))
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S1; //当水台子下发清温度系数时,将流量系数写为1
|
||
}
|
||
else
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S2;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case UP_DEAL_S1:
|
||
{
|
||
if(TASK_IDLE == EepIfIdle())//存储温度系数到EEPROM
|
||
{
|
||
memcpy(&(cal_flow_coefficient[0].datas_map.data0), default_flow_coefficient, sizeof (default_flow_coefficient));
|
||
EepWrite(&(cal_flow_coefficient[0].datas_map.data0), FRAME_FLOW_LOW_COEFFICIENT_ADDR, 72, &s_eep_complete_mbus);
|
||
up_deal_stat_mbus = UP_DEAL_S2;
|
||
}
|
||
}
|
||
break;
|
||
case UP_DEAL_S2:
|
||
{
|
||
if(TASK_IDLE == EepIfIdle())//存储温度系数到EEPROM完成
|
||
{
|
||
Frame_Para_Init();
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0;
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
//写流量系数 **修改写流量系数限制(0.5-1.5)2019年7月5日
|
||
static void frame_func_s3_WT_SetFowcoefficient(void)
|
||
{
|
||
if(TASK_IDLE == EepIfIdle())
|
||
{
|
||
g_frame_temp_len_mbus =0;
|
||
if (0x01 == Sys_data_object.P1.start_using_flg) //出厂启用
|
||
{
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
return;
|
||
}
|
||
|
||
UNION_4U8TOU32 flow_small;
|
||
UNION_4U8TOU32 flow_medium0;
|
||
UNION_4U8TOU32 flow_medium1;
|
||
UNION_4U8TOU32 flow_medium2;
|
||
UNION_4U8TOU32 flow_medium3;
|
||
UNION_4U8TOU32 flow_large;
|
||
fram_tools_writeU32ByBuf(flow_small.data_buf, (new_message_data_rev_mbus), 0);
|
||
fram_tools_writeU32ByBuf(flow_medium0.data_buf, (new_message_data_rev_mbus + 4), 0);
|
||
fram_tools_writeU32ByBuf(flow_medium1.data_buf, (new_message_data_rev_mbus + 8), 0);
|
||
fram_tools_writeU32ByBuf(flow_medium2.data_buf, (new_message_data_rev_mbus + 12), 0);
|
||
fram_tools_writeU32ByBuf(flow_medium3.data_buf, (new_message_data_rev_mbus + 16), 0);
|
||
fram_tools_writeU32ByBuf(flow_large.data_buf, (new_message_data_rev_mbus + 20), 0);
|
||
if(( (FLOW_COEFFICIENT_MIN < flow_small.datas) && (flow_small.datas < FLOW_COEFFICIENT_MAX) ) && ( (FLOW_COEFFICIENT_MIN < flow_medium0.datas) && (flow_medium0.datas < FLOW_COEFFICIENT_MAX) )
|
||
&& ( (FLOW_COEFFICIENT_MIN < flow_medium1.datas) && (flow_medium1.datas < FLOW_COEFFICIENT_MAX) ) && ( (FLOW_COEFFICIENT_MIN < flow_medium2.datas) && (flow_medium2.datas < FLOW_COEFFICIENT_MAX) )
|
||
&& ( (FLOW_COEFFICIENT_MIN < flow_medium3.datas) && (flow_medium3.datas < FLOW_COEFFICIENT_MAX) ) && ( (FLOW_COEFFICIENT_MIN < flow_large.datas) && (flow_large.datas < FLOW_COEFFICIENT_MAX) ))
|
||
{
|
||
if(LOW_TYPE==*(new_message_data_rev_mbus + 24))
|
||
{
|
||
memcpy(&(cal_flow_coefficient[0].datas_map.data0), new_message_data_rev_mbus, 24);
|
||
EepWrite(&(cal_flow_coefficient[0].datas_map.data0), FRAME_FLOW_LOW_COEFFICIENT_ADDR, 24, &s_eep_complete_mbus);
|
||
}
|
||
else if(MIDDLE_TYPE==*(new_message_data_rev_mbus + 24))
|
||
{
|
||
memcpy(&(cal_flow_coefficient[6].datas_map.data0), new_message_data_rev_mbus, 24);
|
||
EepWrite(&(cal_flow_coefficient[6].datas_map.data0), FRAME_FLOW_MIDDLE_COEFFICIENT_ADDR, 24, &s_eep_complete_mbus);
|
||
}
|
||
else if(LARGE_TYPE==*(new_message_data_rev_mbus + 24))
|
||
{
|
||
memcpy(&(cal_flow_coefficient[12].datas_map.data0), new_message_data_rev_mbus, 24);
|
||
EepWrite(&(cal_flow_coefficient[12].datas_map.data0), FRAME_FLOW_HIGH_COEFFICIENT_ADDR, 24, &s_eep_complete_mbus);
|
||
}
|
||
else if(ALL_TYPE==*(new_message_data_rev_mbus + 24))
|
||
{
|
||
memcpy(&(cal_flow_coefficient[0].datas_map.data0), default_flow_coefficient, sizeof (default_flow_coefficient));
|
||
EepWrite(&(cal_flow_coefficient[0].datas_map.data0), FRAME_FLOW_LOW_COEFFICIENT_ADDR, 72, &s_eep_complete_mbus);
|
||
}
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0;
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
else
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
}
|
||
}
|
||
}
|
||
|
||
//(清)出厂启用
|
||
static void frame_func_s3_WT_StartOrClearUsing(void)
|
||
{
|
||
if(TASK_IDLE == EepIfIdle())
|
||
{
|
||
g_frame_temp_len_mbus =0;
|
||
if (0x01 == *(new_message_data_rev_mbus))
|
||
{
|
||
Sys_data_object.P1.start_using_flg = 0x01;
|
||
}
|
||
else if (0x00 == *(new_message_data_rev_mbus))
|
||
{
|
||
Sys_data_object.P1.start_using_flg = 0x00;
|
||
}
|
||
else
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
return;
|
||
}
|
||
EepWrite(&Sys_data_object.P1.start_using_flg, EEP_FRAME_STARTUSING_ADDR, 1, &s_eep_complete_mbus);
|
||
Frame_Para_Init();
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = *new_message_data_rev_mbus;
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0;
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
}
|
||
|
||
//写多项式系数
|
||
static void frame_func_s3_WT_SetPolyNomialcoefficient(void)
|
||
{
|
||
if(TASK_IDLE == EepIfIdle())
|
||
{
|
||
TYP_FLOW_COEFFICIENT coefficient_buffer[MULT_COEFFICIENT_BUF_NUM]= {0};//多项式建模参数变量缓存
|
||
g_frame_temp_len_mbus = 0;
|
||
if (0x01 == Sys_data_object.P1.start_using_flg) //出厂启用
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
return;
|
||
}
|
||
if(FM_METER_TYPE != *(new_message_data_rev_mbus))
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
return;
|
||
}
|
||
memcpy(&(coefficient_buffer[0].value[0]), (new_message_data_rev_mbus +1), sizeof (cal_coefficient));
|
||
if((0 ==coefficient_buffer[1].flt) && (0 ==coefficient_buffer[2].flt) && (0 ==coefficient_buffer[12].flt)&& (0 ==coefficient_buffer[13].flt)
|
||
&&(0 ==coefficient_buffer[23].flt)&& (0 ==coefficient_buffer[24].flt)&& (0 ==coefficient_buffer[34].flt)&& (0 ==coefficient_buffer[35].flt)
|
||
&& (0 ==coefficient_buffer[45].flt)&& (0 ==coefficient_buffer[46].flt))
|
||
{
|
||
memcpy(&cal_coefficient[0].flt, default_coefficient,sizeof(default_coefficient));
|
||
}
|
||
else
|
||
{
|
||
for(u8 i=0;i<MULT_COEFFICIENT_BUF_NUM;i++)
|
||
{
|
||
if((COEFFICIENT_MAX< coefficient_buffer[i].flt)||(coefficient_buffer[i].flt <COEFFICIENT_MIN))//判断范围有待确认-20191112
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
return;
|
||
}
|
||
}
|
||
memcpy(&(cal_coefficient[0].value[0]), (new_message_data_rev_mbus +1), sizeof (cal_coefficient));
|
||
}
|
||
EepWrite(&cal_coefficient[0].value[0], FRAME_FLOW_COEFFICIENT_ADDR, sizeof (cal_coefficient), &s_eep_complete_mbus);
|
||
g_frame_temp_send_buf_mbus[g_frame_temp_len_mbus++] = 0;
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_SUCCESS;
|
||
}
|
||
}
|
||
|
||
|
||
//解积成MBUS规约
|
||
u8 crack_frame_MBUS(u16 frame_lenth,u8 *frame_buffer)//
|
||
{
|
||
u16 tmp_i = 0;
|
||
u16 tmp_j = 0;
|
||
u8 tmp_check = 0;
|
||
u8 enc_tmp_addr[7];//缓存解密的地址
|
||
for (tmp_i = 0; tmp_i < frame_lenth; tmp_i++)
|
||
{
|
||
if (FM_HEAD_MARK == *(frame_buffer + tmp_i))
|
||
{
|
||
if (MET_TYPE == *(frame_buffer + tmp_i + 1))
|
||
{
|
||
//判断是表计规约还是模组/水台子规约,第10个字节>2,说明是水台子/模组的规约数据长度,否则就是表计的sta
|
||
frame_struct_MBUS.head_site = tmp_i; //记录帧头
|
||
frame_struct_MBUS.len = *(frame_buffer + tmp_i + 10);//数据长度
|
||
frame_struct_MBUS.end_site = frame_struct_MBUS.head_site + frame_struct_MBUS.len + 12;
|
||
frame_struct_MBUS.check_len = frame_struct_MBUS.end_site - frame_struct_MBUS.head_site - 1;
|
||
//检测数据帧是否有效
|
||
if ((frame_struct_MBUS.end_site < frame_lenth))
|
||
{
|
||
if(FM_END_MARK == *(frame_buffer + frame_struct_MBUS.end_site))
|
||
{
|
||
s_frame_flag_MBUS.enc_reply_flg = 0;
|
||
frame_struct_MBUS.ctrl = *(frame_buffer + frame_struct_MBUS.head_site + 9);
|
||
frame_struct_MBUS.DI0 = *(frame_buffer + frame_struct_MBUS.head_site + 11);
|
||
frame_struct_MBUS.DI1 = *(frame_buffer + frame_struct_MBUS.head_site + 12);
|
||
frame_struct_MBUS.serial_num0 = *(frame_buffer + frame_struct_MBUS.head_site + 13);
|
||
new_message_data_rev_mbus = (frame_buffer + frame_struct_MBUS.head_site + 15);
|
||
switch(frame_struct_MBUS.ctrl)
|
||
{
|
||
//地址加密的规约
|
||
case MFM_READ_MAC_ARGUMENT_CTRL://读物理地址
|
||
case MFM_SET_TEMPERATURECOEFFICIENT_ARGUMENT_CTRL://写温度系数
|
||
case MFM_SET_FLOWCOEFFICIENT_ARGUMENT_CTRL://写流量系数
|
||
case MFM_SET_VERIFICATIONSTATE_ARGUMENT_CTRL://设为检定
|
||
case MFM_START_OR_STOP_TEST_ARGUMENT_CTRL://启动停止测试
|
||
case MFM_START_OR_CLEAR_USING_ARGUMENT_CTRL://出厂启用
|
||
case FM_SET_POLYNOMIALCOEFFICIENT_ARGUMENT_CTRL://写多项式系数
|
||
{
|
||
frame_struct_MBUS.key_num = *(frame_buffer + frame_struct_MBUS.head_site + 14);
|
||
tmp_check = SA_crc((frame_buffer + frame_struct_MBUS.head_site), frame_struct_MBUS.check_len, frame_struct_MBUS.key_num);
|
||
if (tmp_check == *(frame_buffer + frame_struct_MBUS.end_site - 1))
|
||
{
|
||
if (MFM_READ_MAC_ARGUMENT_CTRL == frame_struct_MBUS.ctrl)//读物理地址,保存加密字key_num
|
||
{
|
||
if (SUCCESS == check_apply_addr(frame_buffer + frame_struct_MBUS.head_site + 2, Sys_data_object.P1.met_addr))
|
||
{
|
||
s_frame_flag_MBUS.rev_key_num = *(frame_buffer + frame_struct_MBUS.head_site + 14);
|
||
return SUCCESS_IES;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (tmp_j = 0; tmp_j < 7; tmp_j++)
|
||
{
|
||
enc_tmp_addr[tmp_j] = *(frame_buffer + frame_struct_MBUS.head_site + 2 + tmp_j);
|
||
}
|
||
Address_Encrypt((frame_buffer + frame_struct_MBUS.head_site + 2), frame_struct_MBUS.key_num); //解密地址
|
||
if (Num_Check(frame_struct_MBUS.key_num, Sys_data_object.P1.last_key_num)) //num ok
|
||
{
|
||
for (tmp_j = 0; tmp_j < 7; tmp_j++)
|
||
{
|
||
s_frame_flag_MBUS.enc_tmp_addr[tmp_j] = enc_tmp_addr[tmp_j];
|
||
}
|
||
s_frame_flag_MBUS.enc_reply_flg = TRUE;
|
||
return SUCCESS_IES;
|
||
}
|
||
Sys_data_object.P1.last_key_num = Num_Change(frame_struct_MBUS.key_num, Sys_data_object.P1.enable_bak_key); //更新NUM
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
//使用广播地址的规约
|
||
case MFM_READ_ADDR_ARGUMENT_CTRL:
|
||
case MFM_SET_ADDR_ARGUMENT_CTRL:
|
||
{
|
||
for (tmp_j = frame_struct_MBUS.head_site; tmp_j < (frame_struct_MBUS.end_site - 1); tmp_j++)
|
||
{
|
||
tmp_check += *(frame_buffer + tmp_j);
|
||
}
|
||
if (tmp_check != *(frame_buffer + frame_struct_MBUS.end_site - 1))//CS校验错误
|
||
{
|
||
return ERROR_IES;
|
||
}
|
||
if (SUCCESS == check_apply_addr(frame_buffer + frame_struct_MBUS.head_site + 2, broad_addr))
|
||
{
|
||
return SUCCESS_IES;
|
||
}
|
||
}
|
||
break;
|
||
//其他非加密规约
|
||
default:
|
||
{
|
||
for (tmp_j = frame_struct_MBUS.head_site; tmp_j < (frame_struct_MBUS.end_site - 1); tmp_j++)
|
||
{
|
||
tmp_check += *(frame_buffer + tmp_j);
|
||
}
|
||
if (tmp_check != *(frame_buffer + frame_struct_MBUS.end_site - 1))//CS校验错误
|
||
{
|
||
return ERROR_IES;
|
||
}
|
||
if (SUCCESS == check_apply_addr(frame_buffer + frame_struct_MBUS.head_site + 2, Sys_data_object.P1.met_addr))
|
||
{
|
||
return SUCCESS_IES;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return ERROR_IES;
|
||
}
|
||
//MBUS/水台子规约处理
|
||
u8 up_deal_code_mbus(void)
|
||
{
|
||
task_complete_mbus = PTL_PACK_BUSY;
|
||
switch(frame_struct_MBUS.ctrl)
|
||
{
|
||
case MFM_READ_ADDR_ARGUMENT_CTRL://读地址
|
||
{
|
||
frame_func_reply_WT_ReadAddr();
|
||
frame_struct_MBUS.ack_ctrl = MFM_READ_ADDR_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_READ_TEMPERATURECOEFFICIENT_ARGUMENT_CTRL://读温度系数
|
||
{
|
||
frame_func_reply_WT_ReadTemperatureCoefficient();
|
||
frame_struct_MBUS.ack_ctrl = MFM_READ_TEMPERATURECOEFFICIENT_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_READ_MAC_ARGUMENT_CTRL://读物理地址
|
||
{
|
||
frame_func_reply_WT_ReadMac();
|
||
frame_struct_MBUS.ack_ctrl = MFM_READ_MAC_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_SET_VERIFICATIONSTATE_ARGUMENT_CTRL://进检定
|
||
{
|
||
frame_func_reply_WT_SetVerificationState();
|
||
frame_struct_MBUS.ack_ctrl = MFM_SET_VERIFICATIONSTATE_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_READ_SERIALNUM_ARGUMENT_CTRL://读序列号
|
||
{
|
||
frame_func_reply_WT_ReadSerialNum();
|
||
frame_struct_MBUS.ack_ctrl = MFM_READ_SERIALNUM_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_OUT_VERIFICATIONSTATE_ARGUMENT_CTRL://退检定
|
||
{
|
||
frame_func_reply_WT_OutVerificationState();
|
||
frame_struct_MBUS.ack_ctrl = MFM_OUT_VERIFICATIONSTATE_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_READ_FLOWCOEFFICIENT_ARGUMENT_CTRL://读流量系数
|
||
{
|
||
frame_func_reply_WT_ReadFlowCoefficient();
|
||
frame_struct_MBUS.ack_ctrl = MFM_READ_FLOWCOEFFICIENT_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_READ_VERIFICATIONDATA_ARGUMENT_CTRL://读检定数据
|
||
{
|
||
frame_func_reply_WT_ReadVerificationData();
|
||
frame_struct_MBUS.ack_ctrl = MFM_READ_VERIFICATIONDATA_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_START_OR_STOP_TEST_ARGUMENT_CTRL://启动停止测试
|
||
{
|
||
frame_func_reply_WT_StartOrStopTest();
|
||
frame_struct_MBUS.ack_ctrl = MFM_START_OR_STOP_TEST_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case FM_READ_POLYNOMIALCOEFFICIENT_ARGUMENT_CTRL://读多项式系数
|
||
{
|
||
frame_func_reply_WT_ReadPolyNomialcoefficient();
|
||
frame_struct_MBUS.ack_ctrl = FM_READ_POLYNOMIALCOEFFICIENT_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_SET_TEMPERATURECOEFFICIENT_ARGUMENT_CTRL://写温度系数
|
||
{
|
||
frame_func_s3_WT_SetTempratureConefficient();
|
||
frame_struct_MBUS.ack_ctrl = MFM_SET_TEMPERATURECOEFFICIENT_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_SET_FLOWCOEFFICIENT_ARGUMENT_CTRL://写流量系数
|
||
{
|
||
frame_func_s3_WT_SetFowcoefficient();
|
||
frame_struct_MBUS.ack_ctrl = MFM_SET_FLOWCOEFFICIENT_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case MFM_START_OR_CLEAR_USING_ARGUMENT_CTRL://出厂启用
|
||
{
|
||
frame_func_s3_WT_StartOrClearUsing();
|
||
frame_struct_MBUS.ack_ctrl = MFM_START_OR_CLEAR_USING_REPLY_CTRL;
|
||
}
|
||
break;
|
||
case FM_SET_POLYNOMIALCOEFFICIENT_ARGUMENT_CTRL://写多项式系数
|
||
{
|
||
frame_func_s3_WT_SetPolyNomialcoefficient();
|
||
frame_struct_MBUS.ack_ctrl = FM_SET_POLYNOMIALCOEFFICIENT_REPLY_CTRL;
|
||
}
|
||
break;
|
||
default:
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
task_complete_mbus = PTL_PACK_FAIL;
|
||
}
|
||
break;
|
||
}
|
||
return task_complete_mbus;
|
||
}
|
||
|
||
void Frame_ResetDealState_Mbus(void)
|
||
{
|
||
up_deal_stat_mbus = UP_DEAL_S0;
|
||
}
|
||
/*******************************************************************************
|
||
* @fun_name: Frame_CreatCrcCs_Ack
|
||
* @brief : 组cs或CRC校验帧
|
||
* @param[in] : *p;len
|
||
* @param[out]: None
|
||
* @retval : None
|
||
* @other :
|
||
******************************************************************************/
|
||
void Frame_CreatCrcCs_Ack(u8* p_send_buf, u16* p_send_len)
|
||
{
|
||
int tmp_i=0;
|
||
//组应答帧头
|
||
p_send_buf[0] = 0xFE;
|
||
p_send_buf[1] = 0xFE;
|
||
p_send_buf[2] = FM_HEAD_MARK;
|
||
p_send_buf[3] = MET_TYPE;
|
||
if (MFM_SOLIDIFY_MAC_ARGUMENT_CTRL == frame_struct_MBUS.ctrl)
|
||
{
|
||
for (tmp_i = 0; tmp_i < 7; tmp_i++)
|
||
{
|
||
p_send_buf[4 + tmp_i] = Sys_data_object.P1.mac_addr[tmp_i];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (1 == s_frame_flag_MBUS.enc_reply_flg)
|
||
{
|
||
s_frame_flag_MBUS.enc_reply_flg = 0;
|
||
for (tmp_i = 0; tmp_i < 7; tmp_i++)
|
||
{
|
||
p_send_buf[4 + tmp_i] = s_frame_flag_MBUS.enc_tmp_addr[tmp_i];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (tmp_i = 0; tmp_i < 7; tmp_i++)
|
||
{
|
||
p_send_buf[4 + tmp_i] = Sys_data_object.P1.met_addr[tmp_i];
|
||
}
|
||
}
|
||
|
||
if (MFM_READ_MAC_ARGUMENT_CTRL == frame_struct_MBUS.ctrl)
|
||
{
|
||
Address_Encrypt(&p_send_buf[4], s_frame_flag_MBUS.rev_key_num);
|
||
}
|
||
}
|
||
switch(frame_struct_MBUS.ctrl)
|
||
{
|
||
//CRC校验的规约
|
||
case MFM_READ_MAC_ARGUMENT_CTRL:
|
||
case MFM_SET_TEMPERATURECOEFFICIENT_ARGUMENT_CTRL:
|
||
case MFM_SET_FLOWCOEFFICIENT_ARGUMENT_CTRL:
|
||
case MFM_SET_VERIFICATIONSTATE_ARGUMENT_CTRL:
|
||
case MFM_START_OR_STOP_TEST_ARGUMENT_CTRL:
|
||
case MFM_START_OR_CLEAR_USING_ARGUMENT_CTRL:
|
||
case FM_SET_POLYNOMIALCOEFFICIENT_ARGUMENT_CTRL:
|
||
{
|
||
p_send_buf[11] = frame_struct_MBUS.ack_ctrl;
|
||
p_send_buf[12] = (4+g_frame_temp_len_mbus);
|
||
p_send_buf[13] = frame_struct_MBUS.DI0;
|
||
p_send_buf[14] = frame_struct_MBUS.DI1;
|
||
p_send_buf[15] = frame_struct_MBUS.serial_num0;
|
||
p_send_buf[16] = frame_struct_MBUS.key_num;
|
||
for(tmp_i =0;tmp_i<g_frame_temp_len_mbus;tmp_i++)
|
||
{
|
||
p_send_buf[17+tmp_i] = g_frame_temp_send_buf_mbus[tmp_i];
|
||
}
|
||
if(frame_struct_MBUS.ctrl == MFM_READ_MAC_REPLY_CTRL)
|
||
{
|
||
Address_Encrypt(&p_send_buf[17], frame_struct_MBUS.key_num);
|
||
}
|
||
p_send_buf[17+g_frame_temp_len_mbus] = SA_crc(&p_send_buf[2], (p_send_buf[12] + 11), frame_struct_MBUS.key_num);
|
||
p_send_buf[18+g_frame_temp_len_mbus] = FM_END_MARK;
|
||
*p_send_len = (19+g_frame_temp_len_mbus);
|
||
}
|
||
break;
|
||
//CS校验的规约
|
||
default:
|
||
{
|
||
p_send_buf[11] = frame_struct_MBUS.ack_ctrl;
|
||
p_send_buf[12] = (3+g_frame_temp_len_mbus);
|
||
p_send_buf[13] = frame_struct_MBUS.DI0;
|
||
p_send_buf[14] = frame_struct_MBUS.DI1;
|
||
p_send_buf[15] = frame_struct_MBUS.serial_num0;
|
||
for(tmp_i=0; tmp_i<g_frame_temp_len_mbus; tmp_i++)
|
||
{
|
||
p_send_buf[16+tmp_i] = g_frame_temp_send_buf_mbus[tmp_i];
|
||
}
|
||
p_send_buf[16+g_frame_temp_len_mbus] = check_cs(&p_send_buf[2], (p_send_buf[12] + 11));
|
||
p_send_buf[17+g_frame_temp_len_mbus] = FM_END_MARK;
|
||
*p_send_len = (18+g_frame_temp_len_mbus);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
|