/**
  ******************************************************************************
  * @file    BLV_Nor_Dev_VirtualCard.c
  * @author  BLW RCU  development Team
  * @version V1.0.0
  * @date    2025年02月09日
  * @brief   无插卡取电
	======================无卡取电TFTP日志格式==================================
		--协议格式，以 “:” 作为分隔符
			VCLog:信息类型:参数
		--协议内容
			--端口状态变化 T1		参数 - 回路:状态
				格式举例：VCLog:T1:1:1
			--端口触发占比 T2		参数 - 回路:阈值:触发占比	2025-10-13取消
				格式举例：VCLog:T2:1:50:30
			--逻辑条件判定 T3		参数 - 条件组:条件序号:阈值有无人标志位:端口状态
				格式举例：VCLog:T3:1:1:1:1111111111
			--事件触发成立 T4		参数 - 事件序号
				格式举例：VCLog:T4:1
			--文本事件记录 T5		参数 - 文本内容    	2025-10-13取消
				格式举例：VCLog:T5:ALL_LOOP OFF
			--端口触发占比 T6		参数 - 回路:触发占比:有人状态:触发阈值:释放阈值
				格式举例：VCLog:T6:1:12.6:1:60:30
	===============================================================================
  * @log    
			20250209	曹聪
				修改无插卡取电 - 判断有人到无人逻辑
				修改点：
					1、有人到无人判断中："最后一步"判断逻辑改为 - 在2倍的延时时间内，持续满足延时时间的，便算条件成立；如果在2倍的延时时间内，没有满足条件成立，便回到有人到无人判断逻辑的"第一步"
					2、通道CH1 固定接入门磁 - 
						在门磁状态不符合，"最后一步"的情况下，将记录 2倍延时时间 的时间戳重新开始计时
			20250903	曹聪
				修改无卡取电
				修改点：
					1、增加插卡状态变化、检测有无人状态变化、身份信息变化所产生的事件
					2、增加按键触发无人至有人事件 是否启用标志位
					3、增加“最后一步”判断的超时时间，不在是默认的 2倍延时时间
			20250909	曹聪
				修改初始化状态 从外部SRAM中读取上一次取电状态，如果有的话，就恢复上一次的状态，没有的话，就算了
			20250917	曹聪
				修改无卡取电判断分为条件组逻辑与长时间判断	
				修改点：
					1、条件组逻辑中 每个步骤增加超时退出，然后返回判断的“无人->有人 判定的第一步”或“有人->无人 判定的第一步”
					2、条件组逻辑中 条件在规定时间内，满足设定状态时间超过阈值则判定该条件成立，条件组逻辑执行步骤跳到下一步。
						->	回路 == 触发，则判断持续触发的时间
						->	回路 == 释放，则判定持续释放的时间
						->	阈值：在规定时间内，持续触发时间占规定时间的百分比，设定范围为0~100，当阈值为0时，只要满足条件就算通过
					3、长时间判断中 每一个回路独立设置一个滑动窗口(检测时间),无人->有人 判定阈值,有人->无人 判定阈值
						->	滑动窗口(检测时间),以平滑窗口方式持续判断，每秒一个值；在这一秒内，只要有过触发，就算这一秒触发
						->	当前状态为无人的情况下，则判定回路中累计多少时间触发判断为有人，同时产生“室内雷达有人”事件
						->	当前状态为有人的情况下，则判定回路中累计多少时间触发判定为无人，同时产生“室内雷达无人”事件
						->	每个回路都可单独设定是否启用，启用的回路中任意一个满足判定阈值则判断为条件成立
						->	每当“有人\无人”状态发生变化时，所有回路的缓冲区全部按照“有人\无人”状态进行填充，并重新开始计数
					4、当条件组逻辑判断不处于 “无人->有人 判定的第一步”或“有人->无人 判定的第一步” 时，便认为当前在执行条件组逻辑判断;
						在执行条件组逻辑判断期间，“长时间判断”暂停
					5、RS485按键触发，便判定为“有人”状态，并且将所有回路的缓冲区全部按照“有人”状态进行填充
					6、无卡事件修改为一下几个
						->	(0x01)开门进入：通过条件组逻辑判断“无人->有人”成立时，认为判断到人员进入，触发“开门进入”事件
						->	(0x02)卡在人离：通过条件组逻辑判断“有人->无人”成立，且卡还插着时，触发“卡在人离”事件
						->	(0x03)无卡人离：通过条件组逻辑判断“有人->无人”成立，且无卡时，触发“无卡人离”事件
						->	(0x04)室内雷达有人：长时间判断中，判断“无人->有人”成立，触发“室内雷达有人”事件
						->	(0x05)室内雷达无人：长时间判断中，判断“有人->无人”成立，触发“室内雷达无人”事件
						->	(0x06)室内按键触发：室内检测到任意RS485 有上报按键动作，便会触发“室内按键触发”事件
			20251008	曹聪
				修改点：
					1、条件组逻辑中 “有人->无人”判定增加两个事件，短暂人离，长时间人离
						->	(0x07)短暂人离：当前状态为有人的情况下，关门，指定时间段内雷达未触发，触发"短暂人离"事件
						->	(0x08)长时间人离: 当前状态为有人的情况下，关门，短离之后，指定时间段内雷达未触发，触发“长时间人离”事件
						->	“有人->无人”判断过程：关门 -> 短暂人离 -> 长时间人离 -> 无人 ；判定一定遵循此过程，不可逆，短暂人离与长时间人离可选，非必须
						->	在产生关门动作之后，"短暂人离"事件与"长时间人离"事件有且仅会触发一次
						
			20251013	曹聪
				修改点：
					1、无卡取电TFTP上报日志增加 端口触发占比 T6		参数 - 回路:触发占比:有人状态:触发阈值:释放阈值
						格式举例：VCLog:T6:1:12.6:1:60:30
			
			20260126	曹聪
				修改点：
					1、增加两个事件：
						->	(0x09)短暂人离超时事件：短暂人离判断过程中任意一步超时都将回到有人->无人判断的第一步，触发"短暂人离超时"事件
						->	(0x0A)长期人离超时事件：长期人离判断过程中任意一步超时都将回到有人->无人判断的第一步，触发"长期人离超时"事件
			202060129   叶阳文
                修改点：
                    1、长时间判断修改：
                      - 有人-》无人：所有参与长时间检测的传感器采用与逻辑，即，但所有传感器都判断为无人，才判断为房间无人
                      - 无人-》有人：所有参与长时间检测的传感器采用或逻辑，即，任何一个传感器判断到有人，即判断为房间有人
                      - 原有机制：在房间有人、无人状态之间切换时，所有传感器buffer会做一个全量填充（有人->1，无人->0），机制保留
					2、长时间缓冲区填充问题，导致长时间判断无法触发阈值
                      
			2026-02-25	曹聪
				修改点：
					1、将无卡取电设备驱动中的回路状态与服务信息中的回路状态上电时同步状态，但不触发服务信息的事件。
					  
  ******************************************************************************
  */
#include "includes.h"


void Dev_VirtualCard_Dis(uint32_t DevAddr);
uint8_t Dev_VirtualCard_InType_Get(uint32_t DevAddr, uint16_t DevInputLoop, uint16_t DevInputType);
void BLV_VirtualCard_Control_State(uint32_t CfgDevAddIn, uint16_t DevInputAddr, uint32_t devaddr,uint16_t DevOutputLoop,uint16_t start);

void BLV_Nor_Dev_VirtualCard_For_Logic_Init(LOGICFILE_DEVICE_INFO *dev_info,uint8_t *data,uint16_t data_len)
{
	Device_Public_Information_G BUS_Public;
	VIRTUALCARD_STRUCT VCard_Info;
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&VCard_Info,0,sizeof(VIRTUALCARD_STRUCT));

	BUS_Public.addr = dev_info->addr;		//设备地址
	BUS_Public.type = DEV_Virtual_Card;		//设备类型
	BUS_Public.port = dev_info->type;		//设备发送端口
	BUS_Public.baud = 0000;			        //设备发送波特率

	BUS_Public.DevFunInfo.Dev_Data_Process = Dev_VirtualCard_Dis;                  
	BUS_Public.DevFunInfo.Dev_Input_Type_Get = Dev_VirtualCard_InType_Get;         
	BUS_Public.DevFunInfo.Dev_Output_Ctrl = BLV_VirtualCard_Control_State;         

	/*RCU根据MCU复位状态进行设备初始化 - 
		保存标志位成立的情况下，如果是看门狗复位、软件复位、外部手动复位，将之前保存的状态进行设备初始化
		否则采用默认状态初始化(默认状态可通过RCU_POWER_Deivce_State_Init 宏定义 修改默认初始化状态)
	*/
	if( (DevActionGlobal.sram_save_flag == 0xA8) && ((SRAM_Read_DW(SRAM_LOG_RCU_Reboot_Reason) == 0x01) || (SRAM_Read_DW(SRAM_LOG_RCU_Reboot_Reason) == 0x03) || (SRAM_Read_DW(SRAM_LOG_RCU_Reboot_Reason) == 0x05)) )
	{
	
		if(DevActionGlobal.Person_Detected != SOMEONE){
			VCard_Info.ExistState = NOONE;
			VCard_Info.ExistState_Last = NOONE;
			VCard_Info.ConGroupIndx = VC_CONDGROUP_Default_StartGroup;
		}else{
			VCard_Info.ExistState = SOMEONE;
			VCard_Info.ExistState_Last = SOMEONE;
			VCard_Info.ConGroupIndx = DevActionGlobal.VC_ConNToSGruop + 1;
		}
		
		if(DevActionGlobal.CardState == 0x00){
			VCard_Info.CardState = KeyRelease;
			VCard_Info.CardStateLast = KeyRelease;
		}else{
			VCard_Info.CardState = KeyPress;
			VCard_Info.CardStateLast = KeyPress;
		}
		
	}else {

#if RCU_POWER_Deivce_State_Init	
		//默认状态为有人 ，有卡
		VCard_Info.ExistState = SOMEONE;
		VCard_Info.ExistState_Last = SOMEONE;
		VCard_Info.ConGroupIndx = DevActionGlobal.VC_ConNToSGruop + 1;
		
		VCard_Info.CardState = KeyPress;
		VCard_Info.CardStateLast = KeyPress;
#else
		//默认状态为无人 ，无卡
		VCard_Info.ExistState = NOONE;
		VCard_Info.ExistState_Last = NOONE;
		VCard_Info.ConGroupIndx = VC_CONDGROUP_Default_StartGroup;
		
		VCard_Info.CardState = KeyRelease;
		VCard_Info.CardStateLast = KeyRelease;
#endif
		
	}

	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"VCard_Info ExistState:%d",VCard_Info.ExistState);
	//测试使用
//	VCard_Info.ExistState = SOMEONE;
//	VCard_Info.ExistState_Last = SOMEONE;
	
	SRAM_Write_Byte(0x00,SRAM_UDP_ELEReport_VirtualCard);
	SRAM_Write_Byte(0x00,SRAM_UDP_ELEReport_VirtualCard_Last);
	SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);
	
	Add_Nor_Device_To_List2(&BUS_Public,(uint8_t *)&VCard_Info,sizeof(VIRTUALCARD_STRUCT));
}

/*无卡取电 设置长时间检测缓存数据 用于整个缓冲区置位或清楚数据使用*/
void DetWin_WriteData(uint8_t port, uint8_t state, uint16_t size)
{
	uint32_t  detaddr = 0;
	uint8_t data[0x100];
	uint16_t writetime = 0x00;
	uint16_t surplus = 0x00;
	
	memset(data,state,0x100);
	
	writetime = size / 0x100;
	surplus = size % 0x100;
	if(surplus > 0)
	{
		writetime += 1;
	}
	
	detaddr = SRAM_VCard_DetectWin_Start_Addr + (uint32_t)(port * 0x1800);

	for(uint8_t i = 0; i < writetime; i++)
	{
//		Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-----DetWin_WriteData------ addr:%08X",detaddr);
		if((i == (size - 1)) && (surplus != 0x00))
		{
			SRAM_DMA_Write_Buff(data,surplus,detaddr);
		}
		else
		{
			SRAM_DMA_Write_Buff(data,0x100,detaddr);
		}
		detaddr += 0x100;
	}
}

/*无卡取电 设置长时间检测缓存数据 - 针对于Bit写入*/
void DetWin_WriteData_Bit(uint8_t port,uint16_t idex,uint8_t state)
{
	uint32_t  detaddr = 0;
	uint8_t data_val = 0;
	uint16_t bit_offset = 0;                    //2026-01-29,在此时间节点之前使用uint8_t变量,当下标除8大于255时会导致读取的偏移出错
	uint16_t bit_remian = 0;
	
	if( port >=  10)	return ;
	if( idex >= 0xC000)	return ;                //2026-01-28 下标表示的是bit位的下标，而不是地址下标
	
	if(idex != 0x00)
	{
		bit_remian = idex % 8;		//取余
		bit_offset = idex / 8;		//地址偏移
	}
	
	if(bit_remian == 0x00)
	{
		detaddr = SRAM_VCard_DetectWin_Start_Addr + (uint32_t)(port * 0x1800) + (bit_offset) + 1;
	}else {
		detaddr = SRAM_VCard_DetectWin_Start_Addr + (uint32_t)(port * 0x1800) + (bit_offset);
	}
	
	data_val = SRAM_Read_Byte(detaddr);
	
	if(state == 0x01)
	{
		data_val |= 0x01 << bit_remian;
	}else {
		data_val &= ~(0x01 << bit_remian);
	}
	
	SRAM_Write_Byte(data_val,detaddr);
}

/*无卡取电 读取长时间检测缓存数据 - 针对于Bit读取*/
uint8_t DetWin_ReadData_Bit(uint8_t port,uint16_t idex)
{
	uint32_t  detaddr = 0;
	uint8_t data_val = 0;
	uint16_t bit_offset = 0;                        //2026-01-29,在此时间节点之前使用uint8_t变量,当下标除8大于255时会导致读取的偏移出错
	uint16_t bit_remian = 0; 
	
	if( port >=  10)	return 0x00;
	if( idex >= 0xC000)	return 0x00;                //2026-01-28 下标表示的是bit位的下标，而不是地址下标
	
	if(idex != 0x00)
	{
		bit_remian = idex % 8;		//取余
		bit_offset = idex / 8;		//地址偏移
	}
	
	if( bit_remian == 0x00 )
	{
		detaddr = SRAM_VCard_DetectWin_Start_Addr + (uint32_t)(port * 0x1800) + (bit_offset) + 1;
	}else {
		detaddr = SRAM_VCard_DetectWin_Start_Addr + (uint32_t)(port * 0x1800) + (bit_offset);
	}
	
	data_val = SRAM_Read_Byte(detaddr);
	
	if( (data_val & (0x01 << bit_remian)) != 0x00 )
	{
		return 0x01;
	}
	
	return 0x00;
}

/*******************************************************************************
* Function Name  : Dev_VirtualCard_Get_Mapping_Loop_State 
* Description    : 无卡取电 - 获取映射回路的状态
* Input          : 
	dev_info	-	无卡取电设备私有属性结构体指针
	loop_num	- 	读取的回路号
* Return         : 
	0x00	-	获取成功
	0x01	-	获取失败
*******************************************************************************/
uint8_t Dev_VirtualCard_Get_Mapping_Loop_State(VIRTUALCARD_STRUCT *dev_info,uint8_t loop_num)
{
	uint32_t tempaddr = 0x00;
	
	NOR_LVINPUT_INFO DevLVinputInfo;       	//弱电输入 私有变量
	RS485_CARD_INFO Rs485CardInfo;			//插卡取电 私有变量
	RS485_SWI_INFO Rs485SwiInfo;       		//开关 私有变量
	
	switch(dev_info->Port_Info[loop_num].HPort_Type)
	{
		case Dev_Host_LVinput:
			tempaddr = Find_AllDevice_List_Information(dev_info->Port_Info[loop_num].HPort_Type,dev_info->Port_Info[loop_num].HPort_Addr);
			if(tempaddr != NULL)
			{
				SRAM_DMA_Read_Buff((uint8_t *)&DevLVinputInfo,sizeof(NOR_LVINPUT_INFO),tempaddr+Dev_Privately);
				
				if( DevLVinputInfo.Dev_Init_Flag != 0x01 )	return 0x01;	//当前弱电输入还未初始化完成
				
				if((DevLVinputInfo.DevReadBufLast[dev_info->Port_Info[loop_num].HPort_Loop] == KeyPress) \
					|| (DevLVinputInfo.DevReadBufLast[dev_info->Port_Info[loop_num].HPort_Loop] == KeyHold) )
				{
					
					dev_info->PortState[loop_num] = KeyPress;
					dev_info->DetInfo.TriggerNum[loop_num]++;
					
					if(dev_info->PortState[loop_num] != dev_info->PortStateLast[loop_num])
					{
						dev_info->PortStateLast[loop_num] = dev_info->PortState[loop_num];
						
						dev_info->PortStateAct[loop_num] = 0x03;			//上升沿变化
						
						LOG_LogicInfo_DebugRecord("VCLog:T1:%d:%d",loop_num,dev_info->PortState[loop_num]);
						Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"VCard 端口：%d 触发 - CH%d",dev_info->Port_Info[loop_num].HPort_Loop,loop_num);
						if(loop_num == 0x00)
						{
							dev_info->CardState = KeyPress;
						}
					}else{
						dev_info->PortStateAct[loop_num] = KeyPress;		//电平状态，当前无电平变化
					}
				}
				else if( DevLVinputInfo.DevReadBufLast[dev_info->Port_Info[loop_num].HPort_Loop] == KeyRelease )
				{
					dev_info->PortState[loop_num] = KeyRelease;
					
					if(dev_info->PortState[loop_num] != dev_info->PortStateLast[loop_num])
					{									
						dev_info->PortStateLast[loop_num] = dev_info->PortState[loop_num];
						
						dev_info->PortStateAct[loop_num] = 0x04;			//下降沿变化
						
						LOG_LogicInfo_DebugRecord("VCLog:T1:%d:%d",loop_num,dev_info->PortState[loop_num]);
						Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"VCard 端口：%d 释放 - CH%d",dev_info->Port_Info[loop_num].HPort_Loop,loop_num);
						if(loop_num == 0x00)
						{
							dev_info->CardState = KeyRelease;
						}
					}else{
						dev_info->PortStateAct[loop_num] = KeyRelease;		//电平状态，当前无电平变化
					}
				}
			}
			break;
		case DEV_RS485_CARD:
			tempaddr = Find_AllDevice_List_Information(dev_info->Port_Info[loop_num].HPort_Type,dev_info->Port_Info[loop_num].HPort_Addr);
			if(tempaddr != NULL)
			{
				SRAM_DMA_Read_Buff((uint8_t *)&Rs485CardInfo,sizeof(RS485_CARD_INFO),tempaddr+Dev_Privately);
				
				/*2025-09-03 修改RS485取电 - 增加身份判断*/
				if(Rs485CardInfo.Rs485CardFlag == 0x01)
				{
					dev_info->PortState[loop_num] = KeyPress;
					
					dev_info->DetInfo.TriggerNum[loop_num]++;
					if(dev_info->PortState[loop_num] != dev_info->PortStateLast[loop_num])
					{
						dev_info->PortStateLast[loop_num] = dev_info->PortState[loop_num];
						LOG_LogicInfo_DebugRecord("VCLog:T1:%d:%d",loop_num,dev_info->PortState[loop_num]);
						
						if(loop_num == 0x00)
						{
							dev_info->CardState = KeyPress;
						}
					}
				}else {
					dev_info->PortState[loop_num] = KeyRelease;
					
					if(dev_info->PortState[loop_num] != dev_info->PortStateLast[loop_num])
					{
						dev_info->PortStateLast[loop_num] = dev_info->PortState[loop_num];
						LOG_LogicInfo_DebugRecord("VCLog:T1:%d:%d",loop_num,dev_info->PortState[loop_num]);
						
						if(loop_num == 0x00)
						{
							dev_info->CardState = KeyRelease;
						}
					}
				}
			}
			break;
		case DEV_RS485_SWT:
			tempaddr = Find_AllDevice_List_Information(dev_info->Port_Info[loop_num].HPort_Type,dev_info->Port_Info[loop_num].HPort_Addr);
			if(tempaddr != NULL)
			{
				Device_Public_Information_G BUS_Public;   //共用	
				SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),tempaddr);
				if(BUS_Public.Protocol == 0x03)     //针对A9IO
				{
					SRAM_DMA_Read_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),tempaddr+Dev_Privately);
					
					/*A9IO 用于无卡取电逻辑修改
						2025-02-28 
							1、解决问题：获取A9IO 状态与事件触发状态冲突，如果按键事件触发在无卡取电判断先一步执行到，便会将状态清楚。
						这样会导致无卡取电获取不到A9IO的状态；
								解决方式: 获取A9IO 状态改为使用 DevReadBuf_last 状态变量，同时A9IO驱动文件中对该变量的使用做对应的修改
					
							2、解决问题：如果是A9IO 点按触发的话，无卡取电逻辑没有释放，会一直处于触发
								解决方式: 增加机制，如果是点按触发的话，无卡取电逻辑会判定该信号3S有效，3S之后将该状态改为释放状态
					*/
					if(Rs485SwiInfo.DevReadBuf_last[dev_info->Port_Info[loop_num].HPort_Loop] == KeyPress)
					{
						if( (dev_info->PortState[loop_num] == KeyPress) \
							&& ( SysTick_1s - dev_info->PortTiggleTick[loop_num] >= 3 ) )
						{
							dev_info->PortTiggleTick[loop_num] = SysTick_1s;
							
							Rs485SwiInfo.DevReadBuf_last[dev_info->Port_Info[loop_num].HPort_Loop] = KeyRelease;
							dev_info->PortState[loop_num] = KeyRelease;
						
							if(dev_info->PortState[loop_num] != dev_info->PortStateLast[loop_num])
							{									
								dev_info->PortStateLast[loop_num] = dev_info->PortState[loop_num];
								
								dev_info->PortStateAct[loop_num] = 0x04;			//下降沿变化
								
								LOG_LogicInfo_DebugRecord("VCLog:T1:%d:%d:PressRelease",loop_num,dev_info->PortState[loop_num]);
								Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"VCard 端口：%d 点按释放 - CH%d",dev_info->Port_Info[loop_num].HPort_Loop);
								if(loop_num == 0x00)
								{
									dev_info->CardState = KeyRelease;
								}
							}else{
								dev_info->PortStateAct[loop_num] = KeyRelease;		//电平状态，当前无电平变化
							}
							
							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),tempaddr);/*将数据保存*/
							SRAM_DMA_Write_Buff((uint8_t *)&Rs485SwiInfo,sizeof(RS485_SWI_INFO),tempaddr+Dev_Privately);
							
						}else if( dev_info->PortState[loop_num] != KeyPress)
						{
							dev_info->PortTiggleTick[loop_num] = SysTick_1s;
							dev_info->PortState[loop_num] = KeyPress;
							dev_info->DetInfo.TriggerNum[loop_num]++;
							if(dev_info->PortState[loop_num] != dev_info->PortStateLast[loop_num])
							{
								dev_info->PortStateLast[loop_num] = dev_info->PortState[loop_num];
								
								dev_info->PortStateAct[loop_num] = 0x03;			//上升沿变化
								
								LOG_LogicInfo_DebugRecord("VCLog:T1:%d:%d:Press",loop_num,dev_info->PortState[loop_num]);
								Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"VCard 端口：%d 点按触发 - CH%d",dev_info->Port_Info[loop_num].HPort_Loop);
								if(loop_num == 0x00)
								{
									dev_info->CardState = KeyPress;
								}
							}else{
								dev_info->PortStateAct[loop_num] = KeyPress;		//电平状态，当前无电平变化
							}
						}
					}
					else if(Rs485SwiInfo.DevReadBuf_last[dev_info->Port_Info[loop_num].HPort_Loop] == KeyHold)
					{
						dev_info->PortTiggleTick[loop_num] = SysTick_1s;
						dev_info->PortState[loop_num] = KeyPress;
						dev_info->DetInfo.TriggerNum[loop_num]++;
						if(dev_info->PortState[loop_num] != dev_info->PortStateLast[loop_num])
						{
							dev_info->PortStateLast[loop_num] = dev_info->PortState[loop_num];
							
							dev_info->PortStateAct[loop_num] = 0x03;			//上升沿变化
							
							LOG_LogicInfo_DebugRecord("VCLog:T1:%d:%d",loop_num,dev_info->PortState[loop_num]);
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"VCard 端口：%d 触发 - CH%d",dev_info->Port_Info[loop_num].HPort_Loop);
							if(loop_num == 0x00)
							{
								dev_info->CardState = KeyPress;
							}
						}else{
							dev_info->PortStateAct[loop_num] = KeyPress;		//电平状态，当前无电平变化
						}
					}
					else if(Rs485SwiInfo.DevReadBuf_last[dev_info->Port_Info[loop_num].HPort_Loop] == KeyRelease)
					{
						dev_info->PortState[loop_num] = KeyRelease;
						
						if(dev_info->PortState[loop_num] != dev_info->PortStateLast[loop_num])
						{									
							dev_info->PortStateLast[loop_num] = dev_info->PortState[loop_num];
							
							dev_info->PortStateAct[loop_num] = 0x04;			//下降沿变化
							
							LOG_LogicInfo_DebugRecord("VCLog:T1:%d:%d",loop_num,dev_info->PortState[loop_num]);
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"VCard 端口：%d 释放 - CH%d",dev_info->Port_Info[loop_num].HPort_Loop);
							if(loop_num == 0x00)
							{
								dev_info->CardState = KeyRelease;
							}
						}else{
							dev_info->PortStateAct[loop_num] = KeyRelease;	//电平状态，当前无电平变化
						}
					}
				}
			}
			break;
		default:
			break;
	}
	
	
	return 0x00;
}

void Dev_VirtualCard_Dis(uint32_t DevAddr)
{
	Device_Public_Information_G BUS_Public;   //共用	
	VIRTUALCARD_STRUCT VCard_Info;
	
	uint8_t portstate = 0;
    uint8_t PortEn_Cnt = 0x00;          //20260129,长时间雷达检测无人记录满足长时间无人判断的端口数
    uint8_t PortEn_max = 0x00;          //20260129,长时间雷达检测无人中记录开启检测功能的端口总数
    
    
	uint32_t temp_tickout = 0x00;
	uint32_t list_addr = 0;
	uint32_t temp_jumpe_time = 0x00;

	CONDITION_STRUCT condata;
	memset(&condata,0,sizeof(CONDITION_STRUCT));

	uint8_t KeepFlag = 0x00;
	uint8_t condata_save_flag = 0;
	
	if(NULL == DevAddr)
	{
		return ;
	}
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAddr);	//拷贝所有共有数据	
	SRAM_DMA_Read_Buff((uint8_t *)&VCard_Info,sizeof(VIRTUALCARD_STRUCT),DevAddr+Dev_Privately); 
	
	/*初始化映射端口开始*/
	if(VCard_Info.PortInit_Flag == 0x00)
	{
		uint8_t temp[20];
		uint8_t temp_loop = 0;
		memset(&temp,0,sizeof(temp));
		
		Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"Crad_Info:%d - %d",sizeof(VIRTUALCARD_STRUCT),sizeof(Device_Public_Information_G));

		for(uint8_t i = 0; i < DevActionGlobal.VC_PortNum; i++)      //初始化映射端口信息
		{
			list_addr = SRAM_VCard_PortInf_Start_Addr + i * sizeof(VPORT_INFO_STRUCT);   //拿到新地址
			SRAM_Read_Buff(temp, sizeof(VPORT_INFO_STRUCT), list_addr);
			Dbg_Print_Buff(DBG_BIT_LOGIC_STATUS_bit,"VPORT_INFO_STRUCT ",temp,sizeof(VPORT_INFO_STRUCT));
			
			if( (temp[5] != 0x00) && (temp[5] <= VIRTUAL_PORT_MAX) )
			{
				temp_loop = temp[5] - 1;
				VCard_Info.Port_Info[temp_loop].HPort_Type = temp[0];
				VCard_Info.Port_Info[temp_loop].HPort_Addr = temp[1];
				
				VCard_Info.Port_Info[temp_loop].HPort_Loop = temp[3];
				VCard_Info.Port_Info[temp_loop].HPort_Loop <<= 8;
				VCard_Info.Port_Info[temp_loop].HPort_Loop |= temp[2];
				VCard_Info.Port_Info[temp_loop].HPort_Loop -= 0x01;
				
				VCard_Info.Port_Info[temp_loop].PortEnFlag = temp[6];		//回路启用长时间检测 - 使能标志位
				
				/*2025-03-07 检测数量判断 
					1、触发阈值不为0
					2、端口开启检测状态
				*/
				if( VCard_Info.Port_Info[temp_loop].PortEnFlag == 0x01 )
				{
					VCard_Info.DetNum++;
				}
				
				//VCard_Info.PortState[temp_loop] = KeyRelease;
				//初始化IO状态 2026-02-26
				if(Dev_VirtualCard_Get_Mapping_Loop_State(&VCard_Info,temp_loop) == 0x01){
					Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"%s Wait IO Init..",__func__);
					return ;
				}	
				
				ServiceInfo_Set_VirtualCard_LoopState(temp_loop,VCard_Info.PortState[temp_loop]);
				
				//2025-09-19 增加每个回路单独的长时间检测
				VCard_Info.DetInfo.DetWinTotalNum[temp_loop] = temp[8];
				VCard_Info.DetInfo.DetWinTotalNum[temp_loop] <<= 8;
				VCard_Info.DetInfo.DetWinTotalNum[temp_loop] |= temp[7];
				
				switch(temp[9])
				{
					case 0x01:    //秒
						if(VCard_Info.DetInfo.DetWinTotalNum[temp_loop] >= 43200)
						{
							VCard_Info.DetInfo.DetWinTotalNum[temp_loop] = 43200;
						}
						break;
					case 0x02:    //分
						if(VCard_Info.DetInfo.DetWinTotalNum[temp_loop] >= 720)
						{
							VCard_Info.DetInfo.DetWinTotalNum[temp_loop] = 720;
						}
						VCard_Info.DetInfo.DetWinTotalNum[temp_loop] *= 60;
						break;
					case 0x03:    //时
						if(VCard_Info.DetInfo.DetWinTotalNum[temp_loop] >= 12)
						{
							VCard_Info.DetInfo.DetWinTotalNum[temp_loop] = 12;
						}
						VCard_Info.DetInfo.DetWinTotalNum[temp_loop] *= 3600;
						break;
				}
				
				VCard_Info.DetInfo.Trigger_Thres[temp_loop] = temp[4];		//长时间判定触发 - 无人->有人 阈值 
				VCard_Info.DetInfo.Release_Thres[temp_loop] = temp[10];		//长时间判定释放 - 有人->无人 阈值 
				
				VCard_Info.DetInfo.DetWinIdex[temp_loop] = 0x00;
				VCard_Info.DetInfo.FullFlag[temp_loop] = 0x00;
				
			}
			
			Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"初始化映射端口%d 类型:%d 地址:%d 回路:%d 状态:%d 阈值:%d-%d 使能标志:%d - %dS",\
				temp_loop,\
				VCard_Info.Port_Info[temp_loop].HPort_Type,\
				VCard_Info.Port_Info[temp_loop].HPort_Addr,\
				VCard_Info.Port_Info[temp_loop].HPort_Loop,\
				VCard_Info.PortState[temp_loop],\
				VCard_Info.DetInfo.Trigger_Thres[temp_loop],\
				VCard_Info.DetInfo.Release_Thres[temp_loop],\
				VCard_Info.Port_Info[temp_loop].PortEnFlag,\
				VCard_Info.DetInfo.DetWinTotalNum[temp_loop]);
		}
		
		VCard_Info.PortInit_Flag = 0x01;
		VCard_Info.DetInfo.Det1sTime = 0x00;
		
		if(VCard_Info.ExistState == SOMEONE)
		{
			/*如果当前初始化为有人状态*/
			VCard_Info.ConGroupIndx = DevActionGlobal.VC_ConNToSGruop + 1;
			Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"初始化无卡取电状态 - 有人");
			VCard_Info.ExistState = SOMEONE;
			DevActionGlobal.Person_Detected = VCard_Info.ExistState;
			/*清空回路的长时间检测状态 - 注意回路1默认是插卡取电，不进入长时间统计*/
			for(uint8_t i= 1; i < VIRTUAL_PORT_MAX; i++)
			{
				if(VCard_Info.Port_Info[i].HPort_Type != 0x00)
				{
					VCard_Info.DetInfo.DetWinTrigger[i] = VCard_Info.DetInfo.DetWinTotalNum[i];
					VCard_Info.ActThreshold[i] = 100;
					VCard_Info.DetInfo.DetWinIdex[i] = 0;
					VCard_Info.DetInfo.FullFlag[i] = 0x01;
					DetWin_WriteData((i - 1), 0xFF, ((VCard_Info.DetInfo.DetWinTotalNum[i] / 8) + 1 ) );
				}
			}
			
		}else {
			/*如果当前初始化为无人状态*/
			VCard_Info.ExistState = NOONE;
			DevActionGlobal.Person_Detected = VCard_Info.ExistState;
			VCard_Info.ConGroupIndx = VC_CONDGROUP_Default_StartGroup;		//进入无人至有人判断的第一步
			Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"初始化无卡取电状态 - 无人",condata.Condi_Gruop,condata.Condi_Subset);
			
			/*清空回路的长时间检测状态 - 注意回路1默认是插卡取电，不进入长时间统计*/
			for(uint8_t i= 1; i < VIRTUAL_PORT_MAX; i++)
			{
				if(VCard_Info.Port_Info[i].HPort_Type != 0x00)
				{
					VCard_Info.DetInfo.DetWinTrigger[i] = 0x00;
					VCard_Info.ActThreshold[i] = 0;
					VCard_Info.DetInfo.DetWinIdex[i] = 0;
					VCard_Info.DetInfo.FullFlag[i] = 0x01;
					DetWin_WriteData((i - 1), 0x00, ((VCard_Info.DetInfo.DetWinTotalNum[i] / 8) + 1 ) );
				}
			}
			
		}
		
		KeepFlag = 0x01;
	}
	/*初始化映射端口结束*/
	
	
	/*端口状态检测以及触发阈值计算开始 */
	if((SysTick_1ms - VCard_Info.PortTick >= 100) && (VCard_Info.PortInit_Flag == 0x01))
	{
		VCard_Info.PortTick = SysTick_1ms;
		
		VCard_Info.DetInfo.Det1sTime++;
		
		if(VCard_Info.DetInfo.Det1sTime >= 10)	VCard_Info.DetInfo.Det30sTime++;
		
		for(uint8_t i = 0; i < VIRTUAL_PORT_MAX; i++)            
		{
			Dev_VirtualCard_Get_Mapping_Loop_State(&VCard_Info,i);		//获取IO状态 2026-02-26
			
			/*长时间检测 - */
			if( ( (VCard_Info.ExistState == NOONE) && (VCard_Info.ConGroupIndx == VC_CONDGROUP_Default_StartGroup) )
				|| ( (VCard_Info.ExistState == SOMEONE) && (VCard_Info.ConGroupIndx == (DevActionGlobal.VC_ConNToSGruop + 1)) ) )	
			{
				if((i != 0x00) && (VCard_Info.Port_Info[i].PortEnFlag == 0x01))     //端口1固定为有卡取电设备的回路，不参与统计
				{
					portstate = 0x00;
					if(VCard_Info.DetInfo.Det1sTime == 10)     //100ms读一次状态 1s内检测10次
					{
						/*1S内 触发时间大于500ms，才算触发，不是持续触发也算 */
						if(VCard_Info.DetInfo.TriggerNum[i] >= 5)	
						{
							VCard_Info.DetInfo.TriggerNum[i] = 0x00;
							portstate = 0x01;
						}else {
							portstate = 0x00;
						}
						
						if(VCard_Info.DetInfo.FullFlag[i] == 0x01)
						{
							//检测窗口 缓冲数据已满
							if( DetWin_ReadData_Bit((i-1),VCard_Info.DetInfo.DetWinIdex[i]) != portstate )
							{
								//与之前状态不一致
								if(portstate == 0x01)
								{
									if(VCard_Info.DetInfo.DetWinTrigger[i] < VCard_Info.DetInfo.DetWinTotalNum[i])
									{
										VCard_Info.DetInfo.DetWinTrigger[i]++;
									}
								}else {
									if(VCard_Info.DetInfo.DetWinTrigger[i] > 0)
									{
										VCard_Info.DetInfo.DetWinTrigger[i]--;
									}
								}
								DetWin_WriteData_Bit((i-1),VCard_Info.DetInfo.DetWinIdex[i],portstate);
							}else {
								//与之前状态一样，触发计数不改变
							}
						}else {
							//检测窗口 缓冲数据未满
							if(portstate == 0x01)
							{
								if(VCard_Info.DetInfo.DetWinTrigger[i] < VCard_Info.DetInfo.DetWinTotalNum[i])
								{
									VCard_Info.DetInfo.DetWinTrigger[i]++;
								}
							}
							DetWin_WriteData_Bit((i-1),VCard_Info.DetInfo.DetWinIdex[i],portstate);
						}
						
						if(VCard_Info.DetInfo.DetWinIdex[i] < VCard_Info.DetInfo.DetWinTotalNum[i])
						{
							VCard_Info.DetInfo.DetWinIdex[i]++;
						}else {
							VCard_Info.DetInfo.DetWinIdex[i] = 0x00;
							VCard_Info.DetInfo.FullFlag[i] = 0x01;
						}
						
						/*触发阈值计算*/
						VCard_Info.ActThreshold[i] = (float)VCard_Info.DetInfo.DetWinTrigger[i] * 100 / (float)VCard_Info.DetInfo.DetWinTotalNum[i];
					
						/*30S - 如果当前有触发的话，记录一下触发状态*/
						if(VCard_Info.DetInfo.Det30sTime >= 30)
						{
							if(VCard_Info.ActThreshold[i] != 0x00)
							{
								/*日志记录端口触发占比 - T6
									2025-10-13 之前记录端口触发占比是T2 参数：回路:阈值:触发占比
										现在改为 记录端口触发占比是T6 参数：回路:触发占比:有人状态:触发阈值:释放阈值
								*/
								Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"端口 %d 触发:%d 次数：%d - %d   触发阈值：%.02f",i + 1,portstate,\
									VCard_Info.DetInfo.DetWinTrigger[i],VCard_Info.DetInfo.DetWinTotalNum[i],VCard_Info.ActThreshold[i]);
								LOG_LogicInfo_DebugRecord("VCLog:T6:%d:%.02f:%d:%d:%d",i,VCard_Info.ActThreshold[i],VCard_Info.ExistState,VCard_Info.DetInfo.Trigger_Thres[i],VCard_Info.DetInfo.Release_Thres[i]);
                                
                                Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"缓冲区标记 %d, 当前下标:%d ",VCard_Info.DetInfo.FullFlag[i],VCard_Info.DetInfo.DetWinIdex[i]);
                           
							}
						}
					
					}
				}
			}else {
				//暂停长时间统计
				//Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"回路%d 暂停长时间统计",i + 1);
			}
		}
		
		if(VCard_Info.DetInfo.Det1sTime >= 10)     //100ms读一次状态 1s内检测10次
		{
			if(VCard_Info.DetInfo.Det30sTime >= 30)	{
				VCard_Info.DetInfo.Det30sTime = 0x00;
				
				Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"- 状态:%d 条件组:%d 判定-%d,%d,%d,%d,%d,%d,%d,%d,%d,%d Time:%d-%d",VCard_Info.ExistState,VCard_Info.ConGroupIndx,\
					VCard_Info.PortStateAct[0],VCard_Info.PortStateAct[1],VCard_Info.PortStateAct[2],VCard_Info.PortStateAct[3],VCard_Info.PortStateAct[4],\
					VCard_Info.PortStateAct[5],VCard_Info.PortStateAct[6],VCard_Info.PortStateAct[7],VCard_Info.PortStateAct[8],VCard_Info.PortStateAct[9],\
					(SysTick_1s - VCard_Info.Condition_Trigger_Tick),(SysTick_1s - VCard_Info.Last_Trigger_Tick));
			}
			
			
			
			VCard_Info.DetInfo.Det1sTime = 0x00;
		}
		
		KeepFlag = 0x01;
	}
	/*端口状态检测以及触发阈值计算结束*/
	
	/*有人无人条件判断执行开始*/
	if(VCard_Info.ExistState == NOONE)
	{
		for(uint8_t j = 0; j < DevActionGlobal.VC_ConNToSSubset; j++)
		{
			condata_save_flag = 0x00;
			
			list_addr = SRAM_VCard_ConNToS_Start_Addr + j * sizeof(CONDITION_STRUCT);   
			SRAM_Read_Buff((uint8_t*)&condata, sizeof(CONDITION_STRUCT), list_addr);
			
			/*“第一步”要是满足的话，条件便重新判断*/
			if( (condata.Condi_Gruop == VC_CONDGROUP_Default_StartGroup) || (condata.Condi_Gruop == VCard_Info.ConGroupIndx) )
			{
				//Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-有人至无人 条件%d-%d 判定-",condata.Condi_Gruop,condata.Condi_Subset);
				
				//条件判定成立 - 消抖时间
				temp_jumpe_time = condata.Judgment_Time;
				if(condata.Judgment_Unit == 0x03)
				{
					temp_jumpe_time = temp_jumpe_time * 3600;		//时
				}else if(condata.Judgment_Unit == 0x02)
				{
					temp_jumpe_time = temp_jumpe_time * 60;			//分
				}else {
					//秒
				}
				
				//条件判定 - 超时时间
				temp_tickout = condata.Timeout_Time;
				if(condata.Timeout_Unit == 0x03)
				{
					temp_tickout = temp_tickout * 3600;		//时
				}else if(condata.Timeout_Unit == 0x02)
				{
					temp_tickout = temp_tickout * 60;			//分
				}else {
					//秒
				}
				
				//判定条件是否满足
				if(((condata.Port_State[0] == 0x00) || (condata.Port_State[0] == VCard_Info.PortStateAct[0])) && \
				   ((condata.Port_State[1] == 0x00) || (condata.Port_State[1] == VCard_Info.PortStateAct[1])) && \
				   ((condata.Port_State[2] == 0x00) || (condata.Port_State[2] == VCard_Info.PortStateAct[2])) && \
				   ((condata.Port_State[3] == 0x00) || (condata.Port_State[3] == VCard_Info.PortStateAct[3])) && \
				   ((condata.Port_State[4] == 0x00) || (condata.Port_State[4] == VCard_Info.PortStateAct[4])) && \
				   ((condata.Port_State[5] == 0x00) || (condata.Port_State[5] == VCard_Info.PortStateAct[5])) && \
				   ((condata.Port_State[6] == 0x00) || (condata.Port_State[6] == VCard_Info.PortStateAct[6])) && \
				   ((condata.Port_State[7] == 0x00) || (condata.Port_State[7] == VCard_Info.PortStateAct[7])) && \
				   ((condata.Port_State[8] == 0x00) || (condata.Port_State[8] == VCard_Info.PortStateAct[8])) && \
				   ((condata.Port_State[9] == 0x00) || (condata.Port_State[8] == VCard_Info.PortStateAct[9])) && \
				   ((condata.Port_State[10] == 0x00) || (condata.Port_State[9] == VCard_Info.PortStateAct[10])) )
				{
					//满足触发条件
					if(condata.Trigger_Flag != 0x01)
					{
						KeepFlag = 0x01;
						condata_save_flag = 0x01;
						
						condata.Trigger_Flag = 0x01;
						condata.Trigger_Tick = SysTick_1s;
						
						VCard_Info.Condition_Trigger_Tick = SysTick_1s;
					}
				}else{
					//不满足触发条件
					if(condata.Trigger_Flag != 0x00)
					{
						KeepFlag = 0x01;
						condata_save_flag = 0x01;
						
						condata.Trigger_Flag = 0x00;
					}
				}
				
				//超时判断，条件不处于“第一步”时，超时返回"第一步"
				if( (condata.Condi_Gruop != VC_CONDGROUP_Default_StartGroup) && (SysTick_1s - VCard_Info.Last_Trigger_Tick >= temp_tickout) )
				{
					KeepFlag = 0x01;
					condata_save_flag = 0x01;
					
					VCard_Info.Last_Trigger_Tick = SysTick_1s;
					
					condata.Trigger_Flag = 0x00;
					condata.Trigger_Tick = SysTick_1s;									//清楚触发标志位
					VCard_Info.Condition_Trigger_Tick = SysTick_1s;
					
					VCard_Info.ConGroupIndx = VC_CONDGROUP_Default_StartGroup;		//条件返回无人->有人 判定条件组1
					
					Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-条件%d-%d 判定超时 返回条件组%d-",condata.Condi_Gruop,condata.Condi_Subset,VCard_Info.ConGroupIndx);
				}else {
					//条件超时判定不成立的情况下，判定条件是否满足成立时间
					if( ( condata.Trigger_Flag == 0x01 ) && ( SysTick_1s - VCard_Info.Condition_Trigger_Tick >= temp_jumpe_time ) )
					{
						KeepFlag = 0x01;
						condata_save_flag = 0x01;
						
						//条件 - 满足时间，判定成立
						condata.Trigger_Flag = 0x00;
						condata.Trigger_Tick = SysTick_1s;	
						
						VCard_Info.Condition_Trigger_Tick = SysTick_1s;
						
						/*防止过度打印调试信息与TFTP日志*/
						if( condata.Condi_Gruop == VCard_Info.ConGroupIndx )
						{
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"无人至有人 %d 条件组成立 %d",condata.Condi_Gruop,VCard_Info.ConGroupIndx);
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"- 状态:%d 条件组:%d 判定-%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",VCard_Info.ExistState,VCard_Info.ConGroupIndx,\
								VCard_Info.PortStateAct[0],VCard_Info.PortStateAct[1],VCard_Info.PortStateAct[2],VCard_Info.PortStateAct[3],VCard_Info.PortStateAct[4],\
								VCard_Info.PortStateAct[5],VCard_Info.PortStateAct[6],VCard_Info.PortStateAct[7],VCard_Info.PortStateAct[8],VCard_Info.PortStateAct[9]);
						
							LOG_LogicInfo_DebugRecord("VCLog:T3:%d:%d:%d:%d%d%d%d%d%d%d%d%d%d",\
							condata.Condi_Gruop,j,condata.Exist_Flag,condata.Port_State[0],condata.Port_State[1],condata.Port_State[2],\
							condata.Port_State[3],condata.Port_State[4],condata.Port_State[5],condata.Port_State[6],condata.Port_State[7],\
							condata.Port_State[8],condata.Port_State[9]);
						}else {
							
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"无人至有人 %d 条件组成立 %d %d",condata.Condi_Gruop,VCard_Info.ConGroupIndx,j);
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"- 状态:%d 条件组:%d 判定-%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",VCard_Info.ExistState,VCard_Info.ConGroupIndx,\
								VCard_Info.PortStateAct[0],VCard_Info.PortStateAct[1],VCard_Info.PortStateAct[2],VCard_Info.PortStateAct[3],VCard_Info.PortStateAct[4],\
								VCard_Info.PortStateAct[5],VCard_Info.PortStateAct[6],VCard_Info.PortStateAct[7],VCard_Info.PortStateAct[8],VCard_Info.PortStateAct[9]);
						}
						
						//切换条件组，同时记录条件成立时间，用于下一个条件超时判定使用
						VCard_Info.Last_Trigger_Tick = SysTick_1s;	
						VCard_Info.ConGroupIndx = condata.Condi_Gruop + 1;
						VCard_Info.Last_ConGroupType = 0x00;
						
						if( VCard_Info.ConGroupIndx > DevActionGlobal.VC_ConNToSGruop )
						{
							VCard_Info.ConGroupIndx = DevActionGlobal.VC_ConNToSGruop + 1;
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-条件%d-%d 判定有人-",condata.Condi_Gruop,condata.Condi_Subset);
							VCard_Info.ExistState = SOMEONE;
							DevActionGlobal.Person_Detected = VCard_Info.ExistState;
							
							//Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-事件:开门进入--");
							VCard_Info.Action |= VC_Event_DoorSensor_Flag;
							
							Udp_Addtion_Roomstate(BUS_Public.type,BUS_Public.addr,0x00,VC_EventID_DoorSensor);
							SRAM_Write_Byte(VC_EventID_DoorSensor,SRAM_UDP_ELEReport_VirtualCard);
							SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);
							LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_DoorSensor);
							
							/*清空回路的长时间检测状态 - 注意回路1默认是插卡取电，不进入长时间统计*/
							for(uint8_t i= 1; i < VIRTUAL_PORT_MAX; i++)
							{
								if(VCard_Info.Port_Info[i].HPort_Type != 0x00)
								{
									VCard_Info.DetInfo.DetWinTrigger[i] = VCard_Info.DetInfo.DetWinTotalNum[i];
									VCard_Info.ActThreshold[i] = 100;
									VCard_Info.DetInfo.DetWinIdex[i] = 0;
									VCard_Info.DetInfo.FullFlag[i] = 0x01;
									DetWin_WriteData((i - 1), 0xFF, ((VCard_Info.DetInfo.DetWinTotalNum[i] / 8) + 1 ) );
								}
							}
						}
					}
				}
				
				if(condata_save_flag == 0x01)
				{
					SRAM_Write_Buff((uint8_t*)&condata, sizeof(CONDITION_STRUCT), list_addr);
				}
			}
		}
	}
	else if(VCard_Info.ExistState == SOMEONE)
	{
		/*有人至无人判断*/
		for(uint8_t j = 0; j < DevActionGlobal.VC_ConSToNSubset; j++)
		{
			condata_save_flag = 0x00;
			
			list_addr = SRAM_VCard_ConSToN_Start_Addr + j * sizeof(CONDITION_STRUCT);   
			SRAM_Read_Buff((uint8_t*)&condata, sizeof(CONDITION_STRUCT), list_addr);
			
			/*“第一步”要是满足的话，条件便重新判断*/
			if( (condata.Condi_Gruop == (DevActionGlobal.VC_ConNToSGruop + 1) ) || (condata.Condi_Gruop == VCard_Info.ConGroupIndx) )
			{
				//条件判定成立 - 消抖时间
				temp_jumpe_time = condata.Judgment_Time;
				if(condata.Judgment_Unit == 0x03)
				{
					temp_jumpe_time = temp_jumpe_time * 3600;		//时
				}else if(condata.Judgment_Unit == 0x02)
				{
					temp_jumpe_time = temp_jumpe_time * 60;			//分
				}else {
					//秒
				}
				
				//条件判定 - 超时时间
				temp_tickout = condata.Timeout_Time;
				if(condata.Timeout_Unit == 0x03)
				{
					temp_tickout = temp_tickout * 3600;			//时
				}else if(condata.Timeout_Unit == 0x02)
				{
					temp_tickout = temp_tickout * 60;			//分
				}else {
					//秒
				}
				
				if( (condata.Condi_Gruop != (DevActionGlobal.VC_ConNToSGruop + 1) ) && (condata.Condi_Gruop == VCard_Info.ConGroupIndx) )
				{
					if( ( VCard_Info.Last_ConGroupType == VC_CONDGROUP_BrieflyLeaving_Type ) && (condata.Exist_Flag != VCard_Info.Last_ConGroupType) )
					{
						/*产生短暂人离事件 */
						//Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"产生短暂人离事件 - %d",condata.Condi_Gruop);
						VCard_Info.Last_ConGroupType = 0x00;
						VCard_Info.Action |= VC_Event_ShortAway_Flag;
						
						Udp_Addtion_Roomstate(BUS_Public.type,BUS_Public.addr,0x00,VC_EventID_ShortAway);
						SRAM_Write_Byte(VC_EventID_ShortAway,SRAM_UDP_ELEReport_VirtualCard);
						SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);			//2026-01-20	增加记录时间戳
						LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_ShortAway);
						KeepFlag = 0x01;
					}else if( ( VCard_Info.Last_ConGroupType == VC_CONDGROUP_LongTermLeaving_Type ) && (condata.Exist_Flag != VCard_Info.Last_ConGroupType) )
					{
						/*产生长时间人离事件 */
						//Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"产生长时间人离事件 - %d",condata.Condi_Gruop);
						VCard_Info.Last_ConGroupType = 0x00;
						VCard_Info.Action |= VC_Event_LongAway_Flag;
						
						Udp_Addtion_Roomstate(BUS_Public.type,BUS_Public.addr,0x00,VC_EventID_LongAway);
						SRAM_Write_Byte(VC_EventID_LongAway,SRAM_UDP_ELEReport_VirtualCard);
						SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);			//2026-01-20	增加记录时间戳
						LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_LongAway);
						KeepFlag = 0x01;
					}
				}
				
				if(((condata.Port_State[0] == 0x00) || (condata.Port_State[0] == VCard_Info.PortStateAct[0])) && \
				   ((condata.Port_State[1] == 0x00) || (condata.Port_State[1] == VCard_Info.PortStateAct[1])) && \
				   ((condata.Port_State[2] == 0x00) || (condata.Port_State[2] == VCard_Info.PortStateAct[2])) && \
				   ((condata.Port_State[3] == 0x00) || (condata.Port_State[3] == VCard_Info.PortStateAct[3])) && \
				   ((condata.Port_State[4] == 0x00) || (condata.Port_State[4] == VCard_Info.PortStateAct[4])) && \
				   ((condata.Port_State[5] == 0x00) || (condata.Port_State[5] == VCard_Info.PortStateAct[5])) && \
				   ((condata.Port_State[6] == 0x00) || (condata.Port_State[6] == VCard_Info.PortStateAct[6])) && \
				   ((condata.Port_State[7] == 0x00) || (condata.Port_State[7] == VCard_Info.PortStateAct[7])) && \
				   ((condata.Port_State[8] == 0x00) || (condata.Port_State[8] == VCard_Info.PortStateAct[8])) && \
				   ((condata.Port_State[9] == 0x00) || (condata.Port_State[8] == VCard_Info.PortStateAct[9])) && \
				   ((condata.Port_State[10] == 0x00) || (condata.Port_State[9] == VCard_Info.PortStateAct[10])) )
				{
					//满足触发条件
					if(condata.Trigger_Flag != 0x01)
					{
						KeepFlag = 0x01;
						condata_save_flag = 0x01;
						
						condata.Trigger_Flag = 0x01;
						condata.Trigger_Tick = SysTick_1s;
						
						VCard_Info.Condition_Trigger_Tick = SysTick_1s;
					}
				}else{
					//不满足触发条件
					if(condata.Trigger_Flag != 0x00)
					{
						condata_save_flag = 0x01;
						condata.Trigger_Flag = 0x00;
					}
				}
				
				//超时判断，条件不处于“第一步”时，超时返回"第一步"
				if( (condata.Condi_Gruop != DevActionGlobal.VC_ConNToSGruop + 1) && (SysTick_1s - VCard_Info.Last_Trigger_Tick >= temp_tickout) )
				{
					KeepFlag = 0x01;
					condata_save_flag = 0x01;
					
					VCard_Info.Last_Trigger_Tick = SysTick_1s;
					
					condata.Trigger_Flag = 0x01;										//清楚触发标志位
					condata.Trigger_Tick = SysTick_1s;
					
					VCard_Info.Condition_Trigger_Tick = SysTick_1s;
					
					if( condata.Exist_Flag == VC_CONDGROUP_BrieflyLeaving_Type )
					{
						/*产生短暂人离超时事件 */
						//Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"产生短暂人离超时事件 - %d",condata.Condi_Gruop);
						VCard_Info.Last_ConGroupType = 0x00;
						VCard_Info.Action |= VC_Event_ShortAwayTimeout_Flag;
						
						Udp_Addtion_Roomstate(BUS_Public.type,BUS_Public.addr,0x00,VC_EventID_ShortAwayTimeout);
						SRAM_Write_Byte(VC_EventID_ShortAwayTimeout,SRAM_UDP_ELEReport_VirtualCard);
						SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);			//2026-01-20	增加记录时间戳
						LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_ShortAwayTimeout);
					}else if( condata.Exist_Flag == VC_CONDGROUP_LongTermLeaving_Type )
					{
						/*产生长时间人离超时事件 */
						//Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"产生长时间人离超时事件 - %d",condata.Condi_Gruop);
						VCard_Info.Last_ConGroupType = 0x00;
						VCard_Info.Action |= VC_Event_LongAwayTimeout_Flag;
						
						Udp_Addtion_Roomstate(BUS_Public.type,BUS_Public.addr,0x00,VC_EventID_LongAwayTimeout);
						SRAM_Write_Byte(VC_EventID_LongAwayTimeout,SRAM_UDP_ELEReport_VirtualCard);
						SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);			//2026-01-20	增加记录时间戳
						LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_LongAwayTimeout);
					}
					
					VCard_Info.ConGroupIndx = DevActionGlobal.VC_ConNToSGruop + 1;		//条件返回有人->无人 判定的第一步
					
					Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-条件%d-%d 判定超时 返回条件组%d-",condata.Condi_Gruop,condata.Condi_Subset,VCard_Info.ConGroupIndx);
				}else {
					//条件超时判定不成立的情况下，判定条件是否满足成立时间
					if( ( condata.Trigger_Flag == 0x01 ) && ( SysTick_1s - VCard_Info.Condition_Trigger_Tick >= temp_jumpe_time ) )
					{
						KeepFlag = 0x01;
						condata_save_flag = 0x01;
						
						//条件 - 满足时间，判定成立
						VCard_Info.Condition_Trigger_Tick = SysTick_1s;
						condata.Trigger_Flag = 0x00;
						condata.Trigger_Tick = SysTick_1s;
						
						if( condata.Condi_Gruop == VCard_Info.ConGroupIndx )
						{
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"有人至无人 %d 条件组成立",condata.Condi_Gruop);
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"- 状态:%d 条件组:%d 判定-%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",VCard_Info.ExistState,VCard_Info.ConGroupIndx,\
								VCard_Info.PortStateAct[0],VCard_Info.PortStateAct[1],VCard_Info.PortStateAct[2],VCard_Info.PortStateAct[3],VCard_Info.PortStateAct[4],\
								VCard_Info.PortStateAct[5],VCard_Info.PortStateAct[6],VCard_Info.PortStateAct[7],VCard_Info.PortStateAct[8],VCard_Info.PortStateAct[9]);
						
							LOG_LogicInfo_DebugRecord("VCLog:T3:%d:%d:%d:%d%d%d%d%d%d%d%d%d%d",\
							condata.Condi_Gruop,j,condata.Exist_Flag,condata.Port_State[0],condata.Port_State[1],condata.Port_State[2],\
							condata.Port_State[3],condata.Port_State[4],condata.Port_State[5],condata.Port_State[6],condata.Port_State[7],\
							condata.Port_State[8],condata.Port_State[9]);
						}else {
							//条件组 1 成立
							
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"有人至无人 %d 条件组成立 %d %d",condata.Condi_Gruop,VCard_Info.ConGroupIndx,j);
						}
						
						VCard_Info.Last_ConGroupType = condata.Exist_Flag;		//当前条件组成立，将条件类型保存下来用于触发"短暂人离"与"长时间人离"
						
						//切换条件组，同时记录条件成立时间，用于下一个条件超时判定使用
						VCard_Info.Last_Trigger_Tick = SysTick_1s;	
						VCard_Info.ConGroupIndx = condata.Condi_Gruop + 1;
						
						if( VCard_Info.ConGroupIndx > DevActionGlobal.VC_ConSToNGruop )
						{
							VCard_Info.ExistState = NOONE;
							DevActionGlobal.Person_Detected = VCard_Info.ExistState;
							
							VCard_Info.ConGroupIndx = VC_CONDGROUP_Default_StartGroup;		//进入无人至有人判断的第一步
							Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-条件%d-%d 判定无人-",condata.Condi_Gruop,condata.Condi_Subset);
							
							if(VCard_Info.CardState == 0x01)
							{
								//Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-事件:卡在人离--");
								VCard_Info.Action |= VC_Event_CardedPersonLeft_Flag;
								
								Udp_Addtion_Roomstate(BUS_Public.type,BUS_Public.addr,0x00,VC_EventID_CardedPersonLeft);
								SRAM_Write_Byte(VC_EventID_CardedPersonLeft,SRAM_UDP_ELEReport_VirtualCard);
								LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_CardedPersonLeft);
							}else {
								//Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-事件:无卡人离--");
								VCard_Info.Action |= VC_Event_UncardedPersonLeft_Flag;
								
								Udp_Addtion_Roomstate(BUS_Public.type,BUS_Public.addr,0x00,VC_EventID_UncardedPersonLeft);
								SRAM_Write_Byte(VC_EventID_UncardedPersonLeft,SRAM_UDP_ELEReport_VirtualCard);
								LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_UncardedPersonLeft);
							}
							SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);			//2026-01-20	增加记录时间戳
							
							/*清空回路的长时间检测状态 - 注意回路1默认是插卡取电，不进入长时间统计*/
							for(uint8_t i = 1; i < VIRTUAL_PORT_MAX; i++)
							{
								if(VCard_Info.Port_Info[i].HPort_Type != 0x00)
								{
									VCard_Info.DetInfo.DetWinTrigger[i] = 0x00;
									VCard_Info.ActThreshold[i] = 0;
									VCard_Info.DetInfo.DetWinIdex[i] = 0;
									VCard_Info.DetInfo.FullFlag[i] = 0x01;
									DetWin_WriteData((i - 1), 0x00, ((VCard_Info.DetInfo.DetWinTotalNum[i] / 8) + 1 ) );
								}
							}
						}
					}
				}
				
				if(condata_save_flag == 0x01)
				{
					SRAM_Write_Buff((uint8_t*)&condata, sizeof(CONDITION_STRUCT), list_addr);
				}
			}
		}
	}
	/*有人无人条件判断执行结束*/
	
	/*根据阈值判断有无人开始 - 该阈值判断逻辑 在条件判断非第一步时生效 */
	if( (VCard_Info.ExistState == NOONE) && (VCard_Info.ConGroupIndx == VC_CONDGROUP_Default_StartGroup)  )
	{
		/*当前无人状态，且条件逻辑判断处于无人至有人 第一步时，执行长时间判断：启用的回路，任意一个满足回路对应的阈值判断，则条件成立，检测状态变为有人*/
		for(uint8_t i = 1; i < VIRTUAL_PORT_MAX; i++)
		{
			if( (VCard_Info.Port_Info[i].PortEnFlag == 0x01) && (VCard_Info.DetInfo.Trigger_Thres[i] != 0x00) )
			{
				if(VCard_Info.ActThreshold[i] >= VCard_Info.DetInfo.Trigger_Thres[i])
				{
					KeepFlag = 0x01;
					
					/*将状态改变为有人，且所有回路的缓冲区全部按照“有人”状态进行填充，并重新开始计数*/
					VCard_Info.Action |= VC_Event_RadarPersonDetected_Flag;
					
					Udp_Addtion_Roomstate(BUS_Public.type,BUS_Public.addr,0x00,VC_EventID_RadarPersonDetected);
					SRAM_Write_Byte(VC_EventID_RadarPersonDetected,SRAM_UDP_ELEReport_VirtualCard);
					SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);			//2026-01-20	增加记录时间戳
					LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_RadarPersonDetected);
					
					VCard_Info.ExistState = SOMEONE;
					DevActionGlobal.Person_Detected = VCard_Info.ExistState;
					
					VCard_Info.Last_ConGroupType = 0x00;
					VCard_Info.ConGroupIndx = DevActionGlobal.VC_ConNToSGruop + 1;
					Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-长时间检测 回路%d %d - %.02f 判定有人-",i,VCard_Info.DetInfo.Trigger_Thres[i],VCard_Info.ActThreshold[i]);
					
					for(uint8_t i= 1; i < VIRTUAL_PORT_MAX; i++)
					{
						if(VCard_Info.Port_Info[i].HPort_Type != 0x00)
						{
							VCard_Info.DetInfo.DetWinTrigger[i] = VCard_Info.DetInfo.DetWinTotalNum[i];
							VCard_Info.ActThreshold[i] = 100;
							VCard_Info.DetInfo.DetWinIdex[i] = 0;
							VCard_Info.DetInfo.FullFlag[i] = 0x01;
							DetWin_WriteData((i - 1), 0xFF, ((VCard_Info.DetInfo.DetWinTotalNum[i] / 8) + 1 ) );
						}
					}
					
					break;
				}
			}
		}
	}else if( (VCard_Info.ExistState == SOMEONE) && (VCard_Info.ConGroupIndx == (DevActionGlobal.VC_ConNToSGruop + 1) ) )
	{
        PortEn_Cnt = 0x00;
        PortEn_max = 0x00;
        
		/*当前有人状态，且条件逻辑判断处于有人至无人 第一步时，执行长时间判断：启用的回路，任意一个满足回路对应的阈值判断，则条件成立，检测状态变为无人*/
		for(uint8_t i = 1; i < VIRTUAL_PORT_MAX; i++)
		{
			if( (VCard_Info.Port_Info[i].PortEnFlag == 0x01) && (VCard_Info.DetInfo.Release_Thres[i] < 100) )
			{
                PortEn_max++;       //记录启动长时间检测的回路数量
				if(VCard_Info.ActThreshold[i] <= VCard_Info.DetInfo.Release_Thres[i])
				{
					PortEn_Cnt++;   //记录满足判定条件的启动长时间检测的回路数量
				}
			}
		}
        
        //20260129 -无卡取电 - 有人状态:长时间检测无人 - 所有参与长时间判断端口，全部判断无人才认为房间无人
        if((PortEn_Cnt != 0x00)&&(PortEn_max != 0x00))
        {
            if(PortEn_Cnt == PortEn_max)
            {
                KeepFlag = 0x01;
                
                /*将状态改变为无人，且所有回路的缓冲区全部按照“无人”状态进行填充，并重新开始计数*/
                VCard_Info.Action |= VC_Event_RadarPersonLeft_Flag;
                SRAM_Write_Byte(VC_EventID_RadarPersonLeft,SRAM_UDP_ELEReport_VirtualCard);
                SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);			//2026-01-20	增加记录时间戳
                LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_RadarPersonLeft);
                
                VCard_Info.ExistState = NOONE;
                DevActionGlobal.Person_Detected = VCard_Info.ExistState;
                
                VCard_Info.ConGroupIndx = VC_CONDGROUP_Default_StartGroup;		//进入无人至有人判断的第一步
                Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-长时间检测所有回路: 判定无人-");
                
                for(uint8_t i= 1; i < VIRTUAL_PORT_MAX; i++)
                {
                    if(VCard_Info.Port_Info[i].HPort_Type != 0x00)
                    {
                        VCard_Info.DetInfo.DetWinTrigger[i] = 0x00;
                        VCard_Info.ActThreshold[i] = 0;
                        VCard_Info.DetInfo.DetWinIdex[i] = 0;
                        VCard_Info.DetInfo.FullFlag[i] = 0x01;
                        DetWin_WriteData((i - 1), 0x00, ((VCard_Info.DetInfo.DetWinTotalNum[i] / 8) + 1 ) );
                    }
                }                
            }
        }
        
        PortEn_Cnt = 0x00;
        PortEn_max = 0x00;
	}
	/*根据阈值判断有无人结束*/
	
	/*未取电情况下，按键取电*/
	
	if( DevActionGlobal.People_Flag == 0x01 )     
	{
		DevActionGlobal.People_Flag = 0x00;
		
		KeepFlag = 0x01;
		
		/*按键有触发，无论当前室内状态判断为无人还是有人，都将状态修改为有人，同时长时间检测逻辑中的缓存值全部刷新为有人*/
		VCard_Info.Action |= VC_Event_RS485ButtonPress_Flag;
		
		Udp_Addtion_Roomstate(BUS_Public.type,BUS_Public.addr,0x00,VC_EventID_RS485ButtonPress);
		SRAM_Write_Byte(VC_EventID_RS485ButtonPress,SRAM_UDP_ELEReport_VirtualCard);
		SRAM_Write_DW(SysTick_1ms,SRAM_UDP_ELEReport_VirtualCard_Tick);			//2026-01-20	增加记录时间戳
		LOG_LogicInfo_DebugRecord("VCLog:T4:%d",VC_EventID_RS485ButtonPress);
		
		VCard_Info.ExistState = SOMEONE;
		DevActionGlobal.Person_Detected = VCard_Info.ExistState;
		VCard_Info.Last_ConGroupType = 0x00;
		Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-室内按键触发 当前条件:%d %d %d--",VCard_Info.ConGroupIndx,(DevActionGlobal.VC_ConNToSGruop + 1),DevActionGlobal.VC_ConSToNGruop);
		if( (VCard_Info.ConGroupIndx < (DevActionGlobal.VC_ConNToSGruop + 1)) || (VCard_Info.ConGroupIndx > DevActionGlobal.VC_ConSToNGruop) )
		{
			VCard_Info.ConGroupIndx = DevActionGlobal.VC_ConNToSGruop + 1;	//有人->无人判断第一步
			Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-室内按键触发 条件跳转至:%d --",VCard_Info.ConGroupIndx);
		}
		
		for(uint8_t i= 1; i < VIRTUAL_PORT_MAX; i++)
		{
			if(VCard_Info.Port_Info[i].HPort_Type != 0x00)
			{
				VCard_Info.DetInfo.DetWinTrigger[i] = VCard_Info.DetInfo.DetWinTotalNum[i];
				VCard_Info.ActThreshold[i] = 100;
				VCard_Info.DetInfo.DetWinIdex[i] = 0;
				VCard_Info.DetInfo.FullFlag[i] = 0x01;
				DetWin_WriteData((i - 1), 0xFF, ((VCard_Info.DetInfo.DetWinTotalNum[i] / 8) + 1 ) );
			}
		}

	}
	/*未取电情况下，按键取电*/
	
	//端口变化状态，只处理一次，便清楚变化状态
	if( (VCard_Info.PortStateAct[0] != VCard_Info.PortState[0])		\
		|| (VCard_Info.PortStateAct[1] != VCard_Info.PortState[1])	\
		|| (VCard_Info.PortStateAct[2] != VCard_Info.PortState[2])	\
		|| (VCard_Info.PortStateAct[3] != VCard_Info.PortState[3])	\
		|| (VCard_Info.PortStateAct[4] != VCard_Info.PortState[4])	\
		|| (VCard_Info.PortStateAct[5] != VCard_Info.PortState[5])	\
		|| (VCard_Info.PortStateAct[6] != VCard_Info.PortState[6])	\
		|| (VCard_Info.PortStateAct[7] != VCard_Info.PortState[7])	\
		|| (VCard_Info.PortStateAct[8] != VCard_Info.PortState[8])	\
		|| (VCard_Info.PortStateAct[9] != VCard_Info.PortState[9])	\
		|| (VCard_Info.PortStateAct[10] != VCard_Info.PortState[10]) )
	{
		KeepFlag = 0x01;
		
		VCard_Info.PortStateAct[0] = VCard_Info.PortState[0];
		VCard_Info.PortStateAct[1] = VCard_Info.PortState[1];
		VCard_Info.PortStateAct[2] = VCard_Info.PortState[2];
		VCard_Info.PortStateAct[3] = VCard_Info.PortState[3];
		VCard_Info.PortStateAct[4] = VCard_Info.PortState[4];
		VCard_Info.PortStateAct[5] = VCard_Info.PortState[5];
		VCard_Info.PortStateAct[6] = VCard_Info.PortState[6];
		VCard_Info.PortStateAct[7] = VCard_Info.PortState[7];
		VCard_Info.PortStateAct[8] = VCard_Info.PortState[8];
		VCard_Info.PortStateAct[9] = VCard_Info.PortState[9];
		VCard_Info.PortStateAct[10] = VCard_Info.PortState[10];
	}
	
	if(0x01 == KeepFlag)
	{
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&VCard_Info, sizeof(VIRTUALCARD_STRUCT));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAddr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&VCard_Info,sizeof(VIRTUALCARD_STRUCT),DevAddr+Dev_Privately);
	}
}

uint8_t Dev_VirtualCard_InType_Get(uint32_t DevAddr, uint16_t DevInputLoop, uint16_t DevInputType)
{
	Device_Public_Information_G BUS_Public;   //共用	
	VIRTUALCARD_STRUCT VCard_Info;
	uint8_t Ret = CtrlInvalid;         //控制无效
	
	
	if(DevAddr == 0x00)	return Ret;
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAddr);	//拷贝所有共有数据	
	SRAM_DMA_Read_Buff((uint8_t *)&VCard_Info,sizeof(VIRTUALCARD_STRUCT),DevAddr+Dev_Privately);	/*拷贝设备私有信息*/
	
	switch(DevInputType)
	{
		case VC_EventID_DoorSensor:    			//开门进入
		case VC_EventID_CardedPersonLeft:      	//卡在人离
		case VC_EventID_UncardedPersonLeft:		//无卡人离
		case VC_EventID_RadarPersonDetected:	//室内雷达有人
		case VC_EventID_RadarPersonLeft:		//室内雷达无人
		case VC_EventID_RS485ButtonPress:		//室内按键触发
		case VC_EventID_ShortAway:				//短暂人离
		case VC_EventID_LongAway:				//长时间人离
		case VC_EventID_ShortAwayTimeout:		//短暂人离超时事件
		case VC_EventID_LongAwayTimeout:		//长期人离超时事件
		
			if( ( VCard_Info.Action & (0x01 << (DevInputType - 1)) ) != 0x00 )
			{
				Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"-无卡取电 事件触发:%02x - %02x ",VCard_Info.Action,DevInputType);
				VCard_Info.Action &= ~(0x01 << (DevInputType - 1));
				Ret = CtrlValid;
			}
			break;
		default:
			break;
	}
	
	
	if(CtrlValid == Ret)
	{
		Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"VirtualCard Action Clear!!!!");
		
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&VCard_Info, sizeof(VIRTUALCARD_STRUCT));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAddr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&VCard_Info,sizeof(VIRTUALCARD_STRUCT),DevAddr+Dev_Privately);
		
	}
	
	return Ret;
}



void BLV_VirtualCard_Control_State(uint32_t CfgDevAddIn, uint16_t DevInputAddr, uint32_t devaddr,uint16_t DevOutputLoop,uint16_t start)
{
	uint8_t temp1 = 0,temp_start = 0,temp_content = 0;
	Device_Public_Information_G BUS_Public;   //共用
	VIRTUALCARD_STRUCT VCard_Info;
	
	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"BLV_NoCard_Control_State");
	
	if(devaddr == 0x00)	return;
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),devaddr);	//拷贝所有共有数据	
	SRAM_DMA_Read_Buff((uint8_t *)&VCard_Info,sizeof(VIRTUALCARD_STRUCT),devaddr+Dev_Privately);
	
	temp_start = start&0xFF;
	temp_content = (start >> 8) & 0xFF;
	
	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"NoCard Ctrl:%d  %d",temp_start,temp_content);
	
	switch(temp_start)
	{
		case 0x03:   //设置窗口检测时间
			if(temp_content <= 240)
			{
				//VCard_Info.DetWinTime = temp_content;
				VCard_Info.PortInit_Flag = 0x00;
			}
			temp1++;
			break;
		default:    //	其他情况直接返回
			break;
	}
	
	if(temp1 != 0x00)
	{
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&VCard_Info, sizeof(VIRTUALCARD_STRUCT));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),devaddr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&VCard_Info,sizeof(VIRTUALCARD_STRUCT),devaddr+Dev_Privately);
	}
}



