using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using PunkHPX8_Core;
using PunkHPX8_RT.Devices.AXIS;
using PunkHPX8_RT.Devices.Facilities;
using PunkHPX8_RT.Devices.SRD;
using MECF.Framework.Common.Beckhoff.AxisProvider;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;
using static PunkHPX8_RT.Modules.SRD.RunWaferRecipeStateMachine;
namespace PunkHPX8_RT.Modules.SRD
{
    public class SRDRunWaferRecipeRoutine : RoutineBase, IRoutine
    {
        private enum RunStep
        {
            RunWafer_Start,
            RunWafer_CheckFacilities,
            RunWafer_PreparingExhaustOff,
            RunWafer_WaitExhaustOff,
            RunWafer_EngageChuckVacuum,
            RunWafer_CheckVacuum,
            RunWafer_CloseTheDoor,
            RunWafer_CheckDoorClosed,
            RunWafer_ArmToHome,
            RunWafer_Diverting_CheckArmHome,
            RunWafer_Diverting_CheckOtherSRD,
            RunWafer_Diverting_WaterOn,
            RunWafer_Diverting_WithFlowCheck,
            RunWafer_Diverting_WaterAboveOff,
            RunWafer_Washing_ArmToCenter,
            RunWafer_Washing_CheckArmCenter,
            RunWafer_Washing_PoolingFrontSide,
            RunWafer_Washing_PoolingWithFlowCheck,
            RunWafer_Washing_StartRotation,
            RunWafer_Washing_PreFlowCheck,
            RunWafer_Washing_Finished,
            RunWafer_Drying_PreN2Time,
            RunWafer_Drying_ExhaustFanDelay,
            RunWafer_Drying_ExhaustFanOn,
            RunWafer_Drying_N2On, 
            RunWafer_Drying_StopRotation,
            RunWafer_Drying_PreWaferPresenceCheck,
            RunWafer_Drying_RotationStartMotion,
            RunWafer_Drying_WaferPresenceCheck,
            RunWafer_Drying_PostN2Time,
            RunWafer_Drying_CheckRotationFinished,
            RunWafer_CheckArmHome,
            End
        }
        #region 常量 
        private const int MAX_ARM_HOME_RETRIES = 3;
        /// 
        /// 旋转增加时长
        /// 
        private const int ROTATION_PLUS_TIME = 10;
        /// 
        /// ROTATION电机转速比例
        /// 
        private const int SPEED_RATIO = 10;
        #endregion
        #region 内部变量
        /// 
        /// Arm Axis
        /// 
        private JetAxisBase _armAxis;
        /// 
        /// Rotation Axis
        /// 
        private JetAxisBase _rotationAxis;
        /// 
        /// SRD Common
        /// 
        private SrdCommonDevice _srdCommon;
        /// 
        /// Total SRD
        /// 
        private TotalSRDDevice _totalSRDDevice;
        /// 
        /// 另外SRD实例 
        /// 
        private SRDEntity _otherSrdEntity;
        /// 
        /// Loader Common
        /// 
        private SystemFacilities _systemFacilities;
        /// 
        /// Arm重试次数
        /// 
        private int _armRetryTimes = 0;
        /// 
        /// Recipe
        /// 
        private SrdRecipe _srdRecipe;
        /// 
        /// 记时
        /// 
        private int _enterTime;
        /// 
        /// Diverting Flow时长
        /// 
        private int _divertingFlowCheckTimeSpan;
        /// 
        /// Pooling Flow时长
        /// 
        private int _poolingFlowCheckTimeSpan;
        /// 
        /// Washing Flow时长
        /// 
        private int _washingFlowCheckTimeSpan;
        /// 
        /// SRD rotation Provider对象
        /// 
        private BeckhoffProviderAxis _rotationProviderAxis;
        /// 
        /// SRD arm Provider对象
        /// 
        private BeckhoffProviderAxis _armProviderAxis;
        /// 
        /// 转换增加的时间
        /// 
        private int _rotationPlusSecond = ROTATION_PLUS_TIME;
        /// 
        /// N2 Enabled
        /// 
        private bool _n2Enabled = false;
        /// 
        /// Dry速度
        /// 
        private int _drySpeed;
        /// 
        /// Wafer Presence Accel/Decel比例 
        /// 
        private int _waferPresenceCheckAccelDecelPercentage;
        /// 
        /// Wafer Presence Speed
        /// 
        private int _waferPresenceSpeedInRPMs;
        /// 
        /// Wafer Presence distance
        /// 
        private int _waferPresenceDistance;
        /// 
        /// 状态机进入时间
        /// 
        private int _startTime;
        /// 
        /// Wafer Presence Test功能是否启用
        /// 
        private bool _presenceTestEnabled;
        /// 
        /// Rinse时间=Max(FrontRinseTime, BackRinseTime) 单位s
        /// 
        private double _rinseTime;
        /// 
        /// Rinse中另一个水阀开关状态
        /// 
        private bool _isAnotherWaterOn;
        /// 
        /// exhaust进入时间
        /// 
        private int _exhaustFanTime;
        /// 
        /// 是否正在用水
        /// 
        private bool _isUsingWater;
        /// 
        /// Presence Test Flag
        /// 
        private bool _presenceTestFlag = false;
        #endregion
        #region 属性
        /// 
        /// 是否正在用水
        /// 
        public bool IsUsingWater { get { return _isUsingWater; } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public SRDRunWaferRecipeRoutine(string module) : base(module)
        {
        }
        /// 
        /// 中止
        /// 
        public void Abort()
        {
            Runner.Stop("SRD RunWaferRecipe Abort");
        }
        /// 
        /// 监控
        /// 
        /// 
        public RState Monitor()
        {
            Runner.RunIf(RunStep.RunWafer_Start, !_presenceTestFlag, RunWaferStartCheckStatus, _delay_1ms)
                .RunIf(RunStep.RunWafer_CheckFacilities, !_presenceTestFlag, CheckFacilities, _delay_1ms)
                .RunIf(RunStep.RunWafer_PreparingExhaustOff, !_presenceTestFlag, PreparingExhaustOff, _delay_1ms)
                .WaitWithStopConditionIf(RunStep.RunWafer_WaitExhaustOff, !_presenceTestFlag, PreparingExhaustOffEndStatus, PreparingExhaustOffStopStatus, _delay_5s)
                .RunIf(RunStep.RunWafer_EngageChuckVacuum, !_presenceTestFlag, EngageChuckVacuum, _delay_1ms)
                .WaitWithStopConditionIf(RunStep.RunWafer_CheckVacuum, !_presenceTestFlag, CheckChuckVacuumEndStatus, CheckChuckVacuumStopStatus, _delay_5s)
                .RunIf(RunStep.RunWafer_CloseTheDoor, !_presenceTestFlag, CloseDoor, _delay_1ms)
                .WaitWithStopConditionIf(RunStep.RunWafer_CheckDoorClosed, !_presenceTestFlag, CheckDoorClosedEndStatus, CheckDoorClosedStopStatus, _delay_5s)
                .RunIf(RunStep.RunWafer_ArmToHome, !_presenceTestFlag, ArmToHome, _delay_1ms)
                .WaitWithStopConditionIf(RunStep.RunWafer_CheckArmHome, !_presenceTestFlag, CheckArmEndStatus,CheckArmStopStatus)
                .WaitIf(RunStep.RunWafer_Diverting_CheckOtherSRD, !_presenceTestFlag, CheckOtherSRD,_delay_60s)
                .RunIf(RunStep.RunWafer_Diverting_WaterOn, !_presenceTestFlag, WaterOn,_delay_1ms)
                .WaitWithStopConditionIf(RunStep.RunWafer_Diverting_WithFlowCheck, !_presenceTestFlag, CheckFlowEndStatus,CheckFlowStopStatus)
                .RunIf(RunStep.RunWafer_Diverting_WaterAboveOff, !_presenceTestFlag, WaterAboveOff,_delay_1ms)
                .RunIf(RunStep.RunWafer_Washing_ArmToCenter, !_presenceTestFlag, ArmToCenter, _delay_1ms)
                .WaitWithStopConditionIf(RunStep.RunWafer_Washing_CheckArmCenter, !_presenceTestFlag, CheckArmToCenterEndStatus,CheckArmToCenterStopStatus,_delay_60s)
                .RunIf(RunStep.RunWafer_Washing_PoolingFrontSide, !_presenceTestFlag, PoolingFrontSideWaterOn,_delay_1ms)
                .WaitWithStopConditionIf(RunStep.RunWafer_Washing_PoolingWithFlowCheck, !_presenceTestFlag, PoolingCheckFlowEndStatus,PoolingCheckFlowStopStatus)
                .RunIf(RunStep.RunWafer_Washing_StartRotation, !_presenceTestFlag, StartRotation,_delay_1ms)
                .WaitWithStopConditionIf(RunStep.RunWafer_Washing_PreFlowCheck, !_presenceTestFlag, WashingPreFlowCheckEndStatus,WashingPreFlowCheckStopStatus)
                .RunIf(RunStep.RunWafer_Washing_Finished, !_presenceTestFlag, WashingFinished,_delay_1ms)
                .WaitWithStopConditionIf(RunStep.RunWafer_Drying_PreN2Time, !_presenceTestFlag, CheckArmMotionEndStatus,CheckArmMotionStopStatus)
                .DelayIf(RunStep.RunWafer_Drying_ExhaustFanDelay, !_presenceTestFlag, _srdRecipe.ExhaustFanDelay*1000)
                .RunIf(RunStep.RunWafer_Drying_ExhaustFanOn, !_presenceTestFlag, ExhaustFanOn,_delay_1ms)
                .DelayIf(RunStep.RunWafer_Drying_N2On, !_presenceTestFlag, _srdRecipe.BackN2DryTime*1000)
                .RunIf(RunStep.RunWafer_Drying_StopRotation, !_presenceTestFlag, StopRotation,_delay_1ms)
                //5s检验Rotation是否停止
                .Wait(RunStep.RunWafer_Drying_PreWaferPresenceCheck, CheckRotationStopEndStatus,_delay_5s)
                //Rotation开始运动至指定角度
                .Run(RunStep.RunWafer_Drying_RotationStartMotion,RotationMotion,_delay_1ms)
                //Rotation过程中Wafer Presence check
                .WaitWithStopCondition(RunStep.RunWafer_Drying_WaferPresenceCheck,RotationMotionEndStatus,RotationMotionStopStatus)
                //Rotation重新Home
                .Run(RunStep.RunWafer_Drying_PostN2Time,PostN2Time,_delay_1ms)
                //检验Rotation Home状态
                .WaitWithStopCondition(RunStep.RunWafer_Drying_CheckRotationFinished,CheckRotationHomedThenExhaust,CheckRotationHomedStopStatus)
                .Run(RunStep.RunWafer_CheckArmHome, LastCheckArmHomed,_delay_1ms)
                .End(RunStep.End, NullFun, _delay_1ms);
            return Runner.Status;
        }
        /// 
        /// 启动
        /// 
        /// 
        /// 
        private bool RunWaferStartCheckStatus()
        {
            _startTime = Environment.TickCount;
            return true;
        }
        /// 
        /// 检查Facilities
        /// 
        /// 
        /// 
        private bool CheckFacilities()
        {
            if (_srdCommon.CommonData.FluidContainment)
            {
                NotifyError(eEvent.ERR_SRD, "Fluid Containment sensor is On", 0);
                return false;
            }
            if (!_systemFacilities.SrdDiEnable)
            {
                NotifyError(eEvent.ERR_SRD, "Srd DI Is Disable",0);
                return false;
            }
            return true;
        }
        /// 
        /// 关闭Exhaust风机
        /// 
        /// 
        /// 
        private bool PreparingExhaustOff()
        {
            bool result = _srdCommon.N2OffAction("", null);
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, "Preparing Exhaust Off is failed", 0);
                return false;
            }
            return true;
        }
        /// 
        /// 检验关闭Exhaust风机结束状态
        /// 
        /// 
        private bool PreparingExhaustOffEndStatus()
        {
            return !_srdCommon.CommonData.ExhaustOn;
        }
        /// 
        /// 检验关闭Exhaust风机停止状态
        /// 
        /// 
        private bool PreparingExhaustOffStopStatus()
        {
            //if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
            //{
            //    NotifyError(eEvent.ERR_SRD, "Waiting Exhaust Off is failed");
            //    return true;
            //}
            return false;
        }
        /// 
        /// Chuck Vacuum
        /// 
        /// 
        /// 
        private bool EngageChuckVacuum()
        {
            if (_srdCommon.IsWaferPresence)
            {
                bool result = _srdCommon.ChuckVacuumOnAction("", null);
                if (!result)
                {
                    NotifyError(eEvent.ERR_SRD, "Chuck Vacuum On Action is failed",0);
                }
                return result;
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, Module, "EngageChuckVacuum has been ignored");
                return true;
            }
        }
        /// 
        /// 检验ChuckVacuum结束状态
        /// 
        /// 
        private bool CheckChuckVacuumEndStatus()
        {
            if (_srdCommon.IsWaferPresence)
            {
                return _srdCommon.Status == RState.End && !_srdCommon.CommonData.ChuckVacuum;
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, Module, "CheckVacuum has been ignored");
                return true;
            }
        }
        /// 
        /// 检验ChuckVacuum停止状态
        /// 
        /// 
        private bool CheckChuckVacuumStopStatus()
        {
            if (_srdCommon.IsWaferPresence)
            {
                if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
                {
                    NotifyError(eEvent.ERR_SRD, "Check Vacuum is failed", 0);
                    return true;
                }
                return false;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// Close Door
        /// 
        /// 
        /// 
        private bool CloseDoor()
        {
            if (_srdCommon.CommonData.DoorOpened)
            {
                bool result = _srdCommon.DoorCloseAction("", null);
                if (!result)
                {
                    NotifyError(eEvent.ERR_SRD, "Door Close Action is failed",0);
                    return result;
                }
            }
            return true;
        }
        /// 
        /// 检验DoorClosed结束状态
        /// 
        /// 
        /// 
        private bool CheckDoorClosedEndStatus()
        {
            return _srdCommon.Status == RState.End && _srdCommon.CommonData.DoorClosed;
        }
        /// 
        /// 检验DoorClosed结束状态
        /// 
        /// 
        /// 
        private bool CheckDoorClosedStopStatus()
        {
            if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
            {
                NotifyError(eEvent.ERR_SRD, "Check Door Closed is failed", 0);
                return true;
            }
            return false;
        }
        /// 
        /// Arm To Home
        /// 
        /// 
        private bool ArmToHome()
        {
            _armAxis.Home(false);
            return true;
        }
        /// 
        /// 检验Arm home结束状态
        /// 
        /// 
        private bool CheckArmEndStatus()
        {
            if (_armAxis.IsHomed && _armAxis.Status == RState.End)
            {
                _armRetryTimes = 0;
                return true;
            }
            return false;
        }
        /// 
        /// 检验Arm停止状态
        /// 
        /// 
        private bool CheckArmStopStatus()
        {
            if (_armAxis.Status == RState.Failed || _armAxis.Status == RState.Timeout)
            {
                if (_armRetryTimes < MAX_ARM_HOME_RETRIES)
                {
                    _armAxis.Home(false);
                    _armRetryTimes++;
                }
                else
                {
                    NotifyError(eEvent.ERR_SRD, $"Arm Home Retry Home {_armRetryTimes + 1} times is over {MAX_ARM_HOME_RETRIES}",0);
                    return true;
                }
            }
            return false;
        }
        /// 
        /// 检验另外一个SRD是否在用水
        /// 
        /// 
        /// 
        private bool CheckOtherSRD()
        {            
            return (_otherSrdEntity == null || !_otherSrdEntity.IsUsingWater);
        }
        /// 
        /// 打开Above water
        /// 
        /// 
        /// 
        private bool WaterOn()
        {
            if (_srdRecipe.FrontDivertTime > 0)
            {
                if (_srdRecipe.FrontDivertTime > _srdRecipe.DivertPlusPoolDelay)
                {
                    _divertingFlowCheckTimeSpan = _srdRecipe.DivertPlusPoolDelay * 1000;
                }
                else
                {
                    _divertingFlowCheckTimeSpan = _srdRecipe.FrontDivertTime * 1000;
                }
                if (!_srdCommon.CommonData.WaterAbove)
                {
                    
                    bool result = _srdCommon.WaterAboveOn();
                    if (result)
                    {
                        LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Above On");
                        _isUsingWater = true;
                        _enterTime = Environment.TickCount;
                    }
                    else
                    {
                        NotifyError(eEvent.ERR_SRD, "Water Above On is failed", 0);
                    }
                    return result;
                }
                return true;
            }
            else
            {
                if (_srdCommon.CommonData.WaterAbove)
                {
                    bool result = _srdCommon.WaterAboveOff();
                    if (result)
                    {
                        LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Above Off");
                        _isUsingWater = false;
                        _enterTime = Environment.TickCount;
                    }
                    else
                    {
                        NotifyError(eEvent.ERR_SRD, "Water Above Off is failed", 0);
                    }
                    return result;
                }
                return true;
            }
        }
        /// 
        /// 检验流量结束状态
        /// 
        /// 
        private bool CheckFlowEndStatus()
        {
            if (_srdRecipe.FrontDivertTime == 0)
            {
                return true;
            }
            int ticks = Environment.TickCount - _enterTime;
            if (ticks >= _srdRecipe.FrontDivertTime * 1000)
            {
                return true;
            }
            return false;
        }
        /// 
        /// 检验水压
        /// 
        /// 
        /// 
        private bool CheckFlowStopStatus()
        {
            int ticks = Environment.TickCount - _enterTime;
            if (ticks <= _divertingFlowCheckTimeSpan)
            {
                if (_totalSRDDevice.WaterPressure > _srdRecipe.MaxDivertPlusPoolPressure)
                {
                    NotifyError(eEvent.ERR_SRD, $"Water Pressure {_totalSRDDevice} is over {_srdRecipe.MaxDivertPlusPoolPressure}",0);
                    return true;
                }
            }
            return false;
        }
        /// 
        /// WaterAbove Off
        /// 
        /// 
        private bool WaterAboveOff()
        {
            if (_srdCommon.CommonData.WaterAbove)
            {
                bool result = _srdCommon.WaterAboveOff();
                _isUsingWater = false;
                if (result)
                {
                    LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Above off");
                }
                else
                {
                    NotifyError(eEvent.ERR_SRD, "Water Above On is failed", 0);
                }
                return result;
            }
            return true;
        }
        /// 
        /// Arm运动至Center
        /// 
        /// 
        /// 
        private bool ArmToCenter()
        {
            bool result = _armAxis.PositionStation("Center");
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, "Arm to Center is failed", 0);
            }
            return result;
        }
        /// 
        /// check Arm是否运动至Center
        /// 
        /// 
        /// 
        private bool CheckArmToCenterEndStatus()
        {
            return _armAxis.Status == RState.End;
        }
        /// 
        /// check Arm是否运动至Center停止状态
        /// 
        /// 
        private bool CheckArmToCenterStopStatus()
        {
            if (_armAxis.Status == RState.Failed||_armAxis.Status==RState.Timeout)
            {
                NotifyError(eEvent.ERR_SRD, "Check Arm to Center is failed", 0);
                return true;
            }
            return false;
        }
        /// 
        /// 打开Above water
        /// 
        /// 
        /// 
        private bool PoolingFrontSideWaterOn()
        {
            if (_srdRecipe.FrontPoolTime > 0)
            {
                if (_srdRecipe.FrontPoolTime > _srdRecipe.DivertPlusPoolDelay)
                {
                    _poolingFlowCheckTimeSpan = _srdRecipe.DivertPlusPoolDelay * 1000;
                }
                else
                {
                    _poolingFlowCheckTimeSpan = _srdRecipe.FrontDivertTime * 1000;
                }
                if (!_srdCommon.CommonData.WaterAbove)
                {
                    bool result = _srdCommon.WaterAboveOn();
                    if (result)
                    {
                        LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Above On");
                        _enterTime = Environment.TickCount;                        
                        _isUsingWater = true;
                        
                    }
                    else
                    {
                        NotifyError(eEvent.ERR_SRD, "Water Above On is failed",0);
                    }
                    return result;
                }
                return true;
            }
            else
            {
                return true;
            }
        }
        /// 
        /// 检验Pooling流量结束状态
        /// 
        /// 
        private bool PoolingCheckFlowEndStatus()
        {
            if (_srdRecipe.FrontPoolTime == 0)
            {
                return true;
            }
            int ticks = Environment.TickCount - _enterTime;
            if (ticks >= _srdRecipe.FrontPoolTime * 1000)
            {
                return true;
            }
            return false;
        }
        /// 
        /// 检验Pooling流量停止状态
        /// 
        /// 
        /// 
        private bool PoolingCheckFlowStopStatus()
        {
            int ticks = Environment.TickCount - _enterTime;
            if (ticks <= _poolingFlowCheckTimeSpan)
            {
                if (_totalSRDDevice.WaterPressure > _srdRecipe.MaxWashPressure)
                {
                    NotifyError(eEvent.ERR_SRD, $"Water Pressure {_totalSRDDevice.WaterPressure} is over {_srdRecipe.MaxWashPressure}", 0);
                    return true;
                }
                if (_totalSRDDevice.WaterPressure < _srdRecipe.MinWaterPressure)
                {
                    NotifyError(eEvent.ERR_SRD, $"Water Pressure {_totalSRDDevice.WaterPressure} is less {_srdRecipe.MinWaterPressure}",0);
                    return true;
                }
            }
            return false;
        }
        /// 
        /// 开始旋转
        /// 
        /// 
        /// 
        private bool StartRotation()
        {
            if (_srdCommon.CommonData.DoorOpened)
            {
                NotifyError(eEvent.ERR_SRD, "Door is not closed. Can't do rotation", 0);
                return false;
            }
            double _scale = _rotationProviderAxis.ScaleFactor;
            bool above = _srdRecipe.FrontRinseTime > _srdRecipe.BackRinseTime;
            int timespan = above ? _srdRecipe.FrontRinseTime : _srdRecipe.BackRinseTime;
            //rinse 目标位置 
            double rinsePosition = timespan * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.RinseSpeed);
            //dry目标位置
            double dryPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.DrySpeed) * _srdRecipe.BackN2DryTime;
            //为了让 rotation 不停止,增加了旋转时间(覆盖Arm运动时间)
            double plusPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.DrySpeed) * _rotationPlusSecond;
            int targetPosition = (int)Math.Round((rinsePosition + dryPosition + plusPosition) * _scale, 0);
            int rotationSpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.RinseSpeed), 0);
            _drySpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.DrySpeed * SPEED_RATIO), 0);
            bool result = _rotationAxis.ProfilePosition(targetPosition, rotationSpeed * SPEED_RATIO, 0, 0);
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, "Start Rotation is failed",0);
                return false;
            }
            LOG.WriteLog(eEvent.INFO_SRD, Module, "Start Rotation");
            //如果BackRinseTime大,则先开WaterBelow后开WaterAbove        
            if (_srdRecipe.BackRinseTime > _srdRecipe.FrontRinseTime)
            {
                _rinseTime = _srdRecipe.BackRinseTime;
                //关闭WaterAbove
                if (_srdCommon.CommonData.WaterAbove)
                {
                    if (!_srdCommon.WaterAboveOff())
                    {
                        NotifyError(eEvent.ERR_SRD, "Water Above Off is failed", 0);
                        return false;
                    }
                    LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Above Off");
                }
                //打开WaterBelow
                if (!_srdCommon.CommonData.WaterBelow)
                {
                    if (!_srdCommon.WaterBelowOn())
                    {
                        NotifyError(eEvent.ERR_SRD, "Water Below On is failed",0);
                        return false;
                    }
                    LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Below On");
                }
                //Rinse开始时间
                _enterTime = Environment.TickCount;
                //另一个水阀状态变为未开(即WaterAbove)
                _isAnotherWaterOn = false;
                //计算水压检测滞后时间
                if (_srdRecipe.BackRinseTime > _srdRecipe.FlowCheckDelay)
                {
                    _washingFlowCheckTimeSpan = _srdRecipe.FlowCheckDelay * 1000;
                }
                else
                {
                    _washingFlowCheckTimeSpan = _srdRecipe.BackRinseTime * 1000;
                }
                return true;
            }
            else
            {
                _rinseTime = _srdRecipe.FrontRinseTime;
                //如果FrontRinseTime大,则先开WaterAbove后开WaterBelow
                //打开WaterAbove
                if (!_srdCommon.CommonData.WaterAbove)
                {
                    if (!_srdCommon.WaterAboveOn())
                    {
                        NotifyError(eEvent.ERR_SRD, "Water Above Off is failed", 0);
                        return false;
                    }
                    LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Above On");
                }
                //关闭WaterBelow
                if (_srdCommon.CommonData.WaterBelow)
                {
                    //打开WaterBelow
                    if (!_srdCommon.WaterBelowOff())
                    {
                        NotifyError(eEvent.ERR_SRD, "Water Below On is failed",0);
                        return false;
                    }
                    LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Below Off");
                }
                //另一个水阀状态变为未开(即WaterBelow)
                _isAnotherWaterOn = false;
                //Rinse开始时间
                _enterTime = Environment.TickCount;
                //计算水压检测滞后时间
                if (_srdRecipe.FrontRinseTime > _srdRecipe.FlowCheckDelay)
                {
                    _washingFlowCheckTimeSpan = _srdRecipe.FlowCheckDelay * 1000;
                }
                else
                {
                    _washingFlowCheckTimeSpan = _srdRecipe.BackRinseTime * 1000;
                }
                return true;
            }
        }
        /// 
        /// Washing PreFlow 流量结束状态
        /// 
        /// 
        /// 
        private bool WashingPreFlowCheckEndStatus()
        {
            int ticks = Environment.TickCount - _enterTime;
            if (ticks >= _rinseTime * 1000)
            {
                //达到RinseTime完成Wash
                return true;
            }
            return false;
        }
        /// 
        /// Washing PreFlow 流量停止状态
        /// 
        /// 
        private bool WashingPreFlowCheckStopStatus()
        {
            int ticks = Environment.TickCount - _enterTime;
            //打开另一个未开的水阀
            if (!_isAnotherWaterOn)
            {
                //延迟abs(BackRinseTime - FrontRinseTime)秒打开另一个水阀
                if (_srdRecipe.BackRinseTime > _srdRecipe.FrontRinseTime)
                {
                    //若BackRinseTime > FrontRinseTime,则延迟BackRinseTime - FrontRinseTime秒打开Water Above
                    if (ticks >= _rinseTime * 1000 - _srdRecipe.FrontRinseTime * 1000 && !_srdCommon.CommonData.WaterAbove)
                    {
                        bool result = _srdCommon.WaterAboveOn();
                        if (!result)
                        {
                            NotifyError(eEvent.ERR_SRD, "Water Above Off is failed", 0);
                            return true;
                        }
                        _isAnotherWaterOn = true;
                        LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Above On");
                    }
                }
                else
                {
                    //若FrontRinseTime > BackRinseTime,则延迟FrontRinseTime - BackRinseTime秒打开Water Below
                    if (ticks >= _rinseTime * 1000 - _srdRecipe.BackRinseTime * 1000 && !_srdCommon.CommonData.WaterBelow)
                    {
                        bool result = _srdCommon.WaterBelowOn();
                        if (!result)
                        {
                            NotifyError(eEvent.ERR_SRD, "Water Below On is failed",0);
                            return true;
                        }
                        LOG.WriteLog(eEvent.INFO_SRD, Module, "Water Below On");
                    }
                }
            }
            //测水压
            if (ticks > _washingFlowCheckTimeSpan)
            {
                if (_totalSRDDevice.WaterPressure > _srdRecipe.MaxWashPressure)
                {
                    NotifyError(eEvent.ERR_SRD, $"Water Pressure {_totalSRDDevice.WaterPressure} is over {_srdRecipe.MaxWashPressure}", 0);
                    return true;
                }
                if (_totalSRDDevice.WaterPressure < _srdRecipe.MinWaterPressure)
                {
                    NotifyError(eEvent.ERR_SRD, $"Water Pressure {_totalSRDDevice.WaterPressure} is less {_srdRecipe.MinWaterPressure}",0);
                    return true;
                }
            }
            return false;
        }
        /// 
        /// Washing结束
        /// 
        /// 
        /// 
        private bool WashingFinished()
        {
            if (_srdCommon.CommonData.WaterAbove)
            {
                if (!_srdCommon.WaterAboveOff())
                {
                    NotifyError(eEvent.ERR_SRD, "Water Above Off is failed",0);
                    return false;
                }
            }
            if (_srdCommon.CommonData.WaterBelow)
            {
                if (!_srdCommon.WaterBelowOff())
                {
                    NotifyError(eEvent.ERR_SRD, "Water Below Off is failed", 0);
                    return false;
                }
            }
            _isUsingWater = false;
            if (_n2Enabled)
            {
                bool result = _armAxis.PositionStation("Center");
                if (!result)
                {
                    NotifyError(eEvent.ERR_SRD, "Arm to Center is failed",0);
                }
                return result;
            }
            else
            {
                bool result = _armAxis.PositionStation("Home");
                if (!result)
                {
                    NotifyError(eEvent.ERR_SRD, "Arm To Home is failed", 0);
                }
                return result;
            }
        }
        /// 
        /// 检验Arm是否运动到位
        /// 
        /// 
        private bool CheckArmMotionEndStatus()
        {
            //Arm是否运动到位
            if (_armAxis.Status == RState.End)
            {
                //调整速度为 drySpeed
                bool result = _rotationAxis.ChangeSpeed(_drySpeed);
                if (!result)
                {
                    NotifyError(eEvent.ERR_SRD, "Change Speed to Dry Speed is failed",0);
                    return false;
                }
                if (_n2Enabled)
                {
                    //todo 打开N2 Above和N2 Below
                }
                _exhaustFanTime = Environment.TickCount;
                return true;
            }
            return false;
        }
        /// 
        /// 检验Arm是否运动到位
        /// 
        /// 
        private bool CheckArmMotionStopStatus()
        {
            if (_armAxis.Status == RState.Failed||_armAxis.Status==RState.Timeout)
            {
                NotifyError(eEvent.ERR_SRD, "Arm Axis Status is in Failed", 0);
                return true;
            }
            return false;
        }
        /// 
        /// Exhaust delay
        /// 
        /// 
        /// 
        private bool ExhaustFanOn()
        {
            bool result = _srdCommon.N2On();
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, "Exhaust On failed",0);
                return false;
            }
            if (_n2Enabled)
            {
                //todo 关闭N2Above和N2 Below
            }
            return true;
        }
        /// 
        /// 停止旋转
        /// 
        /// 
        private bool StopRotation()
        {
            bool result = _rotationAxis.StopPositionOperation();
            LOG.WriteLog(eEvent.INFO_SRD, Module, "Stop Rotation is done");
            return result;
        }
        /// 
        /// 检验Rotation是否停止
        /// 
        /// 
        private bool CheckRotationStopEndStatus()
        {
            if (!_rotationAxis.IsRun && _rotationAxis.Status == RState.End)
            {
                return true;
            }
            return false;
        }
        /// 
        /// Rotation运行指定角度
        /// 
        /// 
        private bool RotationMotion()
        {
            double scale = _rotationProviderAxis.ScaleFactor;
            int currentRotation = (int)Math.Round(_rotationAxis.MotionData.MotorPosition * scale, 0);
            //Presence Test目标位置(单位为°)
            int targetPosition = (int)Math.Round(scale * _waferPresenceDistance, 0) + currentRotation;
            //转速单位转换 RPM(r/min) to degree/s
            double degree = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_waferPresenceSpeedInRPMs);
            //Presence Test目标转速
            int profileVelocity = (int)Math.Round(scale * degree, 0);
            //加速度
            int acceleration = (int)Math.Round(_rotationAxis.ProfileAcceleration * _waferPresenceCheckAccelDecelPercentage / 100, 0);
            //减速度
            int deceleration = (int)Math.Round(_rotationAxis.ProfileDeceleration * _waferPresenceCheckAccelDecelPercentage / 100, 0);
            if (_srdCommon.CommonData.DoorOpened)
            {
                NotifyError(eEvent.ERR_SRD, "Door is not closed. Can't do rotation", 0);
                return false;
            }
            bool result = _rotationAxis.ProfilePosition(targetPosition, profileVelocity * SPEED_RATIO, acceleration, deceleration);
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, "Start Rotation is failed",0);
                return false;
            }            
            return true;
        }
        /// 
        /// Rotation运动结束状态
        /// 
        /// 
        private bool RotationMotionEndStatus()
        {
            return _rotationAxis.Status == RState.End;
        }
        /// 
        /// Rotation运动
        /// 
        /// 
        private bool RotationMotionStopStatus()
        {
            bool stopResult = _rotationAxis.Status == RState.Failed || _rotationAxis.Status == RState.Timeout;
            if (!stopResult)
            {
                if (_presenceTestEnabled && _srdCommon.IsWaferPresence)
                {
                    if (_srdCommon.WaferPresence != "WellPlaced")
                    {
                        NotifyError(eEvent.ERR_SRD, $"Rotation Motioning wafer presence is {_srdCommon.WaferPresence}",0);
                        return true;
                    }
                }
            }
            else
            {
                return true;
            }
            return false;
        }
        /// 
        /// Post N2 Time(Stop rotation ,home rotation)
        /// 
        /// 
        /// 
        private bool PostN2Time()
        {
            bool homeResult = _rotationAxis.Home(false);
            if (!homeResult)
            {
                NotifyError(eEvent.ERR_SRD, $"{Module}.Arm is not homed", 0);
                return false;
            }
            return true;
        }
        /// 
        /// 检验Rotation是否Homed,Home后关闭排风扇
        /// 
        /// 
        /// 
        private bool CheckRotationHomedThenExhaust()
        {
            bool result = _rotationAxis.IsHomed && _rotationAxis.Status == RState.End;
            if(result)
            {
                //关闭排风扇
                if (_srdCommon.CommonData.ExhaustOn)
                {
                    _srdCommon.N2OffAction("", null);
                }
            }
            return result;
        }
        /// 
        /// 检验Rotation Home 停止状态
        /// 
        /// 
        private bool CheckRotationHomedStopStatus()
        {
            return _rotationAxis.Status == RState.Failed || _rotationAxis.Status == RState.Timeout;
        }
        /// 
        /// 检验
        /// 
        /// 
        /// 
        private bool LastCheckArmHomed()
        {
            string currentLocation = _armAxis.CurrentStation;
            bool armHomed = _armAxis.IsHomed;
            if (!armHomed)
            {
                NotifyError(eEvent.ERR_SRD, $"{Module}.Arm is not homed", 0);
                return false;
            }
            if (!currentLocation.Contains("Home"))
            {
                NotifyError(eEvent.ERR_SRD, $"{Module}.Arm is not in home station", 0);
                return false;
            }
            return true;
        }
        
        /// 
        /// 启动
        /// 
        /// 
        /// 
        public RState Start(params object[] objs)
        {
            _isUsingWater = false;
            if (objs.Length >= 2 && (bool)objs[1])
            {
                _presenceTestFlag = true;
            }
            else
            {
                _presenceTestFlag = false;
            }
            _srdRecipe = (SrdRecipe)objs[0];
            if (_srdRecipe == null)
            {
                NotifyError(eEvent.ERR_SRD, "srd recipe is null", 0);
                return RState.Failed;
            }
            _armAxis = DEVICE.GetDevice($"{Module}.Arm");
            if (!_armAxis.IsHomed)
            {
                NotifyError(eEvent.ERR_SRD, "Arm is not homed", 0);
                return RState.Failed;
            }
            _rotationAxis = DEVICE.GetDevice($"{Module}.Rotation");
            if (!_rotationAxis.IsHomed)
            {
                NotifyError(eEvent.ERR_SRD, "Rotation is not homed",0);
                return RState.Failed;
            }
            _srdCommon = DEVICE.GetDevice($"{Module}.Common");
            _totalSRDDevice = DEVICE.GetDevice("SRD");
            if (_srdCommon.IsWaferPresence)
            {
                if (_srdCommon.WaferPresence != "WellPlaced")
                {
                    NotifyError(eEvent.ERR_SRD, "Wafer Presence is not WellPlaced", 0);
                    return RState.Failed;
                }
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_SRD, Module, "Wafer Presence Test has been ignored");
            }
            if (SC.ContainsItem("SRD.SRDRotationPlusSecond"))
            {
                _rotationPlusSecond = SC.GetValue("SRD.SRDRotationPlusSecond");
            }
            if (SC.ContainsItem("SRD.N2Enabled"))
            {
                _n2Enabled = SC.GetValue("SRD.N2Enabled");
            }
            //Wafer Presence Test
            if (SC.ContainsItem($"SRD.{Module}EnablePresenceCheckvalue"))
            {
                _presenceTestEnabled = SC.GetValue($"SRD.{Module}EnablePresenceCheckvalue");
            }
            _systemFacilities = DEVICE.GetDevice("System.Facilities");
            string otherSRD = Module == "SRD1" ? "SRD2" : "SRD1";
            _otherSrdEntity = Singleton.Instance.GetModule(otherSRD);
            _rotationProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{Module}.Rotation");
            if (_rotationProviderAxis == null)
            {
                NotifyError(eEvent.ERR_SRD, $"{Module}.Rotation Provider is not exist", 0);
                return RState.Failed;
            }
            _armProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{Module}.Arm");
            if (_armProviderAxis == null)
            {
                NotifyError(eEvent.ERR_SRD, $"{Module}.Arm Provider is not exist",0);
                return RState.Failed;
            }
            _waferPresenceCheckAccelDecelPercentage = SC.GetValue("SRD.WaferPresenceCheckAccelDecelPercentage");
            _waferPresenceSpeedInRPMs = SC.GetValue("SRD.WaferPresenceCheckSpeedInRPMs");
            _waferPresenceDistance = SC.GetValue("SRD.WaferPresenceCheckDistanceInDegrees");
            return Runner.Start(Module, "Start Run Wafer");
        }
    }
}