#include "../User/include/includes.h"

VIRTUALCARD_STRUCT VCard_Info;
SENSORDET_INFO_T sensor_info;
CONDITION_STRUCT condata;

uint8_t portstate = 0;  //长时间检测窗口的有无人判断

//长时间判断缓冲区
//uint8_t portBuff[810] = {0x00};
uint8_t portBuff[DETECTION_Window_OnlyPort*3] = {0x00};


//1、初始化相关IO、结构体
void Sensor_Init(void)
{
    memset(&sensor_info,0,sizeof(SENSORDET_INFO_T));
    memset(&VCard_Info,0,sizeof(VIRTUALCARD_STRUCT));
    memset(&condata,0,sizeof(CONDITION_STRUCT));

    //传感器输入
    GPIOA_ModeCfg(WashRoom_Pin, GPIO_ModeIN_PU);
    GPIOA_ModeCfg(BedRoom_Pin, GPIO_ModeIN_PU);
    GPIOA_ModeCfg(GateWay_Pin, GPIO_ModeIN_PU);
    GPIOA_ModeCfg(Retain_Pin, GPIO_ModeIN_PU);

    //输出
    GPIOA_ModeCfg(DET_EXIST1, GPIO_ModeOut_PP_5mA);
    GPIOA_ModeCfg(DET_EXIST2, GPIO_ModeOut_PP_5mA);
    GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeOut_PP_5mA);
    GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
    GPIOA_ModeCfg(GPIO_Pin_10, GPIO_ModeOut_PP_5mA);
    GPIOA_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_5mA);


    //初始化为低
    GPIOA_SetBits(DET_EXIST1);
    GPIOA_SetBits(DET_EXIST2);
    GPIOA_SetBits(GPIO_Pin_8);
    GPIOA_SetBits(GPIO_Pin_9);
    GPIOA_SetBits(GPIO_Pin_10);
    GPIOA_SetBits(GPIO_Pin_11);

}

uint16_t CRC16(uint8_t *aStr ,uint16_t len)
{
    uint16_t xda , xdapoly;
    uint16_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 = (uint8_t)(xda & 0x01);
            xda >>= 1;
            if( xdabit ) xda ^= xdapoly;
        }
    }
    return xda;
}

/******************************************************
 * @name    : Get_Port_State
 * @brief   : 获得端口状态
 * @param   : ch : 对应端口状态
 ******************************************************* */
uint8_t Get_Port_State(uint8_t ch)
{
    uint8_t state = DET_SER_PRESS;

    switch(ch)
    {
        case DET_CH0:   //插卡信号 - 暂无
            state = DET_SER_LOOSEN;
            break;
        case DET_CH1:       //门磁
            if(GPIOA_ReadPortPin(Retain_Pin) != 0x00) {
                state = DET_SER_LOOSEN;
            }
            break;
        case DET_CH2:
            if(GPIOA_ReadPortPin(WashRoom_Pin) != 0x00) {
                state = DET_SER_LOOSEN;
            }
            break;
        case DET_CH3:
            if(GPIOA_ReadPortPin(BedRoom_Pin) != 0x00){
                state = DET_SER_LOOSEN;
            }
            break;
        case DET_CH4:
            if(GPIOA_ReadPortPin(GateWay_Pin) != 0x00){
                state = DET_SER_LOOSEN;
            }
            break;
        default:
            state = DET_SER_LOOSEN;
            break;
    }

    return state;
}


/******************************************************
 * @name    : DIP_ScanTask
 * @brief   : 端口状态消抖
 * @param   :
 ******************************************************* */
void DIP_ScanTask(void)
{
    static uint32_t update_20ms = 0;

    if (SysTick_1ms - update_20ms > DIP_SCAN_Time)
    {
        update_20ms = SysTick_1ms;

        for (uint8_t i = 0; i < DET_MAX; i++)
        {
            if (Get_Port_State(i) == DET_SER_PRESS)
            {
                VCard_Info.g_Dip.delayCnt_OFF[i] = 0;
                if (VCard_Info.g_Dip.delayCnt_ON[i] < DIP_DELAY_COUNT)
                {
                    VCard_Info.g_Dip.delayCnt_ON[i]++;
                }
                else
                {
                    VCard_Info.g_Dip.DIP_val |= (DIP_VAL_ON << i);
                    VCard_Info.g_Dip.delayCnt_ON[i] = 0;
                }
            }
            else
            {
                VCard_Info.g_Dip.delayCnt_ON[i] = 0;
                if (VCard_Info.g_Dip.delayCnt_OFF[i] < DIP_DELAY_COUNT)
                {
                    VCard_Info.g_Dip.delayCnt_OFF[i]++;
                }
                else
                {
                    VCard_Info.g_Dip.DIP_val &= ~(DIP_VAL_ON << i);
                    VCard_Info.g_Dip.delayCnt_OFF[i] = 0;
                }
            }
        }
    }
}


/******************************************************
 * @name    : Get_DETCH_State
 * @brief   : 获得消抖后端口雷达状态
 * @param   : ch : 对应端口状态
 ******************************************************* */
uint8_t Get_DETCH_State(uint8_t ch)
{
    uint8_t state = DET_SER_LOOSEN;

    if( (ch < DET_MAX)&&((VCard_Info.g_Dip.DIP_val&(0x01<<ch)) != 0x00) )
    {
        state = DET_SER_PRESS;
    }

    return state;
}



/******************************************************
 * @name    : FZL_CtrlOut
 * @brief   : 控制输出泛智联电平
 * @param   : state : 控制状态
 ******************************************************* */
void FZL_CtrlOut(uint8_t state)
{

    switch(state)
    {
    case 0x00:
        GPIOA_SetBits(DET_EXIST1);
        GPIOA_SetBits(DET_EXIST2);
        GPIOA_SetBits(GPIO_Pin_8);
        GPIOA_SetBits(GPIO_Pin_9);
        GPIOA_SetBits(GPIO_Pin_10);
        GPIOA_SetBits(GPIO_Pin_11);

        sensor_info.det_ctrlout_state = 0x00;
        break;
    case 0x01:
        GPIOA_ResetBits(DET_EXIST1);
      //  GPIOA_ResetBits(GPIO_Pin_10);

        sensor_info.det_ctrlout_state = 0x01;
        sensor_info.det_action_tick = SysTick_1ms;
       break;
    case 0x02:

        GPIOA_ResetBits(DET_EXIST2);
       // GPIOA_ResetBits(DET_EXIST1);

        sensor_info.det_ctrlout_state = 0x01;
        sensor_info.det_action_tick = SysTick_1ms;
        break;
    case 0x03:

        GPIOA_ResetBits(GPIO_Pin_8);
        sensor_info.det_ctrlout_state = 0x01;
        sensor_info.det_action_tick = SysTick_1ms;
        break;
    case 0x04:
      //  GPIOA_SetBits(DET_EXIST1);
        GPIOA_ResetBits(GPIO_Pin_9);

        sensor_info.det_ctrlout_state = 0x01;
        sensor_info.det_action_tick = SysTick_1ms;
        break;
    case 0x05:

        GPIOA_ResetBits(GPIO_Pin_10);
        sensor_info.det_ctrlout_state = 0x01;
        sensor_info.det_action_tick = SysTick_1ms;
        break;
    case 0x06:

        GPIOA_ResetBits(GPIO_Pin_11);
        sensor_info.det_ctrlout_state = 0x01;
        sensor_info.det_action_tick = SysTick_1ms;
        break;

    default:
        break;
    }

}


/*无卡取电 设置长时间检测缓存数据 用于整个缓冲区置位或清楚数据使用*/
void DetWin_WriteData(uint8_t port, uint8_t state, uint16_t size)
{
    uint16_t  detaddr = 0x00;
    uint16_t writetime = 0x00;
    uint16_t surplus = 0x00;

    writetime = size ;

    if( writetime > DETECTION_Window_OnlyPort )
    {
        writetime = DETECTION_Window_OnlyPort;
    }
   // Dbg_Println(DBG_BIT_Debug_STATUS,"Write Len:%d",writetime);
    detaddr = port * DETECTION_Window_OnlyPort;

    for(uint8_t i = 0; i < writetime; i++)
    {
        portBuff[detaddr+i] = state;
    }
}


/*无卡取电 设置长时间检测缓存数据 - 针对于Bit写入*/
void DetWin_WriteData_Bit(uint8_t port,uint16_t idex,uint8_t state)
{
    uint16_t  detaddr = 0;
    uint8_t data_val = 0;
    uint8_t bit_offset = 0;
    uint8_t bit_remian = 0;

    if( port >=  3)    return;
    if( idex >= DETECTION_Window_OnlyPort*8) return;    //一个端口最多存多少位

    if(idex != 0x00)
    {
        bit_remian = idex % 8;      //取余
        bit_offset = idex / 8;      //地址偏移
    }

//    if( (idex > 0x08) && (bit_remian) != 0x00 )
//    {
//        detaddr = (uint16_t)(port * DETECTION_Window_OnlyPort) + (bit_offset) + 1;
//    }else {
//        detaddr = (uint16_t)(port * DETECTION_Window_OnlyPort) + (bit_offset);
//    }

    detaddr = (uint16_t)(port * DETECTION_Window_OnlyPort) + (bit_offset);
    data_val = portBuff[detaddr];

    if(state == 0x01)
    {
        data_val |= 0x01 << bit_remian;
    }else {
        data_val &= ~(0x01 << bit_remian);
    }

    portBuff[detaddr] = data_val;
}


/***************************************************************
 * 函数名        : DetWin_ReadData_Bit
 * 函数功能    : 无卡取电 读取长时间检测缓存数据 - 针对于Bit读取
 * 输入参数    : Port : 端口号,注意不记录插卡取电端口
 *         idex : 要读取的数据下标，按bit
 * 返回参数    :
 ****************************************************************/
uint8_t DetWin_ReadData_Bit(uint8_t port,uint16_t idex)
{
    uint32_t  detaddr = 0;
    uint8_t data_val = 0;
    uint8_t bit_offset = 0;
    uint8_t bit_remian = 0;

    if( port >=  3)    return 0x00;
    if( idex >= DETECTION_Window_OnlyPort*8) return 0x00;

    if(idex != 0x00)
    {
        bit_remian = idex % 8;      //取余
        bit_offset = idex / 8;      //地址偏移
    }

//    if( (idex > 0x08) && (bit_remian) != 0x00 )
//    {
//        detaddr = (uint16_t)(port * DETECTION_Window_OnlyPort) + (bit_offset) + 1;
//    }else {
//        detaddr = (uint16_t)(port * DETECTION_Window_OnlyPort) + (bit_offset);
//    }

    detaddr = (uint16_t)(port * DETECTION_Window_OnlyPort) + (bit_offset);
    data_val = portBuff[detaddr];

    if( (data_val & (0x01 << bit_remian)) != 0x00 )
    {
        return 0x01;
    }

    return 0x00;
}


void Blv_CardlessPower_Tack(void)
{
    uint8_t condata_save_flag = 0x00;
    uint32_t temp_jumpe_time = 0x00;
    uint32_t temp_tickout = 0x00;
    uint32_t temp_init_time = 0x00;

    //1、初始化
    if(VCard_Info.PortInit_Flag == 0x00)
    {
        uint8_t temp[15];
        uint8_t temp_loop = 0;
        memset(&temp,0,sizeof(temp));

        for(uint8_t i = 0; i < VIRTUAL_PORT_MAX; i++)      //初始化映射端口信息
        {
            memcpy(&temp, PortInfo[i], sizeof(VPORT_INFO_STRUCT) );
           // Dbg_Print_Buff(DBG_BIT_PC_COMM,"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] = DET_SER_LOOSEN;

                //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];

              //  Dbg_Println(DBG_BIT_DEVICE_STATUS,"Det1:%d",VCard_Info.DetInfo.DetWinTotalNum[temp_loop]);
                switch(temp[9])
                {
                    case 0x01:    //秒
                        if(VCard_Info.DetInfo.DetWinTotalNum[temp_loop] >= DETECTION_Window_Sec_Max)
                        {
                            VCard_Info.DetInfo.DetWinTotalNum[temp_loop] = DETECTION_Window_Sec_Max;
                        }
                        break;
                    case 0x02:    //分
                        if(VCard_Info.DetInfo.DetWinTotalNum[temp_loop] >= DETECTION_Window_Min_Max)
                        {
                            VCard_Info.DetInfo.DetWinTotalNum[temp_loop] = DETECTION_Window_Min_Max;
                        }
                        VCard_Info.DetInfo.DetWinTotalNum[temp_loop] *= 60;
                        break;
                    case 0x03:    //时
                        if(VCard_Info.DetInfo.DetWinTotalNum[temp_loop] >= DETECTION_Window_Hour_Max)
                        {
                            VCard_Info.DetInfo.DetWinTotalNum[temp_loop] = DETECTION_Window_Hour_Max;
                        }
                        VCard_Info.DetInfo.DetWinTotalNum[temp_loop] *= 3600;
                        break;
                }
               // Dbg_Println(DBG_BIT_DEVICE_STATUS,"Det2:%d",VCard_Info.DetInfo.DetWinTotalNum[temp_loop]);
                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;

                //YYW,20251011,初始化清空下标和触发百分比。
                VCard_Info.DetInfo.DetWinTrigger[temp_loop] = 0x00;
                VCard_Info.ActThreshold[temp_loop] = 0;

            }
            WDT_Feed();
            Dbg_Println(DBG_BIT_DEVICE_STATUS,"初始化映射端口%d 映射类型:%d 映射回路:%d 阈值:%d-%d 使能标志:%d - %dS",\
                temp_loop,\
                VCard_Info.Port_Info[temp_loop].HPort_Type,\
                VCard_Info.Port_Info[temp_loop].HPort_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;
        VCard_Info.ConGroupIndx = VC_CONDGROUP_Default_StartGroup;
        VCard_Info.ExistState = NOONE;
        VCard_Info.rdrsta_change_flag = 0x01;
        VCard_Info.Action = 0x00;
        //YYW,20251011,清空长时间缓冲区
        memset(portBuff,0x00,(DETECTION_Window_OnlyPort*3));
        for(uint8_t i = 0x00;i<VIRTUAL_GP_NUM_MAX;i++ ){
           g_portGp.PortGroupInfo[i][14]= 0x00;
        }

    }



    //2、端口变化检测
    if((SysTick_1ms - VCard_Info.PortTick >= 50) && (VCard_Info.PortInit_Flag == 0x01))
    {
        VCard_Info.PortTick = SysTick_1ms;
        VCard_Info.DetInfo.Det1sTime++;

        //2.1、端口变化检测
        for(uint8_t i = 0; i < VIRTUAL_PORT_MAX; i++)
        {
            if (Get_DETCH_State(i) == DET_SER_PRESS)
            {
                VCard_Info.PortState[i] = DET_SER_PRESS;
                VCard_Info.DetInfo.TriggerNum[i]++;

                if(VCard_Info.PortState[i] != VCard_Info.PortStateLast[i])
                {
                    VCard_Info.rdrsta_change_flag = 0x01;

                    if(VCard_Info.PortStateLast[i] == DET_SER_LOOSEN)
                    {
                        if(i == 0x01){  //门磁关，端口状态为：释放到触发
                            //VCard_Info.Action |= VC_Event_DoorSensorClose_Flag;

                        }else if(i == 0x02){    //洗手间雷达感应有人，端口状态为：释放到触发
                            //VCard_Info.Action |= VC_Event_BathroomRadarOn_Flag;
                            sensor_info.bath_rarON_flag = 0x01;
                            sensor_info.bath_rarOn_time = SysTick_1ms;
                        }
                    }

                    VCard_Info.PortStateLast[i] = VCard_Info.PortState[i];

                    VCard_Info.PortStateAct[i] = DET_OPENTOCLOSE;

                    Dbg_Println(DBG_BIT_DEVICE_STATUS,"取电，触发 - CH%d",i);
                    if(i == 0x00)
                    {
                        VCard_Info.CardState = DET_SER_PRESS;
                    }

                }else{
                    VCard_Info.PortStateAct[i] = DET_SER_PRESS;      //电平状态，当前无电平变化
                }
            }
            else if(Get_DETCH_State(i) == DET_SER_LOOSEN)
            {
                VCard_Info.PortState[i] = DET_SER_LOOSEN;

                if(VCard_Info.PortState[i] != VCard_Info.PortStateLast[i])
                {
                    VCard_Info.rdrsta_change_flag = 0x01;

                    if(VCard_Info.PortStateLast[i] == DET_SER_PRESS)
                    {
                        if(i == 0x01){          //门磁开，端口状态为：触发到释放
                        //VCard_Info.Action |= VC_Event_DoorSensorOpen_Flag;
                            sensor_info.door_rarON_flag = 0x01;
                            sensor_info.door_rarOn_time = SysTick_1ms;
                        }else if(i == 0x02){    //洗手间雷达感应无人，端口状态为：触发到释放
                            //VCard_Info.Action |= VC_Event_BathroomRadarOFF_Flag;
                            sensor_info.bath_rarOFF_flag = 0x01;
                            sensor_info.bath_rar_deltime = SysTick_1ms;
                        }
                    }

                    VCard_Info.PortStateLast[i] = VCard_Info.PortState[i];

                    VCard_Info.PortStateAct[i] = DET_CLOSETOOPEN;
                    Dbg_Println(DBG_BIT_DEVICE_STATUS,"取电，不触发 - CH%d",i);

                    if(i == 0x00)  //插拔卡状态
                    {
                        VCard_Info.CardState = DET_SER_LOOSEN;
                    }
                }else{
                    VCard_Info.PortStateAct[i] = DET_SER_LOOSEN;        //电平状态，当前无电平变化
                }
            }


            //2.2、长时间检测
            if( ( (VCard_Info.ExistState == NOONE) && (VCard_Info.ConGroupIndx == VC_CONDGROUP_Default_StartGroup) )
                || ( (VCard_Info.ExistState == SOMEONE) && (VCard_Info.ConGroupIndx == (g_portGp.VC_ConNToSGruop + 1)) ) )
            {
                if((i > 0x01) && (VCard_Info.Port_Info[i].PortEnFlag == 0x01))     //端口1,2固定为有卡取电、门磁设备的回路，不参与统计
                {
                    portstate = 0x00;
                    if(VCard_Info.DetInfo.Det1sTime == 300)     //50ms读一次状态， 15s记录一次，内检测300次
                    {
                        /*1S内 触发时间大于500ms，才算触发，不是持续触发也算 */
                        if(VCard_Info.DetInfo.TriggerNum[i] >= 150)
                        {
                            VCard_Info.DetInfo.TriggerNum[i] = 0x00;
                            portstate = 0x01;
                        }else {
                            portstate = 0x00;
                        }

                        if(VCard_Info.DetInfo.FullFlag[i] == 0x01)
                        {
                            //检测窗口 缓冲数据已满
                            if( DetWin_ReadData_Bit((i-2),VCard_Info.DetInfo.DetWinIdex[i]) != portstate )
                            {
                                //与之前状态不一致
                                if(portstate == 0x01)
                                {
                                    if(VCard_Info.DetInfo.DetWinTrigger[i] + DETECTION_Window_BitMin < VCard_Info.DetInfo.DetWinTotalNum[i])
                                    {
                                        VCard_Info.DetInfo.DetWinTrigger[i] += DETECTION_Window_BitMin;
                                    }else{
                                        VCard_Info.DetInfo.DetWinTrigger[i] = VCard_Info.DetInfo.DetWinTotalNum[i];
                                    }
                                }else {
                                    if(VCard_Info.DetInfo.DetWinTrigger[i] > DETECTION_Window_BitMin)
                                    {
                                        VCard_Info.DetInfo.DetWinTrigger[i] -= DETECTION_Window_BitMin;
                                    }else{
                                        VCard_Info.DetInfo.DetWinTrigger[i] = 0;
                                    }
                                }
                            DetWin_WriteData_Bit((i-2),VCard_Info.DetInfo.DetWinIdex[i],portstate);
                            }else {
                                //与之前状态一样，触发计数不改变
                            }
                        }else {
                            //检测窗口 缓冲数据未满
                            if(portstate == 0x01)
                            {
                                if(VCard_Info.DetInfo.DetWinTrigger[i] + DETECTION_Window_BitMin < VCard_Info.DetInfo.DetWinTotalNum[i])
                                {
                                    VCard_Info.DetInfo.DetWinTrigger[i] += DETECTION_Window_BitMin;
                                }else{
                                    VCard_Info.DetInfo.DetWinTrigger[i] = VCard_Info.DetInfo.DetWinTotalNum[i];
                                }

                            }
                            DetWin_WriteData_Bit((i-2),VCard_Info.DetInfo.DetWinIdex[i],portstate);
                        }

                        if( (VCard_Info.DetInfo.DetWinIdex[i]*DETECTION_Window_BitMin) < 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];
                        VCard_Info.ActThreshold[i] = (VCard_Info.DetInfo.DetWinTrigger[i] * 100) / VCard_Info.DetInfo.DetWinTotalNum[i];
                        Dbg_Println(DBG_BIT_PC_COMM,"端口 %d 触发:%d 次数：%d - %d   触发阈值：%d",i + 1,portstate,\
                            VCard_Info.DetInfo.DetWinTrigger[i],VCard_Info.DetInfo.DetWinTotalNum[i],(uint32_t)VCard_Info.ActThreshold[i]);
                    }
                }
            }else {
                //暂停长时间统计
                //Dbg_Println(DBG_BIT_PC_COMM,"回路%d 暂停长时间统计",i + 1);
            }
        }

        //2.3、打印调试信息
        if(VCard_Info.DetInfo.Det1sTime == 300)     //50ms读一次状态 15s内检测200次
        {
            Dbg_Println(DBG_BIT_PC_COMM,"- 状态:%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],\
                (SysTick_1s - VCard_Info.Condition_Trigger_Tick),(SysTick_1s - VCard_Info.Last_Trigger_Tick) );

            Ble_Printfln(DBG_BIT_BLE_STATUS,"-状态:%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],\
                    (SysTick_1s - VCard_Info.Condition_Trigger_Tick),(SysTick_1s - VCard_Info.Last_Trigger_Tick) );

            VCard_Info.DetInfo.Det1sTime = 0x00;
        }

    }

    //3、有人无人条件判断执行开始
     if(VCard_Info.ExistState == NOONE)
     {
         for(uint8_t j = 0; j < g_portGp.VC_ConNToSSubset; j++)
         {
             condata_save_flag = 0x00;

             //条件组初始化参数,YYW,
             memset(&condata,0,sizeof(CONDITION_STRUCT));
             memcpy(&condata, g_portGp.PortGroupInfo[j], sizeof(CONDITION_STRUCT) );

             /*“第一步”要是满足的话，条件便重新判断*/
             if( (condata.Condi_Gruop == VC_CONDGROUP_Default_StartGroup) || (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.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]))  )
                 {
                     //满足触发条件
                     if(condata.Trigger_Flag != 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 != VC_CONDGROUP_Default_StartGroup) && (SysTick_1s - VCard_Info.Last_Trigger_Tick >= temp_tickout) )
                 {
                     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_PC_COMM,"-条件%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 ) )
                     {
                         condata_save_flag = 0x01;

                         //条件 - 满足时间，判定成立
                         condata.Trigger_Flag = 0x00;
                        // condata.Trigger_Tick = SysTick_1s;

                         VCard_Info.Condition_Trigger_Tick = SysTick_1s;

                         /*防止过度打印调试信息*/
                         if( condata.Condi_Gruop == VCard_Info.ConGroupIndx )
                         {
                             Dbg_Println(DBG_BIT_PC_COMM,"无人至有人 %d 条件组成立 %d",condata.Condi_Gruop,VCard_Info.ConGroupIndx);
                           //Dbg_Println(DBG_BIT_PC_COMM,"- 状态:%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]);
                           Ble_Printfln(DBG_BIT_BLE_STATUS,"无人至有人 %d 条件组成立 %d",condata.Condi_Gruop,VCard_Info.ConGroupIndx);
                         }else {
                             Dbg_Println(DBG_BIT_PC_COMM,"无人至有人 %d 条件组成立 %d,%d",condata.Condi_Gruop,VCard_Info.ConGroupIndx,j);
                           //Dbg_Println(DBG_BIT_PC_COMM,"- 状态:%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]);
                             Ble_Printfln(DBG_BIT_BLE_STATUS,"无人至有人 %d 条件组成立 %d,%d",condata.Condi_Gruop,VCard_Info.ConGroupIndx,j);
                         }


                         //切换条件组，同时记录条件成立时间，用于下一个条件超时判定使用
                         VCard_Info.Last_Trigger_Tick = SysTick_1s;
                         VCard_Info.ConGroupIndx = condata.Condi_Gruop + 1;
                         VCard_Info.Last_ConGroupType = 0x00;

                         if( VCard_Info.ConGroupIndx > g_portGp.VC_ConNToSGruop )
                         {
                             VCard_Info.ConGroupIndx = g_portGp.VC_ConNToSGruop + 1;
                             Dbg_Println(DBG_BIT_PC_COMM,"-条件%d-%d 判定有人-",condata.Condi_Gruop,condata.Condi_Subset);
                             VCard_Info.ExistState = SOMEONE;
                             VCard_Info.rdrsta_change_flag = 0x01;
                             Dbg_Println(DBG_BIT_PC_COMM,"-事件:开门进入--");
                             VCard_Info.Action |= VC_Event_PersonDet_Flag;

                             /*清空回路的长时间检测状态 - 注意回路1默认是插卡取电，不进入长时间统计*/
                             for(uint8_t i= 2; 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 - 2), 0xFF, ((VCard_Info.DetInfo.DetWinTotalNum[i] / (8*DETECTION_Window_BitMin)) + 1 ) );
                                 }
                             }
                         }
                     }
                 }

                 if(condata_save_flag == 0x01)
                 {
                     memcpy(g_portGp.PortGroupInfo[j],&condata , sizeof(CONDITION_STRUCT) );
                 }
             }
         }
     }
     else if(VCard_Info.ExistState == SOMEONE)
     {
         /*有人至无人判断*/
         for(uint8_t j = 0; j < g_portGp.VC_ConSToNSubset; j++)
         {
             condata_save_flag = 0x00;
             //条件组初始化参数,YYW,
             memset(&condata,0,sizeof(CONDITION_STRUCT));
             memcpy(&condata, g_portGp.PortGroupInfo[j + g_portGp.VC_ConNToSSubset], sizeof(CONDITION_STRUCT) );

             /*“第一步”要是满足的话，条件便重新判断*/
             if( (condata.Condi_Gruop == (g_portGp.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 {
                     //秒
                 }

                 //YYW,20251009,短暂人离，长时间人离
                 if( (condata.Condi_Gruop != (g_portGp.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_PC_COMM,"产生短暂人离事件 - %d",condata.Condi_Gruop);
                          VCard_Info.Last_ConGroupType = 0x00;
                       //   VCard_Info.Action |= VC_Event_BrieflyLeaving_Flag;

                      }else if( ( VCard_Info.Last_ConGroupType == VC_CONDGROUP_LongTermLeaving_Type ) && (condata.Exist_Flag != VCard_Info.Last_ConGroupType) )
                      {
                          /*产生长时间人离事件 */
                       //   Dbg_Println(DBG_BIT_PC_COMM,"产生长时间人离事件 - %d",condata.Condi_Gruop);
                          VCard_Info.Last_ConGroupType = 0x00;
                      }
                  }

                 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])) )
                 {
                     //满足触发条件
                     if(condata.Trigger_Flag != 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 != g_portGp.VC_ConNToSGruop + 1) && (SysTick_1s - VCard_Info.Last_Trigger_Tick >= temp_tickout) )
                 {
                     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;
                     VCard_Info.ConGroupIndx = g_portGp.VC_ConNToSGruop + 1;      //条件返回有人->无人 判定的第一步

                     Dbg_Println(DBG_BIT_PC_COMM,"-条件%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 ) )
                     {
                         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_PC_COMM,"有人至无人 %d 条件组成立",condata.Condi_Gruop);
                             Ble_Printfln(DBG_BIT_BLE_STATUS,"有人至无人 %d 条件组成立",condata.Condi_Gruop);
                         }else {
                             //条件组 1 成立
                             Dbg_Println(DBG_BIT_PC_COMM,"有人至无人 %d 条件组成立 %d,%d",condata.Condi_Gruop,VCard_Info.ConGroupIndx,j);
                             Ble_Printfln(DBG_BIT_BLE_STATUS,"有人至无人 %d 条件组成立 %d,%d",condata.Condi_Gruop,VCard_Info.ConGroupIndx,j);
                         }

                         VCard_Info.Last_ConGroupType = condata.Exist_Flag;     //YYW,20251009,当前条件组成立，将条件类型保存下来用于触发"短暂人离"与"长时间人离"
                         //切换条件组，同时记录条件成立时间，用于下一个条件超时判定使用
                         VCard_Info.Last_Trigger_Tick = SysTick_1s;
                         VCard_Info.ConGroupIndx = condata.Condi_Gruop + 1;

                         if( VCard_Info.ConGroupIndx > g_portGp.VC_ConSToNGruop )
                         {
                             VCard_Info.ExistState = NOONE;
                             VCard_Info.rdrsta_change_flag = 0x01;
                             VCard_Info.ConGroupIndx = VC_CONDGROUP_Default_StartGroup;      //进入无人至有人判断的第一步

                             Dbg_Println(DBG_BIT_PC_COMM,"-条件%d-%d 判定无人-",condata.Condi_Gruop,condata.Condi_Subset);

                             if(VCard_Info.CardState == 0x01)
                             {
                                 //Dbg_Println(DBG_BIT_PC_COMM,"-事件:卡在人离--");
                                 //VCard_Info.Action |= VC_Event_CardedPersonLeft_Flag;
                             }else {
                                 Dbg_Println(DBG_BIT_PC_COMM,"-事件:无卡人离--");
                                 VCard_Info.Action |= VC_Event_NoPersonDet_Flag;
                             }

                             /*清空回路的长时间检测状态 - 注意回路1默认是插卡取电，不进入长时间统计*/
                             for(uint8_t i= 2; 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 - 2), 0x00, ((VCard_Info.DetInfo.DetWinTotalNum[i] / (8*DETECTION_Window_BitMin)) + 1 ) );
                                 }
                             }
                         }
                     }
                 }

                 if(condata_save_flag == 0x01)
                 {
                     memcpy(g_portGp.PortGroupInfo[j + g_portGp.VC_ConNToSSubset],&condata , sizeof(CONDITION_STRUCT) );
                 }
             }
         }
     }
     /*有人无人条件判断执行结束*/



     /*根据阈值判断有无人开始 - 该阈值判断逻辑 在条件判断非第一步时生效 */
     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])
                 {
                     /*将状态改变为有人，且所有回路的缓冲区全部按照“有人”状态进行填充，并重新开始计数*/
                     //VCard_Info.Action |= VC_Event_RadarPersonDetected_Flag;
                     VCard_Info.Last_ConGroupType = 0x00;   //YYW,20251009
                     VCard_Info.ExistState = SOMEONE;
                     VCard_Info.ConGroupIndx = g_portGp.VC_ConNToSGruop + 1;

                     Dbg_Println(DBG_BIT_PC_COMM,"-长时间检测 回路%d %d - %d 判定有人-",i,VCard_Info.DetInfo.Trigger_Thres[i],(uint32_t)VCard_Info.ActThreshold[i]);
                     Ble_Printfln(DBG_BIT_BLE_STATUS,"-长时间检测 回路%d %d - %d 判定有人-",i,VCard_Info.DetInfo.Trigger_Thres[i],(uint32_t)VCard_Info.ActThreshold[i]);
                     for(uint8_t i= 2; 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 - 2), 0xFF, ((VCard_Info.DetInfo.DetWinTotalNum[i] / (8*DETECTION_Window_BitMin)) + 1 ) );
                         }
                     }

                     break;
                 }
             }
         }
     }else if( (VCard_Info.ExistState == SOMEONE) && (VCard_Info.ConGroupIndx == (g_portGp.VC_ConNToSGruop + 1) ) )
     {
         /*当前有人状态，且条件逻辑判断处于有人至无人 第一步时，执行长时间判断：启用的回路，任意一个满足回路对应的阈值判断，则条件成立，检测状态变为无人*/
         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) )
             {
                 if(VCard_Info.ActThreshold[i] <= VCard_Info.DetInfo.Release_Thres[i])
                 {
                     /*将状态改变为无人，且所有回路的缓冲区全部按照“无人”状态进行填充，并重新开始计数*/
                     //VCard_Info.Action |= VC_Event_RadarPersonLeft_Flag;

                     VCard_Info.ExistState = NOONE;
                     VCard_Info.ConGroupIndx = VC_CONDGROUP_Default_StartGroup;      //进入无人至有人判断的第一步

                     Dbg_Println(DBG_BIT_PC_COMM,"-长时间检测 回路%d %d - %d 判定无人-",i,VCard_Info.DetInfo.Release_Thres[i],(uint32_t)VCard_Info.ActThreshold[i]);
                     Ble_Printfln(DBG_BIT_BLE_STATUS,"-长时间检测 回路%d %d - %d 判定无人-",i,VCard_Info.DetInfo.Release_Thres[i],(uint32_t)VCard_Info.ActThreshold[i]);
                     for(uint8_t i= 2; 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 - 2), 0x00, ((VCard_Info.DetInfo.DetWinTotalNum[i] / (8*DETECTION_Window_BitMin)) + 1 ) );
                         }
                     }

                     break;
                 }
             }
         }
     }
     /*根据阈值判断有无人结束*/



     //端口变化状态，只处理一次，便清除变化状态
     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[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];
     }

}

//获取当前事件状态
uint8_t Dev_VirtualCard_InType_Get(void)
{
    uint8_t Ret = 0;         //控制无效

    if((VCard_Info.Action&0x3F) != 0x00)
    {
        for(uint8_t i = 0x00; i < 8; i++)
        {
            if( ( VCard_Info.Action & (0x01 << i) ) != 0x00 )
            {
                //Dbg_Println(DBG_BIT_PC_COMM,"- 无卡取电 事件触发: %02x - %d ",VCard_Info.Action,i);
                VCard_Info.Action &= ~(0x01 << i);
                Ret = (i + 1);     //控制有效
                break;
            }
        }
    }

    return Ret;
}


//事件输出控制
void Action_Task(void)
{
    uint8_t rev = 0x00;
    static uint32_t scan_tisk = 0x00;

    // 门磁延迟控制
    //if((VCard_Info.PortState[1] == DET_SER_LOOSEN)&&(sensor_info.door_rarON_flag == 0x01))
    if(sensor_info.door_rarON_flag == 0x01)
    {
        if(SysTick_1ms - sensor_info.door_rarOn_time >= g_rar_info.Door_RARON_Time)
        {
            Dbg_Println(DBG_BIT_PC_COMM,"门磁开，开门事件");
            Ble_Printfln(DBG_BIT_BLE_STATUS, "门磁开，开门事件");

            sensor_info.door_rarOn_time = SysTick_1ms;
            sensor_info.door_rar_deltime = SysTick_1ms;
            sensor_info.door_rarON_flag = 0x02;

            VCard_Info.Action |= VC_Event_DoorSensorOpen_Flag;
        }
    }else if((sensor_info.door_rarON_flag == 0x02))
    {
        if(SysTick_1ms - sensor_info.door_rar_deltime >= g_rar_info.Door_RARFF_TimeOut)
        {
            Dbg_Println(DBG_BIT_PC_COMM,"门磁关，关门事件");
            Ble_Printfln(DBG_BIT_BLE_STATUS,"门磁关，关门事件");

            sensor_info.door_rar_deltime = SysTick_1ms;
            sensor_info.door_rarON_flag = 0x00;

            VCard_Info.Action |= VC_Event_DoorSensorClose_Flag;
        }
    }

    // 卫生间灯延迟控制
    if(sensor_info.bath_rarON_flag == 0x01)
    {
        sensor_info.bath_rar_deltime = SysTick_1ms;
        if(SysTick_1ms - sensor_info.bath_rarOn_time >= g_rar_info.BATH_RARON_Time)
        {
            if(VCard_Info.ExistState == SOMEONE){       // 有人的情况下，浴室雷达开浴室灯事件才能使用

                sensor_info.bath_rarOn_time = SysTick_1ms;
                sensor_info.bath_rarON_flag = 0x02;

                Dbg_Println(DBG_BIT_PC_COMM,"洗手间有人，开灯事件");
                Ble_Printfln(DBG_BIT_BLE_STATUS,"洗手间有人，开灯事件");
                VCard_Info.Action |= VC_Event_BathroomRadarOn_Flag;
            }
        }
    }else if(VCard_Info.PortState[2] == DET_SER_LOOSEN)
    {
        if((sensor_info.bath_rarON_flag == 0x02)&&(sensor_info.bath_rarOFF_flag == 0x01))
        {
            if(SysTick_1ms - sensor_info.bath_rar_deltime >= g_rar_info.BATH_RARFF_TimeOut)
            {
                sensor_info.bath_rar_deltime = SysTick_1ms;
                sensor_info.bath_rarON_flag = 0x00;
                sensor_info.bath_rarOFF_flag = 0x00;

                Dbg_Println(DBG_BIT_PC_COMM,"洗手间无人，关灯事件");
                Ble_Printfln(DBG_BIT_BLE_STATUS,"洗手间无人，关灯事件");

                VCard_Info.Action |= VC_Event_BathroomRadarOFF_Flag;
            }
        }
    }




    //1、泛智联事件输出间隔
    if(SysTick_1ms - scan_tisk >= 500){
        scan_tisk = SysTick_1ms;
        rev = Dev_VirtualCard_InType_Get();

        if(rev != 0x00)
        {
            FZL_CtrlOut(rev);

            Dbg_Println(DBG_BIT_PC_COMM,"- 事件输出: %d ",rev);
            rev = 0x00;
        }
    }

    //2、输出控制
    if(sensor_info.det_ctrlout_state != 0x00) {
        if(SysTick_1ms - sensor_info.det_action_tick >= 200){
            sensor_info.det_action_tick = SysTick_1ms;

            Dbg_Println(DBG_BIT_PC_COMM," FZL Close");
            FZL_CtrlOut(0x00);
            sensor_info.det_ctrlout_state = 0x00;
        }
    }

}




/*******************************************************************************
 * @FunctionName : NetCRC16_Data
 * @Description  : CRC校验 - CRC在检验数据中
 * @Input        :
    aStr    : 需要校验的数组首地址
    len     : 数据的长度 --Flash中的数据校验一般是512Byte
    crc_id  : CRC在数组中的下标位置，低地址在前,只传低地址
 * @Return       : 数据的校验值
 *******************************************************************************/
uint16_t NetCRC16_Data(uint8_t *aStr ,uint16_t len,uint16_t crc_id)
{
    uint16_t xda , xdapoly ;
    uint16_t i,j, xdabit ;
    xda = 0xFFFF ;
    xdapoly = 0xA001 ;  // (X**16 + X**15 + X**2 + 1)
    for(i=0;i<len;i++)
    {
        if((i == crc_id) || (i == (crc_id + 1)))
        {
            xda ^= 0x00;
        }else {
            xda ^= aStr[i];
        }

        for(j=0;j<8;j++)
        {
            xdabit = (uint8_t )(xda & 0x01) ;
            xda >>= 1 ;
            if( xdabit ) xda ^= xdapoly ;
        }
    }

    return xda;
}



void NoCard_Reply_Packing_Processing(uint8_t *data,uint16_t len,uint8_t state)
{
    if(len < 11) return;

    uint8_t SdData[15];
    uint16_t Sdlen = 0x00;
    uint16_t CRC_Check = 0x00;

    SdData[Sdlen++] = data[0];
    SdData[Sdlen++] = data[1];
    //长度
    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x00;
    //CRC
    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x00;

    SdData[Sdlen++] = data[6];
    SdData[Sdlen++] = data[7];
    SdData[Sdlen++] = data[8];
    SdData[Sdlen++] = data[9];
    SdData[Sdlen++] = data[10];

    SdData[Sdlen++] = state;

    SdData[2] = (Sdlen&0xFF);
    SdData[3] = ( (Sdlen >> 8)&0xFF);

    CRC_Check = CRC16(SdData,Sdlen);
    SdData[4] = (CRC_Check&0xFF);
    SdData[5] = ((CRC_Check >> 8)&0xFF);

    UART_SendString(SdData,Sdlen);
    Ble_Buff_Print(SdData,Sdlen);

}



//无卡取电端口参数设置
//软件内部端口固定五个，1：插卡状态    2：门磁    3-5：传感器
//硬件端口：门磁 + 3个传感器
uint8_t NoCard_Set_PortInfo_Processing(uint8_t* data,uint16_t lens)
{
    if(lens < 22) return 0x01;

    uint8_t para = 0x0B;
    uint8_t para_len = 11;
    uint8_t port_id = data[para+5];//(data[para+2] + (data[para+3] << 8));
    uint8_t revdata[11];

    memcpy(revdata,&data[para],para_len);

    if(port_id != 0x00 && port_id <= VIRTUAL_PORT_MAX)  //1-5
    {
        if(revdata[4] > 100 )
        {
            revdata[4] = 100;
        }
        if(revdata[10] > 100 )
        {
            revdata[10] = 100;
        }

        if(memcmp(&PortInfo[port_id-1],revdata,para_len) != 0x00 )
        {
            memcpy(&PortInfo[port_id-1],revdata,para_len);
            VCard_Info.PortInit_Flag = 0x00;//端口初始化
            Dbg_Println(DBG_BIT_PC_COMM, "Set_PortInfo Succ:%d",port_id);
            Ble_Printfln(DBG_BIT_BLE_STATUS,"Set Succ");
            EEPROM_Write_PortInfo();
        }
        else{
            Dbg_Println(DBG_BIT_PC_COMM, "No Need Save");
        }
    }else{
        NoCard_Reply_Packing_Processing(data,lens,0x02);
        return 0x02;
    }

    NoCard_Reply_Packing_Processing(data,lens,0x01);
    return 0x00;
}



//读取版本号的回复
uint8_t NoCard_Read_Version_Processing(uint8_t* data,uint16_t lens)
{
    uint8_t SdData[15];
    uint16_t Sdlen = 0x00;
    uint16_t CRC_Check = 0x00;

    SdData[Sdlen++] = data[0];
    SdData[Sdlen++] = data[1];
    //长度
    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x00;
    //CRC
    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x00;

    //帧号
    SdData[Sdlen++] = data[6];
    SdData[Sdlen++] = data[7];
    SdData[Sdlen++] = data[8];
    SdData[Sdlen++] = data[9];

    //命令字
    SdData[Sdlen++] = 0x01;

    SdData[Sdlen++] = FW_Version;   //软件版本号
    SdData[Sdlen++] = EE_Version;   //硬件版本号
    SdData[Sdlen++] = Peripheral_GetBLEState();

    SdData[2] = (Sdlen&0xFF);
    SdData[3] = ( (Sdlen >> 8)&0xFF);

    CRC_Check = CRC16(SdData,Sdlen);
    SdData[4] = (CRC_Check&0xFF);
    SdData[5] = ((CRC_Check >> 8)&0xFF);

    UART_SendString(SdData,Sdlen);
    Ble_Buff_Print(SdData,Sdlen);

    return 0x00;
}



//无卡取电条件组设置
uint8_t NoCard_Set_CondGpJd_Processing(uint8_t* data,uint16_t lens)
{
    if(lens < 25) return 0x01;

    uint8_t para = 0x0B;
    uint8_t para_len = 14;
    uint8_t revdata[15];
    uint8_t rev = 0x02;

    uint8_t Gp_num = 0x00;  //组号，
    uint8_t Gp2_num = 0x00; //子组号

    memcpy(revdata,&data[para],para_len);
    Gp_num = revdata[1];
    Gp2_num = revdata[2];

    //验证是否正确，并获得条件组数量、条件子序号数量，验证错误就不存入flash
    if((Gp_num != 0x00)&&(Gp_num <= VC_NONE_Default_StartGroup))  //1-5
    {
        for(uint8_t i = 0x00;i<VIRTUAL_GP_NUM_MAX;i++ )
        {
            if((g_portGp.PortGroupInfo[i][0] == revdata[0])&&(g_portGp.PortGroupInfo[i][1] == revdata[1])&&(g_portGp.PortGroupInfo[i][2] == revdata[2]))  //合法条件
            {
                if(memcmp(&g_portGp.PortGroupInfo[i],revdata,para_len) != 0x00)
                {
                    memcpy(&g_portGp.PortGroupInfo[i],revdata,para_len);

                    VCard_Info.PortInit_Flag = 0x00;//端口初始化
                    Dbg_Println(DBG_BIT_PC_COMM, "Set_CondGp Succ");
                    Ble_Printfln(DBG_BIT_BLE_STATUS,"Set Succ");
                    EEPROM_Write_PortGroupData(&g_portGp);
                    rev = 0x01;
                    break;
                }else{

                    Dbg_Println(DBG_BIT_PC_COMM, "the same");
                    rev = 0x01;
                    break;
                }
            }
        }
    }else{
       // NoCard_Reply_Packing_Processing(data,lens,0x02);
    }

    NoCard_Reply_Packing_Processing(data,lens,rev);

    return 0x00;
}



//无卡取电打印数据设置
uint8_t NoCard_Set_Printf_Processing(uint8_t *data,uint16_t lens)
{
    if(Dbg_Switch != (data[11]&0x1F) )
    {
        Dbg_Switch = (data[11]&0x1F);
     //   NoCard_Reply_Packing_Processing(data,lens,0x01);
    }

    NoCard_Reply_Packing_Processing(data,lens,0x01);
    return 0x00;
}



/******************************************************
 * @name    : NoCard_Set_RDR_Processing
 * @brief   : 指令控制打开雷达打印
 * @param   : data : 接收缓冲,  lens : 接收长度
 ******************************************************* */
uint8_t NoCard_Set_RDR_Processing(uint8_t *data,uint16_t lens)
{
    if(data[11] == 0x01)
    {
        if((Dbg_Switch&0x04) != 0x00 )
        {
            Dbg_Switch &= 0x3B;      //关闭其他打印
            Dbg_Switch |= 0x20;
        }
        Dbg_Println(DBG_BIT_PC_COMM, "RDR_Sta Start");
        VCard_Info.rdrsta_change_flag = 0x01;
        VCard_Info.print_rdrsta_flag = 0x01;
        NoCard_Reply_Packing_Processing(data,lens,0x01);
    }
    else if(data[11] == 0x02)
    {
        Dbg_Switch &= (~0x20);
        Dbg_Println(DBG_BIT_PC_COMM, "RDR_Sta End");
        VCard_Info.print_rdrsta_flag = 0x00;
        NoCard_Reply_Packing_Processing(data,lens,0x01);
    }

    return 0x00;
}



//设置门磁、浴室雷达参数
uint8_t NoCard_Set_RDRPara_Processing(uint8_t* data,uint16_t lens)
{
    if(lens < 20) return 0x01;
    uint8_t rev = 0x00;
    uint8_t temp_tim_unit = 0x00;
    uint32_t temp_tim = 0x00;

    if( (data[11]&0x01) != 0x00 )
    {
        temp_tim = data[12];
        temp_tim_unit = data[13];
        if(temp_tim_unit == 2){
            temp_tim = (temp_tim*60*1000);
        }else{
            temp_tim = (temp_tim*1000);
        }
        if(temp_tim > 1800000){
            temp_tim = 1800000;
        }
        if(temp_tim != g_rar_info.Door_RARON_Time){
            g_rar_info.Door_RARON_Time = temp_tim;
            rev = 0x01;
        }


        temp_tim = data[14];
        temp_tim_unit = data[15];
        if(temp_tim_unit == 2){
            temp_tim = (temp_tim*60*1000);
        }else{
            temp_tim = (temp_tim*1000);
        }
        if(temp_tim > 1800000){
            temp_tim = 1800000;
        }
        if(temp_tim < 5000){     //延时关功能必须大于5s
            temp_tim = 5000;
        }
        if(temp_tim != g_rar_info.Door_RARFF_TimeOut){
            g_rar_info.Door_RARFF_TimeOut = temp_tim;
            rev = 0x01;
        }
    }

    if( (data[11]&0x02) != 0x00 )
    {
        temp_tim = data[16];
        temp_tim_unit = data[17];
        if(temp_tim_unit == 2){
            temp_tim = (temp_tim*60*1000);
        }else{
            temp_tim = (temp_tim*1000);
        }
        if(temp_tim > 1800000){
            temp_tim = 1800000;
        }
        if(temp_tim != g_rar_info.BATH_RARON_Time){
            g_rar_info.BATH_RARON_Time = temp_tim;
            rev = 0x01;
        }

        /**>    <**/
        temp_tim = data[18];
        temp_tim_unit = data[19];
        if(temp_tim_unit == 2){
            temp_tim = (temp_tim*60*1000);
        }else{
            temp_tim = (temp_tim*1000);
        }
        if(temp_tim > 1800000){
            temp_tim = 1800000;
        }
        if(temp_tim < 5000){        //延时关功能必须大于5s
            temp_tim = 5000;
        }
        if(temp_tim != g_rar_info.BATH_RARFF_TimeOut){
            g_rar_info.BATH_RARFF_TimeOut = temp_tim;
            rev = 0x01;
        }
    }


    if(rev != 0x00)
    {
        EEPROM_Write_RARDelayTim(&g_rar_info);
    }

    NoCard_Reply_Packing_Processing(data,lens,0x01);

    return 0x00;
}



/******************************************************
 * @name    : print_RDRSta_Changw
 * @brief   : 组包发送雷达触发状态
 * @param   :
 ******************************************************* */
void print_RDRSta_Changw(void)
{
    uint8_t SdData[15];
    uint16_t Sdlen = 0x00;
    uint16_t CRC_Check = 0x00;
    uint8_t RDR_Sta = 0x00;

    SdData[Sdlen++] = 0xCC;
    SdData[Sdlen++] = 0xC0;
    //长度
    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x00;
    //CRC
    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x00;

    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x00;
    SdData[Sdlen++] = 0x11;

    //data
    SdData[Sdlen++] = 0x04;     //有效端口数量
    SdData[Sdlen++] = VCard_Info.ExistState;     //有无人状态

    if((VCard_Info.PortStateAct[1] == 1)||(VCard_Info.PortStateAct[1] == 3)){
        RDR_Sta |= 0x01;
    }

    if((VCard_Info.PortStateAct[2] == 1)||(VCard_Info.PortStateAct[2] == 3)){
        RDR_Sta |= 0x02;
    }

    if((VCard_Info.PortStateAct[3] == 1)||(VCard_Info.PortStateAct[3] == 3)){
        RDR_Sta |= 0x04;
    }

    if((VCard_Info.PortStateAct[4] == 1)||(VCard_Info.PortStateAct[4] == 3)){
        RDR_Sta |= 0x08;
    }
    SdData[Sdlen++] = RDR_Sta;

    SdData[2] = (Sdlen&0xFF);
    SdData[3] = ( (Sdlen >> 8)&0xFF);

    CRC_Check = CRC16(SdData,Sdlen);
    SdData[4] = (CRC_Check&0xFF);
    SdData[5] = ((CRC_Check >> 8)&0xFF);


    Ble_Buff_Print(SdData,Sdlen);
}




/******************************************************
 * @name    : print_RDRsta_Tack
 * @brief   : 间隔    200ms 输出雷达状态
 * @param   :
 ******************************************************* */
void print_RDRsta_Tack(void)
{
    static uint32_t print_rdrsta_tisk = 0x00;

    if(VCard_Info.print_rdrsta_flag == 0x01)
    {
        VCard_Info.print_rdrsta_flag = 0x02;
        print_rdrsta_tisk = SysTick_1ms;
        Dbg_Println(DBG_BIT_PC_COMM,"print RAR_sta init");
    }


    //断开蓝牙连接自动关打印
    if((VCard_Info.print_rdrsta_flag != 0x00)&&((Peripheral_GetBLEState() != GAPROLE_CONNECTED)&&(Peripheral_GetBLEState() != GAPROLE_CONNECTED_ADV)) )
    {
        Dbg_Println(DBG_BIT_PC_COMM,"Stop print RAR_sta");

        VCard_Info.print_rdrsta_flag = 0x00;
        print_rdrsta_tisk = SysTick_1ms;
    }

    if((VCard_Info.rdrsta_change_flag != 0x00)&&(SysTick_1ms - print_rdrsta_tisk >= 200))       //端口状态改变或者有无人状态改变
    {
        print_rdrsta_tisk = SysTick_1ms;
        if(VCard_Info.rdrsta_change_flag <= 0x03){
            VCard_Info.rdrsta_change_flag++;
        }else{
            VCard_Info.rdrsta_change_flag = 0x00;
        }

        if(VCard_Info.print_rdrsta_flag == 0x02)
        {
            //打印雷达状态
            print_RDRSta_Changw();
        }
    }
}


//接收处理
uint8_t BLV_DETInfo_Recv_Processing(uint8_t* RecvData,uint16_t RecvLen)
{
    uint16_t crc_temp = 0;

    if(RecvLen < 11)       //2024-11-11         增加长度判断,避免长度错误导致卡在ＣＲＣ校验循环里最终开门狗复位
    {
        Dbg_Println(DBG_BIT_PC_COMM, "Recv_Pro MAXLens Err");
        Ble_Printfln(DBG_BIT_BLE_STATUS, "Lens Err");
        return 0x01;
    }


    if( ((RecvData[3]<<8) + RecvData[2])!= RecvLen)
    {
        Dbg_Println(DBG_BIT_PC_COMM, "Recv_Pro Lens Err");
        Ble_Printfln(DBG_BIT_BLE_STATUS, "Lens Err");
        return 0x01;
    }

    if((RecvData[0] != 0xCC) || (RecvData[1] != 0xC0))
    {
        Dbg_Println(DBG_BIT_PC_COMM, "Recv_Pro Head Err");
        Ble_Printfln(DBG_BIT_BLE_STATUS, "Head Err");
        return 0x02;
    }

    crc_temp = (RecvData[5]<<8) +  RecvData[4];
    if(crc_temp != NetCRC16_Data(RecvData,RecvLen,4))
    {
        Dbg_Println(DBG_BIT_PC_COMM, "Recv_Pro CRC Err: %04X,%04X",crc_temp,NetCRC16_Data(RecvData,RecvLen,4));
        Ble_Printfln(DBG_BIT_BLE_STATUS, "CRC Err: %04X,%04X",crc_temp,NetCRC16_Data(RecvData,RecvLen,4));
        return 0x03;
    }

    Dbg_Println(DBG_BIT_PC_COMM, "Recv_Pro ACK: %02X",RecvData[10]);
    switch(RecvData[10])
    {
        case 0x01:      //读取版本号
            NoCard_Read_Version_Processing(RecvData,RecvLen);

            break;
        case 0x08:      //条件组设置
            NoCard_Set_CondGpJd_Processing(RecvData,RecvLen);
            break;
        case 0x09:      //端口设置
            NoCard_Set_PortInfo_Processing(RecvData,RecvLen);
            break;
        case 0x0B:      //OTA升级开始
            if(RecvData[11] == 0x01)
            {
                PRINT("OTA Up Start\n");

                BLE_OTA_flag = 0x01;
            }
            break;
        case 0x0C:      //打印设置
            NoCard_Set_Printf_Processing(RecvData,RecvLen);
            break;
        case 0x11:      //设置雷达状态输出
            NoCard_Set_RDR_Processing(RecvData,RecvLen);
            break;
        case 0x13:      //控制按键触发
            if(RecvData[11] == 0x01)
            {
                if(RecvData[12] != 0x00)
                {
                    VCard_Info.Action |= RecvData[12];
                }

                NoCard_Reply_Packing_Processing(RecvData,RecvLen,0x01);
            }
            break;
        case 0x16:      //设置参数
            NoCard_Set_RDRPara_Processing(RecvData,RecvLen);
            break;
        default:

            break;
    }


    return 0x00;
}









