using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.RecipeCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.CommonData.Reservoir;
using MECF.Framework.Common.Persistent.Reservoirs;
using MECF.Framework.Common.TwinCat;
using System;
using System.Collections.Generic;
using System.Reflection;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.ToolLayout;
using System.Collections.ObjectModel;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.Beckhoff.IOAxis;
using System.Linq;
using MECF.Framework.Common.Alarm;
using MECF.Framework.Common.ProcessCell;
using MECF.Framework.Common.Persistent.Temperature;
using CyberX8_Core;
using CyberX8_RT.Devices.Facilities;
using CyberX8_RT.Devices.Metal;
using CyberX8_RT.Devices.Reservoir;
using CyberX8_RT.Devices.Safety;
using CyberX8_RT.Devices.Temperature;
using CyberX8_RT.Modules.Metal;
using CyberX8_RT.Modules.Reservoir;
using CyberX8_RT.Modules;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.Reservoir
{
    public class CompactMembranReservoirDevice : BaseDevice, IDevice
    {
        private enum ReservoirOperation
        {
            None,
            ManualANDiReplen,
            ManualCADiReplen,
            AutoANDiReplen,
            AutoCADiReplen
        }
        #region 常量
        private const string PERSISTENT_VALUE = "PersistentValue";
        private const string CA_DI_REPLEN = "CADiReplen";
        private const string AN_DI_REPLEN = "ANDiReplen";
        private const string CA_WATER_LEVEL = "CAWaterLevel";
        private const string AN_WATER_LEVEL = "ANWaterLevel";
        private const string AN_PUMP = "ANPump";
        private const string CROSS_DOSE_ENABLE = "CrossDoseEnable";
        private const string TRANSFER_PUMP_STM_STATUS = "TransferPumpSTMStatus";
        private const string TRANSFER_PUMP_POS_STATUS = "TransferPumpPOSStatus";
        private const string TRANSFER_ACTUAL_POSITION = "TransferActualPosition";
        private const string TRANSFER_PUMP_ENABLE = "TransferPumpEnable";
        private const string TRANSFER_PUMP_RESET = "TransferPumpReset";
        private const string TRANSFER_PUMP_EXECUTE = "TransferPumpExecute";
        private const string TRANSFER_PUMP_TARGET_POSITION = "TransferPumpTargetPosition";
        private const string TRANSFER_PUMP_SPEED = "TransferPumpSpeed";
        private const string TRANSFER_PUMP_START_TYPE = "TransferPumpStartType";
        private const string TRANSFER_PUMP_ACCELERATION = "TransferPumpAcceleration";
        private const string TRANSFER_PUMP_DECELERATION = "TransferPumpDeceleration";
        private const string AN_BYPASS_FLOW = "ANBypassFlow";
        private const string AN_A_DRAIN_PUMP = "ANADrainPump";
        private const string AN_B_DRAIN_PUMP = "ANBDrainPump";
        private const string AN_BY_PASS = "ANByPass";
        //private const string AN_SLIP_STREAM_PUMP = "ANSlipStreamPump";
        private const string AN_TRANSFER_FLOW = "ANTransferFlow";
        //private const string CA_SLIP_STREAM_PUMP = "CASlipStreamPump";
        private const string CA_PUMP_SPEED = "CAPumpSpeed";
        private const string CA_PUMP_RUNNING = "CAPumpRunning";
        private const string CA_HED_FLOW = "CAHedFlow";
        private const string CDA_FLOW_VALVE = "CDAFlowValve";
        private const string CA_BY_PASS = "CAByPass";
        private const string CA_PUMP_ENABLE = "CAPumpEnable";
        private const string EVAPORATORLEVEL = "EvaporatorLevel";
        private const string AN_BYPASS_COUNTERFLOW = "ANBypassFlow";
        private const string AN_SAMPLE_FLOW = "ANSampleFlow";
        private const string CA_SAMPLE_FLOW = "CASampleFlow";
        private const string STRATUS = "Stratus";
        private const string AUTO = "Auto";
        private const string COUNTER_VALUE = "CounterValue";
        private const string COUNTER_START = "Start";
        private const string COUNTER_STOP = "Stop";
        private const string COUNTER_RESET = "Reset";
        private const int ENABLE = 5;
        #endregion
        #region 内部变量
        /// 
        /// AN Level取样平均值
        /// 
        private double _avgANLevel;
        /// 
        /// AN Level取样队列
        /// 
        private Queue _ANLevelSamples;
        /// 
        /// CA Level取样平均值
        /// 
        private double _avgCALevel;
        /// 
        /// CA Level取样队列
        /// 
        private Queue _CALevelSamples;
        /// 
        /// AN/CA level计算平均值取样数
        /// 
        private int levelSampleCount;
        /// 
        /// Prewet 持久性数值对象
        /// 
        private ReservoirsPersistentValue _persistentValue;
        /// 
        /// 变量是否初始化字典
        /// 
        private Dictionary _variableInitializeDic = new Dictionary();
        /// 
        /// 数据
        /// 
        private CompactMembranReservoirData _reservoirData = new CompactMembranReservoirData();
        /// 
        /// Recipe
        /// 
        private ResRecipe _resRecipe;
        /// 
        /// 阳极Pump速度
        /// 
        private double _anPumpSpeed = 0;
        /// 
        /// 阴极Pump速度
        /// 
        private double _caPumpSpeed = 0;
        /// 
        /// 定时器
        /// 
        private PeriodicJob _periodicJob;
        /// 
        /// 注水Helper
        /// 
        private ReservoirDiReplenHelper _direplenHelper;
        /// 
        /// 泵速Helper
        /// 
        private ReservoirPumpSpeedHelper _pumpSpeedHelper;
        /// 
        /// 当前操作
        /// 
        private ReservoirOperation _currentOperation;
        /// 
        /// 手动注水时间(秒)
        /// 
        private int _manualReplenSecond = 0;
        /// 
        /// 注水是否出错
        /// 
        private bool _isDiReplenInFault = false;
        /// 
        /// Fast leak Test时间间隔
        /// 
        private int _aNLeakOperatingUpdateTime;
        /// 
        /// Fast leak Test Tolerance Value
        /// 
        private double _aNFastLeakLevelTolerance;
        /// 
        /// 计时器是否正在运行
        /// 
        private bool _isTestRunning = false;
        /// 
        /// 是否检测到漏液
        /// 
        private bool _isLeakDetected = false;
        /// 
        /// 漏液的体积
        /// 
        private double _leakVolume;
        /// 
        /// 开始检测slow leak test时的ANLevel
        /// 
        private double _StartSlowLeakTestANLevel;
        /// 
        /// 配置的metal device集合
        /// 
        private ObservableCollection _metalDevices = new ObservableCollection();
        /// 
        /// 是否存在anflow有流量
        /// 
        private bool _isHasAnFlow;
        /// 
        /// 是否存在metal 在auto模式
        /// 
        private bool _isHasMetalInAuto;
        /// 
        /// 设备是否进行过初始化
        /// 
        private bool _isInitialized;
        /// 
        /// 是否安装CrossDose
        /// 
        private bool _isCrossDoseInstalled;
        /// 
        /// fastleaktest的开始时间
        /// 
        private DateTime _fastLeakStartTime;
        /// 
        /// slowleaktest的开始时间
        /// 
        private DateTime _slowLeakStartTime;
        /// 
        /// fastleak 测试时间间隔
        /// 
        private TimeSpan _fastLeakTestSpan;
        /// 
        /// slowleak 测试时间间隔
        /// 
        private TimeSpan _slowLeakTestSpan;
        /// 
        /// clearLeakVolumeTime
        /// 
        private double _clearLeakVolumeTime;
        /// 
        /// ANTransferFlow(CrossDose Flow)
        /// 
        private CounterFlowData _anTransferFlow = new CounterFlowData();
        /// 
        /// ReservoirANByPassCounterFlow
        /// 
        private CounterFlowData _reservoirCounterByPassFlow = new CounterFlowData();
        /// 
        /// Counter字典
        /// 
        private Dictionary _nameCounterFlowData = new Dictionary();
        /// 
        /// CrossDoseHelper
        /// 
        private CrossDoseHelper _crossDoseHelper;
        /// 
        /// CrossDose是否初始化
        /// 
        private bool _isCrossDoseInitialized;
        /// 
        /// WarningFlag
        /// 
        private List _isCAFlowRateWARN;
        private List _isANAFlowRateWARN;
        private List _isANBFlowRateWARN;
        private bool _isTCControlWARN = false;
        /// 
        /// flow fault hold off时长
        /// 
        private int _flowFaultHoldOffTime = 10;
        private DateTime _AnPumpSafeDetectTime;
        private double _metalTotalFlow;
        /// 
        /// ErrorMessage
        /// 
        private bool _isAnPumpSafeDetectedActivate = false;
        private bool _isANAutoDIReplenError = false;
        private bool _isCAAutoDIReplenError = false;
        private bool _isSystemAutoMode = false;
        /// 
        /// 用于控制打印错误log
        /// 
        private HashSet errorLogSet = new HashSet();
        #endregion
        #region 属性
        /// 
        /// 数据
        /// 
        public CompactMembranReservoirData ReservoirData { get { return _reservoirData; } }
        /// 
        /// 操作模式
        /// 
        public string OperationMode { get { return _persistentValue.OperatingMode; } }
        /// 
        /// 工程模式
        /// 
        public string EngineerMode { get { return _persistentValue.RecipeOperatingMode; } }
        /// 
        /// 阳极是否需要补水
        /// 
        public bool AnNeedDireplen { get { return CheckANNeedDiReplen(); } }
        /// 
        /// 阴极是否需要补水
        /// 
        public bool CANeedDiReplen { get { return CheckCANeedDiReplen(); } }
        /// 
        /// 检验阴极是否highlevel
        /// 
        public bool IsCAHighLevel { get { return CheckCAHighLevelStatus(); } }
        /// 
        /// 检验阴极是否lowlevel
        /// 
        public bool IsCALowLevel { get { return CheckCALowLevelStatus(); } }
        /// 
        /// 检验阳极是否highlevel
        /// 
        public bool IsANHighLevel { get { return CheckANHighLevelStatus(); } }
        /// 
        /// 检验阳极是否lowlevel
        /// 
        public bool IsANLowLevel { get { return CheckANLowLevelStatus(); } }
        /// 
        /// 正在补水
        /// 
        public bool IsDireplenOn { get { return _reservoirData.ANDiReplen || _reservoirData.CADiReplen; } }
        /// 
        /// 当前Recipe
        /// 
        public ResRecipe Recipe { get { return _resRecipe; } }
        /// 
        /// 是否自动模式
        /// 
        public bool IsAuto { get { return _persistentValue.OperatingMode == AUTO; } }
        /// 
        /// ANTransferFlow
        /// 
        public CounterFlowData ANTransferFlow { get { return _anTransferFlow; } }
        /// 
        /// ReservoirCounterByPassFlow
        /// 
        public CounterFlowData ReservoirCounterByPassFlow { get { return _reservoirCounterByPassFlow; } }
        #endregion
        /// 
        /// 初始化成功清除对应的错误log
        /// 
        /// 
        public void ClearErrorLogSet(string module)
        {
            // 使用构造函数复制 HashSet
            HashSet newHashSet = new HashSet(errorLogSet);
            foreach (var item in newHashSet)
            {
                if (item.Contains(module))
                {
                    errorLogSet.Remove(item);
                }
            }
        }
        /// 
        /// 构造函数
        /// 
        /// 
        /// 
        public CompactMembranReservoirDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
        {
            _anPumpSpeed = SC.GetValue($"Reservoir.ANDefaultPumpSpeed");
            _caPumpSpeed = SC.GetValue("Reservoir.CADefaultPumpSpeed");
            _aNLeakOperatingUpdateTime = SC.GetValue($"Reservoir.{Module}.ANLeakOperatingUpdateTime");
            _aNFastLeakLevelTolerance = SC.GetValue($"Reservoir.{Module}.ANFastLeakLevelTolerance");
            _clearLeakVolumeTime = SC.GetValue($"Reservoir.{Module}.CleraLeakVolumeTime");
            _flowFaultHoldOffTime = SC.GetValue($"Reservoir.{Module}.FlowFaultHoldOffTime") / 1000;
            levelSampleCount = SC.GetValue("Reservoir.LevelAvgSamples");
            levelSampleCount = levelSampleCount == 0 ? 20 : levelSampleCount;
            _ANLevelSamples = new Queue(levelSampleCount);
            _CALevelSamples = new Queue(levelSampleCount);
            _periodicJob = new PeriodicJob(200, OnTimer, $"{Module}.Timer", true, true);
            double updateTime = _aNLeakOperatingUpdateTime > 0 ? Convert.ToDouble(_aNLeakOperatingUpdateTime) : 3.00;//配置文件没有则默认3分钟
            _fastLeakTestSpan = TimeSpan.FromMinutes(updateTime);
            //slow leak test 时间间隔一个小时,因为leak test开始后要等待clearleakvolumeTime重新开始,因此时间间隔就等于两者相加,第一次执行减掉就行。
            _slowLeakTestSpan = TimeSpan.FromMinutes(60) + TimeSpan.FromMinutes(_clearLeakVolumeTime);
        }
        /// 
        /// 初始化
        /// 
        /// 
        public bool Initialize()
        {
            InitializeParameter();
            InitializeRoutine();
            SubscribeData();
            InitializeOperation();
            SubscribeValueAction();
            return true;
        }
        /// 
        /// 初始化Routine
        /// 
        private void InitializeRoutine()
        {
        }
        /// 
        /// 初始化参数
        /// 
        private void InitializeParameter()
        {
            _persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(Module);
            if (_persistentValue == null)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Persistent Value Object is not exist");
            }
            if (!string.IsNullOrEmpty(_persistentValue.Recipe))
            {
                _resRecipe = RecipeFileManager.Instance.LoadGenericityRecipe(_persistentValue.Recipe);
            }
            _direplenHelper = new ReservoirDiReplenHelper(Module, _persistentValue);
            ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
            if (reservoirItem != null)
            {
                foreach (var item in reservoirItem.MetalCells)
                {
                    if (item.ModuleName != Module)
                    {
                        CompactMembranMetalDevice metalDevice = DEVICE.GetDevice(item.ModuleName);
                        if (metalDevice != null)
                        {
                            _metalDevices.Add(metalDevice);
                        }
                    }
                }
                if (reservoirItem.CrossDoseType != "" && reservoirItem.CrossDoseType != "None")
                {
                    _isCrossDoseInstalled = true;
                    _crossDoseHelper = new CrossDoseHelper(Module);
                    _isCrossDoseInitialized = false;
                }
                _isCAFlowRateWARN = new List(new bool[_metalDevices.Count]);
                _isANAFlowRateWARN = new List(new bool[_metalDevices.Count]);
                _isANBFlowRateWARN = new List(new bool[_metalDevices.Count]);
            }
        }
        /// 
        /// 订阅数据
        /// 
        private void SubscribeData()
        {
            ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
            DATA.Subscribe($"{Module}.ReservoirData", () => _reservoirData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ReservoirAverageANLevel", () => _avgANLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ReservoirAverageCALevel", () => _avgCALevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _persistentValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ANPumpSpeed", () => _anPumpSpeed, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.CAPumpSpeed", () => _caPumpSpeed, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.RecipeName", () => (_resRecipe != null ? _resRecipe.Ppid : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ANLevel", () => _reservoirData.ANLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.CALevel", () => _reservoirData.CALevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ANBypassFlow", () => _reservoirData.ANBypassFlow, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.HedFlow", () => _reservoirData.CAHedFlow, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.CurrentRecipe", () => _resRecipe, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.DIValveMaxOnTime", () => SC.GetValue($"Reservoir.{Module}.DIValveMaxOnTime") * 60, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsManualCAReplen", () => { return _currentOperation == ReservoirOperation.ManualCADiReplen; }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsManualANReplen", () => { return _currentOperation == ReservoirOperation.ManualANDiReplen; }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsCAHighLevel", () => IsCAHighLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsCALowLevel", () => IsCALowLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsANHighLevel", () => IsANHighLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsANLowLevel", () => IsANLowLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsDIReplenInFault", () => _isDiReplenInFault, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.EvaporatorType", () => reservoirItem.EvaporatorType, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.CroseDoseType", () => reservoirItem.CrossDoseType, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsLeakDetected", () => _isLeakDetected, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsCrossDoseInstalled", () => _isCrossDoseInstalled, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ANBypassCounterFlow", () => ReservoirCounterByPassFlow.CounterValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            if (_isCrossDoseInstalled)
            {
                DATA.Subscribe($"{Module}.ANTransferFlow", () => ANTransferFlow != null ? ANTransferFlow.CounterValue : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
                DATA.Subscribe($"{Module}.IsCalibrateEnable", () => (_crossDoseHelper != null && _crossDoseHelper.CrossDoseState == RState.Running) ? false : true, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            }
        }
        /// 
        /// 初始化操作
        /// 
        private void InitializeOperation()
        {
            OP.Subscribe($"{Module}.DisabledAction", DisabledOperation);
            OP.Subscribe($"{Module}.ManualAction", ManualOperation);
            OP.Subscribe($"{Module}.AutoAction", AutoOperation);
            OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation);
            OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation);
            OP.Subscribe($"{Module}.LoadRecipe", LoadRecipeOperation);
            OP.Subscribe($"{Module}.AnPumpOn", AnPumpOnOperation);
            OP.Subscribe($"{Module}.ANPumpSpeed", ANPumpSpeed);
            OP.Subscribe($"{Module}.AnPumpOff", AnPumpOffOperation);
            OP.Subscribe($"{Module}.AnADrainPumpOn", AnADrainPumpOn);
            OP.Subscribe($"{Module}.AnADrainPumpOff", AnADrainPumpOff);
            OP.Subscribe($"{Module}.AnBDrainPumpOn", AnBDrainPumpOn);
            OP.Subscribe($"{Module}.AnBDrainPumpOff", AnBDrainPumpOff);
            OP.Subscribe($"{Module}.ANDiReplenOn", ANDiReplenOnOperation);
            OP.Subscribe($"{Module}.ANDiReplenOff", ANDiReplenOff);
            OP.Subscribe($"{Module}.ANByPassOn", ANByPassOn);
            OP.Subscribe($"{Module}.ANByPassOff", ANByPassOff);
            OP.Subscribe($"{Module}.CAPumpOn", CAPumpOn);
            OP.Subscribe($"{Module}.CAPumpSpeed", CAPumpSpeedOperation);
            OP.Subscribe($"{Module}.CAPumpOff", CAPumpOff);
            OP.Subscribe($"{Module}.CADiReplenOn", CADiReplenOnOperation);
            OP.Subscribe($"{Module}.CADiReplenOff", CADiReplenOff);
            OP.Subscribe($"{Module}.CDAFlowOn", CDAFlowOn);
            OP.Subscribe($"{Module}.CDAFlowOff", CDAFlowOff);
            OP.Subscribe($"{Module}.CAByPassOn", CAByPassOn);
            OP.Subscribe($"{Module}.CAByPassOff", CAByPassOff);
            OP.Subscribe($"{Module}.ANSampleOn", ANSampleOn);
            OP.Subscribe($"{Module}.ANSampleOff", ANSampleOff);
            OP.Subscribe($"{Module}.CASampleOn", CASampleOn);
            OP.Subscribe($"{Module}.CASampleOff", CASampleOff);
            OP.Subscribe($"{Module}.ManualANDiReplen", ManualANDiReplen);
            OP.Subscribe($"{Module}.ManualCADiReplen", ManualCADiReplen);
            OP.Subscribe($"{Module}.BaseLineKeyDown", BaseLineKeyDownAction);
            OP.Subscribe($"{Module}.StartLeakTest", StartLeakTestAction);
            OP.Subscribe($"{Module}.ResetTotalTime", ResetTotalTime);
            OP.Subscribe($"{Module}.ClearSlowLeak", ClearSlowLeak);
            if (_isCrossDoseInstalled)
            {
                OP.Subscribe($"{Module}.StartDosing", StartDosing);
                OP.Subscribe($"{Module}.HaltDosing", HaltDosing);
                OP.Subscribe($"{Module}.SetPumpFactor", SetPumpFactor);
                OP.Subscribe($"{Module}.CrossDoseOn", CrossDoseOn);
                OP.Subscribe($"{Module}.CrossDoseOff", CrossDoseOff);
                OP.Subscribe($"{Module}.ResetCrossDose", ResetCrossDose);
            }
        }
        #region Operation
        /// 
        /// 重置时长
        /// 
        /// 
        /// 
        /// 
        private bool ResetTotalTime(string cmd, object[] objs)
        {
            _persistentValue.TotalReplen = 0;
            _persistentValue.LastTotalReplen = 0;
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// DisabledAction
        /// 
        /// 
        /// 
        /// 
        private bool DisabledOperation(string cmd, object[] args)
        {
            string currentOperation = "Disabled";
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            if (_persistentValue != null && reservoirEntity != null && _persistentValue.OperatingMode != currentOperation)
            {
                string preOperation = _persistentValue.OperatingMode;
                if (reservoirEntity.IsBusy)
                {
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} is Busy, can't switch to Disabled mode");
                    return false;
                }
                if (_persistentValue.OperatingMode == "Auto" && reservoirEntity.IsMetalBusy)
                {
                    string busymodule = "";
                    if (_metalDevices != null)
                    {
                        foreach (var item in _metalDevices)
                        {
                            MetalEntity metalEntity = Singleton.Instance.GetModule(item.Module.ToString());
                            if (metalEntity != null && metalEntity.IsBusy)
                            {
                                busymodule += metalEntity.Module.ToString() + "/";
                            }
                        }
                    }
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{busymodule} is Busy, can't switch to Disabled mode");
                    return false;
                }
                foreach (var metalDevice in _metalDevices)
                {
                    metalDevice.DisabledOperation("", null);
                    MetalEntity metalEntity = Singleton.Instance.GetModule(metalDevice.Module);
                    metalEntity.AbortRecipe(null);
                    metalDevice.EnterDisabledOperation();
                }
                if (_isCrossDoseInstalled)
                {
                    HaltDosing("", null);
                    InitializeCrossDose(false);
                }
                EnterDisabledOperation();
                reservoirEntity.EnterInit();
                _persistentValue.OperatingMode = currentOperation;
                LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
            }
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            _currentOperation = ReservoirOperation.None;
            return true;
        }
        /// 
        /// ManualAction
        /// 
        /// 
        /// 
        /// 
        private bool ManualOperation(string cmd, object[] args)
        {
            string currentOperation = "Manual";
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            if (_persistentValue != null && reservoirEntity != null && _persistentValue.OperatingMode != currentOperation)
            {
                string preOperation = _persistentValue.OperatingMode;
                if (reservoirEntity.IsBusy)
                {
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} is Busy, can't switch to Manual mode");
                    return false;
                }
                if (_persistentValue.OperatingMode == "Auto" && reservoirEntity.IsMetalBusy)
                {
                    string busymodule = "";
                    if (_metalDevices != null)
                    {
                        foreach (var item in _metalDevices)
                        {
                            MetalEntity metalEntity = Singleton.Instance.GetModule(item.Module.ToString());
                            if (metalEntity != null && metalEntity.IsBusy)
                            {
                                busymodule += metalEntity.Module.ToString() + "/";
                            }
                        }
                    }
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{busymodule} is Busy, can't switch to Manual mode");
                    return false;
                }
                foreach (var metalDevice in _metalDevices)
                {
                    metalDevice.ManualOperation("", null);
                }
                if (_isCrossDoseInstalled) InitializeCrossDose(false);
                reservoirEntity.EnterInit();
                if (_reservoirData.ANDiReplen) ANDiReplenOff("", null);
                if (_reservoirData.CADiReplen) CADiReplenOff("", null);
                _persistentValue.OperatingMode = currentOperation;
                LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
            }
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            _currentOperation = ReservoirOperation.None;
            return true;
        }
        /// 
        /// AutoAction
        /// 
        /// 
        /// 
        /// 
        private bool AutoOperation(string cmd, object[] args)
        {
            if (IsANLowLevel || IsCALowLevel)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"LowLevel is activated, can't switch to Auto mode");
                return false;
            }
            string currentOperation = "Auto";
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            if (_persistentValue != null && reservoirEntity != null && _persistentValue.OperatingMode != currentOperation)
            {
                string preOperation = _persistentValue.OperatingMode;
                if (reservoirEntity.IsBusy)
                {
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} is Busy, can't switch to Auto mode");
                    return false;
                }
                if (_isCrossDoseInstalled) InitializeCrossDose(false);
                reservoirEntity.EnterInit();
                if (_reservoirData.ANDiReplen) ANDiReplenOff("", null);
                if (_reservoirData.CADiReplen) CADiReplenOff("", null);
                _isDiReplenInFault = false;
                _persistentValue.OperatingMode = currentOperation;
                LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
            }
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// EngineeringModeAction
        /// 
        /// 
        /// 
        /// 
        private bool EngineeringModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Engineering";
            if (_persistentValue != null)
            {
                _persistentValue.RecipeOperatingMode = currentRecipeOperation;
            }
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// ProductionAction
        /// 
        /// 
        /// 
        /// 
        private bool ProductionModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Production";
            if (_persistentValue != null)
            {
                _persistentValue.RecipeOperatingMode = currentRecipeOperation;
            }
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// 加载Recipe
        /// 
        /// 
        /// 
        /// 
        private bool LoadRecipeOperation(string cmd, object[] args)
        {
            _persistentValue.Recipe = args[0].ToString();
            string[] fileRoute = _persistentValue.Recipe.Split('\\');
            string recipeRoute = "";
            if (fileRoute.Length > 2)
            {
                recipeRoute = fileRoute[fileRoute.Length - 2];
            }
            _resRecipe = RecipeFileManager.Instance.LoadGenericityRecipe(_persistentValue.Recipe);
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module.ToString());
            LOG.WriteLog(eEvent.INFO_RESERVOIR, Module.ToString(), $"Load {recipeRoute} Recipe {_resRecipe.Ppid} Success");
            return true;
        }
        /// 
        /// Enter Disabled Operation
        /// 
        /// 
        private void EnterDisabledOperation()
        {
            if (_reservoirData.CAPumpEnable)
            {
                CAPumpOff("CAPumpOff", null);
            }
            if (_reservoirData.ANPump > 0)
            {
                AnPumpOffOperation("", null);
            }
            if (_reservoirData.ANADrainPump > 0)
            {
                AnADrainPumpOff("", null);
            }
            if (_reservoirData.ANBDrainPump > 0)
            {
                AnBDrainPumpOff("", null);
            }
            if (_reservoirData.ANByPass)
            {
                ANByPassOff("", null);
            }
            if (_reservoirData.ANDiReplen)
            {
                ANDiReplenOff("", null);
            }
            if (_reservoirData.CADiReplen)
            {
                CADiReplenOff("", null);
            }
        }
        #endregion
        #region AN DiReplen
        /// 
        /// 阳极DI Replen On
        /// 
        /// 
        /// 
        /// 
        private bool ANDiReplenOnOperation(string cmd, object[] args)
        {
            return ANDiReplenOn(true);
        }
        /// 
        /// 阳极DI Replen On
        /// 
        /// 
        /// 
        public bool ANDiReplenOn(bool showError)
        {
            if (IsANHighLevel)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"ANHighLevel is activate,Can't do AN_DIReple");
                return false;
            }
            if (IsANLowLevel)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"ANLowLevel is activate,Can't do AN_DIReple");
                return false;
            }
            bool preCondition = CheckPreDiReplenCondition(showError);
            if (!preCondition)
            {
                return false;
            }
            if (ReservoirData.CADiReplen)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "CADiReplen is on");
                return false;
            }
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_DI_REPLEN}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// 阳极DI Replen On
        /// 
        /// 
        /// 
        /// 
        private bool ANDiReplenOff(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_DI_REPLEN}");
            bool result = BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
            if (result)
            {
                _persistentValue.IsDiReplenOn = false;
                if (_currentOperation == ReservoirOperation.ManualANDiReplen || _currentOperation == ReservoirOperation.AutoANDiReplen)
                {
                    _currentOperation = ReservoirOperation.None;
                    _persistentValue.LastTotalReplen = _persistentValue.TotalReplen;
                    ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
                }
            }
            return result;
        }
        /// 
        /// 检验DiReplen前置条件
        /// 
        /// 
        public bool CheckPreDiReplenCondition(bool showError)
        {
            if (!CheckFacilitiesDiReplenStatus() && showError)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Facilities DiReplen is Off");
                return false;
            }
            SafetyDevice safetyDevice = DEVICE.GetDevice("Safety");
            if (safetyDevice != null && safetyDevice.SafetyData.ReservoirHighLevel)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Safety high is Activate");
                return false;
            }
            if (CheckOtherReservoirDiReplenStatus(showError))
            {
                return false;
            }
            return true;
        }
        /// 
        /// 检验总Di有没有开
        /// 
        /// 
        private bool CheckFacilitiesDiReplenStatus()
        {
            SystemFacilities systemFacilities = DEVICE.GetDevice("System.Facilities");
            if (systemFacilities != null)
            {
                return systemFacilities.DIReplenEnable;
            }
            return false;
        }
        /// 
        /// 检验是否其他Reservoir Direplen已经
        /// 
        /// 
        private bool CheckOtherReservoirDiReplenStatus(bool showError)
        {
            List reservoirs = ReservoirItemManager.Instance.InstalledModules;
            foreach (string item in reservoirs)
            {
                if (item != Module)
                {
                    ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(item);
                    if (reservoirItem.SubType == STRATUS)
                    {
                        StandardHotReservoirDevice tmpDevice = DEVICE.GetDevice(item);
                        if (tmpDevice.ReservoirData.DiReplen && showError)
                        {
                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{item} direplen valve is on");
                            return true;
                        }
                    }
                    else
                    {
                        CompactMembranReservoirDevice tmpDevice = DEVICE.GetDevice(item);
                        if (tmpDevice.ReservoirData.ANDiReplen && showError)
                        {
                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{item} ANDireplen valve is on");
                            return true;
                        }
                        if (tmpDevice.ReservoirData.CADiReplen && showError)
                        {
                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{item} CADireplen valve is on");
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        #endregion
        #region AnPump
        /// 
        /// AN Pump On 操作
        /// 
        /// 
        /// 
        /// 
        public bool AnPumpOnOperation(string cmd, object[] args)
        {
            double anPumpSpeed = SC.GetValue($"Reservoir.ANDefaultPumpSpeed");
            return AnPump(anPumpSpeed);
        }
        /// 
        /// AN Pump Off操作
        /// 
        /// 
        /// 
        /// 
        private bool AnPumpOffOperation(string cmd, object[] args)
        {
            return AnPump(0);
        }
        /// 
        /// AN Pump
        /// 
        /// 
        /// 
        public bool AnPump(double speed)
        {
            if (speed == 0) //关pump时关掉配置的metal的fill valve
            {
                ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
                if (reservoirItem != null)
                {
                    List metalItems = reservoirItem.MetalCells;
                    if (metalItems != null && metalItems.Count > 0)
                    {
                        foreach (MetalItem metalItem in metalItems)
                        {
                            if (metalItem.Installed)
                            {
                                CompactMembranMetalDevice metalDevice = DEVICE.GetDevice(metalItem.ModuleName);
                                if (metalDevice != null)
                                {
                                    metalDevice.AnSideAFillOff("ANAFillOff", null);
                                    metalDevice.AnSideBFillOff("ANBFillOff", null);
                                }
                            }
                        }
                    }
                }
            }
            SafetyDevice safetyDevice = DEVICE.GetDevice("Safety");
            if (safetyDevice != null && !safetyDevice.SafetyData.PumpEdm)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Safety PumpEdm is Activate");
                return false;
            }
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_PUMP}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, speed);
        }
        /// 
        /// AN Pump调整速度
        /// 
        /// 
        /// 
        /// 
        public bool ANPumpSpeed(string cmd, object[] args)
        {
            if (double.TryParse(args[0].ToString(), out double speed))
            {
                _anPumpSpeed = speed;
                if (_anPumpSpeed > 0)
                {
                    _reservoirData.ANPump = _anPumpSpeed;
                }
                return AnPump(speed);
            }
            else
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{args[0]} is nor invalid speed");
                return false;
            }
        }
        #endregion
        #region AN Drain Pump
        /// 
        /// 阳极A面Drain Pump On
        /// 
        /// 
        /// 
        /// 
        public bool AnADrainPumpOn(string cmd, object[] args)
        {
            double speed = SC.GetValue($"Reservoir.DrainSpeed");
            return AnADrainPump(speed);
        }
        /// 
        /// 阳极A面Drain Pump Off
        /// 
        /// 
        /// 
        /// 
        private bool AnADrainPumpOff(string cmd, object[] args)
        {
            return AnADrainPump(0);
        }
        /// 
        /// 阳极B面Drain Pump On
        /// 
        /// 
        /// 
        /// 
        public bool AnBDrainPumpOn(string cmd, object[] args)
        {
            double speed = SC.GetValue($"Reservoir.DrainSpeed");
            return AnBDrainPump(speed);
        }
        /// 
        /// 阳极B面Drain Pump Off
        /// 
        /// 
        /// 
        /// 
        private bool AnBDrainPumpOff(string cmd, object[] args)
        {
            return AnBDrainPump(0);
        }
        /// 
        /// 阳极A Drain Pump
        /// 
        /// 
        /// 
        public bool AnADrainPump(double speed)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_DRAIN_PUMP}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, speed);
        }
        /// 
        /// 阳极B Drain Pump
        /// 
        /// 
        /// 
        public bool AnBDrainPump(double speed)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_DRAIN_PUMP}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, speed);
        }
        #endregion
        #region AN ByPass
        /// 
        /// 阳极ByPass On
        /// 
        /// 
        /// 
        /// 
        private bool ANByPassOn(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_BY_PASS}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// 阳极ByPass Off
        /// 
        /// 
        /// 
        /// 
        private bool ANByPassOff(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_BY_PASS}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region CA Pump
        /// 
        /// CA Pump调速
        /// 
        /// 
        /// 
        /// 
        private bool CAPumpSpeedOperation(string cmd, object[] args)
        {
            double caMaxPumpSpeed = 0;
            if (SC.ContainsItem("Reservoir.CAMaxPumpSpeed"))
            {
                caMaxPumpSpeed = SC.GetValue("Reservoir.CAMaxPumpSpeed");
            }
            if (double.TryParse(args[0].ToString(), out double speed))
            {
                _caPumpSpeed = speed;
                if (_caPumpSpeed > caMaxPumpSpeed)
                {
                    LOG.WriteLog(eEvent.WARN_METAL, Module, $"CA pump speed:{_caPumpSpeed} is over CA max pump speed {caMaxPumpSpeed}!");
                    return false;
                }
                return CAPumpSpeed(_caPumpSpeed);
            }
            else
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{args[0]} is nor invalid speed");
                return false;
            }
        }
        /// 
        /// 设置阴极泵速
        /// 
        /// 
        /// 
        public bool CAPumpSpeed(double caPumpSpeed)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_SPEED}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, caPumpSpeed);
        }
        /// 
        /// 阴极Pump On
        /// 
        /// 
        /// 
        /// 
        private bool CAPumpOn(string cmd, object[] args)
        {
            double caPumpSpeed = SC.GetValue("Reservoir.CADefaultPumpSpeed");
            bool result = CAPumpSpeed(caPumpSpeed);
            if (result)
            {
                string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_ENABLE}");
                return BeckhoffIOManager.Instance.WriteIoValue(enableIOName, true);
            }
            else
            {
                return false;
            }
        }
        /// 
        /// 阴极Pump Off
        /// 
        /// 
        /// 
        /// 
        private bool CAPumpOff(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_ENABLE}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region CA DiReplen
        /// 
        /// 阴极DI Replen On
        /// 
        /// 
        /// 
        /// 
        private bool CADiReplenOnOperation(string cmd, object[] args)
        {
            return CADiReplenOn(true);
        }
        /// 
        /// 阴极DI Replen On
        /// 
        /// 
        /// 
        private bool CADiReplenOn(bool showError)
        {
            bool preCondition = CheckPreDiReplenCondition(showError);
            if (!preCondition)
            {
                return false;
            }
            if (IsCAHighLevel)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CAHighLevel is activate,Can't do CA_DIReple");
                return false;
            }
            if (IsCALowLevel)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CALowLevel is activate,Can't do CA_DIReple");
                return false;
            }
            if (ReservoirData.ANDiReplen)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "ANDiReplen is on");
                return false;
            }
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_DI_REPLEN}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// 阴极DI Replen Off
        /// 
        /// 
        /// 
        /// 
        private bool CADiReplenOff(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_DI_REPLEN}");
            bool result = BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
            if (result)
            {
                _persistentValue.IsDiReplenOn = false;
                if (_currentOperation == ReservoirOperation.ManualCADiReplen || _currentOperation == ReservoirOperation.AutoCADiReplen)
                {
                    _currentOperation = ReservoirOperation.None;
                    _persistentValue.LastTotalReplen = _persistentValue.TotalReplen;
                    ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
                }
            }
            return result;
        }
        #endregion
        #region CDA Flow
        /// 
        /// 阴极CDA Flow On
        /// 
        /// 
        /// 
        /// 
        private bool CDAFlowOn(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CDA_FLOW_VALVE}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// 阴极CDA Flow Off
        /// 
        /// 
        /// 
        /// 
        private bool CDAFlowOff(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CDA_FLOW_VALVE}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region CA ByPass
        /// 
        /// 阴极ByPass On
        /// 
        /// 
        /// 
        /// 
        public bool CAByPassOn(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_BY_PASS}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// 阴极ByPass Off
        /// 
        /// 
        /// 
        /// 
        public bool CAByPassOff(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_BY_PASS}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region DiReplen Operation
        /// 
        /// 手动阳极注水
        /// 
        /// 
        /// 
        /// 
        private bool ManualANDiReplen(string cmd, object[] args)
        {
            return ManualDiReplen(ANDiReplenOnOperation, ReservoirOperation.ManualANDiReplen, args[0].ToString());
        }
        /// 
        /// 手动阴极注水
        /// 
        /// 
        /// 
        /// 
        private bool ManualCADiReplen(string cmd, object[] args)
        {
            return ManualDiReplen(CADiReplenOnOperation, ReservoirOperation.ManualCADiReplen, args[0].ToString());
        }
        /// 
        /// 将前端输入的baseline更新到持久化文件
        /// 
        /// 
        /// 
        /// 
        private bool BaseLineKeyDownAction(string cmd, object[] args)
        {
            string variableName = args[0].ToString();
            //baseline输入了一个不同的值的话,将新值写入持久化文件
            if (_persistentValue.ANBaseLineLevel.ToString() != args[1].ToString())
            {
                PropertyInfo property = _persistentValue.GetType().GetProperty(variableName);
                if (property != null)
                {
                    property.SetValue(_persistentValue, args[1]);
                }
                ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
                LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"  New ANBaseline {args[1]} was inputed");
                _isTestRunning = false;
            }
            return true;
        }
        private bool StartLeakTestAction(string cmd, object[] args)
        {
            //前端重复点击start直接返回true;
            if (_isTestRunning)
            {
                LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $" Fast leak test has already started");
                return true;
            }
            //判断是否启动fast leak test 参数【0】表示是否初始化,参数【1】表示是否有metal有流量
            if ((bool)args[0] && (bool)args[1])
            {
                LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $" Fast leak test is start");
                _isTestRunning = true;
                //记录fast leak test的开始时间
                _fastLeakStartTime = DateTime.Now;
                //记录slow leak test的开始时间,第一次的开始时间需要加上这个配置时间,正好使第一次执行slow leak test的时间间隔使为1小时。
                _slowLeakStartTime = DateTime.Now + TimeSpan.FromMinutes(_clearLeakVolumeTime);
                //记录slow leak test的开始液位
                _StartSlowLeakTestANLevel = ReservoirData.ANLevel;
            }
            else
            {
                LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $" Leak test precondition not met, stoped");
                _isTestRunning = false;
            }
            return true;
        }
        /// Fast leak test
        /// 
        /// 
        /// 
        private bool FastLeakTestAction()
        {
            bool isHasMetalFlow = false;
            foreach (var metalDevice in _metalDevices)
            {
                if (metalDevice.ANACellFlow.CounterValue > 0 || metalDevice.ANBCellFlow.CounterValue > 0)
                {
                    isHasMetalFlow = true;
                }
            }
            if (!isHasMetalFlow)
            {
                LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $" No ANFLow in {Module}, current fast leak test is skiped");
                //更新_faseLeak的启动时间,使其可以自动周期性检测
                _fastLeakStartTime = DateTime.Now;
                return true;
            }
            double aNBaseLineLevel = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(Module).ANBaseLineLevel;
            if (_reservoirData.ANLevel < aNBaseLineLevel - _aNFastLeakLevelTolerance)
            {
                _isLeakDetected = true; //用于前端页面指示灯
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $" Fast Leak was Detected,Current ANLevel is{_reservoirData.ANLevel},baseline is{aNBaseLineLevel}. Related pump and valve was closed");
                AnPumpOffOperation($"{Module}.AnPumpOff", null);
                //关闭对应的anolyte flow valve
                foreach (var metalDevice in _metalDevices)
                {
                    metalDevice.AnSideAFillOff($"{metalDevice.Name}.ANAFillOff", null);
                    metalDevice.AnSideBFillOff($"{metalDevice.Name}.ANBFillOff", null);
                    metalDevice.AnSideADrainOff($"{metalDevice.Name}.ANADrainOff", null);
                    metalDevice.AnSideBDrainOff($"{metalDevice.Name}.ANBDrainOff", null);
                }
            }
            else
            {
                _isLeakDetected = false;
                string variableName = "ANBaseLineLevel";
                PropertyInfo property = _persistentValue.GetType().GetProperty(variableName);
                if (property != null)
                {
                    property.SetValue(_persistentValue, _reservoirData.ANLevel);
                }
                ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
                LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"No fast leak test was Detected, leak test baseLine was updated");
            }
            //更新_faseLeak的启动时间,使其可以自动周期性检测
            _fastLeakStartTime = DateTime.Now;
            return true;
        }
        /// Slow leak test
        /// 
        /// 
        /// 
        private bool SlowLeakTestAction()
        {
            ReservoirEntity _reservoirEntity = Singleton.Instance.GetModule(Module);
            if (_reservoirEntity != null && _reservoirEntity.IsInitialized)
            {
                _isInitialized = true;
            }
            else
            {
                _isInitialized = false;
            }
            if (_persistentValue.OperatingMode == AUTO)
            {
                foreach (var metalDevice in _metalDevices)
                {
                    if (metalDevice.ANACellFlow.CounterValue > 0 || metalDevice.ANBCellFlow.CounterValue > 0)
                    {
                        _isHasAnFlow = true;
                    }
                    if ("Auto".Equals(metalDevice.OperationMode))
                    {
                        _isHasMetalInAuto = true;
                    }
                }
                if (_isHasAnFlow && _isHasMetalInAuto && _isInitialized)
                {
                    LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $" Slow leak test is start");
                    _leakVolume = ReservoirData.ANLevel - _StartSlowLeakTestANLevel;
                    if (_leakVolume > SC.GetValue($"Reservoir.{Module}.MaxLeakVolume"))
                    {
                        LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, " Slow leak was detected");
                    }
                }
            }
            //更新当前液位
            _StartSlowLeakTestANLevel = ReservoirData.ANLevel;
            //更新启动时间
            _slowLeakStartTime = DateTime.Now;
            return true;
        }
        /// 
        /// 重新开始slow leak test
        /// 
        /// 
        /// 
        /// 
        private bool ClearSlowLeak(string cmd, object[] objs)
        {
            _StartSlowLeakTestANLevel = ReservoirData.ANLevel;
            _slowLeakStartTime = DateTime.Now;
            LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $" Slow leak test was reset");
            return true;
        }
        /// 
        /// 手动注水
        /// 
        /// 
        /// 
        /// 
        private bool ManualDiReplen(Func direplenOn, ReservoirOperation direplenOperation, string timeLength)
        {
            if (_currentOperation != ReservoirOperation.None)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"current operation is {_currentOperation},cannot execute {direplenOperation}");
                return false;
            }
            bool result = direplenOn("", null);
            if (result)
            {
                _currentOperation = direplenOperation;
                _persistentValue.DiReplenTime = DateTime.Now;
                ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
                int.TryParse(timeLength, out _manualReplenSecond);
            }
            return result;
        }
        /// 
        /// 阳极自动注水
        /// 
        /// 
        public bool AutoANDiReplen()
        {
            if (IsANLowLevel)
            {
                if (!_isANAutoDIReplenError)
                {
                    _isANAutoDIReplenError = true;
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"ANLowLevel is activate,Can't AutoANDireplen");
                }
                return false;
            }
            else
            {
                _isANAutoDIReplenError = false;
            }
            return AutoDireplen(ANDiReplenOn, ReservoirOperation.AutoANDiReplen);
        }
        /// 
        /// 阴极自动流水
        /// 
        /// 
        public bool AutoCADiReplen()
        {
            if (IsCALowLevel)
            {
                if (!_isCAAutoDIReplenError)
                {
                    _isCAAutoDIReplenError = true;
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CALowLevel is activate,Can't AutoANDireplen");
                }
                return false;
            }
            else
            {
                _isCAAutoDIReplenError = false;
            }
            return AutoDireplen(CADiReplenOn, ReservoirOperation.AutoCADiReplen);
        }
        /// 
        /// 自动注水
        /// 
        /// 
        private bool AutoDireplen(Func direplenOn, ReservoirOperation reservoirOperation)
        {
            if (_currentOperation != ReservoirOperation.None)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"current operation is {_currentOperation},cannot execute {reservoirOperation}");
                return false;
            }
            if (_resRecipe == null)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"recipe is null");
                return false;
            }
            bool result = direplenOn(false);
            if (result)
            {
                _currentOperation = reservoirOperation;
                _persistentValue.DiReplenTime = DateTime.Now;
            }
            return result;
        }
        #endregion
        #region CrossDose
        /// 
        /// CrossDose开阀
        /// 
        /// 
        /// 
        /// 
        public bool CrossDoseOn(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CROSS_DOSE_ENABLE}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// CrossDose关阀
        /// 
        /// 
        /// 
        /// 
        public bool CrossDoseOff(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CROSS_DOSE_ENABLE}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
        }
        /// 
        /// 手动Dosing
        /// 
        /// 
        /// 
        /// 
        private bool StartDosing(string cmd, object[] args)
        {
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            if (!_isCrossDoseInitialized)
            {
                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, "Please initialize Cross Dose");
                return false;
            }
            double crossDoseVolume = (double)args[0];
            _crossDoseHelper.SetManualDoseOperation();
            return _crossDoseHelper.StartDosing(crossDoseVolume);
        }
        /// 
        /// 停止Dosing
        /// 
        /// 
        /// 
        /// 
        private bool HaltDosing(string cmd, object[] args)
        {
            _crossDoseHelper.ResetDoseOperation();
            _crossDoseHelper.HaltDosing();
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CROSS_DOSE_ENABLE}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
        }
        /// 
        /// Set Pump Factor
        /// 
        /// 
        /// 
        /// 
        private bool SetPumpFactor(string cmd, object[] args)
        {
            double targetPumpFactor = (double)args[0];
            _crossDoseHelper.SetPumpfactor(targetPumpFactor);
            return true;
        }
        /// 
        /// CrossDose初始化
        /// 
        /// 
        public void InitializeCrossDose(bool isInitialized)
        {
            _isCrossDoseInitialized = isInitialized;
        }
        /// 
        /// Reset CrossDose
        /// 
        /// 
        /// 
        /// 
        public bool ResetCrossDose(string cmd, object[] args)
        {
            return _crossDoseHelper.ResetCrossDose();
        }
        /// 
        /// Reset Monitor
        /// 
        /// 
        /// 
        /// 
        public bool ResetCrossDoseMonitor()
        {
            return _crossDoseHelper.ResetCrossDoseMonitor();
        }
        #endregion
        #region Sample
        /// 
        /// ANSample开阀
        /// 
        /// 
        /// 
        /// 
        public bool ANSampleOn(string cmd, object[] args)
        {
            SystemFacilities systemFacility = DEVICE.GetDevice("System.Facilities");
            if (systemFacility != null && !systemFacility.SampleFluidDetect)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "SampleFluidDetect is Activate. Can't open ANSample");
                return false;
            }
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_SAMPLE_FLOW}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// ANSample关阀
        /// 
        /// 
        /// 
        /// 
        public bool ANSampleOff(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_SAMPLE_FLOW}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
        }
        /// 
        /// CASample开阀
        /// 
        /// 
        /// 
        /// 
        public bool CASampleOn(string cmd, object[] args)
        {
            SystemFacilities systemFacility = DEVICE.GetDevice("System.Facilities");
            if (systemFacility != null && !systemFacility.SampleFluidDetect)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "SampleFluidDetect is Activate. Can't open CASample");
                return false;
            }
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_SAMPLE_FLOW}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// CASample关阀
        /// 
        /// 
        /// 
        /// 
        public bool CASampleOff(string cmd, object[] args)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_SAMPLE_FLOW}");
            return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        /// 
        /// 订阅变量数值发生变化
        /// 
        private void SubscribeValueAction()
        {
            BeckhoffIoSubscribeUpdateVariable(CA_DI_REPLEN);
            BeckhoffIoSubscribeUpdateVariable(AN_DI_REPLEN);
            BeckhoffIoSubscribeUpdateVariable(CA_WATER_LEVEL);
            BeckhoffIoSubscribeUpdateVariable(AN_WATER_LEVEL);
            BeckhoffIoSubscribeUpdateVariable(AN_PUMP);
            BeckhoffIoSubscribeUpdateVariable(CROSS_DOSE_ENABLE);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_STM_STATUS);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_POS_STATUS);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_TARGET_POSITION);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_ENABLE);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_EXECUTE);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_RESET);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_SPEED);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_START_TYPE);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_ACCELERATION);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_PUMP_DECELERATION);
            BeckhoffIoSubscribeUpdateVariable(TRANSFER_ACTUAL_POSITION);
            BeckhoffIoSubscribeUpdateVariable(AN_BYPASS_FLOW);
            BeckhoffIoSubscribeUpdateVariable(AN_A_DRAIN_PUMP);
            BeckhoffIoSubscribeUpdateVariable(AN_B_DRAIN_PUMP);
            BeckhoffIoSubscribeUpdateVariable(AN_SAMPLE_FLOW);
            BeckhoffIoSubscribeUpdateVariable(CA_SAMPLE_FLOW);
            BeckhoffIoSubscribeUpdateVariable(CA_PUMP_SPEED);
            BeckhoffIoSubscribeUpdateVariable(CA_PUMP_RUNNING);
            BeckhoffIoSubscribeUpdateVariable(CA_HED_FLOW);
            BeckhoffIoSubscribeUpdateVariable(CDA_FLOW_VALVE);
            BeckhoffIoSubscribeUpdateVariable(AN_BY_PASS);
            BeckhoffIoSubscribeUpdateVariable(CA_BY_PASS);
            BeckhoffIoSubscribeUpdateVariable(CA_PUMP_ENABLE);
            BeckhoffIoSubscribeUpdateVariable(EVAPORATORLEVEL);
            BeckhoffCounterSubscribeUpdateVariable(AN_TRANSFER_FLOW, ANTransferFlow);
            BeckhoffCounter anTransferFlowCounter = BeckhoffCounterManager.Instance.GetBeckhoffCounter($"{Module}.{AN_TRANSFER_FLOW}");
            if (anTransferFlowCounter != null)
            {
                ANTransferFlow.Period = anTransferFlowCounter.Period;
            }
            BeckhoffCounterSubscribeUpdateVariable(AN_BYPASS_COUNTERFLOW, ReservoirCounterByPassFlow);
            BeckhoffCounter reservoirCounterByPassFlow = BeckhoffCounterManager.Instance.GetBeckhoffCounter($"{Module}.{AN_BYPASS_COUNTERFLOW}");
            if (reservoirCounterByPassFlow != null)
            {
                ReservoirCounterByPassFlow.Period = reservoirCounterByPassFlow.Period;
            }
        }
        /// 
        /// 订阅IO变量
        /// 
        /// 
        private void BeckhoffIoSubscribeUpdateVariable(string variable)
        {
            _variableInitializeDic[variable] = false;
            IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
        }
        /// 
        /// 订阅Counter变量
        /// 
        /// 
        private void BeckhoffCounterSubscribeUpdateVariable(string variable, CounterFlowData counterFlowData)
        {
            _nameCounterFlowData[$"{Module}.{variable}"] = counterFlowData;
            BeckhoffCounterManager.Instance.SubscribeModuleVariable($"{Module}.{variable}", COUNTER_VALUE, UpdateCounterVariableValue);
            BeckhoffCounterManager.Instance.SubscribeModuleVariable($"{Module}.{variable}", COUNTER_START, UpdateCounterVariableValue);
            BeckhoffCounterManager.Instance.SubscribeModuleVariable($"{Module}.{variable}", COUNTER_STOP, UpdateCounterVariableValue);
            BeckhoffCounterManager.Instance.SubscribeModuleVariable($"{Module}.{variable}", COUNTER_RESET, UpdateCounterVariableValue);
        }
        /// 
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateCounterVariableValue(string variable, object value)
        {
            string[] strAry = variable.Split('.');
            string lastVariable = strAry[strAry.Length - 1];
            PropertyInfo property = null;
            string key = variable.Replace($".{lastVariable}", "");
            if (_nameCounterFlowData.ContainsKey(key))
            {
                CounterFlowData counterFlowData = _nameCounterFlowData[key];
                if (counterFlowData != null)
                {
                    property = counterFlowData.GetType().GetProperty(lastVariable);
                    if (property != null)
                    {
                        property.SetValue(counterFlowData, value);
                    }
                }
            }
        }
        /// 
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateVariableValue(string variable, object value)
        {
            if (!ReservoirData.IsDataInitialized)
            {
                ReservoirData.IsDataInitialized = true;
            }
            PropertyInfo property = ReservoirData.GetType().GetProperty(variable);
            if (property != null)
            {
                property.SetValue(ReservoirData, value);
                if (variable == AN_WATER_LEVEL)
                {
                    string anLevelCurve = SC.GetStringValue($"Reservoir.{Module}.ANLevelCurve");
                    ReservoirData.ANLevel = LevelCurveManager.Instance.CalculateLevelByWaterLevel(ReservoirData.ANWaterLevel, anLevelCurve);
                }
                else if (variable == CA_WATER_LEVEL)
                {
                    string caLevelCurve = SC.GetStringValue($"Reservoir.{Module}.CALevelCurve");
                    ReservoirData.CALevel = LevelCurveManager.Instance.CalculateLevelByWaterLevel(ReservoirData.CAWaterLevel, caLevelCurve);
                }
            }
            if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
            {
                _variableInitializeDic[variable] = true;
            }
        }
        /// 
        /// 是否所有IO变量初始化完成
        /// 
        /// 
        private bool AllIoVariableInitialized()
        {
            foreach (string item in _variableInitializeDic.Keys)
            {
                if (!_variableInitializeDic[item])
                {
                    LOG.WriteLog(eEvent.ERR_RINSE, Module, $"{item} is not initialized");
                    return false;
                }
            }
            return true;
        }
        /// 
        /// 检验阳极是否需要补水
        /// 
        /// 
        private bool CheckANNeedDiReplen()
        {
            if (IsAuto && _resRecipe != null)
            {
                if (_resRecipe.ANDIReplenEnable && _resRecipe.ANDIReplenCurrentRate == 0 && _resRecipe.ANDIReplenTimeRate == 0)
                {
                    double levelHysteresis = SC.GetValue("Reservoir.LevelHysteresis");
                    return _reservoirData.ANLevel < _resRecipe.ReservoirANLevel - levelHysteresis;
                }
                return false;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// 检验CA是否需要注水
        /// 
        /// 
        public bool CheckCANeedDiReplen()
        {
            if (IsAuto && _resRecipe != null)
            {
                if (_resRecipe.DIReplenEnable && _resRecipe.DIReplenTimeRate == 0 && _resRecipe.DIReplenCurrentRate == 0)
                {
                    double levelHysteresis = SC.GetValue("Reservoir.LevelHysteresis");
                    return _reservoirData.CALevel < _resRecipe.ReservoirCALevel - levelHysteresis;
                }
                return false;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// 检验阴极是否highlevel
        /// 
        public bool CheckCAHighLevelStatus()
        {
            return ReservoirData.CAWaterLevel > SC.GetValue($"Reservoir.{Module}.CAHighLevel") ? true : false;
        }
        /// 
        /// 检验阴极是否lowlevel
        /// 
        public bool CheckCALowLevelStatus()
        {
            return ReservoirData.CAWaterLevel < SC.GetValue($"Reservoir.{Module}.CALowLevel") ? true : false;
        }
        /// 
        /// 检验阳极是否highlevel
        /// 
        public bool CheckANHighLevelStatus()
        {
            return ReservoirData.ANWaterLevel > SC.GetValue($"Reservoir.{Module}.ANHighLevel") ? true : false;
        }
        /// 
        /// 检验阳极是否lowlevel
        /// 
        public bool CheckANLowLevelStatus()
        {
            return ReservoirData.ANWaterLevel < SC.GetValue($"Reservoir.{Module}.ANLowLevel") ? true : false;
        }
        /// 
        /// CAFlowRate Check
        /// 
        private void CAFlowRateCheck()
        {
            if (_resRecipe == null) return;
            for (int i = 0; i < _metalDevices.Count; i++)
            {
                CompactMembranMetalDevice hotMetalDevice = _metalDevices[i];
                if (hotMetalDevice != null && !hotMetalDevice.IsDisable && hotMetalDevice.IsAuto)
                {
                    if (hotMetalDevice.MetalDeviceData == null) continue;
                    if (!hotMetalDevice.FlowValveStable) continue;
                    MetalEntity metalEntity = Singleton.Instance.GetModule(hotMetalDevice.Name);
                    double cellFlow = hotMetalDevice.MetalDeviceData.CellFlow;
                    if (cellFlow < _resRecipe.CAFlowRateErrorLow)
                    {
                        if (!metalEntity.IsError)
                        {
                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateErrorLow parameter:{_resRecipe.CAFlowRateErrorLow}");
                            metalEntity.PostMsg(MetalMsg.Error);
                        }
                    }
                    else if (cellFlow < _resRecipe.CAFlowRateWarningLow)
                    {
                        if (!_isCAFlowRateWARN[i])
                        {
                            LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateWarningLow parameter:{_resRecipe.CAFlowRateWarningLow}");
                            _isCAFlowRateWARN[i] = true;
                        }
                    }
                    else
                    {
                        _isCAFlowRateWARN[i] = false;
                    }
                }
            }
        }
        /// 
        /// ANFlowRate Check
        /// 
        private void ANFlowRateCheck()
        {
            if (_resRecipe == null) return;
            for (int i = 0; i < _metalDevices.Count; i++)
            {
                CompactMembranMetalDevice hotMetalDevice = _metalDevices[i];
                if (hotMetalDevice != null && !hotMetalDevice.IsDisable && hotMetalDevice.IsAuto)
                {
                    if (hotMetalDevice.MetalDeviceData == null) continue;
                    //ANACellFlow
                    MetalEntity metalEntity = Singleton.Instance.GetModule(hotMetalDevice.Name);
                    if (hotMetalDevice.MetalDeviceData.ANAPinEnable && hotMetalDevice.ANAFlowValveStable)
                    {
                        double ANAcellFlow = hotMetalDevice.ANACellFlow.CounterValue;
                        if (ANAcellFlow < _resRecipe.ANFlowRateErrorLow)
                        {
                            if (!metalEntity.IsError)
                            {
                                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{hotMetalDevice.Name} ANASideflow:{ANAcellFlow} is less than recipe's ANFlowRateErrorLow parameter:{_resRecipe.ANFlowRateErrorLow}");
                                metalEntity.PostMsg(MetalMsg.Error);
                            }
                        }
                        else if (ANAcellFlow < _resRecipe.ANFlowRateWarningLow)
                        {
                            if (!_isANAFlowRateWARN[i])
                            {
                                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{hotMetalDevice.Name} ANASideflow:{ANAcellFlow} is less than recipe's ANFlowRateWarningLow parameter:{_resRecipe.ANFlowRateWarningLow}");
                                _isANAFlowRateWARN[i] = true;
                            }
                        }
                        else
                        {
                            _isANAFlowRateWARN[i] = false;
                        }
                    }
                    //ANBCellFlow
                    if (hotMetalDevice.MetalDeviceData.ANBPinEnable && hotMetalDevice.ANBFlowValveStable)
                    {
                        double ANBcellFlow = hotMetalDevice.ANBCellFlow.CounterValue;
                        if (ANBcellFlow < _resRecipe.ANFlowRateErrorLow)
                        {
                            if (!metalEntity.IsError)
                            {
                                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{hotMetalDevice.Name} ANBSideflow:{ANBcellFlow} is less than recipe's ANFlowRateErrorLow parameter:{_resRecipe.ANFlowRateErrorLow}");
                                metalEntity.PostMsg(MetalMsg.Error);
                            }
                        }
                        else if (ANBcellFlow < _resRecipe.ANFlowRateWarningLow)
                        {
                            if (!_isANBFlowRateWARN[i])
                            {
                                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{hotMetalDevice.Name} ANBSideflow:{ANBcellFlow} is less than recipe's ANFlowRateWarningLow parameter:{_resRecipe.ANFlowRateWarningLow}");
                                _isANBFlowRateWARN[i] = true;
                            }
                        }
                        else
                        {
                            _isANBFlowRateWARN[i] = false;
                        }
                    }
                }
            }
        }
        /// 
        /// Temperature Check
        /// 
        private void TemperatureCheck()
        {
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
            TemperatureController temperatureController = DEVICE.GetDevice(reservoirItem.TCID);
            if (temperatureController == null || temperatureController.TemperatureData == null || _resRecipe == null
                || temperatureController.TemperatureData.ControlOperationModel != ENABLE) return;
            double tempValue = temperatureController.TemperatureData.ReserviorTemperature;
            if (tempValue > _resRecipe.TemperatureErrorHigh && !reservoirEntity.IsError)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{temperatureController.Name} temperature:{tempValue} is over recipe's TemperatureErrorHigh parameter:{_resRecipe.TemperatureErrorHigh}");
                reservoirEntity.PostMsg(ReservoirMsg.Error);
            }
            else if (tempValue < _resRecipe.TemperatureErrorLow && !reservoirEntity.IsError)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{temperatureController.Name} temperature:{tempValue} is less than recipe's TemperatureErrorLow parameter:{_resRecipe.TemperatureErrorLow}");
                reservoirEntity.PostMsg(ReservoirMsg.Error);
            }
            else if (tempValue > _resRecipe.TemperatureWarningHigh)
            {
                if (!_isTCControlWARN)
                {
                    LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{temperatureController.Name} temperature:{tempValue} is over recipe's TemperatureWarningHigh parameter:{_resRecipe.TemperatureWarningHigh}");
                    _isTCControlWARN = true;
                }
            }
            else if (tempValue < _resRecipe.TemperatureWarningLow)
            {
                if (!_isTCControlWARN)
                {
                    LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{temperatureController.Name} temperature;{tempValue} is less than recipe's TemperatureWarningLow parameter:{_resRecipe.TemperatureWarningLow}");
                    _isTCControlWARN = true;
                }
            }
            else
            {
                _isTCControlWARN = false;
            }
        }
        /// 
        /// AN LowLevel触发对应操作
        /// 
        private void ANLowLevelOperation()
        {
            if (IsANLowLevel)
            {
                if (_reservoirData.ANPump > 0)
                {
                    AnPumpOffOperation("ANPumpOff", null);
                }
                foreach (var metalDevice in _metalDevices)
                {
                    if (metalDevice.MetalDeviceData.ANAPinEnable)
                    {
                        metalDevice.AnSideAFillOff($"{metalDevice.Name}.ANAFillOff", null);
                    }
                    if (metalDevice.MetalDeviceData.ANBPinEnable)
                    {
                        metalDevice.AnSideBFillOff($"{metalDevice.Name}.ANBFillOff", null);
                    }
                }
            }
        }
        /// 
        /// CA Low Level触发对应操作
        /// 
        private void CALowLevelOperation()
        {
            ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
            if (IsCALowLevel)
            {
                if (_reservoirData.CAPumpEnable)
                {
                    CAPumpOff("CAPumpOff", null);
                }
                foreach (var metalDevice in _metalDevices)
                {
                    if (metalDevice.MetalDeviceData.CellFlowValve)
                    {
                        metalDevice.CellFlowValveOff($"{metalDevice.Name}.FlowOff", null);
                    }
                }
                //禁用TC
                if (!String.IsNullOrEmpty(reservoirItem.TCID))
                {
                    TemperatureController temperatureController = DEVICE.GetDevice(reservoirItem.TCID);
                    if (temperatureController != null && temperatureController.TemperatureData.ControlOperationModel == 5)
                    {
                        temperatureController.DisableOperation("", null);
                    }
                }
            }
        }
        /// 
        /// High Level Common Operation
        /// 
        private void HighLevelOperation()
        {
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            SystemFacilities systemFacilities = DEVICE.GetDevice("System.Facilities");
            if (systemFacilities != null)
            {
                if (systemFacilities.DIFillEnable) systemFacilities.DiFillDisableOperation("DIFillDisableOpeartion", null);
                if (systemFacilities.DIReplenEnable) systemFacilities.DiReplenDisableOperation("DiReplenDisableOperation", null);
                if (_reservoirData.ANDiReplen)
                {
                    _currentOperation = ReservoirOperation.None;
                    ANDiReplenOff("", null);
                }
                if (_reservoirData.CADiReplen)
                {
                    _currentOperation = ReservoirOperation.None;
                    CADiReplenOff("", null);
                }
            }
            if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
        }
        /// 
        /// Low Level common Operation
        /// 
        private void LowLevelOperation()
        {
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            foreach (var metalDevice in _metalDevices)
            {
                MetalEntity metalEntity = Singleton.Instance.GetModule(metalDevice.DeviceID);
                if (metalEntity != null && !metalEntity.IsError)
                {
                    metalEntity.PostMsg(MetalMsg.Error);
                }
            }
            if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
        }
        /// 
        /// WaterLevelMonitor
        /// 
        private void WaterLevelMonitor()
        {
            ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            _isSystemAutoMode = reservoirEntity.IsAuto; ;
            //触发low将对应的reservoir和对应metal切成error         
            if (IsANLowLevel)
            {
                if (!errorLogSet.Contains($"{Module}.IsANLowLevel"))
                {
                    errorLogSet.Add($"{Module}.IsANLowLevel");
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current ANWaterlevel:{ReservoirData.ANWaterLevel} is lower than  ANLowLevel Config:{SC.GetValue($"Reservoir.{Module}.ANLowLevel")}");
                }
                ANLowLevelOperation();
                LowLevelOperation();
                if (_isSystemAutoMode && !AlarmListManager.Instance.IsContainDataError(Module, "ANWaterLevel"))//模块处于Auto模式使将报错信息加入到Alarm
                {
                    AlarmListManager.Instance.AddDataError(Module,
                        $"ANWaterLevel", $"Current ANWaterlevel:{ReservoirData.ANWaterLevel} is lower than  ANLowLevel Config:{SC.GetValue($"Reservoir.{Module}.ANLowLevel")}");
                }
            }
            else if (IsANHighLevel)
            {
                if (!errorLogSet.Contains($"{Module}.IsANHighLevel"))
                {
                    errorLogSet.Add($"{Module}.IsANHighLevel");
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current ANWaterlevel:{ReservoirData.ANWaterLevel} is larger than  ANHighLevel Config:{SC.GetValue($"Reservoir.{Module}.ANHighLevel")}");
                }
                HighLevelOperation();
                if (_isSystemAutoMode && !AlarmListManager.Instance.IsContainDataError(Module, "ANWaterLevel"))
                {
                    AlarmListManager.Instance.AddDataError(Module,
                        $"ANWaterLevel", $"Current ANWaterlevel:{ReservoirData.ANWaterLevel} is larger than  ANHighLevel Config:{SC.GetValue($"Reservoir.{Module}.ANHighLevel")}");
                }
            }
            if (IsCALowLevel)
            {
                if (!errorLogSet.Contains($"{Module}.IsCALowLevel"))
                {
                    errorLogSet.Add($"{Module}.IsCALowLevel");
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current CAWaterlevel:{ReservoirData.CAWaterLevel} is lower than  CALowLevel Config:{SC.GetValue($"Reservoir.{Module}.CALowLevel")}");
                }
                CALowLevelOperation();
                LowLevelOperation();
                if (_isSystemAutoMode && !AlarmListManager.Instance.IsContainDataError(Module, "CAWaterLevel"))
                {
                    AlarmListManager.Instance.AddDataError(Module,
                        $"CAWaterLevel", $"Current CAWaterlevel:{ReservoirData.CAWaterLevel} is lower than  CALowLevel Config:{SC.GetValue($"Reservoir.{Module}.CALowLevel")}");
                }
            }
            else if (IsCAHighLevel)
            {
                if (!errorLogSet.Contains($"{Module}.IsCAHighLevel"))
                {
                    errorLogSet.Add($"{Module}.IsCAHighLevel");
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current CAWaterlevel:{ReservoirData.CAWaterLevel} is large than  CAHighLevel Config:{SC.GetValue($"Reservoir.{Module}.CAHighLevel")}");
                }
                HighLevelOperation();
                if (_isSystemAutoMode && !AlarmListManager.Instance.IsContainDataError(Module, "CAWaterLevel"))
                {
                    AlarmListManager.Instance.AddDataError(Module,
                        $"CAWaterLevel", $"Current CAWaterlevel:{ReservoirData.CAWaterLevel} is large than  CAHighLevel Config:{SC.GetValue($"Reservoir.{Module}.CAHighLevel")}");
                }
            }
            //水位触发recipe里面的high/low参数将对应的reservoir切成error
            if (_resRecipe == null) return;
            //ANLevel监控
            if (ReservoirData.ANLevel < _resRecipe.ANLevelErrorLow)
            {
                if (!errorLogSet.Contains($"{Module}.ANLevel"))
                {
                    errorLogSet.Add($"{Module}.ANLevel");
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current ANlevel:{ReservoirData.ANLevel} is lower than ResRecipe.ANLevelErrorLow:{_resRecipe.ANLevelErrorLow}");
                }
                if (!reservoirEntity.IsError)
                {
                    reservoirEntity.PostMsg(ReservoirMsg.Error);
                }
                if (_isSystemAutoMode && !AlarmListManager.Instance.IsContainDataError(Module, "ANLevel"))
                {
                    AlarmListManager.Instance.AddDataError(Module,
                        $"ANLevel", $"Current ANlevel:{ReservoirData.ANLevel} is lower than ResRecipe.ANLevelErrorLow:{_resRecipe.ANLevelErrorLow}");
                }
            }
            else if (ReservoirData.ANLevel > _resRecipe.ANLevelErrorHigh)
            {
                if (!errorLogSet.Contains($"{Module}.ANLevel"))
                {
                    errorLogSet.Add($"{Module}.ANLevel");
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current ANlevel:{ReservoirData.ANLevel} is larger than ResRecipe.ANLevelErrorHigh:{_resRecipe.ANLevelErrorHigh}");
                }
                if (!reservoirEntity.IsError)
                {
                    reservoirEntity.PostMsg(ReservoirMsg.Error);
                }
                if (_isSystemAutoMode && !AlarmListManager.Instance.IsContainDataError(Module, "ANLevel"))
                {
                    AlarmListManager.Instance.AddDataError(Module,
                        $"ANLevel", $"Current ANlevel:{ReservoirData.ANLevel} is larger than ResRecipe.ANLevelErrorHigh:{_resRecipe.ANLevelErrorHigh}");
                }
            }
            //CALevel监控
            if (ReservoirData.CALevel < _resRecipe.CALevelErrorLow)
            {
                if (!errorLogSet.Contains($"{Module}.CALevel"))
                {
                    errorLogSet.Add($"{Module}.CALevel");
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current CAlevel:{ReservoirData.CALevel} is lower than ResRecipe.CALevelErrorLow:{_resRecipe.CALevelErrorLow}");
                }
                if (!reservoirEntity.IsError)
                {
                    reservoirEntity.PostMsg(ReservoirMsg.Error);
                }
                if (_isSystemAutoMode && !AlarmListManager.Instance.IsContainDataError(Module, "CALevel"))
                {
                    AlarmListManager.Instance.AddDataError(Module,
                        $"CALevel", $"Current CAlevel:{ReservoirData.CALevel} is lower than ResRecipe.CALevelErrorLow:{_resRecipe.CALevelErrorLow}");
                }
            }
            else if (ReservoirData.CALevel > _resRecipe.CALevelErrorHigh)
            {
                if (!errorLogSet.Contains($"{Module}.CALevel"))
                {
                    errorLogSet.Add($"{Module}.CALevel");
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current CAlevel:{ReservoirData.CALevel} is larger than ResRecipe.CALevelErrorHigh:{_resRecipe.CALevelErrorHigh}");
                }
                if (!reservoirEntity.IsError)
                {
                    reservoirEntity.PostMsg(ReservoirMsg.Error);
                }
                if (_isSystemAutoMode && !AlarmListManager.Instance.IsContainDataError(Module, "CALevel"))
                {
                    AlarmListManager.Instance.AddDataError(Module,
                        $"CALevel", $"Current CAlevel:{ReservoirData.CALevel} is larger than ResRecipe.CALevelErrorHigh:{_resRecipe.CALevelErrorHigh}");
                }
            }
        }
        /// 
        /// 定时器
        /// 
        /// 
        private bool OnTimer()
        {
            //补水监控
            if (_direplenHelper != null)
            {
                _direplenHelper.MonitorPeriodTime();
                if (_currentOperation == ReservoirOperation.ManualANDiReplen)
                {
                    bool result = _direplenHelper.MonitorManualDiReplenComplete(_manualReplenSecond, ANDiReplenOff);
                    if (result)
                    {
                        _currentOperation = ReservoirOperation.None;
                    }
                }
                if (_currentOperation == ReservoirOperation.ManualCADiReplen)
                {
                    bool result = _direplenHelper.MonitorManualDiReplenComplete(_manualReplenSecond, CADiReplenOff);
                    if (result)
                    {
                        _currentOperation = ReservoirOperation.None;
                    }
                }
                if (_currentOperation == ReservoirOperation.AutoANDiReplen)
                {
                    AutoDiReplenMonitor(ANDiReplenOff, _reservoirData.ANLevel, _resRecipe.ReservoirANLevel, _resRecipe.ANDIReplenEnable,
                        _resRecipe.ANDIReplenTimeRate, _resRecipe.ANDIReplenCurrentRate);
                }
                if (_currentOperation == ReservoirOperation.AutoCADiReplen)
                {
                    AutoDiReplenMonitor(CADiReplenOff, _reservoirData.CALevel, _resRecipe.ReservoirCALevel, _resRecipe.DIReplenEnable,
                        _resRecipe.DIReplenTimeRate, _resRecipe.DIReplenCurrentRate);
                }
            }
            //计算AN/CA level的平均值
            if (ReservoirData != null)
            {
                //AN
                if (_ANLevelSamples.Count >= levelSampleCount)
                {
                    _ANLevelSamples.Dequeue();
                    _ANLevelSamples.Enqueue(ReservoirData.ANLevel);
                }
                else
                {
                    _ANLevelSamples.Enqueue(ReservoirData.ANLevel);
                }
                //CA
                if (_CALevelSamples.Count >= levelSampleCount)
                {
                    _CALevelSamples.Dequeue();
                    _CALevelSamples.Enqueue(ReservoirData.CALevel);
                }
                else
                {
                    _CALevelSamples.Enqueue(ReservoirData.CALevel);
                }
                _avgANLevel = _ANLevelSamples.Count > 0 ? _ANLevelSamples.Average() : 0;
                _avgCALevel = _CALevelSamples.Count > 0 ? _CALevelSamples.Average() : 0;
            }
            _metalTotalFlow = 0;
            ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
            if (reservoirItem != null)
            {
                List metalItems = reservoirItem.MetalCells;
                if (metalItems != null && metalItems.Count > 0)
                {
                    foreach (MetalItem metalItem in metalItems)
                    {
                        if (metalItem.Installed)
                        {
                            CompactMembranMetalDevice metalDevice = DEVICE.GetDevice(metalItem.ModuleName);
                            if (metalDevice != null)
                            {
                                _metalTotalFlow += metalDevice.ANACellFlow.CounterValue;
                                _metalTotalFlow += metalDevice.ANBCellFlow.CounterValue;
                            }
                        }
                    }
                }
            }
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            //pump安全性检验
            if (_reservoirData.ANPump > 0 && (_reservoirData.ANBypassFlow + ReservoirCounterByPassFlow.CounterValue + _metalTotalFlow) < SC.GetValue($"Reservoir.{Module}.ByPassMetalTotalFlowMinLimit"))
            {
                if (!_isAnPumpSafeDetectedActivate)
                {
                    _isAnPumpSafeDetectedActivate = true;
                    _AnPumpSafeDetectTime = DateTime.Now;
                }
                if ((DateTime.Now - _AnPumpSafeDetectTime).TotalSeconds > _flowFaultHoldOffTime && _isAnPumpSafeDetectedActivate)
                {
                    if (reservoirEntity.IsAuto && !reservoirEntity.IsError)
                    {
                        reservoirEntity.PostMsg(ReservoirMsg.Error);
                    }
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Total flow is less than configuration item ByPassMetalTotalFlowMinLimit :{SC.GetValue($"Reservoir.{Module}.ByPassMetalTotalFlowMinLimit")}, AN Pump off");
                    _isAnPumpSafeDetectedActivate = false;
                    AnPump(0);
                }
            }
            else
            {
                _isAnPumpSafeDetectedActivate = false;
            }
            foreach (CompactMembranMetalDevice device in _metalDevices)
            {
                device.OnTimer(_periodicJob.Interval);
            }
            if (reservoirEntity != null && reservoirEntity.IsError && _isCrossDoseInstalled && _reservoirData.TransferPumpEnable && _reservoirData.TransferPumpExecute)
            {
                _crossDoseHelper.HaltDosing();
            }
            // 判断排气是否触发漏液警报
            if (_reservoirData != null && _reservoirData.EvaporatorLevel && "STD".Equals(reservoirItem.EvaporatorType)) //_reservoirData.EvaporatorLevel true表示触发漏液
            {
                if (_reservoirData.CDAFlowValve)
                {
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"EvaporatorLevel is Activate");
                    CDAFlowOff("CDAFlowOff", null);
                }
                if (_reservoirData.CAPumpEnable)
                {
                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"EvaporatorLevel is Activate");
                    CAPumpOff("CAPumpOff", null);
                }
            }
            //WaterLevel Monitor
            WaterLevelMonitor();
            //触发Safetyhigh将reservoir切成error
            SafetyDevice safetyDevice = DEVICE.GetDevice("Safety");
            if (safetyDevice != null && safetyDevice.SafetyData.ReservoirHighLevel && !reservoirEntity.IsError)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Safety high is Activate");
                reservoirEntity.PostMsg(ReservoirMsg.Error);
            }
            //Sample检测
            SystemFacilities systemFacility = DEVICE.GetDevice("System.Facilities");
            if (systemFacility != null && !systemFacility.SampleFluidDetect)
            {
                if (ReservoirData.ANSampleFlow) ANSampleOff("", null);
                if (ReservoirData.CASampleFlow) CASampleOff("", null);
            }
            if (reservoirEntity == null || !reservoirEntity.IsInitialized)
            {
                return true;
            }
            if (_isCrossDoseInstalled)
            {
                if (_crossDoseHelper.CrossDoseState == RState.Running)
                {
                    _crossDoseHelper.CrossDoseStatusMonitor();
                }
                if (_crossDoseHelper.ResetState == RState.Running)
                {
                    _crossDoseHelper.ResetCrossDoseMonitor();
                }
                if (_persistentValue.OperatingMode == "Auto")
                {
                    _crossDoseHelper.AutoCrossDoseMonitor(_isCrossDoseInitialized);
                }
                else
                {
                    _crossDoseHelper.CrossDoseOperationMonitor();
                }
            }
            if (_persistentValue.OperatingMode == AUTO)
            {
                //CAFlowRate判断
                CAFlowRateCheck();
                //ANFlowRate判断
                ANFlowRateCheck();
                //Temperature判断
                TemperatureCheck();
            }
            //判断是否到启动fast leak test的时间
            if (DateTime.Now - _fastLeakStartTime >= _fastLeakTestSpan - TimeSpan.FromMilliseconds(200) && DateTime.Now - _fastLeakStartTime <= _fastLeakTestSpan + TimeSpan.FromMilliseconds(200))
            {
                FastLeakTestAction();
            }
            //判断是否到启动slow leak test的时间
            if (DateTime.Now - _slowLeakStartTime >= _slowLeakTestSpan - TimeSpan.FromMilliseconds(200) && DateTime.Now - _slowLeakStartTime <= _slowLeakTestSpan + TimeSpan.FromMilliseconds(200))
            {
                SlowLeakTestAction();
            }
            return true;
        }
        /// 
        /// 自动注水监控
        /// 
        /// 
        /// 
        /// 
        private void AutoDiReplenMonitor(Func direplenOff, double level, double recipeLevel, bool replenEnable,
            int direplenTimeRate, int direplenCurrentRate)
        {
            bool result = _direplenHelper.AutoDiReplenMonitorTimeOut(direplenOff);
            if (result)
            {
                _currentOperation = ReservoirOperation.None;
                //触发注水异常信号
                _isDiReplenInFault = true;
            }
            else
            {
                //按液位补水
                result = _direplenHelper.AutoDiReplenMonitorComplete(level, recipeLevel, replenEnable, direplenTimeRate, direplenCurrentRate, direplenOff);
                if (result)
                {
                    _currentOperation = ReservoirOperation.None;
                }
            }
        }
        /// 
        /// ReservoirUsage监控
        /// 
        public void ReservoirUsageMonitor()
        {
            ReservoirUsage reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(Module);
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
            if (reservoirUsage == null || reservoirEntity == null) return;
            //reservoirTotalAmpHours Check
            double reservoirTotalAmpHoursWarningLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.ReservoirTotalAmpHoursWarningLimit"))
            {
                reservoirTotalAmpHoursWarningLimit = (double)SC.GetValue($"Reservoir.{Module}.ReservoirTotalAmpHoursWarningLimit");
            }
            double reservoirTotalAmpHoursFaultLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.ReservoirTotalAmpHoursFaultLimit"))
            {
                reservoirTotalAmpHoursFaultLimit = (double)SC.GetValue($"Reservoir.{Module}.ReservoirTotalAmpHoursFaultLimit");
            }
            if (reservoirUsage.TotalUsage > reservoirTotalAmpHoursFaultLimit && reservoirTotalAmpHoursFaultLimit != 0)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Total Usage(AHr):{reservoirUsage.TotalUsage} is over config item ReservoirTotalAmpHoursFaultLimit:{reservoirTotalAmpHoursFaultLimit}");
                reservoirEntity.PostMsg(ReservoirMsg.Error);
                AlarmListManager.Instance.AddDataError(Module,
                    $"TotalUsage", $"{Module} Total Usage(AHr):{reservoirUsage.TotalUsage} is over ReservoirTotalAmpHoursFaultLimit:{reservoirTotalAmpHoursFaultLimit}");
            }
            else if (reservoirUsage.TotalUsage > reservoirTotalAmpHoursWarningLimit && reservoirTotalAmpHoursWarningLimit != 0)
            {
                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Total Usage(AHr):{reservoirUsage.TotalUsage} is over config item ReservoirTotalAmpHoursWarningLimit:{reservoirTotalAmpHoursWarningLimit}");
                AlarmListManager.Instance.AddWarn(Module,
                    $"TotalUsage", $"{Module} Total Usage(AHr):{reservoirUsage.TotalUsage} is over ReservoirTotalAmpHoursWarningLimit:{reservoirTotalAmpHoursWarningLimit}");
            }
            //MembraneTotalAmpHoursCheck
            double membraneTotalAmpHoursWarningLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.MembraneTotalAmpHoursWarningLimit"))
            {
                membraneTotalAmpHoursWarningLimit = (double)SC.GetValue($"Reservoir.{Module}.MembraneTotalAmpHoursWarningLimit");
            }
            double membraneTotalAmpHoursFaultLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.MembraneTotalAmpHoursFaultLimit"))
            {
                membraneTotalAmpHoursFaultLimit = (double)SC.GetValue($"Reservoir.{Module}.MembraneTotalAmpHoursFaultLimit");
            }
            if (reservoirUsage.MembranceUsage > membraneTotalAmpHoursFaultLimit && membraneTotalAmpHoursFaultLimit != 0)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Membrane Usage(AHr):{reservoirUsage.MembranceUsage} is over config item MembraneTotalAmpHoursFaultLimit:{membraneTotalAmpHoursFaultLimit}");
                reservoirEntity.PostMsg(ReservoirMsg.Error);
                AlarmListManager.Instance.AddDataError(Module,
                    $"MembraneUsage", $"{Module} Membrane Usage(AHr):{reservoirUsage.MembranceUsage} is over MembraneTotalAmpHoursFaultLimit:{membraneTotalAmpHoursFaultLimit}");
            }
            else if (reservoirUsage.MembranceUsage > membraneTotalAmpHoursWarningLimit && membraneTotalAmpHoursWarningLimit != 0)
            {
                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Membrane Usage(AHr):{reservoirUsage.MembranceUsage} is over config item MembraneTotalAmpHoursWarningLimit:{membraneTotalAmpHoursWarningLimit}");
                AlarmListManager.Instance.AddWarn(Module,
                   $"MembraneUsage", $"{Module} Membrane Usage(AHr):{reservoirUsage.MembranceUsage} is over MembraneTotalAmpHoursWarningLimit:{membraneTotalAmpHoursWarningLimit}");
            }
            //ANBathTotalAmpHoursCheck
            double anBathTotalAmpHoursWarningLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.ANBathTotalAmpHoursWarningLimit"))
            {
                anBathTotalAmpHoursWarningLimit = (double)SC.GetValue($"Reservoir.{Module}.ANBathTotalAmpHoursWarningLimit");
            }
            double anBathTotalAmpHoursFaultLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.ANBathTotalAmpHoursFaultLimit"))
            {
                anBathTotalAmpHoursFaultLimit = (double)SC.GetValue($"Reservoir.{Module}.ANBathTotalAmpHoursFaultLimit");
            }
            if (reservoirUsage.AnodeUsage > anBathTotalAmpHoursFaultLimit && anBathTotalAmpHoursFaultLimit != 0)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Anolyte Bath Usage(AHr):{reservoirUsage.AnodeUsage} is over config item ANBathTotalAmpHoursFaultLimit:{anBathTotalAmpHoursFaultLimit}");
                reservoirEntity.PostMsg(ReservoirMsg.Error);
                AlarmListManager.Instance.AddDataError(Module,
                    $"AnodeUsage", $"{Module} Anolyte Bath Usage(AHr):{reservoirUsage.AnodeUsage} is over ANBathTotalAmpHoursFaultLimit:{anBathTotalAmpHoursFaultLimit}");
            }
            else if (reservoirUsage.AnodeUsage > anBathTotalAmpHoursWarningLimit && anBathTotalAmpHoursWarningLimit != 0)
            {
                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Anolyte Bath Usage(AHr):{reservoirUsage.AnodeUsage} is over config item ANBathTotalAmpHoursWarningLimit:{anBathTotalAmpHoursWarningLimit}");
                AlarmListManager.Instance.AddWarn(Module,
                    $"AnodeUsage", $"{Module} Anolyte Bath Usage(AHr):{reservoirUsage.AnodeUsage} is over ANBathTotalAmpHoursWarningLimit:{anBathTotalAmpHoursWarningLimit}");
            }
            //BathTotalAmpHoursCheck
            double bathTotalAmpHoursWarningLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.BathTotalAmpHoursWarningLimit"))
            {
                bathTotalAmpHoursWarningLimit = (double)SC.GetValue($"Reservoir.{Module}.BathTotalAmpHoursWarningLimit");
            }
            double bathTotalAmpHoursFaultLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.BathTotalAmpHoursFaultLimit"))
            {
                bathTotalAmpHoursFaultLimit = (double)SC.GetValue($"Reservoir.{Module}.BathTotalAmpHoursFaultLimit");
            }
            if (reservoirUsage.BathUsage > bathTotalAmpHoursFaultLimit && bathTotalAmpHoursFaultLimit != 0)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Bath Usage(AHr):{reservoirUsage.BathUsage} is over config item BathTotalAmpHoursFaultLimit:{bathTotalAmpHoursFaultLimit}");
                reservoirEntity.PostMsg(ReservoirMsg.Error);
                AlarmListManager.Instance.AddDataError(Module,
                    $"BathUsage", $"{Module} Bath Usage(AHr):{reservoirUsage.BathUsage} is over BathTotalAmpHoursFaultLimit:{bathTotalAmpHoursFaultLimit}");
            }
            else if (reservoirUsage.BathUsage > bathTotalAmpHoursWarningLimit && bathTotalAmpHoursWarningLimit != 0)
            {
                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Bath Usage(AHr):{reservoirUsage.BathUsage} is over config item BathTotalAmpHoursWarningLimit:{bathTotalAmpHoursWarningLimit}");
                AlarmListManager.Instance.AddWarn(Module,
                    $"BathUsage", $"{Module} Bath Usage(AHr):{reservoirUsage.BathUsage} is over BathTotalAmpHoursWarningLimit:{bathTotalAmpHoursWarningLimit}");
            }
            //BathTotalDaysCheck
            int bathTotalDaysWarningLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.BathTotalDaysWarningLimit"))
            {
                bathTotalDaysWarningLimit = SC.GetValue($"Reservoir.{Module}.BathTotalDaysWarningLimit");
            }
            int bathTotalDaysFaultLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.BathTotalDaysFaultLimit"))
            {
                bathTotalDaysFaultLimit = SC.GetValue($"Reservoir.{Module}.BathTotalDaysFaultLimit");
            }
            if (reservoirUsage.BathUsageDays > bathTotalDaysFaultLimit && bathTotalDaysFaultLimit != 0)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Bath Usage(Days):{reservoirUsage.BathUsageDays} is over config item BathTotalDaysFaultLimit:{bathTotalDaysFaultLimit}");
                reservoirEntity.PostMsg(ReservoirMsg.Error);
                AlarmListManager.Instance.AddDataError(Module,
                    $"BathUsageDays", $"{Module} Bath Usage(Days):{reservoirUsage.BathUsageDays} is over BathTotalDaysFaultLimit:{bathTotalDaysFaultLimit}");
            }
            else if (reservoirUsage.BathUsageDays > bathTotalDaysWarningLimit && bathTotalDaysWarningLimit != 0)
            {
                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Bath Usage(Days):{reservoirUsage.BathUsage} is over config item BathTotalDaysWarningLimit:{bathTotalDaysWarningLimit}");
                AlarmListManager.Instance.AddWarn(Module,
                    $"BathUsageDays", $"{Module} Bath Usage(Days):{reservoirUsage.BathUsageDays} is over BathTotalDaysWarningLimit:{bathTotalDaysWarningLimit}");
            }
            //ReservoirTotalWafersCheck
            int reservoirTotalWafersWarningLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.ReservoirTotalWafersWarningLimit"))
            {
                reservoirTotalWafersWarningLimit = SC.GetValue($"Reservoir.{Module}.ReservoirTotalWafersWarningLimit");
            }
            int reservoirTotalWafersFaultLimit = 0;
            if (SC.ContainsItem($"Reservoir.{Module}.ReservoirTotalWafersFaultLimit"))
            {
                reservoirTotalWafersFaultLimit = SC.GetValue($"Reservoir.{Module}.ReservoirTotalWafersFaultLimit");
            }
            if (reservoirUsage.TotalWafers > reservoirTotalWafersFaultLimit && reservoirTotalWafersFaultLimit != 0)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Total Wafers:{reservoirUsage.TotalWafers} is over config item ReservoirTotalWafersFaultLimit:{reservoirTotalWafersFaultLimit}");
                reservoirEntity.PostMsg(ReservoirMsg.Error);
                AlarmListManager.Instance.AddDataError(Module,
                    $"TotalWafers", $"{Module} Total Wafers:{reservoirUsage.TotalWafers} is over ReservoirTotalWafersFaultLimit:{reservoirTotalWafersFaultLimit}");
            }
            else if (reservoirUsage.TotalWafers > reservoirTotalWafersWarningLimit && reservoirTotalWafersWarningLimit != 0)
            {
                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Total Wafers:{reservoirUsage.TotalWafers} is over config item ReservoirTotalWafersWarningLimit:{reservoirTotalWafersWarningLimit}");
                AlarmListManager.Instance.AddWarn(Module,
                    $"TotalWafers", $"{Module} Total Wafers:{reservoirUsage.TotalWafers} is over ReservoirTotalWafersWarningLimit:{reservoirTotalWafersWarningLimit}");
            }
        }
        public void Monitor()
        {
        }
        public void Reset()
        {
        }
        public void Terminate()
        {
        }
    }
}