@@ -1,6 +1,8 @@
package com.zhidao.support.adas.high.common.autopilot.ability ;
import android.text.TextUtils ;
import androidx.annotation.NonNull ;
import androidx.annotation.Nullable ;
@@ -9,18 +11,20 @@ import com.zhidao.support.adas.high.AdasOptions;
import com.zhidao.support.adas.high.BuildConfig ;
import com.zhidao.support.adas.high.OnAdasListener ;
import com.zhidao.support.adas.high.common.CupidLogUtils ;
import com.zhjt.mogo.adas.data.Adas ;
import com.zhjt.mogo.adas.data.AdasConstants ;
import com.zhjt.mogo.adas.data.bean.LaunchConditionData ;
import com.zhjt.mogo.adas.data.bean.NodeStateInfo ;
import com.zhjt.mogo.adas.data.bean.UnableLaunchReason ;
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
import java.util.Set ;
import java.util.Timer ;
import java.util.TimerTask ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.concurrent.atomic.AtomicBoolean ;
import java.util.concurrent.atomic.AtomicInteger ;
import chassis.Chassis ;
import chassis.ChassisStatesOuterClass ;
@@ -59,17 +63,19 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
private AutopilotAbility330 autopilotAbility330 ;
private AutopilotAbility350And360 autopilotAbility350And360 ;
private AutopilotAbility360 autopilotAbility360 ;
private AutopilotAbility440 autopilotAbility440 ;
private AutopilotAbilityFSM autopilotAbilityFsm ;
private Timer startTimer ;
private Timer timeoutTimer ; //SSM和FSM超时计时器
private long ssmReceiveTime ; //SSM接收时间
private long fsmReceiveTime ; //FSM接收时间
private final AtomicBoolean isInitAutopilotAbility = new AtomicBoolean ( false ) ; //是否初始化完成
private final AtomicBoolean isOldSsmTimeout = new AtomicBoolean ( false ) ; //SSM是否超时 老状态
private final AtomicBoolean isOldFsmTimeout = new AtomicBoolean ( false ) ; //FSM是否超时 老状态
private final AtomicBoolean isInitCarConfig = new AtomicBoolean ( false ) ; //车辆信息是否初始化
private final Map < AdasConstants . NodeName , Adas . NodeStateInfo > nodeStateInfos = new HashMap < > ( ) ;
private boolean isSupportFSM2024 = false ;
private final AtomicInteger isSupportFSM2024 = new AtomicInteger ( - 1 ) ; //-1: 未初始化 0: 不支持 1: 通过SSM V2判断支持 2: 通过FSM数据源判断支持
private final Map < AdasConstants . NodeName , NodeStateInfo > nodeStateInfos = new ConcurrentHashMap < > ( ) ;
private AutopilotAbilityManager ( ) {
}
@@ -85,6 +91,20 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
return INSTANCE ;
}
private void initStartData ( ) {
nodeStateInfos . clear ( ) ;
NodeStateInfo ssmInfo = new NodeStateInfo ( AdasConstants . NodeName . SSM , AdasConstants . NodeState . NODE_EXIST ) ;
ssmInfo . setExistState ( AdasConstants . NodeExistState . NODE_EXIST_NORMAL ) ;
nodeStateInfos . put ( AdasConstants . NodeName . SSM , ssmInfo ) ;
nodeStateInfos . put ( AdasConstants . NodeName . FSM2024 , new NodeStateInfo ( AdasConstants . NodeName . FSM2024 , AdasConstants . NodeState . NODE_UNKNOWN ) ) ;
}
private void initStopData ( ) {
nodeStateInfos . clear ( ) ;
nodeStateInfos . put ( AdasConstants . NodeName . SSM , new NodeStateInfo ( AdasConstants . NodeName . SSM , AdasConstants . NodeState . NODE_UNKNOWN ) ) ;
nodeStateInfos . put ( AdasConstants . NodeName . FSM2024 , new NodeStateInfo ( AdasConstants . NodeName . FSM2024 , AdasConstants . NodeState . NODE_UNKNOWN ) ) ;
}
public void setLaunchAutopilotGear ( Set < Chassis . GearPosition > launchAutopilotGear ) {
if ( autopilotAbility230 ! = null ) {
autopilotAbility230 . setLaunchAutopilotGear ( launchAutopilotGear ) ;
@@ -156,7 +176,7 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
*/
public void setStatusInfo ( SystemStatusInfo . StatusInfo statusInfo ) {
ssmReceiveTime = System . currentTimeMillis ( ) ;
onCallSSMTimeout ( false ) ;
onCallSSMTimeout ( AdasConstants . SsmSource . SSM_VER1 , false ) ;
if ( autopilotAbility250 ! = null ) {
autopilotAbility250 . setStatusInfo ( statusInfo ) ;
}
@@ -167,7 +187,8 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
public void setStatusInfo ( SsmInfo . SsmStatusInf statusInfo ) {
ssmReceiveTime = System . currentTimeMillis ( ) ;
onCallSSMTimeout ( false ) ;
onCallSSMTimeout ( AdasConstants . SsmSource . SSM_VER2 , false ) ;
detectionTopicExistence ( statusInfo ) ;
if ( autopilotAbility350And360 ! = null ) {
autopilotAbility350And360 . setStatusInfo ( statusInfo ) ;
}
@@ -177,10 +198,10 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
}
public void setFSM2024State ( Fsm2024 . FSMStateMsg fsmState ) {
fsmReceiveTime = System . currentTimeMillis ( ) ;
updateFSMNormalStateFromFSM ( ) ;
onCallFSMTimeout ( false ) ;
if ( autopilotAbility440 ! = null ) {
autopilotAbility440 . setFSMState ( fsmState ) ;
if ( autopilotAbilityFsm ! = null ) {
autopilotAbilityFsm . setFSMState ( fsmState ) ;
}
}
@@ -219,67 +240,85 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
* @param name 节点名称 目前只有SSM和FSM2024
* @return 状态 SSM只能查询到超时状态; FSM2024可以查询到节点是否存在状态以及超时状态;
*/
public Adas . NodeStateInfo getNodeStateInfo ( AdasConstants . NodeName name ) {
Adas . NodeStateInfo state = nodeStateInfos . get ( name ) ;
public NodeStateInfo getNodeStateInfo (@NonNull AdasConstants . NodeName name ) {
NodeStateInfo state = nodeStateInfos . get ( name ) ;
if ( state = = null ) {
state = Adas . NodeStateInfo . newBuilder ( ) . setNodeState ( AdasConstants . NodeState . NODE_UNKNOWN ) . build ( ) ;
nodeStateInfos . put ( name , state ) ;
return new NodeStateInfo ( name , AdasConstants . NodeState . NODE_UNKNOWN ) ;
}
return state ;
}
//检测节点是否存在
private void detectionTopicExistence ( ) {
/**
* 检测节点是否存在
* 判断条件: SSM消息中冷启动完成( statusInfo.getAutoPilotReady()==ture)
* 后查询自动驾驶关键节点列表中是否有包含fsm节点名称
*/
private void detectionTopicExistence ( SsmInfo . SsmStatusInf statusInfo ) {
if ( isSupportFSM2024 . get ( ) = = - 1 ) {
if ( statusInfo . getAutoPilotReady ( ) ) {
List < SsmInfo . NodeInf > list = statusInfo . getAutoPilotUnreadyListList ( ) ;
boolean isSupport = false ;
for ( SsmInfo . NodeInf info : list ) {
String name = info . getNodeName ( ) ;
if ( ! TextUtils . isEmpty ( name ) & & name . toLowerCase ( ) . contains ( " fsm " ) ) {
//支持FSM
isSupport = true ;
break ;
}
}
updateFSMStateFromSSM ( isSupport ? 1 : 0 ) ;
}
}
}
private void initAutopilotAbility ( ) {
stopAllTimer ( ) ;
isSupportFSM2024 = false ;
if ( mapVersion > = 40400 & & ( isJinlv | | isJinlvM1 | | isJinlvM2 ) ) {
isSupportFSM2024 = true ;
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本:440 " ) ;
if ( autopilotAbility440 = = null ) {
autopilotAbility440 = new AutopilotAbility440 ( this ) ;
autopilotAbility440 . start ( this ) ;
}
} else if ( mapVersion > = 30600 & & isFutianSweeper ) {
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 360清扫车专用 " ) ;
if ( autopilotAbility360 = = null ) {
autopilotAbility360 = new AutopilotAbility360 ( this ) ;
autopilotAbility360 . start ( this ) ;
}
} else if ( ( mapVersion > = 30500 & & ( isJinlvM1 | | isHQ ) ) | | mapVersion > = 30600 ) {
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 350和360共用 " ) ;
if ( autopilotAbility350And360 = = null ) {
autopilotAbility350And360 = new AutopilotAbility350And360 ( this ) ;
autopilotAbility350And360 . start ( this ) ;
}
if ( ! isInitAutopilotAbility . get ( ) ) {
isInitAutopilotAbility . set ( true ) ;
stopAllTimer ( ) ;
if ( isSupportFSM2024 . get ( ) > 0 ) {
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本:FSM版本 " ) ;
if ( autopilotAbilityFsm = = null ) {
autopilotAbilityFsm = new AutopilotAbilityFSM ( this ) ;
autopilotAbilityFsm . start ( this ) ;
}
} else if ( mapVersion > = 30600 & & isFutianSweeper ) {
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 360清扫车专用 " ) ;
if ( autopilotAbility360 = = null ) {
autopilotAbility360 = new AutopilotAbility360 ( this ) ;
autopilotAbility360 . start ( this ) ;
}
} else if ( ( mapVersion > = 30500 & & ( isJinlvM1 | | isHQ ) ) | | mapVersion > = 30600 ) {
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 350和360共用 " ) ;
if ( autopilotAbility350And360 = = null ) {
autopilotAbility350And360 = new AutopilotAbility350And360 ( this ) ;
autopilotAbility350And360 . start ( this ) ;
}
} else if ( mapVersion > = 30300 & & isFutianSweeper ) { //目前只有MAP330的清扫车用的新的FSM状态原因查询
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 330清扫车专用 " ) ;
if ( autopilotAbility330 = = null ) {
autopilotAbility330 = new AutopilotAbility330 ( this , mapVersion ) ;
autopilotAbility330 . start ( this ) ;
} else if ( mapVersion > = 30300 & & isFutianSweeper ) { //目前只有MAP330的清扫车用的新的FSM状态原因查询
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 330清扫车专用 " ) ;
if ( autopilotAbility330 = = null ) {
autopilotAbility330 = new AutopilotAbility330 ( this , mapVersion ) ;
autopilotAbility330 . start ( this ) ;
}
} else if ( mapVersion > = 20500 ) {
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 250 " ) ;
if ( autopilotAbility250 = = null ) {
autopilotAbility250 = new AutopilotAbility250 ( this ) ;
autopilotAbility250 . start ( this ) ;
}
} else {
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 230 " ) ;
if ( autopilotAbility230 = = null ) {
autopilotAbility230 = new AutopilotAbility230 ( this ) ;
autopilotAbility230 . start ( this ) ;
}
}
} else if ( mapVersion > = 20500 ) {
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 250 " ) ;
if ( autopilotAbility250 = = null ) {
autopilotAbility250 = new AutopilotAbility250 ( this ) ;
autopilotAbility250 . start ( this ) ;
}
} else {
CupidLogUtils . log ( TAG , " 能否启动自驾能力检测使用版本: 230 " ) ;
if ( autopilotAbility230 = = null ) {
autopilotAbility230 = new AutopilotAbility230 ( this ) ;
autopilotAbility230 . start ( this ) ;
startTimeoutTimer ( ) ; //MAP230及以下没有SSM和FSM所以不需要超时
}
Set < Chassis . GearPosition > launchAutopilotGear = getGearPositions ( ) ;
setLaunchAutopilotGear ( launchAutopilotGear ) ;
}
if ( autopilotAbility230 = = null ) {
startTimeoutTimer ( ) ; //MAP230及以下没有SSM和FSM所以不需要超时
}
Set < Chassis . GearPosition > launchAutopilotGear = getGearPositions ( ) ;
setLaunchAutopilotGear ( launchAutopilotGear ) ;
}
private @Nullable Set < Chassis . GearPosition > getGearPositions ( ) {
@@ -307,6 +346,130 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
return launchAutopilotGear ;
}
/**
* 连接工控机成功调用此函数, 如果dockerVersion还未获取到将启动最低版本的启动自动驾驶能力检测
* 此函数为保险措施 以防无法获取工控机版本时 也能 正常执行逻辑
*/
public synchronized void start ( ) {
isInitAutopilotAbility . set ( false ) ;
initStartData ( ) ;
if ( startTimer = = null ) {
startTimer = new Timer ( ) ;
startTimer . schedule ( new TimerTask ( ) {
@Override
public void run ( ) {
if ( ! isInitCarConfig . get ( ) & & AdasManager . getInstance ( ) . getIpcConnectionStatus ( ) = = AdasConstants . IpcConnectionStatus . CONNECTED ) {
mapVersion = 20300 ;
isSupportFSM2024 . set ( - 1 ) ;
initAutopilotAbility ( ) ;
isInitAutopilotAbility . set ( false ) ;
}
}
} , 15000L ) ; //15秒原因: 需要后去CarConfig 对象, 两个地方调用initAutopilotAbility(); 初始化 一个在这, 另一个在setCarConfig(),如果setCarConfig() 证明获取版本还未成功, 获取版本会重试3次每次间隔四秒
}
}
/**
* 连接工控机成功调用此函数, 如果dockerVersion还未获取到将启动最低版本的启动自动驾驶能力检测
* 此函数为保险措施 以防无法获取工控机版本时 也能 正常执行逻辑
*/
public synchronized void startTimeoutTimer ( ) {
if ( timeoutTimer = = null ) {
ssmReceiveTime = System . currentTimeMillis ( ) ;
fsmReceiveTime = System . currentTimeMillis ( ) ;
timeoutTimer = new Timer ( ) ;
timeoutTimer . schedule ( new TimerTask ( ) {
@Override
public void run ( ) {
//SSM超时检测
long timeDifference = System . currentTimeMillis ( ) - ssmReceiveTime ;
if ( timeDifference > = DEFAULT_TIMEOUT ) {
onCallSSMTimeout ( AdasConstants . SsmSource . SSM_UNKNOWN , true ) ;
//超时
if ( autopilotAbility250 ! = null ) {
autopilotAbility250 . onCallTimeout ( ) ;
}
if ( autopilotAbility330 ! = null ) {
autopilotAbility330 . onCallTimeout ( ) ;
}
if ( autopilotAbility350And360 ! = null ) {
autopilotAbility350And360 . onCallTimeout ( ) ;
}
if ( autopilotAbility360 ! = null ) {
autopilotAbility360 . onCallTimeout ( ) ;
}
}
//FSM超时检测
if ( isSupportFSM2024 . get ( ) > 0 ) {
timeDifference = System . currentTimeMillis ( ) - fsmReceiveTime ;
if ( timeDifference > = DEFAULT_TIMEOUT ) {
onCallFSMTimeout ( true ) ;
if ( autopilotAbilityFsm ! = null ) {
autopilotAbilityFsm . onCallFsmTimeout ( ) ;
}
}
}
}
} , 1000L , DEFAULT_TIMEOUT ) ;
}
}
private void updateFSMNormalStateFromFSM ( ) {
fsmReceiveTime = System . currentTimeMillis ( ) ;
if ( isSupportFSM2024 . get ( ) ! = 2 ) {
updateFSMSupportState ( 2 , AdasConstants . NodeExistState . NODE_EXIST_NORMAL ) ;
}
}
private void updateFSMStateFromSSM ( int isSupport ) {
if ( isSupportFSM2024 . get ( ) = = - 1 ) {
updateFSMSupportState ( isSupport , null ) ;
}
}
private void updateFSMSupportState ( int isSupport , AdasConstants . NodeExistState existState ) {
isSupportFSM2024 . set ( isSupport ) ;
CupidLogUtils . i ( TAG , " 是否支持FSM= " + isSupport ) ;
if ( isSupport > 0 ) {
isInitAutopilotAbility . set ( false ) ;
initAutopilotAbility ( ) ;
}
NodeStateInfo info = getNodeStateInfo ( AdasConstants . NodeName . FSM2024 ) ;
info . setNodeState ( isSupport > 0 ? AdasConstants . NodeState . NODE_EXIST : AdasConstants . NodeState . NODE_NOT_EXIST ) ;
info . setExistState ( existState ) ;
listener . onNodeStateInfo ( info ) ;
}
private synchronized void onCallSSMTimeout ( AdasConstants . SsmSource source , boolean isTimeout ) {
if ( isTimeout ! = isOldSsmTimeout . get ( ) ) {
isOldSsmTimeout . set ( isTimeout ) ;
if ( ! isTimeout ) {
if ( source = = AdasConstants . SsmSource . SSM_VER1 ) {
//SSM 1版本时 不支持FSM
CupidLogUtils . i ( TAG , " SSM版本1不支持FSM " ) ;
updateFSMStateFromSSM ( 0 ) ;
}
}
NodeStateInfo info = getNodeStateInfo ( AdasConstants . NodeName . SSM ) ;
info . setNodeState ( AdasConstants . NodeState . NODE_EXIST ) ;
info . setExistState ( isTimeout ? AdasConstants . NodeExistState . NODE_EXIST_TIMEOUT : AdasConstants . NodeExistState . NODE_EXIST_NORMAL ) ;
listener . onNodeStateInfo ( info ) ;
}
}
private synchronized void onCallFSMTimeout ( boolean isTimeout ) {
if ( isTimeout ! = isOldFsmTimeout . get ( ) ) {
isOldFsmTimeout . set ( isTimeout ) ;
NodeStateInfo info = getNodeStateInfo ( AdasConstants . NodeName . FSM2024 ) ;
info . setNodeState ( AdasConstants . NodeState . NODE_EXIST ) ;
info . setExistState ( isTimeout ? AdasConstants . NodeExistState . NODE_EXIST_TIMEOUT : AdasConstants . NodeExistState . NODE_EXIST_NORMAL ) ;
listener . onNodeStateInfo ( info ) ;
}
}
private void stop230 ( ) {
if ( autopilotAbility230 ! = null ) {
autopilotAbility230 . stop ( ) ;
@@ -343,9 +506,9 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
}
private void stop440 ( ) {
if ( autopilotAbility440 ! = null ) {
autopilotAbility440 . stop ( ) ;
autopilotAbility440 = null ;
if ( autopilotAbilityFsm ! = null ) {
autopilotAbilityFsm . stop ( ) ;
autopilotAbilityFsm = null ;
}
}
@@ -356,97 +519,13 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
}
}
/**
* 连接工控机成功调用此函数, 如果dockerVersion还未获取到将启动最低版本的启动自动驾驶能力检测
* 此函数为保险措施 以防无法获取工控机版本时 也能 正常执行逻辑
*/
public synchronized void start ( ) {
if ( startTimer = = null ) {
startTimer = new Timer ( ) ;
startTimer . schedule ( new TimerTask ( ) {
@Override
public void run ( ) {
if ( ! isInitCarConfig . get ( ) & & AdasManager . getInstance ( ) . getIpcConnectionStatus ( ) = = AdasConstants . IpcConnectionStatus . CONNECTED ) {
mapVersion = 20300 ;
initAutopilotAbility ( ) ;
}
}
} , 15000L ) ; //15秒原因: 需要后去CarConfig 对象, 两个地方调用initAutopilotAbility(); 初始化 一个在这, 另一个在setCarConfig(),如果setCarConfig() 证明获取版本还未成功, 获取版本会重试3次每次间隔四秒
}
}
private void stopTimeoutTimer ( ) {
if ( timeoutTimer ! = null ) {
isOldSsmTimeout . set ( false ) ;
isOldFsmTimeout . set ( false ) ;
ssmReceiveTime = 0 ;
fsmReceiveTime = 0 ;
timeoutTimer . cancel ( ) ;
timeoutTimer = null ;
}
}
/**
* 连接工控机成功调用此函数, 如果dockerVersion还未获取到将启动最低版本的启动自动驾驶能力检测
* 此函数为保险措施 以防无法获取工控机版本时 也能 正常执行逻辑
*/
public synchronized void startTimeoutTimer ( ) {
if ( timeoutTimer = = null ) {
ssmReceiveTime = System . currentTimeMillis ( ) ;
fsmReceiveTime = System . currentTimeMillis ( ) ;
timeoutTimer = new Timer ( ) ;
timeoutTimer . schedule ( new TimerTask ( ) {
@Override
public void run ( ) {
//SSM超时检测
long timeDifference = System . currentTimeMillis ( ) - ssmReceiveTime ;
if ( timeDifference > = DEFAULT_TIMEOUT ) {
onCallSSMTimeout ( true ) ;
//超时
if ( autopilotAbility250 ! = null ) {
autopilotAbility250 . onCallTimeout ( ) ;
}
if ( autopilotAbility330 ! = null ) {
autopilotAbility330 . onCallTimeout ( ) ;
}
if ( autopilotAbility350And360 ! = null ) {
autopilotAbility350And360 . onCallTimeout ( ) ;
}
if ( autopilotAbility360 ! = null ) {
autopilotAbility360 . onCallTimeout ( ) ;
}
}
//FSM超时检测
if ( isSupportFSM2024 ) {
timeDifference = System . currentTimeMillis ( ) - fsmReceiveTime ;
if ( timeDifference > = DEFAULT_TIMEOUT ) {
onCallFSMTimeout ( true ) ;
if ( autopilotAbility440 ! = null ) {
autopilotAbility440 . onCallFsmTimeout ( ) ;
}
}
}
}
} , 1000L , DEFAULT_TIMEOUT ) ;
}
}
private synchronized void onCallSSMTimeout ( boolean isTimeout ) {
if ( isTimeout ! = isOldSsmTimeout . get ( ) ) {
isOldSsmTimeout . set ( isTimeout ) ;
listener . onSsmReceiveTimeout ( isTimeout ) ;
}
}
private synchronized void onCallFSMTimeout ( boolean isTimeout ) {
if ( isTimeout ! = isOldFsmTimeout . get ( ) ) {
isOldFsmTimeout . set ( isTimeout ) ;
listener . onFsm2024ReceiveTimeout ( isTimeout ) ;
}
}
private void stopAllTimer ( ) {
stopTimeoutTimer ( ) ;
stopTimer ( ) ;
@@ -456,10 +535,17 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
stop350And360 ( ) ;
stop360 ( ) ;
stop440 ( ) ;
isOldSsmTimeout . set ( false ) ;
isOldFsmTimeout . set ( false ) ;
ssmReceiveTime = 0 ;
fsmReceiveTime = 0 ;
}
public synchronized void stop ( ) {
stopAllTimer ( ) ;
initStopData ( ) ;
isInitAutopilotAbility . set ( false ) ;
isSupportFSM2024 . set ( - 1 ) ;
isInitCarConfig . set ( false ) ;
mapVersion = - 1 ;
isFutianSweeper = false ;
@@ -469,7 +555,6 @@ public class AutopilotAbilityManager implements OnAutopilotAbilityListener {
isJinlvM1 = false ;
isJinlvM2 = false ;
isKaiwo = false ;
isSupportFSM2024 = false ;
}
}