


/**
  ******************************************************************************
  * @file    BLV_485_Dev_PirFun.c
  * @author  BLW RCU  development Team
  * @version SongHan
  * @date    2021年12月10日
  * @brief   485Pir初始化   
	* @attention 设备Pir输入
	*									输入检测：  有
	*                 输入类型：  有	
	*                 执行函数：  无		
	*            			执行方式：  无
	*															 
	*															
  ******************************************************************************
  */
#include "BLV_485_Dev_PirFun.h"
  

#include "includes.h"

#define REPEATSENDTIMEMAX     0x03

uint8_t Dev_Pir_InType_Get(uint32_t DevAddr, uint16_t DevInputLoop, uint16_t DevInputType);

uint8_t BLW_Pir_CycleDis(uint32_t DevAdd);  
//void BLW_PirCycle(uint32_t DevAdd);  
void BLW_PirCycle(Device_Public_Information_G *BUS_Public, NOR_LVINPUT_INFO *DevLVinputInfo);  
uint8_t BLW_Pir_Check(uint32_t DevAdd ,uint32_t Data_addr, uint16_t DataLen);

#define INFRAREDTYPE            0x02            //红外感应类型
#define PirSnMin                0x00            //最小Sn号
#define PirSnMax                0x07            //最大Sn号

/*弱电输入新增到普通设备链表*/
void BLV_485_Dev_Pir_Init(uint16_t DataLen, uint8_t *Data)
{
	Device_Public_Information_G BUS_Public;
	NOR_LVINPUT_INFO DevLVinputInfo;       //弱电输入局部变量
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&DevLVinputInfo,0,sizeof(NOR_LVINPUT_INFO));
	
	BUS_Public.addr = Data[1];			//设备地址
	BUS_Public.type = Dev_Host_LVinput;		//设备类型
	BUS_Public.port = Polling_Port;			//设备发送端口
	BUS_Public.baud = 115200;			//设备发送波特率9600
	BUS_Public.retry_num = 0x03;		//设备数据重发次数
	BUS_Public.wait_time = 0x0064;		//设备数据发送等待回复时间
	
	BUS_Public.polling_cf = (uint32_t)&BLW_Pir_CycleDis;
	BUS_Public.processing_cf = (uint32_t)&BLW_Pir_Check;
	
	BUS_Public.DevFunInfo.Dev_Input_Type_Get = Dev_Pir_InType_Get;        //
	
	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"添加485Pir设备");
	DevLVinputInfo.DevOffline = DevLVinputInfo.DevOfflineLast = DEV_IS_LINEUNINIT;   //在线状态初始化
	if(Data[8] > LVINPUTNUMMAX)
	{
		 DevLVinputInfo.LVinputValidNum = LVINPUTNUMMAX;
	}
	else
	{
		DevLVinputInfo.LVinputValidNum = Data[8];  //C1_LVINPUTNUMMAX;
	}
	
	Add_POLL_Device_To_List2(&BUS_Public,(uint8_t *)&DevLVinputInfo,sizeof(NOR_LVINPUT_INFO));

}

/*******************************************************************************
* Function Name  : BLV_485_Dev_Pir_Data_Logic_Init 
* Description    : CSIO设备信息初始化函数 - 初始化信息来自逻辑文件
*******************************************************************************/
void BLV_485_Dev_Pir_Data_Logic_Init(LOGICFILE_DEVICE_INFO *dev_info,uint8_t *data,uint16_t data_len)
{
	Device_Public_Information_G BUS_Public;
	NOR_LVINPUT_INFO DevLVinputInfo;       //弱电输入局部变量
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&DevLVinputInfo,0,sizeof(NOR_LVINPUT_INFO));
	
	BUS_Public.addr = dev_info->addr;				//设备地址
	BUS_Public.type = Dev_Host_LVinput;				//设备类型
	BUS_Public.port = Polling_Port;					//设备发送端口
	BUS_Public.baud = dev_info->baud;				//设备发送波特率9600
	BUS_Public.retry_num = dev_info->retry;			//设备数据重发次数
	BUS_Public.wait_time = dev_info->writ_time;		//设备数据发送等待回复时间
	
	BUS_Public.polling_cf = (uint32_t)&BLW_Pir_CycleDis;
	BUS_Public.processing_cf = (uint32_t)&BLW_Pir_Check;
	
	BUS_Public.DevFunInfo.Dev_Input_Type_Get = Dev_Pir_InType_Get;        //
	
	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"添加485Pir设备 Baud:%d Retry:%d WaitTime:%d",dev_info->baud,dev_info->retry,dev_info->writ_time);
	DevLVinputInfo.DevOffline = DevLVinputInfo.DevOfflineLast = DEV_IS_LINEUNINIT;   //在线状态初始化
	if(dev_info->input_num > LVINPUTNUMMAX)
	{
		 DevLVinputInfo.LVinputValidNum = LVINPUTNUMMAX;
	}
	else
	{
		DevLVinputInfo.LVinputValidNum = dev_info->input_num;  //C1_LVINPUTNUMMAX;
	}
	
	Add_POLL_Device_To_List2(&BUS_Public,(uint8_t *)&DevLVinputInfo,sizeof(NOR_LVINPUT_INFO));

}


/**
*@name 弱电输入输入检测函数
*@para
*  DevAddr      设备地址
*  DevInputLoop 回路输入地址  范围0~LVinputValidNum  
*  DevInputType 输入类型
*/

uint8_t Dev_Pir_InType_Get(uint32_t DevAddr, uint16_t DevInputLoop, uint16_t DevInputType)
{
	Device_Public_Information_G BUS_Public;
	NOR_LVINPUT_INFO DevLVinputInfo;       //弱电输入局部变量
	uint8_t Ret = CtrlInvalid;         //控制无效
	
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAddr);		
	SRAM_DMA_Read_Buff((uint8_t *)&DevLVinputInfo,sizeof(NOR_LVINPUT_INFO),DevAddr+Dev_Privately);/*拷贝设备私有信息*/
	
	if(DevInputLoop >= DevLVinputInfo.LVinputValidNum)
	{
		return Ret;
	}   
	   
	if(DevInputType == DevLVinputInfo.DevReadBuf[DevInputLoop])  //找到类型
	{
		DevLVinputInfo.DevReadBuf[DevInputLoop] = 0x00;          //将动作清空
		Ret = CtrlValid;
	}
	
	if(CtrlValid == Ret)
	{
		Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"红外感应，输入动作类型: %d 动作清空", DevInputType);

		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&DevLVinputInfo, sizeof(NOR_LVINPUT_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAddr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&DevLVinputInfo,sizeof(NOR_LVINPUT_INFO),DevAddr+Dev_Privately);
				
	}
	
	return Ret;
	
}


/*******************************************************************************
* Function Name  : BLW_Touch_SwitchCycleDis 
* Description    : BLW触摸开关485数据发送处理函数，包括重发

* Return         : 
	0x01：有数据需要发送
	0x00：没有数据需要发送
*******************************************************************************/
uint8_t BLW_Pir_CycleDis(uint32_t DevAdd)  
{
	Device_Public_Information_G BUS_Public;	
	NOR_LVINPUT_INFO DevLVinputInfo;       //弱电输入局部变量
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAdd);	//拷贝所有共有数据
	SRAM_DMA_Read_Buff((uint8_t *)&DevLVinputInfo,sizeof(NOR_LVINPUT_INFO),DevAdd+Dev_Privately);/*拷贝设备私有信息*/
	
	/*判断设备是否有数据需要发送*/

	BLW_PirCycle(&BUS_Public, &DevLVinputInfo);

	/*通讯记录*/
	BLV_Communication_Record(&DevLVinputInfo.comm_record,0x01,0x00);
	DevLVinputInfo.inquire_tick = SysTick_1ms;
	
	if(DevLVinputInfo.DevSendCnt > BUS_Public.retry_num)
	{
		if(DevLVinputInfo.DevOffline != DEV_IS_OFFLINE)
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Dev485PIR LVinput OFFLINE");
			LOG_Device_Online_Record(Dev_Host_LVinput,SRAM_Read_Byte(DevAdd+Dev_Addr),LogInfo_Device_Offline);	//记录设备离线
		}
		DevLVinputInfo.DevOffline = DEV_IS_OFFLINE;		//判为离线
		if(DevLVinputInfo.DevOffline != DevLVinputInfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
		{
			DevLVinputInfo.DevOfflineLast = DevLVinputInfo.DevOffline;	//更新上一次在线状态
			Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_OFFLINE);	//保存设备在线状态到SRAM
		}
	}
	else 
	{
		DevLVinputInfo.DevSendCnt++;   				//发送次数累计
	}
	
	BUS_Public.check = 0x00;
	BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&DevLVinputInfo, sizeof(NOR_LVINPUT_INFO));
	SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAdd);/*将数据保存*/
	SRAM_DMA_Write_Buff((uint8_t *)&DevLVinputInfo,sizeof(NOR_LVINPUT_INFO),DevAdd+Dev_Privately);
				

	
	
		
	return RS485OCCUPYTIME;
}

#define Rs485PirCycleLen   0x08

/*******************************************************************************
* @name  : BLW_PirCycle 
* @para    :
*    DevAdd    设备存储地址
* @Return   : 无
*  总长度   SN CKS  保留  ADDR LEN TYPE  CMD
*   08      01 5F   F9    00   02   02    A1
*******************************************************************************/
void BLW_PirCycle(Device_Public_Information_G *BUS_Public, NOR_LVINPUT_INFO *DevLVinputInfo)  
{
//	uint8_t port_id = SRAM_Read_Byte(DevAdd + Dev_port);
//	uint8_t SendLen;
											//地址  命令  寄存器
	uint8_t SendData[Rs485PirCycleLen];   //  = {0x01, 0x06, 0x00, 0x00, 0x00};  //定义7个字节数组
    
	SendData[0] = Rs485PirCycleLen;   //内容长度
	SendData[1] = 0x00;
	SendData[1] = BLV_SN_Get(&DevLVinputInfo->DevSn, PirSnMin, PirSnMax);//帧号
	
	SendData[3] = 0xF9;
	SendData[4] = BUS_Public->addr;//SRAM_Read_Byte(DevAdd + Dev_Addr);  //配置到本地的转换
	SendData[5] = 0x02;     
	SendData[6] = INFRAREDTYPE;    //设备类型
	SendData[7] = 0xA1;    //命令
	SendData[2] =	CheckSum_Overlook_Check(SendData, Rs485PirCycleLen, 2);	
	
	/*发送函数*/
//	Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"pir send data---\r\n");
	MCU485_SendString(BUS_Public->port,SendData,Rs485PirCycleLen);	
}

/*BLW红外接收数据处理函数*/
uint8_t BLW_InfraredCtrDataProc(uint8_t *data, NOR_LVINPUT_INFO *DevLVinputInfo)
{
	uint8_t i;
	uint8_t rev = 0;
//	uint8_t DevReadBufLast;
	
//	Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"红外感应接收处理 data[8]:%d, 回路数:%d\r\n",data[8], DevLVinputInfo->LVinputValidNum);
	
	for(i = 0; i < DevLVinputInfo->LVinputValidNum; i++)
	{
//		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"红外感应接收处理 DevReadBufLast:%d\r\n",DevReadBufLast);

		if(DevLVinputInfo->DevReadBufLast[i] != data[8])   //比较不同就赋值
		{
			DevLVinputInfo->DevReadBufLast[i] = data[8];
			switch(data[8])
			{
				case 0x01:
					Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"红外感应点按动作 地址:%d回路:%d",data[4], i);
					DevLVinputInfo->DevReadBuf[i] = KeyPress;          //点按置位
					break;
				case 0x02:
					Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"红外感应松开动作 地址:%d回路:%d",data[4], i);					
					DevLVinputInfo->DevReadBuf[i] = KeyRelease;          //松开置位							
					break;
			}
			rev = 0x01;
		}
	}
	
	return rev;
}


#define Rs485PirRecLenMax   0x0B    //红外感应接收长度限制
#define IsMyData     0x00
#define IsNotMyData  0x01
/*******************************************************************************
* @name  : BLW_Pir_Check 
* @para    : BLWPir接收处理函数

* Return         : 
	0x01：数据处理失败
	0x00：数据处理成功
*******************************************************************************/
uint8_t BLW_Pir_Check(uint32_t DevAdd ,uint32_t Data_addr, uint16_t DataLen) 
{
	uint8_t Crc_buf = 0;
	uint8_t ret = IsNotMyData;
	uint8_t temp = 0;
	NOR_LVINPUT_INFO DevLVinputInfo;       //弱电输入局部变量
	Device_Public_Information_G BUS_Public;	
	uint8_t Data[Rs485PirRecLenMax];   
	
	if((NULL == DevAdd)||(DataLen > Rs485PirRecLenMax))
	{
		return ret;
	}
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAdd);	//拷贝所有共有数据
	SRAM_DMA_Read_Buff((uint8_t *)&DevLVinputInfo,sizeof(NOR_LVINPUT_INFO),DevAdd+Dev_Privately);/*拷贝设备私有信息*/
	SRAM_DMA_Read_Buff(Data, DataLen, Data_addr);/*拷贝485数据*/
	if((DataLen != Data[0]) || (DataLen != Data[5]+0x06) || (INFRAREDTYPE != Data[6]) || (Data[4] != BUS_Public.addr))
	{
		return ret;
	}

	Crc_buf = CheckSum_Overlook_Check(Data, DataLen, 2);//提前保存校验  

	
	if(Crc_buf == Data[2])   //校验通过
	{
		
//		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"红外感应数据校验通过 DevAdd:%d,len:%d\r\n",temp,DataLen);
		ret = IsMyData;  
		
		if(DevLVinputInfo.DevOffline != DEV_IS_ONLINE)
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DevLVinput LogInfo_Device_Online...........");
			LOG_Device_Online_Record(Dev_Host_LVinput,SRAM_Read_Byte(DevAdd+Dev_Addr),LogInfo_Device_Online);	//记录设备离线
		}
		DevLVinputInfo.DevSendCnt = 0x00;
		DevLVinputInfo.DevOffline = DEV_IS_ONLINE;
		if(DevLVinputInfo.DevOffline != DevLVinputInfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
		{
			DevLVinputInfo.DevOfflineLast = DevLVinputInfo.DevOffline;	//更新上一次在线状态
			Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_ONLINE);	//保存设备在线状态到SRAM
		}
		BLV_Communication_Record(&DevLVinputInfo.comm_record,0x02,0x01);		//记录通讯成功
		
		temp = BLW_InfraredCtrDataProc(Data, &DevLVinputInfo);                           //直接处理红外的数据，可以根据回复的地址，找到红外的节点，也可以根据端口的节点集合进行传递节点
		if(temp != 0x00)	/*红外状态改变*/
		{
			LOG_Device_COMM_ASK_TO_Reply_Record(BUS_Public.port, BUS_Public.baud,(SysTick_1ms - DevLVinputInfo.inquire_tick),Data,DataLen);
		}
		
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&DevLVinputInfo, sizeof(NOR_LVINPUT_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAdd);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&DevLVinputInfo,sizeof(NOR_LVINPUT_INFO),DevAdd+Dev_Privately);
		
		
	}
	else {
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Pir SOR_SRAM_CRC Fail:%02X DataLen:%d",Crc_buf,DataLen);
		Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"Pir Fail Data:",Data,DataLen);
	}
	
	
	return ret;
}

#if 0

/*BLW红外接收数据处理函数*/
void BLW_InfraredCtrDataProc(uint8_t *data, CFG_Dev_AddP CfgDevAdd)
{
  RS485_INFRARED_INFOP Rs485Infrared; 
	uint8_t i;
	
	Rs485Infrared = CfgDevAdd->DevDataStruct; //上一个函数已经进行非空判断
	for(i = 0; i < Rs485Infrared->InfraredInputValidNum; i++)
	{
//		if(Rs485Infrared->DevReadBuf_last[i] != data[8])   //不比较直接进行赋值
		{
			Rs485Infrared->DevReadBuf_last[i] = data[8];
			switch(Rs485Infrared->DevReadBuf_last[i])
			{
				case 0x01:
					Rs485Infrared->DevReadBuf[i] = 0x01;
					break;
				case 0x02:
					Rs485Infrared->DevReadBuf[i] = 0x02;
					break;
			}
		}
	}
}


/*BLW红外接收判断函数*/
/**
  * @name  			BLW红外接收处理函数
  * @param  
  *    data       485数据包
  *    DataLen    数据包长度
  *    CfgDevAdd 设备红外节点
  * @retval      1 是我的数据    2 不是我的数据
  * @attention  
  * 地址  读    长度       内容    校验
  *  3C   03   00   02   00   01   70 E8 
	*              
  */
uint8_t BLW_Rs485_Infrared_Check(uint8_t *data, uint16_t DataLen, CFG_Dev_AddP CfgDevAdd)
{
	uint8_t Crc_buf;
	uint8_t Ret = IsnotMyData;
	
	RS485_INFRARED_INFOP Rs485Infrared; 
	

	if((NULL == CfgDevAdd)||(NULL == CfgDevAdd->DevDataStruct)||
		(DataLen != data[0])||(DataLen != data[5]+0x06)||(INFRAREDTYPE != data[6])||(data[4] != CfgDevAdd->DevAddr))//
	{
		return Ret;
	}
	
	Rs485Infrared = CfgDevAdd->DevDataStruct;
	
	Crc_buf = BLW_SOR_Negate(data, DataLen, 2);//提前保存校验  

	if(Crc_buf == data[2])   //校验判断
	{		
		Ret = IsMyData;
		Rs485Infrared->DevSendCnt = 0x00;                                     //收到回复就清计数
		Rs485Infrared->DevOffline = DEV_IS_ONLINE;    //设备在线
		
		BLW_InfraredCtrDataProc(data, CfgDevAdd);                           //直接处理红外的数据，可以根据回复的地址，找到红外的节点，也可以根据端口的节点集合进行传递节点
	}
	return Ret;
}






#endif

