

/**
  ******************************************************************************
  * @file    BLV_485_Dev_SwitchFun.c
  * @author  BLW RCU  development Team
  * @version SongHan
  * @date    2022年03月06日
  * @brief  
	*    485开关总表，所有的开关驱动尽可能放在这张表里面
	*    输入：有
	*    输出：有
	* @log   202205171612     SongHan    增加开关驱动开启关闭标志
  * @log   202205201600     SongHan    唯有主动设备才会	优先处理
  ******************************************************************************
  */


#include "APP_SwitchCtrl.h"

#include <string.h>
#include "BLV_485_Protocol.h"
#include "SPI_SRAM.h"
#include "usart.h"
#include "CH57x_common.h"
#include "check_fun.h"
#include "rw_logging.h"
#include "SRAM_Variable_Address.h"
#include "DBG.h"
#include "Log_api.h"
#include "includes.h"

/*外设驱动列表开始*/
#include "BLV_485_Dev_Touch_SwiFun.h"
#include "BLV_485_Dev_A9IO_SwiFun.h"

/*外设驱动列表结束*/

/*函数指针宏定义*/
typedef void (*DevFunP)(Device_Public_Information_G *BUS_Public, RS485_SWI_INFO *Rs485SwiInfo);	//传递共用数据指针 私有数据指针

/*设备驱动宏定义开始*/
#define RS485_DEV_PRO_FUN_01    DevExistJudgge(RS485_Switch_Touch_Flag, BLV_485_Dev_Touch_Switch_Init) //((DevFunP)NULL)      //T1开关
#define RS485_DEV_PRO_FUN_02    ((DevFunP)NULL) //BLV_485_Dev_Touch_Switch_Init      //C7T开关
#define RS485_DEV_PRO_FUN_03    DevExistJudgge(RS485_Switch_A9IO_Flag, BLV_485_Dev_A9IO_Switch_Init) //((DevFunP)NULL)           //A9IO开关
#define RS485_DEV_PRO_FUN_04    ((DevFunP)NULL)
/*设备驱动宏定义结束*/

uint8_t Dev_Swi_InType_Get(uint32_t DevAddr, uint16_t DevInputLoop, uint16_t DevInputType);
void Dev_Swi_Output_Ctrl(uint32_t CfgDevAddIn, uint16_t DevInputAddr, uint32_t DevAddr, uint16_t DevOutputLoop, uint16_t DevOutputType);
uint16_t Dev_Swi_Loop_State(uint32_t devaddr, uint16_t DevOutputLoop);

#define REPEATSENDTIMEMAX			0x01  	//本设备重发次数上限
#define BLWTOUCHCTRLTIMEOUT			100		//本设备控制超时时间
#define BLWTOUCHASKTIMEOUT			10		//本设备控制回复超时时间


/*******************************************************************************
* @name  :  开关设备驱动总表
* @para  : 
*   DataLen :数据长度
*   Data：   数据数组
* @attention   : 将开关的所有设备参数传进来，
*
*******************************************************************************/

void BLW_RS485_Switch_Init(uint16_t DataLen, uint8_t *Data)
{
	Device_Public_Information_G BUS_Public;
	RS485_SWI_INFO Rs485SwiInfo;       //开关局部变量
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&Rs485SwiInfo,0,sizeof(RS485_SWI_INFO));
	
	BUS_Public.addr = Data[1];			//设备地址
	BUS_Public.type = Data[0];		//设备类型
//	BUS_Public.port = Active_Port;			//设备发送端口
	BUS_Public.baud = 9600;			//设备发送波特率
	BUS_Public.retry_num = 0x00;		//设备数据重发次数
	BUS_Public.wait_time = 100;		//设备数据发送等待回复时间    
//	BUS_Public.polling_cf = (uint32_t)&BLW_Touch_SwitchCycleDis;
//	BUS_Public.processing_cf = (uint32_t)&BLW_Rs485_Touch_Swi_Check;
	
	BUS_Public.DevFunInfo.Dev_Input_Type_Get = Dev_Swi_InType_Get;
	BUS_Public.DevFunInfo.Dev_Output_Ctrl = Dev_Swi_Output_Ctrl;
	BUS_Public.DevFunInfo.Dev_Output_Loop_State_Get = Dev_Swi_Loop_State;
				
	if(Data[8] >= Key_BUFF_Size) Rs485SwiInfo.SwtInputValidNum = Key_BUFF_Size;//初始化开关输入输出数
	else Rs485SwiInfo.SwtInputValidNum = Data[8];
	
	if(Data[10] >= Key_BUFF_Size) Rs485SwiInfo.SwtOutputValidNum = Key_BUFF_Size;//初始化开关输入输出数
	else Rs485SwiInfo.SwtOutputValidNum = Data[10];	
	Rs485SwiInfo.DevOffline = Rs485SwiInfo.DevOfflineLast = DEV_IS_ONLINE;   //在线状态初始化
	switch(Rs485SwiInfo.SwtInputValidNum)
	{
		case 0x06:   //按键数为6
			Rs485SwiInfo.DevSendBuf[6] = 0x01;			//打开背光
			break;
		case 0x05:
			Rs485SwiInfo.DevSendBuf[5] = 0x01;			//打开背光			/*5键开关，6号输出为背光*/
			break;
		case 0x08:   //按键数为8
			Rs485SwiInfo.DevSendBuf[8] = 0x01;			//打开背光			/*8键开关，9号输出为背光*/			
			break;
		case 25:   //按键数为25
			Rs485SwiInfo.DevSendBuf[25] = 0x01;     //打开背光
			break;
	}
	
	switch(Data[7])
	{
		case	 ENUM_RS485_DEV_PRO_01: if(NULL!=RS485_DEV_PRO_FUN_01) RS485_DEV_PRO_FUN_01(&BUS_Public, &Rs485SwiInfo);break; //        
		case	 ENUM_RS485_DEV_PRO_02: if(NULL!=RS485_DEV_PRO_FUN_02) RS485_DEV_PRO_FUN_02(&BUS_Public, &Rs485SwiInfo);break; //          
		case	 ENUM_RS485_DEV_PRO_03: if(NULL!=RS485_DEV_PRO_FUN_03) RS485_DEV_PRO_FUN_03(&BUS_Public, &Rs485SwiInfo);break;                                 //3
		case	 ENUM_RS485_DEV_PRO_04: if(NULL!=RS485_DEV_PRO_FUN_04) RS485_DEV_PRO_FUN_04(&BUS_Public, &Rs485SwiInfo);break;
	}

	switch(Data[2])
	{
		case Active_Port:   //主动端口
			BUS_Public.port = Active_Port;		//设备发送端口
			Add_ACT_Device_To_List2(&BUS_Public,(uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO));
			Act485_Info.device_num += 1;
			break;  
		case Polling_Port:   //轮询端口
			BUS_Public.port = Polling_Port;		//设备发送端口
			Add_POLL_Device_To_List2(&BUS_Public,(uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO));   //将填充后的数据添加到链表
			Poll485_Info.device_num += 1;	
			break;
		case Bus_port:    //总线端口
			break;
	}
}


/*******************************************************************************
* Function Name  : BLW_RS485_Switch_For_Logic_Init 
* Description    : 开关初始化信息来自逻辑文件
*******************************************************************************/
void BLW_RS485_Switch_For_Logic_Init(LOGICFILE_DEVICE_INFO *dev_info,uint8_t *data,uint16_t data_len)
{
	Device_Public_Information_G BUS_Public;
	RS485_SWI_INFO Rs485SwiInfo;       //开关局部变量
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&Rs485SwiInfo,0,sizeof(RS485_SWI_INFO));
	
	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"%s -%d",__func__,dev_info->addr);	
	
	BUS_Public.addr = dev_info->addr;			//设备地址
	BUS_Public.type = dev_info->type;			//设备类型
	BUS_Public.baud = dev_info->baud;				//设备发送波特率
	BUS_Public.retry_num = dev_info->retry;		//设备数据重发次数
	BUS_Public.wait_time = dev_info->writ_time;		//设备数据发送等待回复时间    
//	BUS_Public.polling_cf = (uint32_t)&BLW_Touch_SwitchCycleDis;
//	BUS_Public.processing_cf = (uint32_t)&BLW_Rs485_Touch_Swi_Check;
	Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"增加开关_111:%d,%d",dev_info->retry,dev_info->writ_time);
	BUS_Public.Protocol = dev_info->version;
	
	BUS_Public.DevFunInfo.Dev_Input_Type_Get = Dev_Swi_InType_Get;
	BUS_Public.DevFunInfo.Dev_Output_Ctrl = Dev_Swi_Output_Ctrl;
	BUS_Public.DevFunInfo.Dev_Output_Loop_State_Get = Dev_Swi_Loop_State;
				
	if(dev_info->input_num >= Key_BUFF_Size) Rs485SwiInfo.SwtInputValidNum = Key_BUFF_Size;//初始化开关输入数
	else Rs485SwiInfo.SwtInputValidNum = dev_info->input_num;
	
	if(dev_info->output_num >= Key_BUFF_Size) Rs485SwiInfo.SwtOutputValidNum = Key_BUFF_Size;//初始化开关输出数
	else Rs485SwiInfo.SwtOutputValidNum = dev_info->output_num;	
	Rs485SwiInfo.DevOfflineLast = DEV_IS_ONLINE;   //在线状态初始化
	Rs485SwiInfo.DevOffline = Rs485SwiInfo.DevOfflineLast;
	switch(Rs485SwiInfo.SwtInputValidNum)
	{
		case 0x06:   //按键数为6
			Rs485SwiInfo.DevSendBuf[6] = 0x01;			//打开背光
			break;
		case 0x05:
			Rs485SwiInfo.DevSendBuf[5] = 0x01;			//打开背光			/*5键开关，6号输出为背光*/
			break;
		case 0x08:   //按键数为8
			Rs485SwiInfo.DevSendBuf[8] = 0x01;			//打开背光			/*8键开关，9号输出为背光*/			
			break;
		case 25:   //按键数为25
			Rs485SwiInfo.DevSendBuf[25] = 0x01;     	//打开背光
			break;
	}
	
	switch(BUS_Public.Protocol)
	{
		case	 ENUM_RS485_DEV_PRO_01: if(NULL!=RS485_DEV_PRO_FUN_01) RS485_DEV_PRO_FUN_01(&BUS_Public, &Rs485SwiInfo);break; //        
		case	 ENUM_RS485_DEV_PRO_02: if(NULL!=RS485_DEV_PRO_FUN_02) RS485_DEV_PRO_FUN_02(&BUS_Public, &Rs485SwiInfo);break; //          
		case	 ENUM_RS485_DEV_PRO_03: if(NULL!=RS485_DEV_PRO_FUN_03) RS485_DEV_PRO_FUN_03(&BUS_Public, &Rs485SwiInfo);break;                                 //3
		case	 ENUM_RS485_DEV_PRO_04: if(NULL!=RS485_DEV_PRO_FUN_04) RS485_DEV_PRO_FUN_04(&BUS_Public, &Rs485SwiInfo);break;
	}

	switch(dev_info->port)
	{
		case Active_Port:   //主动端口
			BUS_Public.port = Active_Port;		//设备发送端口
			Add_ACT_Device_To_List2(&BUS_Public,(uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO));
			Act485_Info.device_num += 1;
			break;  
		case Polling_Port:   //轮询端口
			BUS_Public.port = Polling_Port;		//设备发送端口
			Add_POLL_Device_To_List2(&BUS_Public,(uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO));   //将填充后的数据添加到链表
			Poll485_Info.device_num += 1;	
			break;
		case Bus_port:    //总线端口
			break;
	}
}



///**/
//void BLW_Touch_Switch_Feedback(uint32_t devaddr,uint8_t loop,uint8_t start)
//{
////	uint8_t val_check = 0;
////	uint16_t dev_datalen = 0x00;
//	Device_Public_Information_G BUS_Public;	
//	RS485_SWI_INFO Rs485SwiInfo;       //开关局部变量
//	
//	if(devaddr == 0x00) return;
//	
//	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),devaddr);			
//	SRAM_DMA_Read_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),devaddr+Dev_Privately);/*拷贝设备私有信息*/
//	
//	if(loop < Rs485SwiInfo.SwtOutputValidNum)
//	{
//		if(Rs485SwiInfo.DevSendBuf[loop] != start)
//		{
//			Rs485SwiInfo.DevSendBuf[loop] = start;
//			
//			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DevSendBuf loop:%d,start:%d\r\n",loop,start);
//			
//			BUS_Public.check = 0x00;
//			BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485SwiInfo, sizeof(RS485_SWI_INFO));
//			SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),devaddr);/*将数据保存*/
//			SRAM_DMA_Write_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),devaddr+Dev_Privately);
//		
//		}

//	}
//}


/*获取开关在线状态*/
uint8_t Get_Switch_Online_Status(uint32_t devaddr)
{
	RS485_SWI_INFO Rs485SwiInfo;       //开关局部变量
	
	/*拷贝设备私有信息*/
	SRAM_DMA_Read_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),devaddr+Dev_Privately);
	
	if(Rs485SwiInfo.DevOffline == DEV_IS_ONLINE)
	{
		return 0x01;
	}
	return 0x02;
}


/**
*@name 开关输入检测函数
*@para
*  DevAddr      设备地址
*  DevInputLoop 回路输入地址  范围1~RS_SWITCH_CH_MAX  
*  DevInputType 输入类型
*/

uint8_t Dev_Swi_InType_Get(uint32_t DevAddr, uint16_t DevInputLoop, uint16_t DevInputType)
{
	Device_Public_Information_G BUS_Public;   //共用
	RS485_SWI_INFO Rs485SwiInfo;       //开关局部变量
	uint8_t Ret = CtrlInvalid;         //控制无效
//	uint16_t dev_datalen;
//	uint8_t val_check;
	
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAddr);	//拷贝所有共有数据	
	SRAM_DMA_Read_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),DevAddr+Dev_Privately);/*拷贝设备私有信息*/
	
	if(DevInputLoop >= RS_SWITCH_CH_MAX)
	{
		return Ret;
	}
//	if((0x00 == DevInputLoop) || (DevInputLoop > RS_SWITCH_CH_MAX))
//	{
//		return Ret;
//	}
//	DevInputLoop--;  //转换到本地
	
	
	if((Rs485SwiInfo.MultiValidNo[DevInputLoop] > 0) && (Rs485SwiInfo.MultiValidNo[DevInputLoop] < 127))    //当前回路多联有效     2024-05-23
	{
		Rs485SwiInfo.MultiNumber[DevInputLoop]++;
		
		if(Rs485SwiInfo.MultiNumber[DevInputLoop] > Rs485SwiInfo.MultiValidNo[DevInputLoop])    //大于有效联数置零
		{
			Rs485SwiInfo.MultiNumber[DevInputLoop] = 0x01;
		}
	}
	
	if(DevInputType == Rs485SwiInfo.DevReadBuf[DevInputLoop])
	{
		Rs485SwiInfo.DevReadBuf[DevInputLoop] = KeyNoAction;
		
		Ret = CtrlValid|(Rs485SwiInfo.MultiNumber[DevInputLoop]<<1);
		
		if(Ret > 1)
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"%d多联开关 回路:%d 多联下标:%d",BUS_Public.addr,DevInputLoop,Rs485SwiInfo.MultiNumber[DevInputLoop]);
		}
		
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"开关动作清空：%d",Ret);
		
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485SwiInfo, sizeof(RS485_SWI_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAddr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),DevAddr+Dev_Privately);
		
	}
	
	return Ret;
}
/**
	*@name 开关输出控制函数
	*@para
	*  DevAddr      设备地址
	*  DevOutputLoop 回路输出地址  范围0~
	*  DevInputType 输入类型
	*/

void Dev_Swi_Output_Ctrl(uint32_t CfgDevAddIn, uint16_t DevInputAddr, uint32_t DevAddr, uint16_t DevOutputLoop, uint16_t DevOutputType)
{
	uint8_t start = 0x00;
	uint8_t CtrlWay;
//	uint8_t val_check = 0;
//	uint16_t dev_datalen = 0x00;
	Device_Public_Information_G BUS_Public;   //共用	
	RS485_SWI_INFO Rs485SwiInfo;       //开关局部变量
	uint8_t KeepFlag = 0x00;   //保存标志
	
	if(NULL == DevAddr)
	{
		return ;
	}
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAddr);	//拷贝所有共有数据	
	SRAM_DMA_Read_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),DevAddr+Dev_Privately);/*拷贝设备私有信息*/
	
	if(DevOutputLoop >= Rs485SwiInfo.SwtOutputValidNum)
	{
		return ;
	}

//	
	CtrlWay = DevOutputType&0x00ff;   //取低字节

	switch(CtrlWay)  //不为0
	{
		case 0x01:
			start = 0x01;
			if(DevOutputLoop == (Rs485SwiInfo.SwtOutputValidNum - 1))
			{
				DevActionGlobal.SleepMode_State = 0x00;					//退出睡眠模式 2025-09-05
				DevActionGlobal.SleepLight_State = 0x01;			
			}
			break;
		case 0x02:
			start = 0x00;
			if(DevOutputLoop == (Rs485SwiInfo.SwtOutputValidNum - 1))
			{
				DevActionGlobal.SleepMode_State = 0x01;					//进入睡眠模式 2025-09-05
				DevActionGlobal.SleepLight_State = 0x00;	
			}
			break;
		case 0x04:      //取反
			start = Rs485SwiInfo.DevSendBuf[DevOutputLoop];
			if(0x01 == start)
			{
				start = 0x00;
			}
			else
			{
				start = 0x01;
			}	
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"485开关闪烁赋值,start:%d\r\n",start);
			break;
		default: return;   //其他情况直接返回  
			
	}

	
	if(Rs485SwiInfo.DevSendBuf[DevOutputLoop] != start)//
	{
		Rs485SwiInfo.DevSendBuf[DevOutputLoop] = start;
		KeepFlag = 0x01;
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"DevSendBuf loop:%d,start:%d\r\n",DevOutputLoop,start);
	
	}


	if(0x01 == KeepFlag)
	{ 
		if(Active_Port  == BUS_Public.port)
		{
			BLV_Active_Set_List_Addr(DevAddr);    //唯有主动设备优先处理
		}
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485SwiInfo, sizeof(RS485_SWI_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAddr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),DevAddr+Dev_Privately);		
	}
	
//	BLW_Touch_Switch_Feedback(DevAddr, DevOutputLoop, State);
}

/**
  * @name  指定服务信息回路状态得到
  * @param  
  *    devaddr             当前设备的地址
  *    DevOutputLoop       需要查找的服务信息回路
  * @retval 
  *    ret                 回路状态返回    1 开   2关   0为不存在
  * @brief

  */
uint16_t Dev_Swi_Loop_State(uint32_t devaddr, uint16_t DevOutputLoop)
{	
	RS485_SWI_INFO Rs485SwiInfo;       //开关局部变量

	if(devaddr == 0x00)
		return 0x00;
	
	SRAM_DMA_Read_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),devaddr+Dev_Privately);	
	
	if(DevOutputLoop >= Rs485SwiInfo.SwtOutputValidNum)
	{
		return 0x00;
	}
	
	if(Rs485SwiInfo.DevSendBuf[DevOutputLoop])
	{
		return 0x01;
	}
	else
	{
		return 0x02;
	}
	
}
