#include "BLV_BUS_Dev_C5IOFun.h"
#include "SPI_SRAM.h"
#include "check_fun.h"
#include "string.h"
#include "usart.h"
#include "DBG.h"
#include "CH57x_common.h"
#include "rw_logging.h"
#include "SRAM_Variable_Address.h"
#include "Log_api.h"
#include "BLV_Nor_Dev_LVinputFun.h"
#include "PC_DeviceTest_Fun.h"
#include "rtc.h"


/*******************************************************************************
* Function Name  : BLV_BUS_C5IO_For_Logic_Init 
* Description    : CSIO设备信息初始化函数 - 初始化信息来自逻辑文件
*******************************************************************************/
void BLV_BUS_CSIO_For_Logic_Init(LOGICFILE_DEVICE_INFO *dev_info,uint8_t *data,uint16_t data_len)
{
	Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"%s",__func__);
	
	Device_Public_Information_G BUS_Public;
	BUS_C5IO_INFO C5IO_Info;
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&C5IO_Info,0,sizeof(BUS_C5IO_INFO));
	
	BUS_Public.addr = dev_info->addr;			//设备485地址
	BUS_Public.type = DEV_C5IO_Type;			//设备类型
	BUS_Public.port = Bus_port;					//设备发送端口
	BUS_Public.baud = 115200;					//设备发送波特率
	BUS_Public.retry_num = C5IO_REPEATSENDTIMEMAX;		//设备数据重发次数
	BUS_Public.wait_time = C5IO_SEND_WAIT_TIME;		//设备数据发送等待回复时间 
	BUS_Public.polling_cf = (uint32_t)&BLV_BUS_C5IO_Cycle_Call;
	BUS_Public.processing_cf = (uint32_t)&BLV_BUS_C5IO_Data_Processing;
	
	C5IO_Info.DevOfflineLast = DEV_IS_ONLINE;	//在线初始化
	C5IO_Info.DevOffline = C5IO_Info.DevOfflineLast;
	C5IO_Info.C5IO_Version = 1;

	/*默认都为按键类型*/
	C5IO_Info.DI_Type[C5IO_DI_CH1] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;
	C5IO_Info.DI_Type[C5IO_DI_CH2] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;			
	C5IO_Info.DI_Type[C5IO_DI_CH3] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;			
	C5IO_Info.DI_Type[C5IO_DI_CH4] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;			
	C5IO_Info.DI_Type[C5IO_DI_CH5] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;			
	C5IO_Info.DI_Type[C5IO_DI_CH6] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;		
	C5IO_Info.DI_Type[C5IO_DI_CH7] = BUS_C5IO_DI_Key_Type | BUS_C5IO_DI_Level_LOW;			//门铃
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH1] = 0x02;	//设置消抖时间为20ms	
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH2] = 0x02;	//设置消抖时间为20ms
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH3] = 0x02;	//设置消抖时间为20ms
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH4] = 0x02;	//设置消抖时间为20ms
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH5] = 0x02;	//设置消抖时间为20ms
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH6] = 0x02;	//设置消抖时间为20ms
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH7] = 0x02;	//设置消抖时间为20ms

	C5IO_Info.DI_Type[C5IO_DI_CH8] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;
	C5IO_Info.DI_Type[C5IO_DI_CH9] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;			
	C5IO_Info.DI_Type[C5IO_DI_CH10] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;			
	C5IO_Info.DI_Type[C5IO_DI_CH11] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;			
	C5IO_Info.DI_Type[C5IO_DI_CH12] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;			
	C5IO_Info.DI_Type[C5IO_DI_CH13] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;	

	C5IO_Info.DI_Detection_Time[C5IO_DI_CH8] = 0x02;	//设置消抖时间为20ms	
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH9] = 0x02;	//设置消抖时间为20ms
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH10] = 0x02;	//设置消抖时间为20ms
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH11] = 0x02;	//设置消抖时间为20ms
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH12] = 0x02;	//设置消抖时间为20ms
	C5IO_Info.DI_Detection_Time[C5IO_DI_CH13] = 0x02;	//设置消抖时间为20ms


	Add_BUS_Device_To_List2(&BUS_Public,(uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO));
	
	BUS485_Info.device_num += 1;
}

/*******************************************************************************
* Function Name  : BLV_BUS_C5IO_For_Logic_Init 
* Description    : CSIO设备 - DI类型初始化函数 - 初始化信息来自逻辑文件
*******************************************************************************/
void BLV_BUS_CSIO_DI_For_Logic_Init(LOGICFILE_DEVICE_INFO *dev_info,uint8_t *data,uint16_t data_len)
{
	Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"%s",__func__);
	
	uint32_t csio_addr = Find_Device_List_Information(DEV_C5IO_Type,0x00);
	
	if(csio_addr == 0x00) 
	{
//		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"未找到本地IO地址 %d",dev_info->addr);
//		
//		uint32_t read_addr = SRAM_Device_List_Start_Addr;
//		uint32_t end_addr = SRAM_Read_DW(SRAM_ACTIVE_Device_List_Addr);
//		
//		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"设备结束地址 %08X",end_addr);
//		if((end_addr < SRAM_Device_List_Start_Addr) || (end_addr > SRAM_Device_List_End_Addr))	end_addr = SRAM_Device_List_End_Addr;
//		
//		for(uint32_t i=SRAM_Device_List_Start_Addr;i<end_addr;)
//		{
//			if((SRAM_Read_Byte(read_addr + Dev_Type) == DEV_C5IO_Type) && (SRAM_Read_Byte(read_addr + Dev_Addr) == 0x00))
//			{
//				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"找到设备 %08X - %d %d",i,SRAM_Read_Byte(read_addr + Dev_Type),SRAM_Read_Byte(read_addr + Dev_Addr));
//				if(Device_Data_Check(read_addr) == 0)
//				{
//				}
//			}else{
//				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"未找到设备 %08X - %d %d",i,SRAM_Read_Byte(read_addr + Dev_Type),SRAM_Read_Byte(read_addr + Dev_Addr));
//			}
//			read_addr += SRAM_Device_List_Size;
//			i+= SRAM_Device_List_Size;
//			if(read_addr >= end_addr)	
//			{
//			}
//		}
//		
//		
//		BLV_Nor_Dev_LVinput_Init(dev_info->addr,dev_info->input_num);
		return ;
	}else {
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"本地IO地址:%08X",csio_addr);
	}
	
	uint16_t temp_len = 0;
	uint8_t input_num = 0;
	uint8_t input_type = 0;
	uint8_t input_level = 0;
	uint8_t input_time = 0;
	uint8_t input_set_flag = 0;
	
	uint16_t temp = 0;
	uint8_t crc_val = 0;
	
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),csio_addr+Dev_Privately);
	
	input_num = dev_info->input_num;
	
	if(input_num > C5IO_DI_CH_MAX)	
	{
		input_num = C5IO_DI_CH_MAX;
	}
	
	temp_len = input_num*4;	//设置DI类型以及设置触发状态
	
	if((temp_len + LogicFile_DeviceInfo_InputSet) > data_len)
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"初始化DI数据长度不对 %d - %d ",data_len,(temp_len + LogicFile_DeviceInfo_InputSet));
	}
	
	temp_len = 0;
	for(uint8_t i=0;i<input_num;i++)
	{
		input_set_flag = 0;
		input_type = data[LogicFile_DeviceInfo_InputSet + temp_len + 0];
		input_level = data[LogicFile_DeviceInfo_InputSet + temp_len + 1];
		input_time = data[LogicFile_DeviceInfo_InputSet + temp_len + 2];
		
		switch(input_type)
		{
			case BUS_C5IO_DI_Key_Type:
				input_set_flag++;
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI%d - 按键",i);
				C5IO_Info.DI_Type[i] = BUS_C5IO_DI_Key_Type;
				break;
			case BUS_C5IO_DI_Pir_Type:
				input_set_flag++;
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI%d - PIR",i);
				C5IO_Info.DI_Type[i] = BUS_C5IO_DI_Pir_Type;
				break;
			case BUS_C5IO_DI_Dry_Type:
				input_set_flag++;
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI%d - 干接点",i);
				C5IO_Info.DI_Type[i] = BUS_C5IO_DI_Dry_Type;
				break;
			default:
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI%d - 类型不对",i);
				break;
		}
		
		switch(input_level)
		{
			case 0x01:
				input_set_flag++;
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI%d - 触发电平:高电平 消抖时间:%d0ms",i,input_time);
			
				C5IO_Info.DI_Type[i] |= BUS_C5IO_DI_Level_HIGH;
				C5IO_Info.DI_Detection_Time[i] = input_time;
				break;
			case 0x02:
				input_set_flag++;
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI%d - 触发电平:低电平 消抖时间:%d0ms",i,input_time);
				
				C5IO_Info.DI_Type[i] |= BUS_C5IO_DI_Level_LOW;
				C5IO_Info.DI_Detection_Time[i] = input_time;
				break;
			default:
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI%d - 触发电平数据不对 消抖时间:%d0ms",i,input_time);
				break;
		}
		
		
		if(input_set_flag != 0x02)	//设置类型及触发电平不对，采用默认参数
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI%d - 采用默认参数",i);
			C5IO_Info.DI_Type[i] = BUS_C5IO_DI_Dry_Type | BUS_C5IO_DI_Level_LOW;
			C5IO_Info.DI_Detection_Time[i] = 0x02;	//设置消抖时间为20ms	
		}else {
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI%d Start:%d",i,C5IO_Info.DI_Type[i],C5IO_Info.DI_Detection_Time[i]);
		}
		
		temp_len += 4;
	}
	
	SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),csio_addr+Dev_Privately);
	/*计算校验值*/
	SRAM_Write_Byte(0x00,csio_addr+Dev_Check);
	temp = sizeof(BUS_C5IO_INFO) + Dev_Privately;
	crc_val = Dev_CheckSum(csio_addr,temp);
	SRAM_Write_Byte(crc_val,csio_addr+Dev_Check);		//校验值重新写入
	
	BLV_Nor_Dev_LVinput_Init(dev_info->addr,dev_info->input_num);
}


/*******************************************************************************
* Function Name  : BLV_BUS_C5IO_Cycle_Call 
* Description    : C5IO轮询发送函数函数
* Input          : 
	dev_addr	: 设备信息地址
* Return         :
	0x01：等待发送
*******************************************************************************/
uint8_t BLV_BUS_C5IO_Cycle_Call(uint32_t dev_addr)
{
//	uint16_t temp = 0;
//	uint8_t crc_val = 0;
//	temp = SRAM_Read_Byte(dev_addr+Dev_Type);		//判断设备类型
//	if(temp != DEV_C5IO_Type) return 0x01;
	
	Device_Public_Information_G BUS_Public;
	BUS_C5IO_INFO C5IO_Info;
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);	
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	
	if((BUS_Public.port == Bus_port) && (BUS485_Info.BUS_Start == Baud_Wait)) {
		//切换波特率过程中,只发送询问数据
		//Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"切换波特率过程中,只发送询问数据");
		BUS_C5IO_Inquire_Datasend(dev_addr,&C5IO_Info);
		
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&C5IO_Info, sizeof(BUS_C5IO_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
		
		return RS485OCCUPYTIME;
	}
	
	if(C5IO_Info.Relay_Control_Flag != 0x00)
	{
		BUS_C5IO_Relay_Control_Datasend(dev_addr,&C5IO_Info);
	}
	else if(C5IO_Info.Relay_Inching_Control_Flag != 0x00)
	{
		BUS_C5IO_Relay_Inching_Control_Datasend(dev_addr,&C5IO_Info);
	}
	else if(C5IO_Info.DI_Control_Flag != 0x00)
	{
		BUS_C5IO_DI_Control_Datasend(dev_addr,&C5IO_Info);
		/*2022-12-12*/
		if(C5IO_Info.DI_Reset_Flag == 0x01)
		{
			C5IO_Info.DI_Reset_Tick = SysTick_1ms;
			C5IO_Info.DI_Init_flag = 0x00;				//2025-08-07 增加上电后，不产生动作
		}
		/*2022-12-12*/
	}
	else if(C5IO_Info.DO_Control_Flag != 0x00)
	{
		BUS_C5IO_DO_Control_Datasend(dev_addr,&C5IO_Info);
	}
	else if(C5IO_Info.DO_Inching_Control_Flag != 0x00)
	{
		BUS_C5IO_DO_Inching_Control_Datasend(dev_addr,&C5IO_Info);
	}
	else if(C5IO_Info.Relay_Reset_Flag == 0x01)   /*2022-12-12*/
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO Relay Reset!!!!!!");
		C5IO_Info.Relay_Reset_Flag = 0x00;
		C5IO_Info.Relay_Control_Flag = 0xFFFFFFFF;
		BUS_C5IO_Relay_Control_Datasend(dev_addr,&C5IO_Info);
	}
    else if((C5IO_Info.rtc_set_flag == 0x01) || ((DevActionGlobal.TimeSyncFlag & 0x02) == 0x02))   /*2024-08-02*/
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO Set RTC!!!!!!");
		C5IO_Info.rtc_set_flag = 0x00;
		DevActionGlobal.TimeSyncFlag &= 0x01;
		
		BUS_CSIO_SetRTCTime_Datasend(dev_addr,&C5IO_Info);
	}
	else 
	{
		BUS_C5IO_Inquire_Datasend(dev_addr,&C5IO_Info);
	}
	
	C5IO_Info.inquire_tick = SysTick_1ms;	//记录询问时间戳
	
	/*通讯记录 + 调整设备通讯波特率*/
//	temp = BLV_Communication_Baud_Adjust2(&C5IO_Info.comm_record,&BUS_Public);
//	if(temp != 0x00)
//	{
//		switch(temp)
//		{
//			case 0x01:
//				//Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"当前通讯记录未达计算数");
//				break;
//			case 0x02:
//				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO 连续失败次数已达上限，切换通讯波特率");
//				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO Adjust Baud:%ld!",BUS_Public.baud);
//				//LOG_Device_COMM_Adjust_Baud_Record(DEV_C5IO_Type,BUS_Public.addr,BUS_Public.baud);
//				break;
//			case 0x03:
//				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO 通讯失败百分比已达上限，切换通讯波特率");
//				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO Adjust Baud:%ld!",BUS_Public.baud);
//				//LOG_Device_COMM_Adjust_Baud_Record(DEV_C5IO_Type,BUS_Public.addr,BUS_Public.baud);
//				break;
//		}
//	}
//	
//	BLV_Communication_Record(&C5IO_Info.comm_record,0x01,0x00);
	
	if(C5IO_Info.DevSendCnt > C5IO_REPEATSENDTIMEMAX)
	{
		if(C5IO_Info.DevOffline != DEV_IS_OFFLINE)
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO OFFLINE");  //  离线上报
			LOG_Device_Online_Record(DEV_C5IO_Type,BUS_Public.addr,LogInfo_Device_Offline);	//记录设备离线
		}
		
		C5IO_Info.DevOffline = DEV_IS_OFFLINE;		//判为离线
		C5IO_Info.DevSendCnt = 0;
		if(C5IO_Info.DevOffline != C5IO_Info.DevOfflineLast)	//当前在线状态不等于上一次在线状态
		{
			C5IO_Info.DevOfflineLast = C5IO_Info.DevOffline;	//更新上一次在线状态
			Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_OFFLINE);	//保存设备在线状态到SRAM
		}
	}else {
		C5IO_Info.DevSendCnt++;   				//发送次数累计
	}
	
	BUS_Public.check = 0x00;
	BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&C5IO_Info, sizeof(BUS_C5IO_INFO));
	SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
	SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	
	return RS485OCCUPYTIME;
}

/*判定CSIO 时间处于有效期*/
uint8_t BLV_CSIO_RTC_TimeValid(uint8_t *date){
    
    /*判断年限：2024~2050年*/
    if( (RTC_TimeDate_Correct_Figure(date[0]) == 0x00) && ((date[0] >= 0x24) && (date[0] <= 0x50)) ){
        /*判断月份：1~12*/
        if( (RTC_TimeDate_Correct_Figure(date[1]) == 0x00) && ((date[1] >= 0x01) && (date[1] <= 0x12)) ){
            /*判断天数：1~31*/
            if( (RTC_TimeDate_Correct_Figure(date[2]) == 0x00) && ((date[2] >= 0x01) && (date[2] <= 0x31)) ){
                /*判断小时：0~23*/
                if( (RTC_TimeDate_Correct_Figure(date[3]) == 0x00) && (date[3] <= 0x23) ){
                    /*判断分：0~59*/
                    if( (RTC_TimeDate_Correct_Figure(date[4]) == 0x00) && (date[4] <= 0x59) ){
                        /*判断秒：0~59*/
                        if( (RTC_TimeDate_Correct_Figure(date[5]) == 0x00) && (date[5] <= 0x59) ){
                            /*判断星期：0~6*/
                            if( date[6] < 0x07 ){
                                return 0x00;
                            }else{
                                Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO week error:%02x",date[3]);
                            }
                        }else{
                            Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO sec error:%02x",date[3]);
                        }
                    }else{
                        Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO min error:%02x",date[3]);
                    }
                }else{
                    Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO hour error:%02x",date[3]);
                }
            }else{
                Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO day error:%02x",date[2]);
            }
        }else{
            Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO mon error:%02x",date[1]);
        }
    }else{
        Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO year error:%02x",date[0]);  
    }
    
    return 0x01;
}

/*******************************************************************************
* Function Name  : BLV_BUS_C5IO_Data_Processing 
* Description    : C5IO数据处理函数
* Input          : 
	dev_addr	: 设备信息地址
	data_addr	: 数据地址
	len			：数据长度
* Return         : 
	0x00：处理成功
	0x01：处理失败
*******************************************************************************/
uint8_t BLV_BUS_C5IO_Data_Processing(uint32_t dev_addr,uint32_t data_addr,uint16_t len)
{
	uint8_t crc_val = 0;
	uint8_t reset_DI = 0;   //di重设标志
	static uint8_t DI_Init_flg = 0;
	uint8_t temp = 0,temp1 = 0,temp2 = 0,temp3 = 0,temp4 = 0,temp5 = 0;
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	
	static uint8_t rtc_err = 0;
	
	/*新改动：优化处理速度和添加日志*/
	uint16_t deal_len = len;
	if(deal_len > C5IO_RecvData_Len_MAX)	
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO Check_Len Fail!");
		return 0x01;	//和校验
	}
	uint8_t deal_buff[C5IO_RecvData_Len_MAX];
	memset(deal_buff,0,sizeof(deal_buff));
	SRAM_DMA_Read_Buff(deal_buff,deal_len,data_addr);		//读取处理数据长度
	
	if(deal_len < PKT_PARA)
	{
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"C5IO PKT_LEN Fail:",deal_buff,deal_len);
		return 0x01;
	}
	
	if(deal_buff[PKT_LEN] != deal_len)		
	{
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"C5IO PKT_LEN Fail:",deal_buff,deal_len);
		return 0x01;						//长度不对
	}
	
	if(CheckSum(deal_buff,deal_len) != 0x00) 
	{
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"C5IO Check Fail:",deal_buff,deal_len);
		return 0x01;	//和校验
	}
	
	BLV_Communication_Record(&C5IO_Info.comm_record,0x02,0x01);		//记录通讯成功

	if(deal_buff[PKT_ADD_FM] != 0x01)
	{
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"C5IO PKT_ADD_FM Fail:",deal_buff,deal_len);
		return 0x01;						//发送地址不对
	}

	if((deal_buff[PKT_TYPE] & 0x0F) != C5IO_Info.DevSendSN)	
	{
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"C5IO PKT_TYPE Fail:",deal_buff,deal_len);
		return 0x01;			//序号不对
	}

	if(deal_buff[PKT_DevType] != C5IOTYPE)	
	{
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"C5IO PKT_DevType Fail:",deal_buff,deal_len);
		return 0x01;					//设备类型不对
	}

	if(deal_buff[PKT_ADD_TO] != 0x00)	
	{
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"C5IO PKT_ADD_TO Fail:",deal_buff,deal_len);
		return 0x01;						//接收地址不对
	}

	if(deal_buff[PKT_CMD] != BLV_C5IO_Reply_CMD)	
	{
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"C5IO PKT_CMD Fail:",deal_buff,deal_len);
		return 0x01;			//回复命令不对
	}
	
	if(deal_buff[PKT_PARA] == BLV_C5IO_Error_Result)	{
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"C5IO PKT_REV Fail:",deal_buff,deal_len);
		return 0x01;		//回复结果 - 错误的情况下，该包数据不进行处理		2026-01-09
	}
	
	if(C5IO_Info.DevOffline == DEV_IS_OFFLINE)	//设备处于离线状态
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO LogInfo_Device_Online...........");
		LOG_Device_Online_Record(DEV_C5IO_Type,SRAM_Read_Byte(dev_addr+Dev_Addr),LogInfo_Device_Online);	//记录设备离线
	}
	
	C5IO_Info.DevSendCnt = 0x00;
	C5IO_Info.DevOffline = DEV_IS_ONLINE;    //设备在线
	if(C5IO_Info.DevOffline != C5IO_Info.DevOfflineLast)	//当前在线状态不等于上一次在线状态
	{
		Device_Public_Information_G BUS_Public;
		
		C5IO_Info.DevOfflineLast = C5IO_Info.DevOffline;	//更新上一次在线状态
		SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);
		Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_ONLINE);	//保存设备在线状态到SRAM
	}
	
	if((DI_Init_flg == 0) && (deal_buff[PKT_PARA] != 0xF0))  //第一次轮询的回复    2024-04-01  避免第一包不是查询命令回复导致DI类型错误DI不可用问题
	{
		DI_Init_flg = 1;
		#if (USE_FLOOR_TYPE == 1)  //C5底板
			
			if(len > 0x12)    //使用新协议，CSIO
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO USE_FLOOR_TYPE");
				C5IO_Info.DI_Control_Flag = 0x1FFF; //CSIO
				C5IO_Info.C5IO_Version = 3;
			}
			else
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO USE_FLOOR_TYPE");
				C5IO_Info.C5IO_Version = 0;
				C5IO_Info.DI_Control_Flag = 0x7F;   //C5IO
			}
		
		#elif (USE_FLOOR_TYPE == 2)  //C12底板 
			
			if(len > 0x18)    //使用新协议，CSIO
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO USE_FLOOR_TYPE");			
				C5IO_Info.C5IO_Version = 3;
			}
			else
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C12IO USE_FLOOR_TYPE");
				C5IO_Info.C5IO_Version = 1;
			}
			C5IO_Info.DI_Control_Flag = 0x1FFF; //
		#endif
		
		C5IO_Info.CxIO_DI_Control_Flag = C5IO_Info.DI_Control_Flag;    ////记录需要设置的DI回路
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"IO VERSION:%d", C5IO_Info.C5IO_Version);
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI_Control_Flag:%X", C5IO_Info.DI_Control_Flag);
		/*数据解析完毕,保存SRAM中*/
		SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
		/*计算校验值*/
		SRAM_Write_Byte(0x00,dev_addr+Dev_Check);
		crc_val = Dev_CheckSum(dev_addr, sizeof(BUS_C5IO_INFO) + Dev_Privately);
		SRAM_Write_Byte(crc_val,dev_addr+Dev_Check);		//校验值重新写入
		
		return 0x00;
	}
	
	//收到回复确定，清空回复标志
	switch(C5IO_Info.Send_Type)
	{
		case BLV_C5IO_Inquire_CMD:

			break;
		case BLV_C5IO_Set_Relay_CMD:
			if(deal_buff[PKT_PARA] == BLV_C5IO_Relay_Result)	
			{
				C5IO_Info.Relay_Control_Flag &= ~(C5IO_Info.Last_Relay_Control_Flag);
				
				LOG_Device_COMM_Control_Reply_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,deal_buff,deal_len);
			}

			break;
		case BLV_C5IO_Set_Relay_Inching_CMD:
			if(deal_buff[PKT_PARA] == BLV_C5IO_Relay_Inching_Result)	
			{
				C5IO_Info.Relay_Inching_Control_Flag &= ~(C5IO_Info.Last_Relay_Inching_Control_Flag);
				
				LOG_Device_COMM_Control_Reply_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,deal_buff,deal_len);
			}
			break;
		case BLV_C5IO_Set_Do_CMD:
			if(deal_buff[PKT_PARA] == BLV_C5IO_Do_Result)	
			{
				C5IO_Info.DO_Control_Flag &= ~(C5IO_Info.Last_DO_Control_Flag);
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"BLV_C5IO_Set_DO_Succ");
				LOG_Device_COMM_Control_Reply_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,deal_buff,deal_len);
			}
			break;
		case BLV_C5IO_Set_Do_Inching_CMD:
			if(deal_buff[PKT_PARA] == BLV_C5IO_Do_Inching_Result)	
			{
				C5IO_Info.DO_Inching_Control_Flag &= ~(C5IO_Info.Last_DO_Inching_Control_Flag);
				
				LOG_Device_COMM_Control_Reply_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,deal_buff,deal_len);
			}
			break;
		case BLV_C5IO_Set_Di_CMD:
			if(deal_buff[PKT_PARA] == BLV_C5IO_Di_Result)	
			{
				C5IO_Info.DI_Control_Flag &= ~(C5IO_Info.Last_DI_Control_Flag);
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"BLV_C5IO_Set_Di_CMD Clear!!!!!!!");
				C5IO_Info.DI_Reset_Flag = 0x00;
				LOG_Device_COMM_Control_Reply_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,deal_buff,deal_len);
			}
			break;
		default: break;
	}
	
	
	
	if(C5IO_Info.C5IO_Version == 1)     //C12IO
	{
		for(uint8_t i=0; i<4; i++)
		{
			temp = deal_buff[PKT_PARA + 1 + i];
			for(uint8_t j=0; j<4; j++)
			{
				temp1 = C5IO_Info.DI_Type[i*4+j] & 0x0F;
				temp2 = (temp >> (j*2)) & 0x03;
				if((temp1 == temp2) && (temp1 == BUS_C5IO_DI_Key_Type) )	//输入类型是否相同
				{
					C5IO_Info.DI_Control_Flag &= ~(0x01<<(i*4+j));
					temp3 = deal_buff[PKT_PARA + 5 + i];
					temp3 = (temp3 >> (j*2)) & 0x03 ;
					if(SysTick_1ms - C5IO_Info.DI_Reset_Tick>1000)  /*2022-12-12*/
					{
						if(temp3 != 0x00)                            
						{
							C5IO_Info.DI_Start[i*4+j] = temp3;
							temp5++;
							Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C12IO DI_Start%d %d !",i*4+j,temp3);
						}
					}
				}else if((temp1 == temp2) && ((temp1 == BUS_C5IO_DI_Pir_Type) || (temp1 == BUS_C5IO_DI_Dry_Type))){
					
					C5IO_Info.DI_Control_Flag &= ~(0x01<<(i*4+j));
					temp3 = deal_buff[PKT_PARA + 5 + i];
					temp3 = (temp3 >> (j*2)) & 0x03 ;
					if(SysTick_1ms - C5IO_Info.DI_Reset_Tick>1000)  /*2022-12-12*/
					{
						if(temp3 != C5IO_Info.DI_Start[i*4+j])       
						{
							C5IO_Info.DI_Start[i*4+j] = temp3;
							temp5++;
							Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C12IO DI_PIR_Start%d %d !",i*4+j,temp3);
						}
					}
					
				}else {				//输入类型不同 - 标志位置一
					if((i*4+j >= C5IO_DI_CH_MAX))  break;
//					Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"C12IO DI_Type %d Fail! \r\n",i*4+j);
					Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C12IO DI_Type %d Fail! temp1:%d , temp2:%d",i*4+j,temp1,temp2);
					reset_DI = 1;   //标记重设DI
				}
			}
		}
		
		C5IO_Info.DI_Level_Actual_Start = deal_buff[PKT_PARA + 9] | (deal_buff[PKT_PARA + 10]<<8);
		C5IO_Info.DO_Level_Actual_Start = deal_buff[PKT_PARA + 11] | (deal_buff[PKT_PARA + 12]<<8);
		if(C5IO_Info.DO_Level_Perfect_Start != C5IO_Info.DO_Level_Actual_Start)		/*比较C5IO_DO参数,是否保存日志*/
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C12IO_DO_Status Change");
			C5IO_Info.DO_Level_Perfect_Start = C5IO_Info.DO_Level_Actual_Start;
			
			/*这个地址暂时保留，后面可以删除*/
			SRAM_Write_Byte(C5IO_Info.DO_Level_Actual_Start,SRAM_LOG_Device_C5IO_DO_Status);
			temp4++;
		}
		
		C5IO_Info.Relay_Level_Actual_Start = deal_buff[PKT_PARA + 15];
		C5IO_Info.Relay_Level_Actual_Start <<= 8 ;
		C5IO_Info.Relay_Level_Actual_Start |= deal_buff[PKT_PARA + 14];
		C5IO_Info.Relay_Level_Actual_Start <<= 8 ;
		C5IO_Info.Relay_Level_Actual_Start |= deal_buff[PKT_PARA + 13];
		
		if(C5IO_Info.Relay_Level_Perfect_Start != C5IO_Info.Relay_Level_Actual_Start)		/*比较C5IO_Relay参数,是否保存日志*/
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C12IO_Relay_Status Change");
			
			C5IO_Info.Relay_Level_Perfect_Start = C5IO_Info.Relay_Level_Actual_Start;
			
			/*这个地址暂时保留，后面可以删除*/
			SRAM_Write_Byte(deal_buff[PKT_PARA + 13],SRAM_LOG_Device_C5IO_Relay_Status);
			SRAM_Write_Byte(deal_buff[PKT_PARA + 14],SRAM_LOG_Device_C5IO_Relay_Status + 1);
			SRAM_Write_Byte(deal_buff[PKT_PARA + 15],SRAM_LOG_Device_C5IO_Relay_Status + 2);
			
			temp4++;
		}
		
		/*PC通讯测试中 2022-07-12*/
		if(temp4 != 0x00)	//如果DO、RELAY状态改变时，上报状态
		{
			if(g_pc_test.test_flag == 0x02)		
			{
				BLV_PC_Testing_Data_Reported(0x02,C5IOTYPE,0x00,SRAM_LOG_Device_C5IO_Relay_Status,4);
			}
		}
		
		if(temp5 != 0x00)
		{
			/*DI 动作状态 对于C12IO和CSIO而言 DI数目为13,用4Byte描述动作*/
			C5IO_Info.DI_Actual_State = deal_buff[PKT_PARA + 8];
			C5IO_Info.DI_Actual_State <<= 8 ;
			C5IO_Info.DI_Actual_State |= deal_buff[PKT_PARA + 7];
			C5IO_Info.DI_Actual_State <<= 8 ;
			C5IO_Info.DI_Actual_State |= deal_buff[PKT_PARA + 6];
			C5IO_Info.DI_Actual_State <<= 8 ;
			C5IO_Info.DI_Actual_State |= deal_buff[PKT_PARA + 5];
			
			if(C5IO_Info.DI_Perfect_State != C5IO_Info.DI_Actual_State)
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C12IO_DI_Status Change");
				
				C5IO_Info.DI_Perfect_State = C5IO_Info.DI_Actual_State;
				
				/*这个地址暂时保留，后面可以删除 暂时用到这2Byte字节地址数据*/
				SRAM_Write_Byte(deal_buff[PKT_PARA + 5],SRAM_LOG_Device_C5IO_DI_Status);
				SRAM_Write_Byte(deal_buff[PKT_PARA + 6],SRAM_LOG_Device_C5IO_DI_Status + 1);
				
				temp4++;
			}
		}
	}
	else if(C5IO_Info.C5IO_Version == 3)     //CSIO
	{
		for(uint8_t i=0; i<4; i++)
		{
			temp = deal_buff[PKT_PARA + 1 + i];
			for(uint8_t j=0; j<4; j++)
			{
				temp1 = C5IO_Info.DI_Type[i*4+j] & 0x0F;
				temp2 = (temp >> (j*2)) & 0x03;
				if((temp1 == temp2) && (temp1 == BUS_C5IO_DI_Key_Type) )	//输入类型是否相同
				{
					C5IO_Info.DI_Control_Flag &= ~(0x01<<(i*4+j));
					temp3 = deal_buff[PKT_PARA + 5 + i];
					temp3 = (temp3 >> (j*2)) & 0x03 ;
					if(SysTick_1ms - C5IO_Info.DI_Reset_Tick>1000)  /*2022-12-12*/
					{
						if(temp3 != 0x00)                           
						{
							C5IO_Info.DI_Start[i*4+j] = temp3;
							temp5++;
							Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO DI_Start%d %d !",i*4+j,temp3);
						}
					}
					
				}else if((temp1 == temp2) && ((temp1 == BUS_C5IO_DI_Pir_Type) || (temp1 == BUS_C5IO_DI_Dry_Type))){
					
					C5IO_Info.DI_Control_Flag &= ~(0x01<<(i*4+j));
					temp3 = deal_buff[PKT_PARA + 5 + i];
					temp3 = (temp3 >> (j*2)) & 0x03 ;
					if(SysTick_1ms - C5IO_Info.DI_Reset_Tick>1000)  /*2022-12-12*/
					{
						if(temp3 != C5IO_Info.DI_Start[i*4+j])
						{
							C5IO_Info.DI_Start[i*4+j] = temp3;
							temp5++;
							Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO DI_PIR_Start%d %d !",i*4+j,temp3);
						}
				    }	
					
				}else {				//输入类型不同 - 标志位置一
					if((i*4+j >= C5IO_DI_CH_MAX))  break;
					Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO DI_Type %d Fail! temp1:%d , temp2:%d",i*4+j,temp1,temp2);
					reset_DI = 1;   //标记重设DI
				}
				
			}
			
		}
		
		//2025-08-07 增加上电后，不产生动作
		if( (C5IO_Info.DI_Init_flag == 0x00) && (SysTick_1ms - C5IO_Info.DI_Reset_Tick > 1000) ){
			C5IO_Info.DI_Init_flag = 0x01;
			
			for(uint8_t i = 0;i<C5IO_DI_CH_MAX;i++)
			{
				C5IO_Info.DI_LastStart[i] = C5IO_Info.DI_Start[i];
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI_Init_flag Init CH%d:%d",i,C5IO_Info.DI_Start[i]);
			}
		}
		
		C5IO_Info.DI_Level_Actual_Start = deal_buff[PKT_PARA + 9] | (deal_buff[PKT_PARA + 10]<<8);
		C5IO_Info.DO_Level_Actual_Start = deal_buff[PKT_PARA + 11] | (deal_buff[PKT_PARA + 12]<<8);
		if(C5IO_Info.DO_Level_Perfect_Start != C5IO_Info.DO_Level_Actual_Start)		/*比较C5IO_DO参数,是否保存日志*/
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO_DO_Status Change");
			C5IO_Info.DO_Level_Perfect_Start = C5IO_Info.DO_Level_Actual_Start;
			
			/*这个地址暂时保留，后面可以删除*/
			SRAM_Write_Byte(C5IO_Info.DO_Level_Actual_Start,SRAM_LOG_Device_C5IO_DO_Status);
			temp4++;
		}
		
        C5IO_Info.comm_version = deal_buff[PKT_PARA + 16];  //CSIO通讯软件版本号
        
		/*硬件RTC 时间获取*/
		if(len >= 31 )   //确保是CSIO
		{
			if( (deal_buff[PKT_PARA + 17] != 0) && (deal_buff[PKT_PARA + 18] != 0) && (deal_buff[PKT_PARA + 19] != 0) )  //年月日不为0
			{
				/*判定时间是否处于有效期内*/
                if(BLV_CSIO_RTC_TimeValid(&deal_buff[PKT_PARA + 17]) == 0x00){
                    /*硬件RTC 在线*/
                    
//                    Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"CSIO Ver:%d RTC Time:%02x-%02x-%02x %02x:%02x:%02x %02x\r\n",deal_buff[PKT_PARA + 16],deal_buff[PKT_PARA + 17] \
                            ,deal_buff[PKT_PARA + 18] \
                            ,deal_buff[PKT_PARA + 19] \
                            ,deal_buff[PKT_PARA + 20] \
                            ,deal_buff[PKT_PARA + 21] \
                            ,deal_buff[PKT_PARA + 22] \
                            ,deal_buff[PKT_PARA + 23]);
                    
                    S_RTC sRTC;
                    
                    g_time_info.csio_rtc_cnt = 0x00;
                    g_time_info.time_select = 0x02;     //使用硬件RTC 时间
                    
                    RTC_ReadDate(&sRTC);
					
                    if(sRTC.year != deal_buff[PKT_PARA + 17]
                        || sRTC.month != deal_buff[PKT_PARA + 18] 
                        || sRTC.day != deal_buff[PKT_PARA + 19] 
                        || sRTC.hour != deal_buff[PKT_PARA + 20]
                        || sRTC.minute != deal_buff[PKT_PARA + 21] 
                        || sRTC.second != deal_buff[PKT_PARA + 22] 
                        || sRTC.week != deal_buff[PKT_PARA + 23] 
                        )
                    {
                        sRTC.year = deal_buff[PKT_PARA + 17];
                        sRTC.month = deal_buff[PKT_PARA + 18];
                        sRTC.day = deal_buff[PKT_PARA + 19];
                        sRTC.hour = deal_buff[PKT_PARA + 20];
                        sRTC.minute = deal_buff[PKT_PARA + 21];
                        sRTC.second = deal_buff[PKT_PARA + 22];
                        sRTC.week = deal_buff[PKT_PARA + 23];
                        
                        RTC_WriteDate(sRTC);
						
						RTC_ReadDate(&RTC_Raw_Data);    //将时间同步给系统时间(RTC_Raw_Data)
						
						rtc_err = 0;
                    }
					else
					{
						if(rtc_err < 200)
						{
						   rtc_err++;
//						   Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"-----------------csio rtcerr:%d-----------",rtc_err);
						}
						else if(rtc_err == 200)
						{
							g_time_info.time_select = 0x01;
						}
					}
                    
                    
                }else{
                    /*硬件RTC 时间格式不对*/
                    
//                    Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"CSIO RTC Time Error:%02x-%02x-%02x %02x:%02x:%02x %02x\r\n",deal_buff[PKT_PARA + 17] \
                            ,deal_buff[PKT_PARA + 18] \
                            ,deal_buff[PKT_PARA + 19] \
                            ,deal_buff[PKT_PARA + 20] \
                            ,deal_buff[PKT_PARA + 21] \
                            ,deal_buff[PKT_PARA + 22] \
                            ,deal_buff[PKT_PARA + 23]);
                    
                    /*将时间设置重新设置一下*/
                    C5IO_Info.rtc_set_flag = 0x01;
                    
                }
			}else{
                /**/
//                Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"CSIO RTC Time Invalid:%02x-%02x-%02x %02x:%02x:%02x %02x\r\n",deal_buff[PKT_PARA + 17] \
                            ,deal_buff[PKT_PARA + 18] \
                            ,deal_buff[PKT_PARA + 19] \
                            ,deal_buff[PKT_PARA + 20] \
                            ,deal_buff[PKT_PARA + 21] \
                            ,deal_buff[PKT_PARA + 22] \
                            ,deal_buff[PKT_PARA + 23]);
            }
            
		}
        
        /*判定时间是否使用硬件RTC 时间 、还是滴答定时器计数    2024-08-03*/
        g_time_info.csio_rtc_cnt++;
        if(g_time_info.csio_rtc_cnt >= 10){
            g_time_info.csio_rtc_cnt = 0;
            
            g_time_info.time_select = 0x01;
        }
        
		/**/
		
		C5IO_Info.Relay_Level_Actual_Start = deal_buff[PKT_PARA + 15];
		C5IO_Info.Relay_Level_Actual_Start <<= 8 ;
		C5IO_Info.Relay_Level_Actual_Start |= deal_buff[PKT_PARA + 14];
		C5IO_Info.Relay_Level_Actual_Start <<= 8 ;
		C5IO_Info.Relay_Level_Actual_Start |= deal_buff[PKT_PARA + 13];
		
		if(C5IO_Info.Relay_Level_Perfect_Start != C5IO_Info.Relay_Level_Actual_Start)		/*比较C5IO_Relay参数,是否保存日志*/
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO_Relay_Status Change");
			
			C5IO_Info.Relay_Level_Perfect_Start = C5IO_Info.Relay_Level_Actual_Start;
			
			/*这个地址暂时保留，后面可以删除*/
			SRAM_Write_Byte(deal_buff[PKT_PARA + 13],SRAM_LOG_Device_C5IO_Relay_Status);
			SRAM_Write_Byte(deal_buff[PKT_PARA + 14],SRAM_LOG_Device_C5IO_Relay_Status + 1);
			SRAM_Write_Byte(deal_buff[PKT_PARA + 15],SRAM_LOG_Device_C5IO_Relay_Status + 2);
			
			temp4++;
		}
		
		/*PC通讯测试中 2022-07-12*/
		if(temp4 != 0x00)	//如果DO、RELAY状态改变时，上报状态
		{
			if(g_pc_test.test_flag == 0x02)		
			{
				BLV_PC_Testing_Data_Reported(0x02,C5IOTYPE,0x00,SRAM_LOG_Device_C5IO_Relay_Status,4);
			}
		}
		
		if(temp5 != 0x00)
		{
			/*DI 动作状态 对于C12IO和CSIO而言 DI数目为13,用4Byte描述动作*/
			C5IO_Info.DI_Actual_State = deal_buff[PKT_PARA + 8];
			C5IO_Info.DI_Actual_State <<= 8 ;
			C5IO_Info.DI_Actual_State |= deal_buff[PKT_PARA + 7];
			C5IO_Info.DI_Actual_State <<= 8 ;
			C5IO_Info.DI_Actual_State |= deal_buff[PKT_PARA + 6];
			C5IO_Info.DI_Actual_State <<= 8 ;
			C5IO_Info.DI_Actual_State |= deal_buff[PKT_PARA + 5];
			
			if(C5IO_Info.DI_Perfect_State != C5IO_Info.DI_Actual_State)
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO_DI_Status Change");
				
				C5IO_Info.DI_Perfect_State = C5IO_Info.DI_Actual_State;
				
				/*这个地址暂时保留，后面可以删除 暂时用到这2Byte字节地址数据*/
				SRAM_Write_Byte(deal_buff[PKT_PARA + 5],SRAM_LOG_Device_C5IO_DI_Status);
				SRAM_Write_Byte(deal_buff[PKT_PARA + 6],SRAM_LOG_Device_C5IO_DI_Status + 1);
				
				temp4++;
			}
		}
	}
	else    //C5IO
	{
		temp = deal_buff[PKT_PARA + 1];
		for(uint8_t i=0;i<4;i++)
		{
			temp1 = C5IO_Info.DI_Type[i] & 0x0F;
			temp2 = (temp >> (i*2)) & 0x03;
			if((temp1 == temp2) && (temp1 == BUS_C5IO_DI_Key_Type) )	//输入类型是否相同
			{
				C5IO_Info.DI_Control_Flag &= ~(0x01<<i);
				temp3 = deal_buff[PKT_PARA + 3];
				temp3 = (temp3 >> (i*2)) & 0x03 ;
				if(SysTick_1ms - C5IO_Info.DI_Reset_Tick>1000)  /*2022-11-21*/
				{
					if(temp3 != 0x00)                                          
					{
						C5IO_Info.DI_Start[i] = temp3;
						temp5++;
						Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO DI_Start%d %d !",i,temp3);
					}
				}
				
			}else if((temp1 == temp2) && ((temp1 == BUS_C5IO_DI_Pir_Type) || (temp1 == BUS_C5IO_DI_Dry_Type))){
				
				C5IO_Info.DI_Control_Flag &= ~(0x01<<i);
				temp3 = deal_buff[PKT_PARA + 3];
				temp3 = (temp3 >> (i*2)) & 0x03 ;
				if(SysTick_1ms - C5IO_Info.DI_Reset_Tick>1000)  /*2022-11-21*/
				{
					if(temp3 != C5IO_Info.DI_Start[i])                     
					{
						C5IO_Info.DI_Start[i] = temp3;
						temp5++;
						Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO DI_PIR_Start%d %d !",i,temp3);
					}
				}
				
			}else {				//输入类型不同 - 标志位置一
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO DI_Type %d Fail! %d:%d",i,temp1,temp2);
				reset_DI = 1;   //标记重设DI
			}
		}
		
		temp = deal_buff[PKT_PARA + 2];
		for(uint8_t i=0;i<3;i++)
		{
			temp1 = C5IO_Info.DI_Type[i+4] & 0x0F;
			temp2 = (temp >> (i*2)) & 0x03;
			if((temp1 == temp2) && (temp1 == BUS_C5IO_DI_Key_Type))	//输入类型是否相同
			{
				C5IO_Info.DI_Control_Flag &= ~(0x01<<(i+4));
				temp3 = deal_buff[PKT_PARA + 4];
				temp3 = (temp3 >> (i*2)) & 0x03 ;
				if(temp3 != 0x00)
				{
					C5IO_Info.DI_Start[i+4] = temp3;
					temp5++;
					Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO DI_Start%d %d !",i+4,temp3);
				}
			}else if((temp1 == temp2) && ((temp1 == BUS_C5IO_DI_Pir_Type) || (temp1 == BUS_C5IO_DI_Dry_Type)) )
			{
				C5IO_Info.DI_Control_Flag &= ~(0x01<<(i+4));
				temp3 = deal_buff[PKT_PARA + 4];
				temp3 = (temp3 >> (i*2)) & 0x03 ;
				if(temp3 != C5IO_Info.DI_Start[i+4])
				{
					C5IO_Info.DI_Start[i+4] = temp3;
					temp5++;
					Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO DI_PIR_Start%d %d !",i+4,temp3);
				}
			}else {				//输入类型不同 - 标志位置一
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO DI_Type %d Fail! temp1:%d , temp2:%d",i+4,temp1,temp2);
				reset_DI = 1;   //标记重设DI
			}
		}
		
		C5IO_Info.DI_Level_Actual_Start = deal_buff[PKT_PARA + 5];
		C5IO_Info.DO_Level_Actual_Start = deal_buff[PKT_PARA + 6];
		if(C5IO_Info.DO_Level_Perfect_Start != C5IO_Info.DO_Level_Actual_Start)		/*比较C5IO_DO参数,是否保存日志*/
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"C5IO_DO_Status Change");
			C5IO_Info.DO_Level_Perfect_Start = C5IO_Info.DO_Level_Actual_Start;
			SRAM_Write_Byte(C5IO_Info.DO_Level_Actual_Start,SRAM_LOG_Device_C5IO_DO_Status);
			temp4++;
		}
		

		
		C5IO_Info.Relay_Level_Actual_Start = deal_buff[PKT_PARA + 9];
		C5IO_Info.Relay_Level_Actual_Start <<= 8 ;
		C5IO_Info.Relay_Level_Actual_Start |= deal_buff[PKT_PARA + 8];
		C5IO_Info.Relay_Level_Actual_Start <<= 8 ;
		C5IO_Info.Relay_Level_Actual_Start |= deal_buff[PKT_PARA + 7];
		
		if(C5IO_Info.Relay_Level_Perfect_Start != C5IO_Info.Relay_Level_Actual_Start)		/*比较C5IO_Relay参数,是否保存日志*/
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO_Relay_Status Change");
			
			C5IO_Info.Relay_Level_Perfect_Start = C5IO_Info.Relay_Level_Actual_Start;
			
			/*这个地址暂时保留，后面可以删除*/
			SRAM_Write_Byte(deal_buff[PKT_PARA + 7],SRAM_LOG_Device_C5IO_Relay_Status);
			SRAM_Write_Byte(deal_buff[PKT_PARA + 8],SRAM_LOG_Device_C5IO_Relay_Status + 1);
			SRAM_Write_Byte(deal_buff[PKT_PARA + 9],SRAM_LOG_Device_C5IO_Relay_Status + 2);
			
			temp4++;
		}
		
		/*PC通讯测试中 2022-07-12*/
		if(temp4 != 0x00)	//如果DO、RELAY状态改变时，上报状态
		{
			if(g_pc_test.test_flag == 0x02)		
			{
				BLV_PC_Testing_Data_Reported(0x02,C5IOTYPE,0x00,SRAM_LOG_Device_C5IO_Relay_Status,4);
			}
		}
		
		if(temp5 != 0x00)
		{

			/*DI 动作状态 对于C12IO和CSIO而言 DI数目为13,用4Byte描述动作*/
			C5IO_Info.DI_Actual_State = deal_buff[PKT_PARA + 4];
			C5IO_Info.DI_Actual_State <<= 8 ;
			C5IO_Info.DI_Actual_State |= deal_buff[PKT_PARA + 3];
	
			
			if(C5IO_Info.DI_Perfect_State != C5IO_Info.DI_Actual_State)
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"CSIO_DI_Status Change");
				
				C5IO_Info.DI_Perfect_State = C5IO_Info.DI_Actual_State;
				
				/*这个地址暂时保留，后面可以删除 暂时用到这2Byte字节地址数据*/
				SRAM_Write_Byte(deal_buff[PKT_PARA + 3],SRAM_LOG_Device_C5IO_DI_Status);
				SRAM_Write_Byte(deal_buff[PKT_PARA + 4],SRAM_LOG_Device_C5IO_DI_Status + 1);
				
				temp4++;
			}
		}
	}
	
	if(reset_DI)   //需要重设DI
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DI_Reset_Flag");
		C5IO_Info.DI_Control_Flag = C5IO_Info.CxIO_DI_Control_Flag;
		C5IO_Info.DI_Reset_Flag = 0x01;
		C5IO_Info.Relay_Reset_Flag = 0x01;
		DI_Init_flg = 0;         //2023-12-18      避免波特率偏导致设置DI类型不成功
	}
	
	/*对于询问命令 - 检测到状态改变了，保存数据和发送时的时间戳*/
	if((C5IO_Info.Send_Type == BLV_C5IO_Inquire_CMD) && (temp4 != 0x00))
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"BLV Inquire_CMD Reply Change");
		LOG_Device_COMM_ASK_TO_Reply_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,(SysTick_1ms - C5IO_Info.inquire_tick),deal_buff,deal_len);
	}
	
	/*数据解析完毕,保存SRAM中*/
	SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	/*计算校验值*/
	SRAM_Write_Byte(0x00,dev_addr+Dev_Check);
	crc_val = Dev_CheckSum(dev_addr, sizeof(BUS_C5IO_INFO) + Dev_Privately);
	SRAM_Write_Byte(crc_val,dev_addr+Dev_Check);		//校验值重新写入
	
	return 0x00;
}

/*******************************************************************************
* Function Name  : BLV_BUS_C5IO_DI_Control_Datasend 
* Description    : C5IO DI数据打包发送函数
*******************************************************************************/
void BUS_C5IO_DI_Control_Datasend(uint32_t dev_addr,BUS_C5IO_INFO *Dev_Info)
{
	uint8_t temp = 0;
	uint8_t send_buff[40];
	memset(send_buff,0,40);
	
	Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"%s",__func__);
	
	if(Dev_Info->C5IO_Version)
	{
		for(uint8_t i=0;i<C5IO_DI_CH_MAX;i++)
		{
			if((Dev_Info->DI_Control_Flag & ( 0x01 << i )))
			{
				temp = PKT_PARA + (i/4);
				send_buff[temp] |= (Dev_Info->DI_Type[i] & 0x03) << ((i%4)*2);
				temp = PKT_PARA + (i/4) + 4;
				send_buff[temp] |= ((Dev_Info->DI_Type[i] >> 4) & 0x03) << ((i%4)*2);
				temp = PKT_PARA + 8 + i;
				send_buff[temp] = Dev_Info->DI_Detection_Time[i];
			}
		}
	}
	else
	{
		for(uint8_t i=0;i<8;i++)		//C5IO
		{
			if((Dev_Info->DI_Control_Flag & ( 0x01 << i )))
			{
				temp = PKT_PARA + (i/4);
				send_buff[temp] |= (Dev_Info->DI_Type[i] & 0x03) << ((i%4)*2);
				temp = PKT_PARA + (i/4) + 2;
				send_buff[temp] |= ((Dev_Info->DI_Type[i] >> 4) & 0x03) << ((i%4)*2);
				temp = PKT_PARA + 4 + i;
				send_buff[temp] = Dev_Info->DI_Detection_Time[i];
			}
		}
	}
	
	Dev_Info->Last_DI_Control_Flag = Dev_Info->DI_Control_Flag;
	
	send_buff[PKT_ADD_FM] = 0x00;			//本机地址
	if(Dev_Info->DevSendCnt == 0x00)
	{
		Dev_Info->DevSendSN++;
		if(Dev_Info->DevSendSN > 0x0F)	Dev_Info->DevSendSN = 0x00;
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);	//设置发送序号
	}else{	
		//本包数据为重发数据
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);
		send_buff[PKT_TYPE] |= BUS_Retry_Flag;
	}
	send_buff[PKT_DevType] = C5IOTYPE;				//设备类型
	send_buff[PKT_ADD_TO] = 0x01;					//设备地址 - C5固定设备地址为0x01
	
	if(Dev_Info->C5IO_Version)
	{
		send_buff[PKT_LEN] = 0x23;						//本次发送数据长度
	}
	else  send_buff[PKT_LEN] = 0x17;       	//本次发送数据长度
	
	send_buff[PKT_CHKSUM] = 0x00;					//校验
	send_buff[PKT_CMD] = BLV_C5IO_Set_Di_CMD;		//设置DI命令
	
	if(Dev_Info->C5IO_Version)
	{
		send_buff[31] = 0x03; //设置阈值min
		send_buff[32] = 0xE8;
		send_buff[33] = 0x0B;  //设置阈值max
		send_buff[34] = 0xB8;
	}
	else
	{
		temp = PKT_PARA + 5 + 7;			//设置阈值min
		send_buff[temp] = 0x03;
		temp = PKT_PARA + 5 + 7 + 1;
		send_buff[temp] = 0xE8;
		temp = PKT_PARA + 5 + 7 + 2;		//设置阈值max
		send_buff[temp] = 0x0B;
		temp = PKT_PARA + 5 + 7 + 3;
		send_buff[temp] = 0xB8;
	}
	
	
	Dev_Info->Send_Type = BLV_C5IO_Set_Di_CMD;
	
	send_buff[PKT_CHKSUM] = CheckSum(send_buff, send_buff[PKT_LEN]);
	temp = SRAM_Read_Byte(dev_addr+Dev_port);
//	Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit, "IO_SEND:", send_buff, send_buff[PKT_LEN]);
	MCU485_SendString(temp,send_buff, send_buff[PKT_LEN]);
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,send_buff,send_buff[PKT_LEN]);
}

/*******************************************************************************
* Function Name  : BLV_BUS_C5IO_DO_Control_Datasend 
* Description    : C5IO DO数据打包发送函数
*******************************************************************************/
void BUS_C5IO_DO_Control_Datasend(uint32_t dev_addr,BUS_C5IO_INFO *Dev_Info)
{
	uint8_t temp = 0;
	uint8_t send_buff[12];
	memset(send_buff,0,12);
	
	for(uint8_t i=0;i<C5IO_DO_CH_MAX;i++)
	{
		if((Dev_Info->DO_Control_Flag & ( 0x01 << i )))
		{
			temp = PKT_PARA + (i/4);
			send_buff[temp] |= (Dev_Info->DO_Control[i] & 0x03) << ((i%4)*2);
		}
	}
	
	Dev_Info->Last_DO_Control_Flag = Dev_Info->DO_Control_Flag;

	send_buff[PKT_ADD_FM] = 0x00;			//本机地址
	if(Dev_Info->DevSendCnt == 0x00)
	{
		Dev_Info->DevSendSN++;
		if(Dev_Info->DevSendSN > 0x0F)	Dev_Info->DevSendSN = 0x00;
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);	//设置发送序号
	}else{	
		//本包数据为重发数据
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);
		send_buff[PKT_TYPE] |= BUS_Retry_Flag;
	}
	send_buff[PKT_DevType] = C5IOTYPE;				//设备类型
	send_buff[PKT_ADD_TO] = 0x01;					//设备地址 - C5固定设备地址为0x01
	
	if(Dev_Info->C5IO_Version)
	{
		send_buff[PKT_LEN] = 0x0B;						//本次发送数据长度
	}
	else  send_buff[PKT_LEN] = 0x09;       	//本次发送数据长度
	
	
	send_buff[PKT_CHKSUM] = 0x00;					//校验
	send_buff[PKT_CMD] = BLV_C5IO_Set_Do_CMD;		//设置DI命令
	Dev_Info->Send_Type = BLV_C5IO_Set_Do_CMD;
	
	send_buff[PKT_CHKSUM] = CheckSum(send_buff, send_buff[PKT_LEN]);
	temp = SRAM_Read_Byte(dev_addr+Dev_port);
	Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit, "IO_SEND:", send_buff, send_buff[PKT_LEN]);
	MCU485_SendString(temp,send_buff, send_buff[PKT_LEN]);
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,send_buff,send_buff[PKT_LEN]);
}

/*******************************************************************************
* Function Name  : BUS_C5IO_DO_Inching_Control_Datasend 
* Description    : C5IO DO Inching数据打包发送函数
*******************************************************************************/
void BUS_C5IO_DO_Inching_Control_Datasend(uint32_t dev_addr,BUS_C5IO_INFO *Dev_Info)
{
	uint8_t temp = 0;
	uint8_t send_buff[45];
	memset(send_buff,0,45);
	
	for(uint8_t i=0;i<C5IO_DO_CH_MAX;i++)
	{
		if((Dev_Info->DO_Inching_Control_Flag & ( 0x01 << i )))
		{
			temp = PKT_PARA + (i/4);
			send_buff[temp] |= (Dev_Info->DO_Mode[i] & 0x03) << ((i%4)*2);		//DO控制模式
			if(Dev_Info->C5IO_Version)
			{
				temp = PKT_PARA + 4 + i*2;
			}
			else  temp = PKT_PARA + 2 + i*2;
			
			send_buff[temp] = (Dev_Info->DO_Inching_Time[i] >> 8)&0xFF;						//DO电动时间
			send_buff[temp+1] = (Dev_Info->DO_Inching_Time[i] & 0xFF);				
			
		}
	}
	
	Dev_Info->Last_DO_Inching_Control_Flag = Dev_Info->DO_Inching_Control_Flag;
	
	send_buff[PKT_ADD_FM] = 0x00;			//本机地址
	if(Dev_Info->DevSendCnt == 0x00)
	{
		Dev_Info->DevSendSN++;
		if(Dev_Info->DevSendSN > 0x0F)	Dev_Info->DevSendSN = 0x00;
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);	//设置发送序号
	}else{	
		//本包数据为重发数据
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);
		send_buff[PKT_TYPE] |= BUS_Retry_Flag;
	}
	send_buff[PKT_DevType] = C5IOTYPE;				//设备类型
	send_buff[PKT_ADD_TO] = 0x01;					//设备地址 - C5固定设备地址为0x01
	
	if(Dev_Info->C5IO_Version)
	{
		send_buff[PKT_LEN] = 0x2B;						//本次发送数据长度
	}
	else  send_buff[PKT_LEN] = 0x19;       	//本次发送数据长度
	
	
	send_buff[PKT_CHKSUM] = 0x00;					//校验
	send_buff[PKT_CMD] = BLV_C5IO_Set_Do_Inching_CMD;		//设置DO点动命令
	Dev_Info->Send_Type = BLV_C5IO_Set_Do_Inching_CMD;
	
	send_buff[PKT_CHKSUM] = CheckSum(send_buff, send_buff[PKT_LEN]);
	temp = SRAM_Read_Byte(dev_addr+Dev_port);
//	Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit, "IO_SEND:", send_buff, send_buff[PKT_LEN]);
	MCU485_SendString(temp,send_buff, send_buff[PKT_LEN]);
	
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,send_buff,send_buff[PKT_LEN]);
}

/*******************************************************************************
* Function Name  : BUS_C5IO_Relay_Control_Datasend 
* Description    : C5IO Relay数据打包发送函数
*******************************************************************************/
void BUS_C5IO_Relay_Control_Datasend(uint32_t dev_addr,BUS_C5IO_INFO *Dev_Info)
{
	uint8_t temp = 0;
	uint8_t send_buff[15];
	memset(send_buff,0,15);
	
	for(uint8_t i=0;i<C5IO_Relay_CH_MAX;i++)
	{
		if((Dev_Info->Relay_Control_Flag & ( 0x01 << i )))
		{
			temp = PKT_PARA + (i/4);
			send_buff[temp] |= (Dev_Info->Relay_Control[i] & 0x03) << ((i%4)*2);
			Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"Relay_Control CH%d",i);
		}
	}
	
	Dev_Info->Last_Relay_Control_Flag = Dev_Info->Relay_Control_Flag;
	
	send_buff[PKT_ADD_FM] = 0x00;			//本机地址
	if(Dev_Info->DevSendCnt == 0x00)
	{
		Dev_Info->DevSendSN++;
		if(Dev_Info->DevSendSN > 0x0F)	Dev_Info->DevSendSN = 0x00;
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);	//设置发送序号
	}else{	
		//本包数据为重发数据
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);
		send_buff[PKT_TYPE] |= BUS_Retry_Flag;
	}
	send_buff[PKT_DevType] = C5IOTYPE;					//设备类型
	send_buff[PKT_ADD_TO] = 0x01;						//设备地址 - C5固定设备地址为0x01
	send_buff[PKT_LEN] = 0x0C;							//本次发送数据长度
	if(Dev_Info->C5IO_Version == 3)
	{
		send_buff[PKT_LEN] = 0x0D;							//本次发送数据长度
	}
	send_buff[PKT_CHKSUM] = 0x00;						//校验
	send_buff[PKT_CMD] = BLV_C5IO_Set_Relay_CMD;			//设置DI命令
	Dev_Info->Send_Type = BLV_C5IO_Set_Relay_CMD;
	
	send_buff[PKT_CHKSUM] = CheckSum(send_buff, send_buff[PKT_LEN]);
	temp = SRAM_Read_Byte(dev_addr+Dev_port);
//	Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit, "IO_SEND:", send_buff, send_buff[PKT_LEN]);
	MCU485_SendString(temp,send_buff, send_buff[PKT_LEN]);
	
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,send_buff,send_buff[PKT_LEN]);
}

/*******************************************************************************
* Function Name  : BUS_C5IO_Relay_Inching_Control_Datasend 
* Description    : C5IO Relay Inching数据打包发送函数
*******************************************************************************/
void BUS_C5IO_Relay_Inching_Control_Datasend(uint32_t dev_addr,BUS_C5IO_INFO *Dev_Info)
{
	uint8_t temp = 0;
	uint8_t send_buff[62];
	memset(send_buff,0,62);
	
	if(Dev_Info->C5IO_Version == 3)
	{
		for(uint8_t i=0;i<C5IO_Relay_CH_MAX;i++)
		{
			if((Dev_Info->Relay_Inching_Control_Flag & ( 0x01 << i )))
			{
				temp = PKT_PARA + (i/4);
				send_buff[temp] |= (Dev_Info->Relay_Mode[i] & 0x03) << ((i%4)*2);		//DO控制模式
				temp = PKT_PARA + 6 + i*2;
				send_buff[temp] = (Dev_Info->Relay_Inching_Time[i] >> 8)&0xFF;						//DO电动时间
				send_buff[temp+1] = (Dev_Info->Relay_Inching_Time[i] & 0xFF);
			}
		}
		
		send_buff[PKT_LEN] = 0x3D;							//本次发送数据长度
	}else {
		for(uint8_t i=0;i<C5IO_Relay_CH21;i++)
		{
			if((Dev_Info->Relay_Inching_Control_Flag & ( 0x01 << i )))
			{
				temp = PKT_PARA + (i/4);
				send_buff[temp] |= (Dev_Info->Relay_Mode[i] & 0x03) << ((i%4)*2);		//DO控制模式
				temp = PKT_PARA + 5 + i*2;
				send_buff[temp] = (Dev_Info->Relay_Inching_Time[i] >> 8)&0xFF;						//DO电动时间
				send_buff[temp+1] = (Dev_Info->Relay_Inching_Time[i] & 0xFF);
			}
		}
		
		send_buff[PKT_LEN] = 0x34;						//本次发送数据长度
	}
	
	Dev_Info->Last_Relay_Inching_Control_Flag = Dev_Info->Relay_Inching_Control_Flag;
	
	send_buff[PKT_ADD_FM] = 0x00;			//本机地址
	if(Dev_Info->DevSendCnt == 0x00)
	{
		Dev_Info->DevSendSN++;
		if(Dev_Info->DevSendSN > 0x0F)	Dev_Info->DevSendSN = 0x00;
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);	//设置发送序号
	}else{	
		//本包数据为重发数据
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);
		send_buff[PKT_TYPE] |= BUS_Retry_Flag;
	}
	send_buff[PKT_DevType] = C5IOTYPE;				//设备类型
	send_buff[PKT_ADD_TO] = 0x01;					//设备地址 - C5固定设备地址为0x01
	
	
	send_buff[PKT_CHKSUM] = 0x00;					//校验
	send_buff[PKT_CMD] = BLV_C5IO_Set_Relay_Inching_CMD;		//设置DI命令
	Dev_Info->Send_Type = BLV_C5IO_Set_Relay_Inching_CMD;
	
	send_buff[PKT_CHKSUM] = CheckSum(send_buff, send_buff[PKT_LEN]);
	temp = SRAM_Read_Byte(dev_addr+Dev_port);
//	Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit, "IO_SEND:", send_buff, send_buff[PKT_LEN]);
	MCU485_SendString(temp,send_buff, send_buff[PKT_LEN]);
	
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,send_buff,send_buff[PKT_LEN]);
}

/*******************************************************************************
* Function Name  : BUS_CSIO_SetRTCTime_Datasend 
* Description    : CSIO 设置RTC时间
*******************************************************************************/
void BUS_CSIO_SetRTCTime_Datasend(uint32_t dev_addr,BUS_C5IO_INFO *Dev_Info)
{
	uint8_t temp = 0;
	uint8_t send_buff[62];
	memset(send_buff,0,62);
	
	
	send_buff[PKT_ADD_FM] = 0x00;			//本机地址
	if(Dev_Info->DevSendCnt == 0x00)
	{
		Dev_Info->DevSendSN++;
		if(Dev_Info->DevSendSN > 0x0F)	Dev_Info->DevSendSN = 0x00;
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);	//设置发送序号
	}else{	
		//本包数据为重发数据
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);
		send_buff[PKT_TYPE] |= BUS_Retry_Flag;
	}
	send_buff[PKT_DevType] = C5IOTYPE;				//设备类型
	send_buff[PKT_ADD_TO] = 0x01;					//设备地址 - C5固定设备地址为0x01
	
	
	send_buff[PKT_CHKSUM] = 0x00;					//校验
	send_buff[PKT_CMD] = BLV_C5IO_SetRTC_CMD;		//设置RTC 时间命令
    Dev_Info->Send_Type = BLV_C5IO_SetRTC_CMD;
	
	if((DevActionGlobal.TimeSyncFlag & 0x01) == 0x01)       //网络时间
	{
		//服务器的当前时间+本地计数
        uint32_t rtc_tick = 0;
    
        rtc_tick = RTC_Conversion_To_Unix(&Net_RTC_Data);	
        //rtc_tick += rtc_hour*3600+rtc_min*60+rtc_sec;
        rtc_tick += SysTick_1s - g_time_info.Mcu_GetTime_tick;
        Unix_Conversion_To_RTC(&Net_RTC_Data,rtc_tick);
		
		send_buff[PKT_PARA] = Net_RTC_Data.year;
		send_buff[PKT_PARA+1] = Net_RTC_Data.month;	
		send_buff[PKT_PARA+2] = Net_RTC_Data.day;	
		send_buff[PKT_PARA+3] = Net_RTC_Data.hour;	
		send_buff[PKT_PARA+4] = Net_RTC_Data.minute;	
		send_buff[PKT_PARA+5] = Net_RTC_Data.second;	
		send_buff[PKT_PARA+6] = Net_RTC_Data.week;
	}
	else                                          //系统时间
	{
		send_buff[PKT_PARA] = MCU_RTC_Data.year;
		send_buff[PKT_PARA+1] = MCU_RTC_Data.month;	
		send_buff[PKT_PARA+2] = MCU_RTC_Data.day;	
		send_buff[PKT_PARA+3] = MCU_RTC_Data.hour;	
		send_buff[PKT_PARA+4] = MCU_RTC_Data.minute;	
		send_buff[PKT_PARA+5] = MCU_RTC_Data.second;	
		send_buff[PKT_PARA+6] = MCU_RTC_Data.week;
	}
    
	send_buff[PKT_LEN] = PKT_PARA + 7;
	
	send_buff[PKT_CHKSUM] = CheckSum(send_buff, send_buff[PKT_LEN]);
	temp = SRAM_Read_Byte(dev_addr+Dev_port);
//	Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit, "IO_SEND:", send_buff, send_buff[PKT_LEN]);
	MCU485_SendString(temp,send_buff, send_buff[PKT_LEN]);
	
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,send_buff,send_buff[PKT_LEN]);
}

/*******************************************************************************
* Function Name  : BUS_C5IO_Inquire_Datasend 
* Description    : C5IO Relay Inching数据打包发送函数
*******************************************************************************/
void BUS_C5IO_Inquire_Datasend(uint32_t dev_addr,BUS_C5IO_INFO *Dev_Info)
{
	uint8_t temp = 0;
	uint8_t send_buff[8];
	memset(send_buff,0,8);
	
	send_buff[PKT_ADD_FM] = 0x00;			//本机地址
	if(Dev_Info->DevSendCnt == 0x00)
	{
		Dev_Info->DevSendSN++;
		if(Dev_Info->DevSendSN > 0x0F)	Dev_Info->DevSendSN = 0x00;
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);	//设置发送序号
	}else{	
		//本包数据为重发数据
		send_buff[PKT_TYPE] |= (Dev_Info->DevSendSN & 0x0F);
		send_buff[PKT_TYPE] |= BUS_Retry_Flag;
	}
	send_buff[PKT_DevType] = C5IOTYPE;				//设备类型
	send_buff[PKT_ADD_TO] = 0x01;					//设备地址 - C5固定设备地址为0x01
	send_buff[PKT_LEN] = 0x07;						//本次发送数据长度
	send_buff[PKT_CHKSUM] = 0x00;					//校验
	send_buff[PKT_CMD] = BLV_C5IO_Inquire_CMD;		//设置DI命令
	Dev_Info->Send_Type = BLV_C5IO_Inquire_CMD;
	
	send_buff[PKT_CHKSUM] = CheckSum(send_buff, send_buff[PKT_LEN]);
	temp = SRAM_Read_Byte(dev_addr+Dev_port);
//	Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit, "IO_SEND:", send_buff, send_buff[PKT_LEN]);
	MCU485_SendString(temp,send_buff, send_buff[PKT_LEN]);
	
}

/*******************************************************************************
* Function Name  : BUS_C5IO_Control_Relay 
* Description    : C5IO 控制继电器状态
* Input          : 
	dev_addr	:设备地址
	loop		:控制继电器回路
	start		:控制继电器状态 0x01:开 0x02:关
*******************************************************************************/
void BUS_C5IO_Control_Relay(uint32_t dev_addr,uint8_t loop,uint8_t start)
{
	uint8_t crc_val = 0,temp1 = loop;
	uint16_t temp = 0;
	if(dev_addr == 0x00) return;
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	
	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"%s",__func__);
	
	if(temp1 < C5IO_Relay_CH_MAX)
	{
		if(start == 0x01)
		{
			C5IO_Info.Relay_Control[temp1] = BUS_C5IO_OUT_HIGH;
			C5IO_Info.Relay_Control_Flag |= 0x0001<<temp1;
			
			Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"%s%d HIGH",__func__,temp1);
		}else if(start == 0x02)
		{
			C5IO_Info.Relay_Control[temp1] = BUS_C5IO_OUT_LOW;
			C5IO_Info.Relay_Control_Flag |= 0x0001<<temp1;
			
			Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"%s%d LOW",__func__,temp1);
		}else if(start == 0x03)
		{
			C5IO_Info.Relay_Control[temp1] = BUS_C5IO_OUT_TOGGLE;
			C5IO_Info.Relay_Control_Flag |= 0x0001<<temp1;
			
			Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"%s%d TOGGLE",__func__,temp1);
		}
	}
	
	SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	/*计算校验值*/
	SRAM_Write_Byte(0x00,dev_addr+Dev_Check);
	temp = sizeof(BUS_C5IO_INFO) + Dev_Privately;
	crc_val = Dev_CheckSum(dev_addr,temp);
	SRAM_Write_Byte(crc_val,dev_addr+Dev_Check);		//校验值重新写入
	
}

/*******************************************************************************
* Function Name  : BUS_C5IO_Control_Do 
* Description    : C5IO 控制Do状态
* Input          : 
	dev_addr	:设备地址
	loop		:控制Do回路
	start		:控制Do状态 0x01:开 0x02:关 0x03:翻转
*******************************************************************************/
void BUS_C5IO_Control_Do(uint32_t dev_addr,uint8_t loop,uint8_t start)
{
	uint8_t crc_val = 0,temp1 = loop;
	uint16_t temp = 0;
	if(dev_addr == 0x00) return;
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	
	if(temp1 < C5IO_DO_CH_MAX)
	{
		if(start == 0x01)
		{
			C5IO_Info.DO_Control[temp1] = BUS_C5IO_OUT_HIGH;
			C5IO_Info.DO_Control_Flag |= 0x01<<temp1;
		}else if(start == 0x02)
		{
			C5IO_Info.DO_Control[temp1] = BUS_C5IO_OUT_LOW;
			C5IO_Info.DO_Control_Flag |= 0x01<<temp1;
		}else if(start == 0x03)
		{
			C5IO_Info.DO_Control[temp1] = BUS_C5IO_OUT_TOGGLE;
			C5IO_Info.DO_Control_Flag |= 0x01<<temp1;
		}
	}	
	
	SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	/*计算校验值*/
	SRAM_Write_Byte(0x00,dev_addr+Dev_Check);
	temp = sizeof(BUS_C5IO_INFO) + Dev_Privately;
	crc_val = Dev_CheckSum(dev_addr,temp);
	SRAM_Write_Byte(crc_val,dev_addr+Dev_Check);		//校验值重新写入
	
}

/*******************************************************************************
* Function Name  : BUS_C5IO_Control_Relay_Inching 
* Description    : C5IO 控制继电器状态
* Input          : 
	dev_addr	:设备地址
	loop		:控制继电器回路
	start		:控制继电器电动状态 0x01:正 0x02:反
	d_time		:电动时间
*******************************************************************************/
void BUS_C5IO_Control_Relay_Inching(uint32_t dev_addr,uint8_t loop,uint8_t start,uint16_t d_time)
{
	uint8_t crc_val = 0,temp1 = loop;
	uint16_t temp = 0;
	if(dev_addr == 0x00) return;
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	
	if(temp1 < C5IO_Relay_CH_MAX)
	{
		if(start == 0x01)
		{
			C5IO_Info.Relay_Mode[temp1] = BUS_C5IO_Right_Inching;
			C5IO_Info.Relay_Inching_Time[temp1] = d_time;
			C5IO_Info.Relay_Inching_Control_Flag |= 0x01<<temp1;
		}else if(start == 0x02)
		{
			C5IO_Info.Relay_Mode[temp1] = BUS_C5IO_Reverse_Inching;
			C5IO_Info.Relay_Inching_Time[temp1] = d_time;
			C5IO_Info.Relay_Inching_Control_Flag |= 0x01<<temp1;
		}else if(start == 0x03)
		{
			C5IO_Info.Relay_Mode[temp1] = BUS_C5IO_Toggle_Inching;
			C5IO_Info.Relay_Inching_Time[temp1] = d_time;
			C5IO_Info.Relay_Inching_Control_Flag |= 0x01<<temp1;
		}
	}
	
	SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	/*计算校验值*/
	SRAM_Write_Byte(0x00,dev_addr+Dev_Check);
	temp = sizeof(BUS_C5IO_INFO) + Dev_Privately;
	crc_val = Dev_CheckSum(dev_addr,temp);
	SRAM_Write_Byte(crc_val,dev_addr+Dev_Check);		//校验值重新写入
	
}

/*******************************************************************************
* Function Name  : BUS_C5IO_Group_Control_Relay 
* Description    : C5IO 控制群控继电器状态
* Input          : 
	dev_addr	:设备地址
	loop		:控制Relay回路
	start		:控制Relay状态 0x01:开 0x00:关
*******************************************************************************/
void BUS_C5IO_Group_Control_Relay(uint32_t dev_addr,uint32_t loop,uint32_t start)
{
	uint8_t crc_val = 0;
	uint16_t temp = 0;
	uint32_t temp1 = loop,temp2 = start;
	if(dev_addr == 0x00) return;
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	
	for(uint8_t i=0;i<C5IO_Relay_CH_MAX;i++)
	{
		if((temp1 & 0x00000001) == 0x00000001)
		{
			if((temp2 & 0x00000001) == 0x00000001)
			{
				C5IO_Info.Relay_Control[i] = BUS_C5IO_OUT_HIGH;
				C5IO_Info.Relay_Control_Flag |= 0x00000001<<i;
			}else {
				C5IO_Info.Relay_Control[i] = BUS_C5IO_OUT_LOW;
				C5IO_Info.Relay_Control_Flag |= 0x00000001<<i;
			}
		}
		temp1 >>= 1;
		temp2 >>= 1;
	}

	SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	/*计算校验值*/
	SRAM_Write_Byte(0x00,dev_addr+Dev_Check);
	temp = sizeof(BUS_C5IO_INFO) + Dev_Privately;
	crc_val = Dev_CheckSum(dev_addr,temp);
	SRAM_Write_Byte(crc_val,dev_addr+Dev_Check);		//校验值重新写入
	
}

/*******************************************************************************
* Function Name  : BUS_CSIO_Set_RTC_Time 
* Description    : CSIO 设置RTC时间
* Input          : 
	dev_addr	:设备地址
	loop		:控制Relay回路
	start		:控制Relay状态 0x01:开 0x00:关
*******************************************************************************/
void BUS_CSIO_Set_RTC_Time(uint32_t dev_addr)
{
	uint8_t crc_val = 0;
	uint16_t temp = 0;
    Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"%s",__func__);
	if(dev_addr == 0x00) return;
    
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	
	/*将时间设置重新设置一下*/
    C5IO_Info.rtc_set_flag = 0x01;

	SRAM_DMA_Write_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),dev_addr+Dev_Privately);
	/*计算校验值*/
	SRAM_Write_Byte(0x00,dev_addr+Dev_Check);
	temp = sizeof(BUS_C5IO_INFO) + Dev_Privately;
	crc_val = Dev_CheckSum(dev_addr,temp);
	SRAM_Write_Byte(crc_val,dev_addr+Dev_Check);		//校验值重新写入
	
}

/*获取继电器状态*/
uint32_t Get_BUS_C5IO_Realy_Status(uint32_t devaddr)
{
	if(devaddr == 0x00) return 0x00000000;

	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),devaddr+Dev_Privately);
	
	return C5IO_Info.Relay_Level_Actual_Start;

}

/*获取在线状态*/
uint8_t Get_BUS_C5IO_Online_Status(uint32_t devaddr)
{
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),devaddr+Dev_Privately);
	
	
	if(C5IO_Info.DevOffline == DEV_IS_ONLINE)
	{
		return 0x01;
	}
	return 0x02;
}

/*******************************************************************************
* Function Name  : Get_Bus_C5IO_COMM_State 
* Description    : C5IO 获取通讯失败记录
* Input          : 
	devaddr		:设备地址
* Return         : 
	0xFF	：获取失败
	其他值	：通讯失败百分比
*******************************************************************************/
uint8_t Get_Bus_C5IO_COMM_State(uint32_t devaddr)
{
	if(devaddr == 0x00) return 0xFF;
	uint16_t dev_rate = 0;
	
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),devaddr+Dev_Privately);
	
	dev_rate = Get_BLV_Communication_Fail_Rate(&C5IO_Info.comm_record);
	
	return dev_rate;
}

/*******************************************************************************
* Function Name  : Get_Bus_CSIO_COMM_Version 
* Description    : 获取CSIO 软件版本
* Input          : 
	devaddr		:设备地址
* Return         : 软件版本号
*******************************************************************************/
uint8_t Get_Bus_CSIO_COMM_Version(uint32_t devaddr)
{
	if(devaddr == 0x00) return 0xFF;
	uint8_t dev_ver = 0;
	
	BUS_C5IO_INFO C5IO_Info;
	SRAM_DMA_Read_Buff((uint8_t *)&C5IO_Info,sizeof(BUS_C5IO_INFO),devaddr+Dev_Privately);
	
	dev_ver = C5IO_Info.comm_version;
	
	return dev_ver;
}


