/**
  ******************************************************************************
  * @file    BLV_Dev_Action.c
  * @author  BLW RCU  development Team
  * @version V1.0.0
  * @date    2021年11月02日
  * @brief   每个无线主网关有通道地址和设备地址，设备地址默认为1，默认只接一个。
	*          通道地址需要主机去下发设置
	* 
  ******************************************************************************
  */
#include "includes.h"

#include "BLV_RF_GatewayHost.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"

/*本地函数调用申明开始*/
uint8_t BLW_RF_GatewayHost_CycleDis(uint32_t dev_addr); 
uint8_t BLW_Rs485_RF_GatewayHost_Check(uint32_t dev_addr,uint32_t data_addr,uint16_t len);
void BLW_RF_GatewayHostAddrRead(Device_Public_Information_G *BUS_Public, RFGatewayHost_INFO *RFGatewayHostinfo);
void BLW_RF_GatewayHostAddrWrite(Device_Public_Information_G *BUS_Public, RFGatewayHost_INFO *RFGatewayHostinfo);

/*本地函数调用申明结束*/
#define    REPEATSENDTIMEMAX 0x03
#define  C12WXLockCh    100
//#define  WuYueWxLock    101

//#define RFGATEWAYHOSTCHANNELVALUE  MACAddr[5]   //无线通道值  每个主机都不一样，需要单独设置
#define RFGATEWAYHOSTCYCLETIMEOUT   5000  //等待间隔时间

/*******************************************************************************
* @Function Name  : BLW_RS485_RF_GatewayHost_Init 
* @Description    : 添加设备到链表 - 主动设备
* @Input          : 
	@type	: 添加的设备类型
	@addr	: 添加的设备地址
	@polling_cf		：设备的数据发送回调函数
	@processing_cf	：设备的数据处理回调函数
* @Return         : None
*******************************************************************************/
void BLW_RS485_RF_GatewayHost_Init(uint8_t devaddr)
{
	Device_Public_Information_G BUS_Public;
	RFGatewayHost_INFO RFGatewayHostinfo;
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&RFGatewayHostinfo,0,sizeof(RFGatewayHost_INFO));
	
	BUS_Public.addr = devaddr;		//设备地址
	BUS_Public.type = DEV_RS485_RFGatewayHost;		//设备类型
	BUS_Public.port = Active_Port;		//设备发送端口
	BUS_Public.baud = 9600;		//设备发送波特率
	BUS_Public.retry_num = 0x03;	//设备数据重发次数
	BUS_Public.wait_time = 0x0064;	//设备数据发送等待回复时间 - 100ms
	BUS_Public.polling_cf = (uint32_t)&BLW_RF_GatewayHost_CycleDis;
	BUS_Public.processing_cf = (uint32_t)&BLW_Rs485_RF_GatewayHost_Check;
	
	RFGatewayHostinfo.RFGatewayHostChannelRef = MACAddr[5];
	RFGatewayHostinfo.DevOffline = RFGatewayHostinfo.DevOfflineLast = DEV_IS_LINEUNINIT;   //在线状态初始化
	Add_ACT_Device_To_List2(&BUS_Public,(uint8_t *)&RFGatewayHostinfo,sizeof(RFGatewayHost_INFO));
}

/*******************************************************************************
* @Function Name  : BLW_RS485_RF_GatewayHost_Logic_Init 
* @Description    : 添加设备到链表 - 主动设备
* @Input          : 
	@type	: 添加的设备类型
	@addr	: 添加的设备地址
	@polling_cf		：设备的数据发送回调函数
	@processing_cf	：设备的数据处理回调函数
* @Return         : None
*******************************************************************************/
void BLW_RS485_RF_GatewayHost_Logic_Init(LOGICFILE_DEVICE_INFO *dev_info,uint8_t *data,uint16_t data_len)
{
	Device_Public_Information_G BUS_Public;
	RFGatewayHost_INFO RFGatewayHostinfo;
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&RFGatewayHostinfo,0,sizeof(RFGatewayHost_INFO));
	
	BUS_Public.addr = dev_info->addr;		//设备地址
	BUS_Public.type = dev_info->type;		//设备类型
	BUS_Public.port = dev_info->port;		//设备发送端口
	BUS_Public.baud = dev_info->baud;		//设备发送波特率 9600
	BUS_Public.retry_num = 0x03;	//设备数据重发次数
	BUS_Public.wait_time = 0x0064;	//设备数据发送等待回复时间 - 100ms
	BUS_Public.polling_cf = (uint32_t)&BLW_RF_GatewayHost_CycleDis;
	BUS_Public.processing_cf = (uint32_t)&BLW_Rs485_RF_GatewayHost_Check;
	
	RFGatewayHostinfo.RFGatewayHostChannelRef = MACAddr[5];
	RFGatewayHostinfo.DevOffline = RFGatewayHostinfo.DevOfflineLast = DEV_IS_LINEUNINIT;   //在线状态初始化
	Add_ACT_Device_To_List2(&BUS_Public,(uint8_t *)&RFGatewayHostinfo,sizeof(RFGatewayHost_INFO));
}

uint8_t BLW_RF_GatewayHost_CycleDis(uint32_t dev_addr)
{
	uint16_t DataLen;
	uint8_t CrcVal;  
	uint8_t Ret = RS485OCCUPYNOTIME;
	RFGatewayHost_INFO RFGatewayHostinfo;               //网关局部变量
	Device_Public_Information_G BUS_Public;          
	
	if(NULL == dev_addr)
	{
		return Ret;
	}
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);				
	SRAM_DMA_Read_Buff((uint8_t *)&RFGatewayHostinfo,sizeof(RFGatewayHost_INFO),dev_addr+Dev_Privately);

	
	if(RFGatewayHostinfo.RFGatewayHostChannel != (uint8_t)RFGatewayHostinfo.RFGatewayHostChannelRef)  //地址不同，如果是0通道，就不用读取。
	{
		RFGatewayHostinfo.RFGatewayHostChannel = (uint8_t)RFGatewayHostinfo.RFGatewayHostChannelRef;
		RFGatewayHostinfo.RFGatewayHostNetCtrlFlag = RFGatewayHostNetRead;   //置读取
	
	}
	
	if(SysTick_1ms >= RFGatewayHostinfo.RFGatewayHostCycleTime)  //超过时间   
	{
		RFGatewayHostinfo.RFGatewayHostCycleTime = SysTick_1ms + RFGATEWAYHOSTCYCLETIMEOUT;

		switch(RFGatewayHostinfo.RFGatewayHostNetCtrlFlag)       //如果网关读取标志置一
		{
			case RFGatewayHostNetRead:  //读
				BLW_RF_GatewayHostAddrRead(&BUS_Public, &RFGatewayHostinfo);//发送读取命令
				Ret = RS485OCCUPYTIME;
				break;
			case RFGatewayHostNetWrite: //写
				BLW_RF_GatewayHostAddrWrite(&BUS_Public, &RFGatewayHostinfo);//发送写入命令
				Ret = RS485OCCUPYTIME;
				break;
			default:
				break;
		}
	}
	
	if(RS485OCCUPYTIME == Ret)
	{
		/*通讯统计*/
		BLV_Communication_Record(&RFGatewayHostinfo.comm_record,0x01,0x00);
		
		if(RFGatewayHostinfo.DevSendCnt > REPEATSENDTIMEMAX)
		{
			if(RFGatewayHostinfo.DevOffline != DEV_IS_OFFLINE)
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"RFGatewayHostinfo DEV_IS_OFFLINE");
				LOG_Device_Online_Record(DEV_RS485_RFGatewayHost,SRAM_Read_Byte(dev_addr+Dev_Addr),LogInfo_Device_Offline);	//记录设备离线
			}
			RFGatewayHostinfo.DevOffline = DEV_IS_OFFLINE;   //离线
			if(RFGatewayHostinfo.DevOffline != RFGatewayHostinfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
			{
				RFGatewayHostinfo.DevOfflineLast = RFGatewayHostinfo.DevOffline;	//更新上一次在线状态
				Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_OFFLINE);	//保存设备在线状态到SRAM
			}
		}
		else
		{
			RFGatewayHostinfo.DevSendCnt++;   //
		}
		
		/*将数据保存进入SRAM中*/
		SRAM_DMA_Write_Buff((uint8_t *)&RFGatewayHostinfo,sizeof(RFGatewayHost_INFO),dev_addr+Dev_Privately);
		
		/*计算校验值*/
		SRAM_Write_Byte(0x00,dev_addr+Dev_Check);
		DataLen = sizeof(RFGatewayHost_INFO) + Dev_Privately;
		CrcVal = Dev_CheckSum(dev_addr,DataLen);
		SRAM_Write_Byte(CrcVal,dev_addr+Dev_Check);		//校验值重新写入
	}
	
	return Ret;
}


#define GATEWAYHOSTADDRREADLEN  0x07
/**
  * @name      主网关地址读取函数
  * @param  
  *    CfgDevAdd        设备节点
  * @retval     无
	*       网关地址 设备类型 设备地址 和校验取反 长度 读命令 内容
	*        00       00       00      F7          01   08     00
  */
void BLW_RF_GatewayHostAddrRead(Device_Public_Information_G *BUS_Public, RFGatewayHost_INFO *RFGatewayHostinfo)
{
//	uint8_t port = SRAM_Read_Byte(dev_addr+Dev_port);      //通讯端口
//	uint8_t DevAddr = SRAM_Read_Byte(dev_addr+Dev_Addr);   //设备地址	
	
	uint8_t SendBuf[7]; // = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00};       //询问是否在线
	
	SendBuf[0] = BUS_Public->addr;//BLV_SN_Get(&RFGatewayHostinfo->RFGatewayHostSn, 0, 255);    
	SendBuf[1] = 0x00;   //设备类型
	SendBuf[2] = 0x00;   //设备地址
	SendBuf[4] = 0x01;   //内容长度
	SendBuf[5] = 0x08;       //读主网关网络通道命令
	SendBuf[6] = 0x00;   //保留
	
	SendBuf[3] = CheckSum_Overlook_Check(SendBuf, GATEWAYHOSTADDRREADLEN, 3);
	
	MCU485_SendString(BUS_Public->port,SendBuf,GATEWAYHOSTADDRREADLEN);

	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record(BUS_Public->port,BUS_Public->baud,SendBuf,GATEWAYHOSTADDRREADLEN);
		
}


#define GATEWAYHOSTADDRWRITELEN  0x07
/**
  * @name      主网关地址写入函数
  * @param  
  *    CfgDevAdd        设备节点
  * @retval     无
	*       网关地址 设备类型 设备地址 和校验取反 长度 读命令 内容
	*        00       00       00      F6          01   07     00
  */
void BLW_RF_GatewayHostAddrWrite(Device_Public_Information_G *BUS_Public, RFGatewayHost_INFO *RFGatewayHostinfo)
{
//	uint8_t port = SRAM_Read_Byte(dev_addr+Dev_port);      //通讯端口
//	uint8_t DevAddr = SRAM_Read_Byte(dev_addr+Dev_Addr);   //设备地址	
	
	uint8_t SendBuf[7]; // = {0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00};       //询问是否在线

	
	SendBuf[0] = BUS_Public->addr;//BLV_SN_Get(&RFGatewayHostinfo->RFGatewayHostSn, 0, 255);    
	SendBuf[1] = 0x00;   //设备类型
	SendBuf[2] = 0x00;   //设备地址
	SendBuf[4] = 0x01;   //内容长度
	SendBuf[5] = 0x07;   //写主网关网络通道命令
	SendBuf[6] = RFGatewayHostinfo->RFGatewayHostChannelRef;   //网络通道地址 gWIZNETINFO.mac[5]
	
	SendBuf[3] = CheckSum_Overlook_Check(SendBuf, GATEWAYHOSTADDRWRITELEN, 3);
	
	MCU485_SendString(BUS_Public->port,SendBuf,GATEWAYHOSTADDRWRITELEN);
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record(BUS_Public->port,BUS_Public->baud,SendBuf,GATEWAYHOSTADDRWRITELEN);
	
}

#define IsMyData     0x00  
#define IsNotMyData  0x01

#define RECLENMAX    20   //超过20个字节，直接返回
/**
  * @name  			 BLW无线主网关485接收处理函数
  * @param  
  *    dev_addr   设备信息地址
  *    data_addr  485数据包地址
  *    len    数据包长度
  * @retval      1 是我的数据    2 不是我的数据
  * @attention   
	*              
  */
uint8_t BLW_Rs485_RF_GatewayHost_Check(uint32_t dev_addr,uint32_t data_addr,uint16_t DataLen)
{
	uint8_t Crc_buf;
	uint8_t Ret = IsNotMyData;
	Device_Public_Information_G BUS_Public;
	RFGatewayHost_INFO RFGatewayHostinfo;               //网关局部变量
	uint8_t data[RECLENMAX];
	uint8_t DevAddr = SRAM_Read_Byte(dev_addr+Dev_Addr);   //设备地址	
	uint16_t dev_datalen;
	if((NULL == dev_addr) || (DataLen > RECLENMAX))   //传的参数异常就直接返回
	{
		return Ret;
	}
	
	SRAM_Read_Buff(data, DataLen, data_addr);   //将485数据拷贝出来 

//	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"主网关数据处理\r\n");

	if(((data[4]+0x06) != DataLen)|| (RFGATEWAYHOSTTYPE != data[1]) || (DevAddr != data[0]))   //不是透传设备类型  或者地址不对
	{
		return Ret;
	}

	Crc_buf = CheckSum_Overlook_Check(data, DataLen, 3);  //提前保存校验

	if(Crc_buf == data[3])   //校验判断
	{
		SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);
		SRAM_DMA_Read_Buff((uint8_t *)&RFGatewayHostinfo,sizeof(RFGatewayHost_INFO),dev_addr+Dev_Privately);
		
		BLV_Communication_Record(&RFGatewayHostinfo.comm_record,0x02,0x01);		//记录通讯成功
		switch(data[5])
		{
			case 0x12:
			case 0x11:
			case 0x16:
			case 0x18:   //读取网络通道，回复报文
				if(RFGatewayHostinfo.DevOffline == DEV_IS_OFFLINE)
				{
					Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"RFGatewayHost DEV_IS_ONLINE");
					LOG_Device_Online_Record(DEV_RS485_RFGatewayHost,SRAM_Read_Byte(dev_addr+Dev_Addr),LogInfo_Device_Online);	//记录设备在线
				}
				Ret = IsMyData;
				RFGatewayHostinfo.DevSendCnt = 0x00;
				RFGatewayHostinfo.DevOffline = DEV_IS_ONLINE;    //设备在线
				if(RFGatewayHostinfo.DevOffline != RFGatewayHostinfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
				{
					RFGatewayHostinfo.DevOfflineLast = RFGatewayHostinfo.DevOffline;	//更新上一次在线状态
					Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_ONLINE);	//保存设备在线状态到SRAM
				}
				break;
		}
		
		switch(data[5])         //命令字
		{
//			case 0x12:      //下发配置的回复
//				RFGatewayHostinfo.RFGatewayHostConfigSendFlag = 0x00;
//				RFGatewayHostinfo.RFGatewayHostConfigSendCnt = REPEATSENDTIMEMAX;
//				break;
//			case 0x11:      //询问连接状态的回复
//				RFGatewayHostinfo.RFGatewayHostOnlineFlag = 0x01;
//				break;
//			case 0x16:
//				RFGatewayHostinfo.RFGatewayHostConfigWriteAskFlag = 0x01;
//				break;
			case 0x17:     //设置网络通道的回复
				RFGatewayHostinfo.RFGatewayHostNetCtrlFlag = RFGatewayHostNetRead;   //将状态改为读
			
				/*日志记录*/
				LOG_Device_COMM_Control_Reply_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,data,DataLen);
				break;
			case 0x18:     //读取网络通道的回复
//				if(0x04 == data[4])  //内容长度为4
				{
					if(RFGatewayHostinfo.RFGatewayHostChannel != data[6])   //按照MAC地址来设置网络地址gWIZNETINFO.mac[5]
					{
						RFGatewayHostinfo.RFGatewayHostNetCtrlFlag = RFGatewayHostNetWrite;  //网络改成写
					}
					else    //如果MAC地址跟回过来的网络地址一样
					{
						RFGatewayHostinfo.RFGatewayHostNetCtrlFlag = RFGatewayHostNetFree;
					}
				}
				
				/*日志记录*/
				LOG_Device_COMM_Control_Reply_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,data,DataLen);
				break;
				
			 
		}
		
		/*将数据保存，重新计算校验值*/
		SRAM_DMA_Write_Buff((uint8_t *)&RFGatewayHostinfo,sizeof(RFGatewayHost_INFO),dev_addr+Dev_Privately);
		
		SRAM_Write_Byte(0x00,dev_addr+Dev_Check);				//校验值清零
		dev_datalen = sizeof(RFGatewayHost_INFO) + Dev_Privately;
		Crc_buf = Dev_CheckSum(dev_addr,dev_datalen);
		SRAM_Write_Byte(Crc_buf,dev_addr+Dev_Check);		//校验值重新写入
		
	}
	return Ret;
}


