#include "includes.h"


/*两字节CRC校验
*len包括校验的长度
*/
void NetCRC16_Check(U8_T *aStr ,U16_T len)
{
	U16_T alen = len-2;   //CRC16???????
	U16_T xda , xdapoly ; //校验后的结果，多项式
	U16_T i,j, xdabit ;  //缓存变量
	
	if(len < 3)        //长度小于3
	{
		return ;         //直接返回
	}
	xda = 0xFFFF ;
	xdapoly = 0xA001 ;	// (X**16 + X**15 + X**2 + 1)
	for(i=0;i<alen;i++) 
	{
		xda ^= aStr[i] ;
		for(j=0;j<8;j++) 
		{
			xdabit = (U8_T)(xda & 0x01) ;
			xda >>= 1 ;
			if( xdabit ) xda ^= xdapoly ;
		}
	}    
	aStr[alen] = (U8_T)(xda & 0xFF) ;
	aStr[alen+1] = (U8_T)(xda>>8) ;
}



/** @name CRC16校验得到
*   @para
*      aStr   数组首地址
*      len    数组长度，不包括校验
*/
U16_T GetCRC16( U8_T *aStr , U16_T len)
{
    U16_T xda , xdapoly ;
    U16_T i, j, xdabit ;
    xda = 0xFFFF ;
    xdapoly = 0xA001 ;  // (X**16 + X**15 + X**2 + 1)
    for (i = 0; i < len; i++)
    {
        xda ^= aStr[i] ;
        for (j = 0; j < 8; j++)
        {
            xdabit = (unsigned char)(xda & 0x01) ;
            xda >>= 1 ;
            if ( xdabit ) xda ^= xdapoly ;
        }
    }
	
    return xda;
}

/*和校验*/
U8_T SOR_CRC(U8_T *Data, U8_T DataLen)
{
	U8_T i;
	U8_T sor_data = 0;
	
	for(i = 0; i < DataLen; i++)//i可能为0 ，也可以是1
	{
		sor_data = sor_data+Data[i];
	}
	return sor_data;
}

/*主动回复组包报文*/
void Rs485_ASend(U32_T valtim)
{
	if(g_eeprom.dev_port != ACTIVE_PORT) return;	
	
	U8_T SendData[24];      //24个字节
	SendData[0] = 0x55;
	SendData[1] = 0x55;
	SendData[2] = 0xee;
	SendData[3] = 0x15;
	
	SendData[4] = 0x03;    //类型
	SendData[5] = g_Dip.DIP_addr;                           
	
	SendData[6] = 0x00;    //Func0    温控器高字节，通常为0
	SendData[7] = TempCtrl.TemState_Now.on_off;    //Func1    温控器低字节，0关 1开
	SendData[8] = 0x00;    //Func2    模式高字节  通常为0
	if (TempCtrl.TemState_Now.mode == MODEL_COLD) {
		SendData[9] = 0x01;    //Func3    模式低字节  1制冷 2制热 3通风
	}else if (TempCtrl.TemState_Now.mode == MODEL_HOT) {
		SendData[9] = 0x02;    //Func3    模式低字节  1制冷 2制热 3通风
	}else if (TempCtrl.TemState_Now.mode == MODEL_WIND) {
		SendData[9] = 0x03;    //Func3    模式低字节  1制冷 2制热 3通风
	}
	
	SendData[10] = TEMTEMPCONVER(TempCtrl.TemState_Now.set_t);   //Func4    设定温度值高字节  整数值
	SendData[11] = 0x00;   //Func5    设定温度值低字节  小数值 ，没有就给0
	SendData[12] = 0x04 - TempCtrl.TemState_Now.fan;   //Func6    风速高字节        为0	
	switch(TempCtrl.TemState_Now.fan)
	{
		case FAN_LOW:   //低速
			SendData[13] = 0x03;
			break;
		case FAN_MID:
			SendData[13] = 0x02;
			break;
		case FAN_HIGH:
			//SendData[13] = 0x04 - TempCtrl.TemState_Now.fan;   //Func7    温控器风速低字节：1 高速，2 中速，3 低速，0 自动,4 停
			SendData[13] = 0x01;
			break;
		case FAN_AUTO:
			SendData[13] = 0x00;         //
			break;
		default:
			SendData[13] = 0x04;         //
			break;
	}
	SendData[14] = 0x00;   //Func8    温控器机器型号高字节
	SendData[15] = 0x00;   //Func9    温控器机器型号低字节
	SendData[16] = TempCtrl.TemState_Now.valve<<3;   //Func10   第3位作为阀开阀关标志位
	SendData[17] = 0x00;   //Func11   备用字节1
	SendData[18] = 0x00;   //Func12   备用字节2
	SendData[19] = 0x00;   //Func13   备用字节3
	SendData[20] = TEMTEMPCONVER(TempCtrl.TemState_Now.indoor_t);   //Func14   室内温度整数值
	SendData[21] = 0x00;   //Func15   室内温度小数值
	
	NetCRC16_Check(&SendData[0+3], SendData[0+3]);    //校验
	
	Set_GroupSend(SendData,24,BUSSend_Cnt,valtim,300);
	
}


/*轮询回复报文*/
void Rs485AskCycleSend(void)
{
	U8_T SendData[24];      //24个字节
	SendData[0] = 0x55;
	SendData[1] = 0x55;
	SendData[2] = 0xee;
	SendData[3] = 0x15;
	
	SendData[4] = 0x03;    			//类型
	SendData[5] = g_Dip.DIP_addr;                           
	
	SendData[6] = 0x00;    			//Func0    温控器高字节，通常为0
	SendData[7] = TempCtrl.TemState_Now.on_off;    				//Func1    温控器低字节，0关 1开
	
	SendData[8] = 0x00;    			//Func2    模式高字节  通常为0
	if (TempCtrl.TemState_Now.mode == MODEL_COLD) {				//Func3    模式低字节  1制冷 2制热 3通风
		SendData[9] = 0x01;			
	}else if (TempCtrl.TemState_Now.mode == MODEL_HOT) {
		SendData[9] = 0x02;		
	}else if (TempCtrl.TemState_Now.mode == MODEL_WIND) {
		SendData[9] = 0x03; 
	}
	
	SendData[10] = TEMTEMPCONVER(TempCtrl.TemState_Now.set_t);   //Func4    设定温度值高字节  整数值
	SendData[11] = 0x00;			//Func5    设定温度值低字节  小数值 ，没有就给0
	
	SendData[12] = 0x04 - TempCtrl.TemState_Now.fan; 			//Func6    风速高字节        为0	
	switch(TempCtrl.TemState_Now.fan)
	{
		case FAN_LOW:   //低速
			SendData[13] = 0x03;	//Func7    温控器风速低字节：1 高速，2 中速，3 低速，0 自动,4 停
			break;
		case FAN_MID:
			SendData[13] = 0x02;
			break;
		case FAN_HIGH: 
			SendData[13] = 0x01;
			break;
		case FAN_AUTO:
			SendData[13] = 0x00;         //
			break;
		default:
			SendData[13] = 0x04;         //
			break;
	}
	
	SendData[14] = 0x00;   		//Func8    温控器机器型号高字节
	SendData[15] = 0x00;   		//Func9    温控器机器型号低字节
	
	SendData[16] = TempCtrl.TemState_Now.valve<<3;   //Func10   第3位作为阀开阀关标志位
	SendData[17] = 0x00;   		//Func11   备用字节1
	SendData[18] = 0x00;   		//Func12   备用字节2
	SendData[19] = 0x00;   		//Func13   备用字节3
	
	SendData[20] = TEMTEMPCONVER(TempCtrl.TemState_Now.indoor_t);   //Func14   室内温度整数值
	SendData[21] = 0x00;   		//Func15   室内温度小数值
	
	NetCRC16_Check(&SendData[0+3], SendData[0+3]);    		//校验

	Set_GroupSend(SendData,24,1,BUSSend_ValidTime3,20);		//组包
	
}


/*控制回复报文*/
void Rs485AskCtrlSend(U8_T* Recdata)
{
	U8_T SendData[10];
	
	SendData[0] = 0x55;
	SendData[1] = 0x55;
	SendData[2] = 0xee;  //头
	
	SendData[3] = 0x07;  //长度
	SendData[4] = 0x03;  //类型
	SendData[5] = g_Dip.DIP_addr;  
	SendData[6] = Recdata[6];//Rs485Tem.AskModeState;  //类型
	SendData[7] = Recdata[7];//0x01;  //内容
	
	NetCRC16_Check(&SendData[0+3], SendData[0+3]);    //校验

	Set_GroupSend(SendData,10,1,BUSSend_ValidTime3,20);	//组包
	
}


/*控制回复报文cmd:0x10*/
void Rs485AskReadSend(U8_T* Recdata)
{
	U8_T SendData[11];
	
	SendData[0] = 0x55;
	SendData[1] = 0x55;
	SendData[2] = 0xee;  //头
	
	SendData[3] = 0x09;  //长度
	SendData[4] = 0x03;  //类型
	SendData[5] = g_Dip.DIP_addr; 
	SendData[6] = Recdata[6];
	SendData[7] = Project_FW_Version;
	SendData[8] = Project_HW_Version;
	SendData[9] = g_eeprom.dev_port;	//所处RCU端口  2024-12-16
	
	NetCRC16_Check(&SendData[0+3], SendData[0+3]);    //校验
	
	Set_GroupSend(SendData,12,1,BUSSend_ValidTime3,20);	//组包
}

/*设置端口回复报文cmd:0x12*/
void Rs485_DevPort_ACK(U8_T* Recdata,U8_T Lens)
{
	Set_GroupSend(Recdata,Lens,1,BUSSend_ValidTime3,20);	//组包
}

U8_T Temp_Rec_Analysis(U8_T *RecData, U16_T Len)
{
	U8_T ret = 0;
	U16_T Crc_buf;   //正确报文校验保存
	
	if((0x09 != Len) && (0x0A != Len))
	{
		return 0x01;
	}

	if((0x55 != RecData[0]) || (0x55 != RecData[1])|| (0xee != RecData[2]) )
	{
		return 0x02;
	}
	if( (RecData[3] + 3 != Len) || (Tem_Type != RecData[4]) || (g_Dip.DIP_addr != RecData[5]) )
	{
		return 0x03;
	}
	
	Crc_buf = GetCRC16(&RecData[3], RecData[3]-2);
	if(Crc_buf == (RecData[Len-2]+(RecData[Len-1]<<8)))   //校验通过
	{
		switch(RecData[6])
		{
			case 0x0A:
				if(g_eeprom.dev_port == ACTIVE_PORT)
				{
					Clear_SendFlag();
				}
				else if(g_eeprom.dev_port == POLLING_PORT)
				{
					Rs485AskCycleSend();
				}
				break; //轮询温控器
			case 0x01:     //开关机
			case 0x02:    //模式
			case 0x03:    //温度
			case 0x04:    //风速
				Rs485AskCtrlSend(RecData);
				break;
			case 0x10:
				Rs485AskReadSend(RecData);     //版本号查询
				
				break;
			case 0x11:                         //设置插卡状态同步功能开启/关闭
				Rs485AskCtrlSend(RecData);
				Dbg_Println(DBG_BIT_SYS_STATUS,"Card_EN Set:%d",TempCtrl.CardEn);
				if(TempCtrl.CardEn != RecData[7])   //00:关闭    01：开启
				{
					TempCtrl.CardEn = RecData[7];
					if(TempCtrl.CardEn == 0x00)
					{
						TempCtrl.CardState = 0x01;
					}
				}
				break;
			case 0x12:    //设置端口        2024-12-16
				if(RecData[7] != g_eeprom.dev_port)
				{
					U8_T rev_val = 0;
					
					g_eeprom.dev_port = RecData[7];
					EEPROM_WriteParaInfo(&g_eeprom);
					
					rev_val = EEPROM_ReadParaInfo(&g_eeprom);
					if(rev_val == 0x00){
						//写入数据成功
						Rs485_DevPort_ACK(RecData,Len);
					}

				}
				break;
		}
		
		
		switch(RecData[6])      
		{
			case 0x01:     //开关机命令								
				switch(RecData[7])     
				{
					case 0x00: 
						TempCtrl.TemState_Now.on_off = TEMP_OFF;     //关机
						break;      
					case 0x01: 
						TempCtrl.TemState_Now.on_off = TEMP_ON;      //开机
						break;      
					default:   
						break;         //报文有误
				}
				break;  
			case 0x02:             //模式命令
				switch(RecData[7])          //
				{	
					case 0x01: 
						TempCtrl.TemState_Now.mode = MODEL_COLD;     //制冷
						break;
					case 0x02: 
						TempCtrl.TemState_Now.mode = MODEL_HOT;      //制热
						break; 
					case 0x03: 
						TempCtrl.TemState_Now.mode = MODEL_WIND;     //送风
						break;       
					default:
						break;
				}
				break;
			case 0x03:             //设置温度命令
				if((TEM_MIN_SET <= RecData[7]) && (RecData[7] < TEM_MAX_SET))  //在指定温度范围内
				{
					TempCtrl.TemState_Now.set_t = (RecData[7]&0x1f);  
				}else if(RecData[7] == TEM_MAX_SET){
					TempCtrl.TemState_Now.set_t = (RecData[7]&0x20);
				}
				break;
			case 0x04:             //风速
				switch(RecData[7])                 //风速
				{		
					case 0x00:  
						TempCtrl.TemState_Now.fan = FAN_AUTO;      //自动风
						break;
					case 0x01:  
						TempCtrl.TemState_Now.fan = FAN_HIGH;      //高风速
						break;
					case 0x02:  
						TempCtrl.TemState_Now.fan = FAN_MID;       //中风速
						break;
					case 0x03:  
						TempCtrl.TemState_Now.fan = FAN_LOW;       //低风速
						break;				
					default:
						TempCtrl.TemState_Now.fan = FAN_LOW;       //低风速
						break;			
				}
				break;
		}
		
		return ret;
		
	}
	else
	{
		return ret = 0x01;
	}
}

/**************************************************************************
 * 函数名：Tem_Rs485_Rec_Pro
 * 描述  ：温控器接收处理函数
 * 输入  ：
 *   RecData   接收数据
 *   Len       数据长度
 * 输出  ：无
 * 调用  ：无
 *************************************************************************/
U8_T Tem_Rs485_Rec_Pro(U8_T *RecData, U16_T Len)
{
	U8_T ret = 0x00;
	if(Temp_Rec_Analysis(RecData,Len) != 0x00)      
	{
		if (Len < 5){         //长度校验 
			return ret = 1;
		}
		
		if(RecData[0] != 0xFF && RecData[1] != 0x08)          
		{
			return ret = 1;
		}
		
		Dbg_Println(DBG_BIT_SYS_STATUS,"Tem_Rs485_Rec_Pro");
		
		if(Len == 0x05 && RecData[4]==SOR_CRC(RecData,4))           //长度为5的旧版协议广播数据
		{
			if(TempCtrl.CardState != RecData[2] && TempCtrl.CardEn == 0x01)    //启用了插卡状态功能
			{
				TempCtrl.CardState = RecData[2];
				TempCtrl.CardFlag = 0x01;
			}
		}
		else if((Len >= 0x0A) && (GetCRC16(RecData, (Len-2)) == (RecData[Len-2]+(RecData[Len-1]<<8))))   //长度不固定的新版协议广播数据
		{
			if(TempCtrl.CardState != RecData[3] && TempCtrl.CardEn == 0x01)    //启用了插卡状态功能      2024-04-17  修正判断条件1错误导致定期亮屏问题
			{
				TempCtrl.CardState = RecData[3];
				TempCtrl.CardFlag = 0x01;
			}
			
			if(TempCtrl.SceneNo != RecData[7])
			{
				TempCtrl.SceneNo = RecData[7];
				TempCtrl.SceneNoTick = SysTick_1ms;
				TempCtrl.SceneFlag = 0x01;
			}
			
			Dbg_Println(DBG_BIT_SYS_STATUS,"SceneNo:%d",TempCtrl.SceneNo);
		}
		else 
		{
			return ret = 1;
		}
	}
	
	return ret;
}