
/**
 ******************************************************************************
 * @file      : BLV_485_Dev_ShangJingTianIrSendFun.c
 * @author    : 叶阳文
 * @version   : V01.01.01
 * @date      : 2026-01-05
 * @brief     : 对接 “南京尚景添IRACC中央空调协议转换模块，型号:IRACC-SWG-H” 设备
 * @attention : 主机强电继电器
 *				    输入检测：  无
 *                  输入类型：  无	
 *                  执行函数：  有	
 *            		执行方式：
 *								空调控制 
 * @note      : 1、设备地址为设备拨码地址
 *              2、设备控制外机地址由设备地址推算，设备地址*6
 *
 *              操作流程：1、读温控状态
 *                        2、对比
 *                        3、下发温控状态
 ******************************************************************************
 */

#include "BLV_485_Dev_ShangJingTianIrSendFun.h"
#include "includes.h"

/*涉及到的外设头文件开始*/
#include "BLV_485_Dev_TempFun.h"
#include "BLV_485_Dev_C7TFun.h"

/*涉及到的外设头文件结束*/
uint8_t SJT_Rs485_IrDis(uint32_t dev_addr);
uint8_t SJT_Rs485_IrCheck(uint32_t dev_addr,uint32_t data_addr,uint16_t len);
void SJT_IrCtrl_State(uint32_t CfgDevAddIn, uint16_t DevInputAddr,uint32_t devaddr,uint16_t DevOutputLoop,uint16_t state);


void RS485_SJTIrSend_Polling_Init(Device_Public_Information_G *BUS_Public, RS485_IR_INFO *RS485IRInfo)
{
	BUS_Public->polling_cf = (uint32_t)&SJT_Rs485_IrDis;
	BUS_Public->processing_cf = (uint32_t)&SJT_Rs485_IrCheck;
    BUS_Public->DevFunInfo.Dev_Output_Ctrl = SJT_IrCtrl_State;
}

void RS485_SJTIrSend_Active_Init(Device_Public_Information_G *BUS_Public, RS485_IR_INFO *RS485IRInfo)
{
	BUS_Public->polling_cf = (uint32_t)&SJT_Rs485_IrDis;
	BUS_Public->processing_cf = (uint32_t)&SJT_Rs485_IrCheck;
    BUS_Public->DevFunInfo.Dev_Output_Ctrl = SJT_IrCtrl_State;
}




/****************************************************************************
* @name         : SJTIR_Rs485_Air_Ctrl
* @Description  : 温控状态控制下发
* @param        :
*           dev_addr : 设备起始地址
* @retval       : 0x00:数据发送成功，0xF0:无数据发送
* @attention    : 一个空调温控状态，占用6个寄存器，12个字节
*******************************************************************************/
void SJTIR_Rs485_Air_Ctrl(uint32_t dev_addr, RS485_IR_INFO *RS485IRInfo)
{
	uint8_t IrSend[20];
	uint8_t port = SRAM_Read_Byte(dev_addr+Dev_port);  
    uint16_t SJT_reg = TEMPREG_START,SJT_RegLen = CTRLTEMPREG;
    uint16_t SJT_temp = 0x00,Send_CRC = 0x00;


    IrSend[0] = SRAM_Read_Byte(dev_addr+Dev_Addr);          //设备地址
    IrSend[1] = WRITEMULTREGCMD;                            //命令字
    IrSend[2] = ((SJT_reg >> 8)&0xFF);                      //控制的寄存器地址的高位
    IrSend[3] = (SJT_reg & 0xFF);                           //控制的寄存器地址的低位
    IrSend[4] = ((SJT_RegLen >> 8)&0xFF);                    //控制的寄存器数量的高位
    IrSend[5] = (SJT_RegLen & 0xFF);                         //控制的寄存器数量的低位
    IrSend[6] = 0x06;                                       //下发的数据字节数，一个寄存器2字节
    
    //RCU风速0:停止，10：低，30：中，50：高, 0xFF：不控制
    if(RS485IRInfo->AirInfo[3] == 0){   
        IrSend[7] = 0x10;
    }else if(RS485IRInfo->AirInfo[3] == 1){   
        IrSend[7] = 0x10;
    }else if(RS485IRInfo->AirInfo[3] == 2){   
        IrSend[7] = 0x30;
    }else if(RS485IRInfo->AirInfo[3] == 3){   
        IrSend[7] = 0x50;
    }else {
        IrSend[7] = 0xFF;
    } 
    
    //开关机状态，60：关，61：开，FF：不控制
    if(RS485IRInfo->AirInfo[0] == 0x00){
        IrSend[8] = 0x60;
    }else if(RS485IRInfo->AirInfo[0] == 0x01){
        IrSend[8] = 0x61;
    }else{
        IrSend[8] = 0xFF;
    }
    
    //空调模式，00 02：制冷， 00 01：制热， 00 00：通风
    IrSend[9] = 0x00;
    if(RS485IRInfo->AirInfo[1] == 0x00){
        IrSend[10] = 0x02;
    }else if(RS485IRInfo->AirInfo[1] == 0x01){
        IrSend[10] = 0x01;
    }else if(RS485IRInfo->AirInfo[1] == 0x02){
        IrSend[10] = 0x00;
    }else{
        IrSend[10] = 0x00;
    }    
    
    //设置温度，160-320
    if(RS485IRInfo->AirInfo[2] < SJTTEM_MIN_SET){
        SJT_temp = (SJTTEM_MIN_SET*10);
    }else if(RS485IRInfo->AirInfo[2] > SJTTEM_MAX_SET){
        SJT_temp = (SJTTEM_MAX_SET*10);
    }else{
        SJT_temp = RS485IRInfo->AirInfo[2]*10;
    }
    IrSend[11] = ((SJT_temp >> 8)&0xFF); 
    IrSend[12] = (SJT_temp & 0xFF);

    
    Send_CRC = NetCRC16_2(IrSend,13);
    IrSend[13] = (Send_CRC & 0xFF);    
    IrSend[14] = ((Send_CRC >> 8)&0xFF); 	
	
	/*发送数据*/
	MCU485_SendString(port,IrSend,15);
	
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record2(dev_addr+Dev_port,dev_addr+Dev_baud,IrSend,15);    
    
}




/****************************************************************************
* @name         : SJT_Rs485_IrDis
* @Description  : 南京尚景添IRACC中央空调协议转换模块轮询控制函数
* @param        :
*           dev_addr : 设备485红外转发起始地址
* @retval       : 0x00:数据发送成功，0xF0:无数据发送
* @attention    : 一个设备只绑定一个空调内机
*******************************************************************************/
uint8_t SJT_Rs485_IrDis(uint32_t dev_addr)
{
	uint8_t i;    
	uint8_t Ret = RS485OCCUPYNOTIME;
	Device_Public_Information_G BUS_Public;	
	RS485_IR_INFO RS485IRInfo;       //红外局部变量

	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);		
	SRAM_DMA_Read_Buff((uint8_t *)&RS485IRInfo,sizeof(RS485_IR_INFO),dev_addr+Dev_Privately);    
    
	for(i = 0; i < 4; i++)
	{
		if(RS485IRInfo.AirInfoLast[i] != RS485IRInfo.AirInfo[i])
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"SJT,空调参数变化");
			RS485IRInfo.IrCtrlAirFlag = 0x01;
			RS485IRInfo.IrCtrlAirCnt = SJT_IRCtrlSendMax;

			if((0x00 == i)&&(0x01 == RS485IRInfo.AirInfo[i]))   //由关到开
			{
				RS485IRInfo.AirOpenFlag = 0x00;                 //置标志位 当接收到红外转发的回复后，还有一次控制的机会   //20250811 关闭此功能测试 李世杰
			}
			memcpy(RS485IRInfo.AirInfoLast, RS485IRInfo.AirInfo, 4);
			break;
		}
	}

	if(0x01 == RS485IRInfo.IrCtrlAirFlag)
	{
		if(0x00 != RS485IRInfo.IrCtrlAirCnt)
		{
			RS485IRInfo.IrCtrlAirCnt--; 
		}
		else
		{
			RS485IRInfo.AirOpenFlag = 0x00;   //本次控制结束，就清特殊标志
			RS485IRInfo.IrCtrlAirFlag = 0x00;
		}

        Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"尚景添空调网关转发控制发送，SendCnt:%d",RS485IRInfo.IrCtrlAirCnt);		
		SJTIR_Rs485_Air_Ctrl(dev_addr, &RS485IRInfo);
		
		/*通讯统计记录*/
		BLV_Communication_Record(&RS485IRInfo.comm_record,0x01,0x00);
		Ret = RS485OCCUPYTIME;
	}
    
    
	if(RS485OCCUPYTIME == Ret)
	{
		if(RS485IRInfo.DevSendCnt > SJT_IRCtrlSendMax)
		{
			if(RS485IRInfo.DevOffline != DEV_IS_OFFLINE)
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Dev_SJTIRSend LogInfo_Device_Offline...........");
				LOG_Device_Online_Record(DEV_IRTYPE,BUS_Public.addr,LogInfo_Device_Offline);	//记录设备离线SRAM_Read_Byte(dev_addr+Dev_Addr)
			}
			RS485IRInfo.DevOffline = DEV_IS_OFFLINE;   //离线
			if(RS485IRInfo.DevOffline != RS485IRInfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
			{
				RS485IRInfo.DevOfflineLast = RS485IRInfo.DevOffline;	//更新上一次在线状态
				Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_OFFLINE);	//保存设备在线状态到SRAM
			}
		}
		else
		{
			RS485IRInfo.DevSendCnt++;
		}
		
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&RS485IRInfo, sizeof(RS485_IR_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&RS485IRInfo,sizeof(RS485_IR_INFO),dev_addr+Dev_Privately);
	}    
    
    return Ret;
}





/********************************************************************************
* @name         : SJT_Rs485_IrCheck
* @Description  : 南京尚景添IRACC中央空调协议转换模块接收处理函数
* @param        :
*           dev_addr : 设备信息地址,  data_addr : 数据地址,  len : 数据长度
* @retval       : 0x00:处理成功,0x01:处理失败
* @attention    : 一个设备只绑定一个空调内机
**********************************************************************************/
uint8_t SJT_Rs485_IrCheck(uint32_t dev_addr,uint32_t data_addr,uint16_t len)
{
	if( (len > RECVDATA_LEN_MAX)||(len < RECVDATA_LEN_MIN) )
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"SJT_IRSend RecvLen Fail!");
		return 0x01;
	}    
    
    /*当前只处理设置寄存器命令的回复*/
	if(0x08 != len)	
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"尚景添空调网关数据长度不对: %d ",len);
		return 0x02;
	}    
    
    
	uint8_t data[RECVDATA_LEN_MAX];    
	uint8_t rev = 0x01;  
	uint16_t crc_val = 0x00; 
	uint16_t temp = 0x00;    
 	Device_Public_Information_G BUS_Public;
	RS485_IR_INFO RS485IRInfo;       //红外局部变量
	
    
	memset(data,0x00,RECVDATA_LEN_MAX);
	SRAM_DMA_Read_Buff(data,len,data_addr);
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);		
	
	
	if(data[0] != BUS_Public.addr)	
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"尚景添空调网关地址不对: %d!!",data[0]);
		return 0x03;
	}

	crc_val = data[len-2] + (data[len-1]<<8);
	if(crc_val == NetCRC16_2(data,len-2))
	{
		rev = 0x00;
        Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"尚景添空调网关CRC校验成功,CMD: %02x",data[1]);   
        
		SRAM_DMA_Read_Buff((uint8_t *)&RS485IRInfo,sizeof(RS485_IR_INFO),dev_addr+Dev_Privately);
		
		if(RS485IRInfo.DevOffline == DEV_IS_OFFLINE)
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Dev_SJTIrSend LogInfo_Device_Online...........");
			LOG_Device_Online_Record(DEV_SWI_TYPE,BUS_Public.addr,LogInfo_Device_Online);                   //记录设备在线
		}
		
		BLV_Communication_Record(&RS485IRInfo.comm_record,0x02,0x01);       //记录通讯成功
		RS485IRInfo.DevSendCnt = 0x00;
		RS485IRInfo.DevOffline = DEV_IS_ONLINE; //设备在线
		if(RS485IRInfo.DevOffline != RS485IRInfo.DevOfflineLast)            //当前在线状态不等于上一次在线状态
		{
			RS485IRInfo.DevOfflineLast = RS485IRInfo.DevOffline;            //更新上一次在线状态
			Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_ONLINE);    //保存设备在线状态到SRAM
		}
        
		switch(data[1]) //南京尚景添IRACC中央空调协议转换模块命令字
		{
			case READREGCMD:        //读寄存器
            
 				/*日志记录*/
				LOG_Device_COMM_Control_Reply_Record(BUS_Public.port, BUS_Public.baud,data,len);
                break;           
			case WRITEONLYREGCMD:   //写单个寄存器
			
				/*日志记录*/
				LOG_Device_COMM_Control_Reply_Record(BUS_Public.port, BUS_Public.baud,data,len);
                break;
			case WRITEMULTREGCMD:   //写多个寄存器
                temp = (data[2]<<8) + (data[3]);
                Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"尚景添空调网关控制回复，Reg: %04X",temp);
            
                if(temp == TEMPREG_START)
                {
                    if(0x01 == RS485IRInfo.AirOpenFlag)   //
                    {
                        RS485IRInfo.AirOpenFlag = 0x00;
                        //RS485IRInfo.IrCtrlAirFlag = 0x01;         //以当前的空调数据参数加多一次控制
                    }
                    else
                    {
                        RS485IRInfo.IrCtrlAirFlag = 0x00;
                    }                    
                }
            
				/*日志记录*/
				LOG_Device_COMM_Control_Reply_Record(BUS_Public.port, BUS_Public.baud,data,len);
				break;
            default:
                break;
		}	

		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&RS485IRInfo, sizeof(RS485_IR_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&RS485IRInfo,sizeof(RS485_IR_INFO),dev_addr+Dev_Privately);
	}else{
        Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"尚景添空调网关CRC错误: %04x",crc_val);
        
    }
    
    return rev;
}


/*******************************************************************************
* @FunctionName : Ir_Control_State 
* @Description  : 南京尚景添IRACC中央空调协议转换模块状态控制函数
* @Input        : DevaddrIn : 触发设备,  devaddr : 设备信息地址,  state : 控制内容
* @Retval       : 无
* @nota         : 只有温控器
*******************************************************************************/
void SJT_IrCtrl_State(uint32_t CfgDevAddIn, uint16_t DevInputAddr,uint32_t devaddr,uint16_t DevOutputLoop,uint16_t state)
{
    uint8_t rev = 0x00;
    
	Device_Public_Information_G BUS_Public;	
	RS485_IR_INFO RS485IRInfo;
	
	if(devaddr == 0x00)	return;
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),devaddr);		
	SRAM_DMA_Read_Buff((uint8_t *)&RS485IRInfo,sizeof(RS485_IR_INFO),devaddr+Dev_Privately);
	
	Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"RS485IRInfo.AirInfo start:", RS485IRInfo.AirInfo, 4);
	
	if((NULL != CfgDevAddIn) && (DEV_RS485_TEMP == SRAM_Read_Byte(CfgDevAddIn+Dev_Type)))   //温控器触发
	{
		RS485_TEMP_INFO Rs485Tem;
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"温控器控制尚景添空调网关转发");
		SRAM_DMA_Read_Buff((uint8_t *)&Rs485Tem,sizeof(RS485_TEMP_INFO),CfgDevAddIn+Dev_Privately);
		
		switch(Rs485Tem.TemState.on_off)
		{
			case 0x01: RS485IRInfo.AirInfo[0] = 0x01; break;        //1开
			case 0x00: RS485IRInfo.AirInfo[0] = 0x00; break;        //0关
            default: break;
		}
		
		switch(Rs485Tem.TemState.mode)
		{
			case TEMP_COLD: RS485IRInfo.AirInfo[1] = 0; break;      //制冷
			case TEMP_HOT:  RS485IRInfo.AirInfo[1] = 1; break;      //制热
			case TEMP_WIND: RS485IRInfo.AirInfo[1] = 2; break;      //送风
            default: break;
		}
        
        // RS485IRInfo.AirInfo[2] = Rs485Tem.TemState.set_t;
		if(Rs485Tem.TemState.set_t==0){                             //设置温度
			Rs485Tem.TemState.set_t=31;
			RS485IRInfo.AirInfo[2] = Rs485Tem.TemState.set_t+1;
		}else{
            RS485IRInfo.AirInfo[2] = Rs485Tem.TemState.set_t;
        }
		
		if(TEMP_FANAUTO == Rs485Tem.TemState.fan){                  //风速自动
			RS485IRInfo.AirInfo[3] = 2;   //中速
		}else{       //其他情况
			RS485IRInfo.AirInfo[3] = Rs485Tem.TemState.fan;         //风速
		}
        
        rev = 0x01;
	}

	Dbg_Print_Buff(DBG_BIT_DEVICE_STATUS_bit,"RS485IRInfo.AirInfo end:", RS485IRInfo.AirInfo, 4);
	
    
    if(rev != 0x00)
    {
        BUS_Public.check = 0x00;
        BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&RS485IRInfo, sizeof(RS485_IR_INFO));
        SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),devaddr);/*将数据保存*/
        SRAM_DMA_Write_Buff((uint8_t *)&RS485IRInfo,sizeof(RS485_IR_INFO),devaddr+Dev_Privately);
    }

}





