/**
  ******************************************************************************
  * @file    BLV_485_Dev_SwiRELAYFun.c
  * @author  BLW RCU  development Team
  * @version SongHan
  * @date    2022年04月06日
  * @brief  
	*    SwiRELAY继电器扩展模块 每个模块有4路
  ******************************************************************************
  */



#include "includes.h"
#include "BLV_485_Dev_SwiRELAYFun.h"
#include "string.h"
#include "SPI_SRAM.h"
#include "usart.h"
#include "check_fun.h"
#include "DBG.h"
#include "rw_logging.h"
#include "SRAM_Variable_Address.h"
#include "Log_api.h"
#include "BLV_Dev_Action.h"


/*SwiRELAY扩展板驱动代码*/

#define REPEATSENDTIMEMAX         0x03  //重发次数上限

//#define   A9EXPANDTYPE           14	    //SwiRELAY类型

#define SwiRELAYSnMin                 0x08            //最大Sn号
#define SwiRELAYSnMax                 0x0F            //最大Sn号

/*本地函数调用开始*/
uint8_t BLW_SwiRELAYCycleCtrl(uint32_t dev_addr); 
uint8_t BLW_Rs485_SwiRELAY_Check(uint32_t dev_addr,uint32_t data_addr,uint16_t len);
void BLW_Rs485_SwiRELAY_Ctrl(Device_Public_Information_G *BUS_Public, NOR_HVOUT_INFO* DevHVoutInfo);


/*本地函数调用结束*/

/*******************************************************************************
* Function Name  : BLW_RS485_SwiRELAY_Data_Init 
* Description    : 添加设备到链表 - 轮询设备
* Input          : 
	type	: 添加的设备类型
	addr	: 添加的设备地址
	polling_cf		：设备的轮询数据发送回调函数
	processing_cf	：设备的数据处理回调函数
* Return         : None
*******************************************************************************/
void BLW_RS485_SwiRELAY_Data_Init(Device_Public_Information_G *BUS_Public, NOR_HVOUT_INFO *DevHVoutInfo)
{

	BUS_Public->polling_cf = (uint32_t)&BLW_SwiRELAYCycleCtrl;
	BUS_Public->processing_cf = (uint32_t)&BLW_Rs485_SwiRELAY_Check;
	DevHVoutInfo->HVSwitchFlag = 0x01;

}



/*******************************************************************************
* Function Name  : BLW_SwiRELAYCycleCtrl 
* Description    : BLWSwiRELAY扩展板轮询兼控制发送函数
*******************************************************************************/
uint8_t BLW_SwiRELAYCycleCtrl(uint32_t dev_addr) 
{
	uint8_t i;     //用于遍历所有回路
	uint8_t Ret = RS485OCCUPYNOTIME;
	Device_Public_Information_G BUS_Public;	
	NOR_HVOUT_INFO DevHVoutInfo;

	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);				
	SRAM_DMA_Read_Buff((uint8_t *)&DevHVoutInfo,sizeof(NOR_HVOUT_INFO),dev_addr+Dev_Privately);
	
	for(i = 0; i < DevHVoutInfo.HVoutLoopValidNum; i++)
	{
		if(DevHVoutInfo.DevHVoutStateLast[i] != DevHVoutInfo.DevHVoutState[i])
		{
			DevHVoutInfo.DevChangeFlag = 0x01;
			DevHVoutInfo.HVoutCtrlCnt = REPEATSENDTIMEMAX;
			DevHVoutInfo.DevHVoutStateLast[i] = DevHVoutInfo.DevHVoutState[i];  //同步所有回路

		}
//		if(DevHVoutInfo.DevSendBuf_last[i] != DevHVoutInfo.DevSendBuf[i])
//		{
//			DevHVoutInfo.SwiRELAYCtrlFlag = 0x01;
//			DevHVoutInfo.HVoutCtrlCnt = REPEATSENDTIMEMAX;
//			memcpy(DevHVoutInfo.DevSendBuf_last, DevHVoutInfo.DevSendBuf, DevHVoutInfo.HVoutLoopValidNum);   //同步这组数据

//			break;
//		} 
	}
	if((0x00 == DevHVoutInfo.DevChangeFlag) && (0x01 == DevHVoutInfo.HVSwitchCtrlFlag))
	{
		DevHVoutInfo.HVSwitchCtrlFlag = 0x00;
		DevHVoutInfo.DevChangeFlag = 0x01;
	}
		
	

	if(0x01 == DevHVoutInfo.DevChangeFlag)
	{
		if(0x00 != DevHVoutInfo.HVoutCtrlCnt)
		{
			DevHVoutInfo.HVoutCtrlCnt--; 
		}else{
			DevHVoutInfo.DevChangeFlag = 0x00;
		}
		BLW_Rs485_SwiRELAY_Ctrl(&BUS_Public, &DevHVoutInfo);           //4路控制，状态控制
		Ret = RS485OCCUPYTIME;
		
		/*通讯记录*/
		BLV_Communication_Record(&DevHVoutInfo.comm_record,0x01,0x00);
	}

	
	if(RS485OCCUPYTIME == Ret)
	{
		if(DevHVoutInfo.DevSendCnt > REPEATSENDTIMEMAX)
		{
			if(DevHVoutInfo.DevOffline != DEV_IS_OFFLINE)
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DevHVoutInfo %d DEV_IS_OFFLINE", BUS_Public.addr);
				LOG_Device_Online_Record(BUS_Public.type,BUS_Public.addr,LogInfo_Device_Offline);	//记录设备离线
			}
			DevHVoutInfo.DevOffline = DEV_IS_OFFLINE;   //离线
			if(DevHVoutInfo.DevOffline != DevHVoutInfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
			{
				DevHVoutInfo.DevOfflineLast = DevHVoutInfo.DevOffline;	//更新上一次在线状态
				Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_OFFLINE);	//保存设备在线状态到SRAM
			}
		}
		else
		{
			DevHVoutInfo.DevSendCnt++;   //
		}
		
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&DevHVoutInfo, sizeof(NOR_HVOUT_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&DevHVoutInfo,sizeof(NOR_HVOUT_INFO),dev_addr+Dev_Privately);
			
		//Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"SwiRELAY crc_val:%02X\r\n",crc_val);
	}

	
	

	
	return Ret;
}

#define RECDATALENMAX   24   //接收数据最大长度

#define IsMyData     0x00  
#define IsNotMyData  0x01
/*******************************************************************************
* Function Name  : BLW_Rs485_SwiRELAY_Check 
* Description    : BLWSwiRELAY扩展板接收数据处理函数
* Input          : 
	dev_addr	: 设备信息地址
	data_addr	: 数据地址
	len			：数据长度
* Return         : 
	0x00：处理成功
	0x01：处理失败
*******************************************************************************/
uint8_t BLW_Rs485_SwiRELAY_Check(uint32_t dev_addr,uint32_t data_addr,uint16_t len)
{
	uint8_t rev = IsNotMyData;
//	uint8_t temp;  //保存命令类型和数据长度
	Device_Public_Information_G BUS_Public;	
	NOR_HVOUT_INFO DevHVoutInfo;
	uint8_t data[RECDATALENMAX];
	
//	uint8_t SwiRELAY_addr = SRAM_Read_Byte(dev_addr+Dev_Addr); //拿到当前设备的地址
//	uint8_t crc_val = SRAM_Read_Word(data_addr+5);        //保存校验
	
	if(len > RECDATALENMAX)
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Swi继电器接收数据长度超出范围!!");
		return rev;     //长度
	}
	
	SRAM_DMA_Read_Buff(data,len,data_addr);   //拷贝485数据
	
	if((0x05 != len)||((data[1] != 0x76)&&(data[1] != 0x73))||(data[len-1] != SOR_CRC(data, len-1))||(data[0] != SRAM_Read_Byte(dev_addr+Dev_Addr)))	   //地址不对  长度不对
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Swi设备地址或长度或校验不对!!");
		return rev;				//校验文件头
	}
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);  				

//	if()   //校验通过
	{
		SRAM_DMA_Read_Buff((uint8_t *)&DevHVoutInfo,sizeof(NOR_HVOUT_INFO),dev_addr+Dev_Privately);
//		temp = SRAM_Read_Byte(data_addr + 6);
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Swi设备校验通过!!");
		
		BLV_Communication_Record(&DevHVoutInfo.comm_record,0x02,0x01);		//记录通讯成功
		
		switch(data[1])  
		{
			case 0x73:     //按键状态
				break;
			case 0x76:
				rev = IsMyData;
				if(DevHVoutInfo.DevOffline != DEV_IS_ONLINE)
				{
					Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"%s Device_Online",__func__);
					LOG_Device_Online_Record(BUS_Public.type,BUS_Public.addr,LogInfo_Device_Online);	//记录设备在线
				}
				DevHVoutInfo.DevSendCnt = 0x00;
				DevHVoutInfo.DevOffline = DEV_IS_ONLINE;    //设备在线
				if(DevHVoutInfo.DevOffline != DevHVoutInfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
				{
					DevHVoutInfo.DevOfflineLast = DevHVoutInfo.DevOffline;	//更新上一次在线状态
					Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_ONLINE);	//保存设备在线状态到SRAM
				}
				DevHVoutInfo.DevChangeFlag = 0x00;
				//2022-12-29
				for(uint8_t i = 0; i < DevHVoutInfo.HVoutLoopValidNum; i++)
				{
					if(DevHVoutInfo.DevHVoutSaveState[i] != DevHVoutInfo.DevHVoutState[i])
					{		
						DevHVoutInfo.DevHVoutSaveState[i] = DevHVoutInfo.DevHVoutState[i];//同步
						if( DevHVoutInfo.DevHVoutState[i] == 0x01 )
						{
							Udp_Addtion_Roomstate(Dev_Host_HVout,BUS_Public.addr,i+1,0x01);
						}
						else if( DevHVoutInfo.DevHVoutState[i] == 0x00 )
						{
							Udp_Addtion_Roomstate(Dev_Host_HVout,BUS_Public.addr,i+1,0x02);
						}
						
						Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"强电开关继电器状态变化");
					}
				}
				
				/*日志记录*/
				LOG_Device_COMM_Control_Reply_Record3(dev_addr+Dev_port,dev_addr+Dev_baud,data_addr,len);
				break;			
		}
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&DevHVoutInfo, sizeof(NOR_HVOUT_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&DevHVoutInfo,sizeof(NOR_HVOUT_INFO),dev_addr+Dev_Privately);
					
	}
//	else {
//		Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"SwiRelay Check Fail !!\r\n");
//		
//	}
	
	return rev;
}




#define SwiRELAYCTRLLEN    5    //扩展板控制报文
/**
	* @name BLW 4路 集中扩展板控制函数
	* @para
	*   dev_addr     设备起始地址   
	* @return         无
  * @attention      发送循环里调用，变量已经被判断
	*/
void BLW_Rs485_SwiRELAY_Ctrl(Device_Public_Information_G *BUS_Public, NOR_HVOUT_INFO* DevHVoutInfo)
{
//	uint8_t port = SRAM_Read_Byte(dev_addr+Dev_port);      //通讯端口
//	uint8_t DevAddr = SRAM_Read_Byte(dev_addr+Dev_Addr);   //设备地址
	                                  //己方地址 发送类型  设备类型      收方地址    LEN          校验和   CMD  4个灯
	uint8_t SendBuf[SwiRELAYCTRLLEN];// 
	uint8_t i;	

	SendBuf[0] = BUS_Public->addr; // DevAddr;  
	SendBuf[1] = 0x76;             //继电器控制
  SendBuf[2] = 0x00;             //清0
	SendBuf[3] = 0x00;             //清0
//	memcpy(&SendBuf[6], &RS485RelayExpandInfo.DevRelayBuf[SwiAddr*2], 2); //扩展板， 下标从5开始
	for(i = 0; i < DevHVoutInfo->HVoutLoopValidNum; i++)
	{
		switch(DevHVoutInfo->DevHVoutState[i])
		{
			case 0x01:
				SendBuf[2+i/4] |= 0x01<<((i%4)*2);       //开
				break;
			case 0x00:
				SendBuf[2+i/4] |= 0x02<<((i%4)*2);      //关
				break;
		}
	}
	SendBuf[SwiRELAYCTRLLEN-1] = SOR_CRC(SendBuf,SwiRELAYCTRLLEN-1);
		
	MCU485_SendString(BUS_Public->port,SendBuf,SwiRELAYCTRLLEN);
	
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record(BUS_Public->port, BUS_Public->baud, SendBuf,SwiRELAYCTRLLEN);	
}



