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 CyberX8_Core;
using System;
using System.Collections.Generic;
using System.Reflection;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.ToolLayout;
using CyberX8_RT.Devices.Facilities;
using CyberX8_RT.Modules.Reservoir;
using CyberX8_RT.Modules;
using CyberX8_RT.Devices.Metal;
using System.Collections.ObjectModel;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.Beckhoff.IOAxis;
using CyberX8_RT.Modules.Metal;
using CyberX8_RT.Devices.Temperature;
using CyberX8_RT.Devices.Safety;
using System.Linq;
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;
private bool _isAnPumpSafeDetectedActivate = false;
private bool _isANAutoDIReplenError =false;
private bool _isCAAutoDIReplenError =false;
#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
///
/// 构造函数
///
///
///
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);
_pumpSpeedHelper = new ReservoirPumpSpeedHelper(Module,this);
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";
if(_persistentValue!=null)
{
ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
if (reservoirEntity == null) return false;
if (_persistentValue.OperatingMode == "Auto" && reservoirEntity.IsMetalBusy)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} is Busy, can't change to disable 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);
EnterDisabledOperation();
if (_isCrossDoseInstalled && _persistentValue.OperatingMode != currentOperation) InitializeCrossDose(false);
if (_persistentValue.OperatingMode != "Disabled") reservoirEntity.EnterInit();
_persistentValue.OperatingMode = 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)
{
if (_persistentValue.OperatingMode == "Auto" && reservoirEntity != null && 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 change to manual mode");
return false;
}
foreach (var metalDevice in _metalDevices)
{
metalDevice.ManualOperation("", null);
}
if (_isCrossDoseInstalled && _persistentValue.OperatingMode != currentOperation) InitializeCrossDose(false);
if (_persistentValue.OperatingMode != "Manual" && reservoirEntity != null) reservoirEntity.EnterInit();
_persistentValue.OperatingMode = 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 Activate");
return false;
}
string currentOperation = "Auto";
if (_persistentValue != null)
{
if (_isCrossDoseInstalled && _persistentValue.OperatingMode != currentOperation) InitializeCrossDose(false);
ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
if (_persistentValue.OperatingMode != "Auto" && reservoirEntity != null) reservoirEntity.EnterInit();
_persistentValue.OperatingMode = 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 IOModuleManager.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 = IOModuleManager.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 IOModuleManager.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 IOModuleManager.Instance.WriteIoValue(ioName, speed);
}
///
/// 阳极B Drain Pump
///
///
///
public bool AnBDrainPump(double speed)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_DRAIN_PUMP}");
return IOModuleManager.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 IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// 阳极ByPass Off
///
///
///
///
private bool ANByPassOff(string cmd, object[] args)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_BY_PASS}");
return IOModuleManager.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 IOModuleManager.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 IOModuleManager.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 IOModuleManager.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 IOModuleManager.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 = IOModuleManager.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 IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// 阴极CDA Flow Off
///
///
///
///
private bool CDAFlowOff(string cmd, object[] args)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CDA_FLOW_VALVE}");
return IOModuleManager.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 IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// 阴极ByPass Off
///
///
///
///
public bool CAByPassOff(string cmd, object[] args)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_BY_PASS}");
return IOModuleManager.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 IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// CrossDose关阀
///
///
///
///
public bool CrossDoseOff(string cmd, object[] args)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CROSS_DOSE_ENABLE}");
return IOModuleManager.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 IOModuleManager.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 IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// ANSample关阀
///
///
///
///
public bool ANSampleOff(string cmd, object[] args)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_SAMPLE_FLOW}");
return IOModuleManager.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 IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// CASample关阀
///
///
///
///
public bool CASampleOff(string cmd, object[] args)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_SAMPLE_FLOW}");
return IOModuleManager.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()
{
ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
if (_resRecipe == null) return;
for (int i = 0; i < _metalDevices.Count; i++)
{
CompactMembranMetalDevice hotMetalDevice = _metalDevices[i];
if (hotMetalDevice != null && !hotMetalDevice.IsDisable && hotMetalDevice.IsAuto )
{
MetalEntity metalEntity = Singleton.Instance.GetModule(hotMetalDevice.Name);
if (hotMetalDevice.MetalDeviceData == null) continue ;
if (!hotMetalDevice.FlowValveStable) continue;
double cellFlow = hotMetalDevice.MetalDeviceData.CellFlow;
if (cellFlow < _resRecipe.CAFlowRateErrorLow && !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()
{
ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
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)
{
double ANAcellFlow = hotMetalDevice.ANACellFlow.CounterValue;
if (ANAcellFlow < _resRecipe.ANFlowRateErrorLow && !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)
{
double ANBcellFlow = hotMetalDevice.ANBCellFlow.CounterValue;
if (ANBcellFlow < _resRecipe.ANFlowRateErrorLow && !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} ANBflow:{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;
}
}
///
/// 定时器
///
///
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);
}
if (_currentOperation == ReservoirOperation.AutoCADiReplen)
{
AutoDiReplenMonitor(CADiReplenOff, _reservoirData.CALevel, _resRecipe.ReservoirCALevel);
}
}
//计算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;
}
}
}
}
}
//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)
{
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);
}
ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module);
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);
}
}
//触发low将对应的reservoir和对应metal切成error
if (IsANLowLevel || IsCALowLevel)
{
if (IsANLowLevel && !reservoirEntity.IsError)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current ANWaterlevel:{ReservoirData.ANWaterLevel} is lower than ANLowLevel Config:{SC.GetValue($"Reservoir.{Module}.ANLowLevel")}");
}
if (IsCALowLevel && !reservoirEntity.IsError)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current CAWaterlevel:{ReservoirData.ANWaterLevel} is lower than CALowLevel Config:{SC.GetValue($"Reservoir.{Module}.CALowLevel")}");
}
foreach (var metalDevice in _metalDevices)
{
MetalEntity metalEntity = Singleton.Instance.GetModule(metalDevice.DeviceID);
if (metalEntity != null && !metalEntity.IsError)
{
metalEntity.PostMsg(MetalMsg.Error);
}
}
reservoirEntity.PostMsg(ReservoirMsg.Error);
}
//触发high将reservoir切成error
if (IsANHighLevel || IsCAHighLevel)
{
if (IsANHighLevel && !reservoirEntity.IsError)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current ANWaterlevel:{ReservoirData.ANWaterLevel} is larger than ANHighLevel Config:{SC.GetValue($"Reservoir.{Module}.ANHighLevel")}");
}
if (IsCAHighLevel && !reservoirEntity.IsError)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current CAWaterlevel:{ReservoirData.CAWaterLevel} is large than CAHighLevel Config:{SC.GetValue($"Reservoir.{Module}.CAHighLevel")}");
}
SystemFacilities systemFacilities = DEVICE.GetDevice("System.Facilities");
if(systemFacilities != null && !reservoirEntity.IsError)
{
systemFacilities.DiFillDisableOperation("DIFillDisableOpeartion", null);
systemFacilities.DiReplenDisableOperation("DiReplenDisableOperation", null);
if (_reservoirData.ANDiReplen)
{
_currentOperation = ReservoirOperation.None;
ANDiReplenOff("", null);
}
if (_reservoirData.CADiReplen)
{
_currentOperation = ReservoirOperation.None;
CADiReplenOff("", null);
}
}
reservoirEntity.PostMsg(ReservoirMsg.Error);
}
//触发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);
}
//判断high/low等指示灯是否触发并执行对应的操作
if (IsANLowLevel)
{
if (_reservoirData.ANPump > 0)
{
AnPumpOffOperation("ANPumpOff", null);
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"ANLowLevel is Activate");
}
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);
}
}
}
if (IsCALowLevel)
{
if (_reservoirData.CAPumpEnable)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CALowLevel is Activate");
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);
}
}
}
//水位触发recipe里面的high/low参数将对应的reservoir切成error
if (_resRecipe != null && (ReservoirData.ANLevel < _resRecipe.ANLevelErrorLow || ReservoirData.ANLevel > _resRecipe.ANLevelErrorHigh
|| ReservoirData.CALevel < _resRecipe.CALevelErrorLow || ReservoirData.CALevel > _resRecipe.CALevelErrorHigh))
{
if (ReservoirData.ANLevel < _resRecipe.ANLevelErrorLow && !reservoirEntity.IsError)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current ANlevel:{ReservoirData.ANLevel} is lower than ResRecipe.ANLevelErrorLow:{_resRecipe.ANLevelErrorLow}");
}
if (ReservoirData.ANLevel > _resRecipe.ANLevelErrorHigh && !reservoirEntity.IsError)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current ANlevel:{ReservoirData.ANLevel} is larger than ResRecipe.ANLevelErrorHigh:{_resRecipe.ANLevelErrorHigh}");
}
if (ReservoirData.CALevel < _resRecipe.CALevelErrorLow && !reservoirEntity.IsError)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current CAlevel:{ReservoirData.CALevel} is lower than ResRecipe.CALevelErrorLow:{_resRecipe.CALevelErrorLow}");
}
if (ReservoirData.CALevel > _resRecipe.CALevelErrorHigh && !reservoirEntity.IsError)
{
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current CAlevel:{ReservoirData.CALevel} is larger than ResRecipe.CALevelErrorHigh:{_resRecipe.CALevelErrorHigh}");
}
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)
{
_pumpSpeedHelper.Monitor(_resRecipe);
//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 result = _direplenHelper.AutoDiReplenMonitorTimeOut(direplenOff);
if (result)
{
_currentOperation = ReservoirOperation.None;
//触发注水异常信号
_isDiReplenInFault = true;
}
else
{
//按液位补水
result = _direplenHelper.AutoDiReplenMonitorComplete(level, recipeLevel,_resRecipe, direplenOff);
if (result)
{
_currentOperation = ReservoirOperation.None;
}
}
}
public void Monitor()
{
}
public void Reset()
{
}
public void Terminate()
{
}
}
}