/**
  ******************************************************************************
  * @file    BLV_485_Dev_BLWFreshAirFun.c
  * @author  BLW RCU  development Team	林开锐
  * @version V1.0.0
  * @date    2023年2月24日
  * @brief   宝来威新风
  ******************************************************************************
  */

#include "includes.h"
#include "BLV_485_Dev_BLWFreshAirFun.h"

#define BLW_FRESHAIR_MAX_SEND_CNT				0x03	//宝来威新风设备最大重发次数
#define BLW_FRESHAIR_RECEIVE_MAX_DATA_LEN		0x18	//宝来威新风设备最大数据长度

/*函数声明开始*/
void BLW_FreshAir_Control(Device_Public_Information_G *BUS_Public,uint8_t function,uint8_t control);	//宝来威新风控制函数
void BLW_FreshAir_Poll_Order(Device_Public_Information_G *BUS_Public);	//宝来威新风轮询命令函数
void BLW_FreshAir_Change_Data(RS485_FreshAir_INFO *FreshAir_Info,uint8_t *data);	//宝来威新风数据变化处理函数
/*函数声明结束*/

/*******************************************************************************
  * @brief      添加宝来威新风设备到链表 - 轮询设备
  * @param  
  *		BUS_Public		设备共有属性指针
  *		FreshAir_Info	485新风设备私有属性指针
  * @retval     None
  * @attention	None
*******************************************************************************/
void BLW_RS485_FreshAir_Init(Device_Public_Information_G *BUS_Public,RS485_FreshAir_INFO *FreshAir_Info)
{
	BUS_Public->polling_cf = (uint32_t)&BLW_FreshAir_Polling_Ctrl;	//宝来威新风轮询控制函数
	BUS_Public->processing_cf = (uint32_t)&BLW_FreshAir_Data_Processing;	//宝来威新风接收处理函数
	
	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"添加宝来威新风设备 %d 地址",BUS_Public->addr);
}

/*******************************************************************************
  * @brief      宝来威新风轮询控制函数
  * @param  
  *		dev_addr	设备信息地址
  * @retval     RS485OCCUPYTIME - 485发送函数会占用时间
				RS485OCCUPYNOTIME - 485发送函数不会占用时间
  * @attention	None
*******************************************************************************/
uint8_t BLW_FreshAir_Polling_Ctrl(uint32_t dev_addr)
{
	uint8_t send_time = RS485OCCUPYNOTIME;	//发送时间（默认发送不占用时间）
	Device_Public_Information_G BUS_Public;	//新风设备共有属性
	RS485_FreshAir_INFO FreshAir_Info;	//新风设备私有属性
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), dev_addr);	//读取共有属性
	SRAM_DMA_Read_Buff((uint8_t *)&FreshAir_Info,sizeof(RS485_FreshAir_INFO), dev_addr+Dev_Privately);	//读取私有属性
	
	if(FreshAir_Info.ctrl_flag.on_off == 0x01)	//控制开关机标志置1	
	{
		if(FreshAir_Info.ctrl_cnt.on_off != 0x00)	//开关机控制次数不为0
		{
			FreshAir_Info.ctrl_cnt.on_off--;	//控制次数减1
		}
		else	//开关机控制次数为0
		{
			FreshAir_Info.ctrl_flag.on_off = 0x00;	//控制开关机标志清0
		}
		BLW_FreshAir_Control(&BUS_Public, FRESHAIR_ON_OFF_FUNCTION, FreshAir_Info.ctrl_content.on_off);	//新风控制
		send_time = RS485OCCUPYTIME;	//发送占用时间
	}
	else if(FreshAir_Info.ctrl_flag.wind_velocity == 0x01)	//控制风速
	{
		if(FreshAir_Info.ctrl_cnt.wind_velocity != 0x00)	//风速控制次数不为0
		{
			FreshAir_Info.ctrl_cnt.wind_velocity--;	//控制次数减1
		}
		else	//风速控制次数为0
		{
			FreshAir_Info.ctrl_flag.wind_velocity = 0x00;	//控制风速标志清0
		}
		BLW_FreshAir_Control(&BUS_Public, FRESHAIR_WIND_VELOCITY_FUNCTION, FreshAir_Info.ctrl_content.wind_velocity);	//新风控制
		send_time = RS485OCCUPYTIME;	//发送占用时间
	}
	else	//其他时候发送轮询命令
	{
		BLW_FreshAir_Poll_Order(&BUS_Public);	//轮询命令
		send_time = RS485OCCUPYTIME;	//发送占用时间
	}
	
	if(send_time == RS485OCCUPYTIME)	//如果发送占用时间
	{
		if(FreshAir_Info.DevSendCnt > BLW_FRESHAIR_MAX_SEND_CNT)	//发送次数大于重发次数
		{
			if(FreshAir_Info.DevOffline != DEV_IS_OFFLINE)	//设备当前不是离线
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"宝来威新风 %d 地址离线！！！",BUS_Public.addr);
				LOG_Device_Online_Record(DEV_RS485_FreshAir, BUS_Public.addr, LogInfo_Device_Offline);	//记录设备离线
			}
			FreshAir_Info.DevOffline = DEV_IS_OFFLINE;	//设备离线
			if(FreshAir_Info.DevOffline != FreshAir_Info.DevOfflineLast)	//当前在线状态不等于上一次在线状态
			{
				FreshAir_Info.DevOfflineLast = FreshAir_Info.DevOffline;	//更新上一次在线状态
				Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_OFFLINE);	//保存设备在线状态到SRAM
			}
		}
		else	//发送次数小于等于重发
		{
			FreshAir_Info.DevSendCnt++;	//发送次数增加
		}
		BLV_Communication_Record(&FreshAir_Info.comm_record, 0x01, 0x00);	//通讯统计
		FreshAir_Info.inquire_tick = SysTick_1ms;	//更新轮询时间戳
		
		BUS_Public.check = 0x00;	//检验清0
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&FreshAir_Info, sizeof(RS485_FreshAir_INFO));	//计算校验
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), dev_addr);	//保存共有数据
		SRAM_DMA_Write_Buff((uint8_t *)&FreshAir_Info, sizeof(RS485_FreshAir_INFO), dev_addr+Dev_Privately);	//保存新风私有数据
	}
	return send_time;
}

/*******************************************************************************
  * @brief      宝来威新风接收处理函数
  * @param  
  *		dev_addr		设备信息地址
  *		data_addr		485数据包地址
  *		DataLen			数据包长度
  * @retval     0-是宝来威新风数据，1-不是宝来威新风数据
  * @attention	None
*******************************************************************************/
uint8_t BLW_FreshAir_Data_Processing(uint32_t dev_addr,uint32_t data_addr,uint16_t len)
{
	uint8_t rec = 0x01, data[BLW_FRESHAIR_RECEIVE_MAX_DATA_LEN];	//返回值（默认不是宝来威新风数据），接收的数据中间变量
	uint16_t crc_value;
	Device_Public_Information_G BUS_Public;	//新风设备共有属性
	RS485_FreshAir_INFO FreshAir_Info;	//新风设备私有属性
	
	SRAM_DMA_Read_Buff(data, len, data_addr);	//读取新风设备的485数据
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), dev_addr);	//读取共有属性
	if((data[0] != 0x55) || ((data[1]) != 0x55) || (data[2] != 0xEE) || (data[3]+0x03 != len) || (data[4] != 0x05) || (BUS_Public.addr != data[5]))
	{
		Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"不是新风设备数据！！！");
		return rec;
	}
	crc_value = data[len - 2] + (data[len - 1] << 8);	//保存之前的CRC16校验值
	if(crc_value == NetCRC16_2(&data[3], len - 5))	//与现在的校验比较相同
	{
		rec = 0x00;	//是宝来威新风数据
		SRAM_DMA_Read_Buff((uint8_t *)&FreshAir_Info,sizeof(RS485_FreshAir_INFO), dev_addr+Dev_Privately);	//读取私有属性
		if(FreshAir_Info.DevOffline != DEV_IS_ONLINE)
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"宝来威新风 %d 地址在线",BUS_Public.addr);
			LOG_Device_Online_Record(DEV_RS485_FreshAir, BUS_Public.addr, LogInfo_Device_Online);	//记录设备在线
		}
		FreshAir_Info.DevSendCnt = 0x00;	//计数清0
		FreshAir_Info.DevOffline = DEV_IS_ONLINE;	//轮询回复，设备在线
		if(FreshAir_Info.DevOffline != FreshAir_Info.DevOfflineLast)	//当前在线状态不等于上一次在线状态
		{
			FreshAir_Info.DevOfflineLast = FreshAir_Info.DevOffline;	//更新上一次在线状态
			Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_ONLINE);	//保存设备在线状态到SRAM
		}
		BLV_Communication_Record(&FreshAir_Info.comm_record,0x02,0x01);	//记录通讯成功
		switch(data[3])	//根据数据长度进行区分
		{
			case 0x15:	//轮询命令（读取新风数据）
				BLW_FreshAir_Change_Data(&FreshAir_Info, &data[0]);	//新风数据变化处理
				break;
			case 0x07:	//设置新风命令回复
				if(data[7] == 0x01)	//命令回复正确，才判断内容，进行清除控制
				{
					switch(data[6])	//针对设置功能回复
					{
						case FRESHAIR_ON_OFF_FUNCTION:	//开关机功能
							Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"宝来威新风 %d 地址设备收到开关机回复，清开关机控制标志", BUS_Public.addr);
							FreshAir_Info.ctrl_flag.on_off = 0x00;	//控制开关机清0
							FreshAir_Info.new_state.on_off = FreshAir_Info.ctrl_content.on_off;	//收到回复，当前开关机状态保存
							break;
						case FRESHAIR_WIND_VELOCITY_FUNCTION:	//风速功能
							Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"宝来威新风 %d 地址设备收到设置风速回复，清设置风速控制标志", BUS_Public.addr);
							FreshAir_Info.ctrl_flag.wind_velocity = 0x00;	//控制风速清0
							FreshAir_Info.new_state.wind_velocity = FreshAir_Info.ctrl_content.wind_velocity;	//收到回复，当前风速状态保存
							break;
					}
				}
				break;
		}
		BUS_Public.check = 0x00;	//检验清0
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&FreshAir_Info, sizeof(RS485_FreshAir_INFO));	//计算校验
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), dev_addr);	//保存共有数据
		SRAM_DMA_Write_Buff((uint8_t *)&FreshAir_Info, sizeof(RS485_FreshAir_INFO), dev_addr+Dev_Privately);	//保存新风私有数据
	}
	return rec;
}

/*******************************************************************************
  * @brief      宝来威新风控制函数
  * @param  
  *		BUS_Public		设备共有属性指针
  *		function		功能控制
  *		control			控制内容
  * @retval     None
  * @attention	None
*******************************************************************************/
void BLW_FreshAir_Control(Device_Public_Information_G *BUS_Public,uint8_t function,uint8_t control)
{
	uint8_t data[10] = {0x55, 0x55, 0xEE, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00};	//要发送的数据
	
	data[5] = BUS_Public->addr;	//设备地址赋值
	switch(function)	//判断命令
	{
		case FRESHAIR_ON_OFF_FUNCTION:	//开关机
			data[6] = FRESHAIR_ON_OFF_FUNCTION;
			data[7] = control;
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"发送宝来威新风设置开关机，地址：%d 状态：%d",BUS_Public->addr,control);
			break;
		case FRESHAIR_WIND_VELOCITY_FUNCTION:	//设置风速
			data[6] = FRESHAIR_WIND_VELOCITY_FUNCTION;
			data[7] = control;
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"发送宝来威新风设置风速，地址：%d 状态：%d",BUS_Public->addr,control);
			break;
	}
	NetCRC16(&data[3], 7);
	MCU485_SendString(BUS_Public->port, data, 10);	//使用485发送
	LOG_Device_COMM_Send_Control_Record(BUS_Public->port, BUS_Public->baud, data, 10);	//日志记录
}

/*******************************************************************************
  * @brief      宝来威新风轮询命令函数
  * @param  
  *		BUS_Public		设备共有属性指针
  *		FreshAir_Info	485新风设备私有属性指针
  * @retval     None
  * @attention	None
*******************************************************************************/
void BLW_FreshAir_Poll_Order(Device_Public_Information_G *BUS_Public)
{
	uint8_t data[9] = {0x55, 0x55, 0xEE, 0x06, 0x05, 0x00, 0x0A, 0x00, 0x00};	//要发送的数据
	
	data[5] = BUS_Public->addr;	//设备地址赋值
	NetCRC16(&data[3], 6);
	MCU485_SendString(BUS_Public->port, data, 9);	//使用485发送
}

/*******************************************************************************
  * @brief      宝来威新风数据变化函数
  * @param  
  *		FreshAir_Info	485新风设备私有属性指针
  *		data			接收数据指针
  * @retval     0 - 数据没变化
				1 - 数据有变化
  * @attention	None
*******************************************************************************/
void BLW_FreshAir_Change_Data(RS485_FreshAir_INFO *FreshAir_Info,uint8_t *data)
{
	FreshAir_Info->new_state.on_off = data[7];	//收到回复，当前开关机状态保存
	FreshAir_Info->new_state.wind_velocity = data[13];	//收到回复，当前风速状态保存
	if(FreshAir_Info->ctrl_content.on_off != FreshAir_Info->ctrl_content_last.on_off)	//开关控制状态同步
	{
		FreshAir_Info->ctrl_content_last.on_off = FreshAir_Info->ctrl_content.on_off;
	}
	if(FreshAir_Info->ctrl_content.wind_velocity != FreshAir_Info->ctrl_content_last.wind_velocity)	//风速控制状态同步
	{
		FreshAir_Info->ctrl_content_last.wind_velocity = FreshAir_Info->ctrl_content.wind_velocity;
	}
}
