using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.UI.Control;
using Aitex.Core.Util;
using MECF.Framework.Common.Beckhoff.IOAxis;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.CommonData.Metal;
using MECF.Framework.Common.Persistent.Reservoirs;
using MECF.Framework.Common.TwinCat;
using CyberX8_Core;
using CyberX8_RT.Devices.Prewet;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using MECF.Framework.Common.ToolLayout;
using CyberX8_RT.Devices.Reservoir;
using MECF.Framework.Common.Layout;
using Aitex.Core.RT.SCCore;
using System.Diagnostics;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.Metal
{
public class CompactMembranMetalDevice : MetalCellDevice
{
private enum ANCellStatus
{
Unknow,
Filling,
Emptying,
Full,
Empty
}
private enum ANCellOperation
{
None,
Fill,
Drain
}
#region 常量
private const string SIDE_A = "SideA";
private const string SIDE_B = "SideB";
private const string AN_A_PINENABLE="ANAPinEnable";
private const string AN_B_PINENABLE = "ANBPinEnable";
private const string AN_A_POUTENABLE = "ANAPoutEnable";
private const string AN_B_POUTENABLE = "ANBPoutEnable";
private const string CELL_FLOW = "CellFlow";
private const string WH_CLAMP = "WHClamp";
private const string WH_UNCLAMP = "WHUnclamp";
private const string CELL_FLOW_VALVE = "CellFlowValve";
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 string AN_A_CELL_FLOW = "ANACellFlow";
private const string AN_B_CELL_FLOW = "ANBCellFlow";
#endregion
#region 内部变量
///
/// 设备数据
///
private CompactMembranMetalDeviceData _metalDeviceData =new CompactMembranMetalDeviceData();
///
/// 变量是否初始化字典
///
private Dictionary _variableInitializeDic = new Dictionary();
///
/// 阳极A面cellFlow
///
private CounterFlowData _anACellFlow = new CounterFlowData();
///
/// 阳极B面cellFlow
///
private CounterFlowData _anBCellFlow = new CounterFlowData();
///
/// Counter字典
///
private Dictionary _nameCounterFlowData = new Dictionary();
///
/// 当前阳极A面操作
///
private ANCellOperation _currentANACellOperation;
///
/// 当前阳机B面操作
///
private ANCellOperation _currentANBCellOperation;
///
/// AN Fill Routine
///
private CompactMembranFillRoutine _anANACellFillRoutine;
///
/// 阳机B面Fill Routine
///
private CompactMembranFillRoutine _anANBCellFillRoutine;
///
/// 阳极A面流量总数值
///
private double _anATotalFillFlow = 0;
///
/// 阳极B面流量总数值
///
private double _anBTotalFillFlow = 0;
///
/// 阳极A面Drain时间
///
private DateTime _anADrainTime = DateTime.Now;
///
/// 阳极B面Drain时间
///
private DateTime _anBDrainTime = DateTime.Now;
///
/// Flow Valve计时
///
private Stopwatch _flowValveStopWatch = new Stopwatch();
#endregion
#region 属性
///
/// 设备数据
///
public CompactMembranMetalDeviceData MetalDeviceData { get { return _metalDeviceData; } }
///
/// 阳极A面CellFlow
///
public CounterFlowData ANACellFlow { get { return _anACellFlow; } }
///
/// 阳极B面CellFlow
///
public CounterFlowData ANBCellFlow { get { return _anBCellFlow; } }
///
/// Flow Valve稳定状态
///
public bool FlowValveStable { get { return _metalDeviceData.CellFlowValve && _flowValveStopWatch.ElapsedMilliseconds >= 3000; } }
#endregion
///
/// 构造函数
///
///
public CompactMembranMetalDevice(string moduleName) : base(moduleName)
{
}
///
/// 初始化
///
///
public override bool Initialize()
{
base.Initialize();
InitializeRoutine();
SubscribeValueAction();
SubscribeData();
return true;
}
///
/// 初始化Routine
///
private void InitializeRoutine()
{
_anANACellFillRoutine = new CompactMembranFillRoutine(Module,"A");
_anANBCellFillRoutine = new CompactMembranFillRoutine(Module,"B");
}
///
/// 订阅数据
///
private void SubscribeData()
{
DATA.Subscribe($"{Module}.MetalData", () => _metalDeviceData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.SideAFlow",()=>ANACellFlow.CounterValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.SideAFlowStatus", () => ANACellFlow.Status, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.SideBFlow", () => ANBCellFlow.CounterValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.SideBFlowStatus",()=>ANBCellFlow.Status, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.CellFlow",()=>MetalDeviceData.CellFlow, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.ANBPinEnable",()=>_metalDeviceData.ANBPinEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.ANAPinEnable", () => _metalDeviceData.ANAPinEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.ANAPoutEnable", () => _metalDeviceData.ANAPoutEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.ANBPoutEnable", () => _metalDeviceData.ANBPoutEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.CellFlowEnable", () => _metalDeviceData.CellFlowValve, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.WaferShuttleClamped", () => _metalDeviceData.WHClamp, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.WaferShuttleUnclamped", () => _metalDeviceData.WHUnclamp, SubscriptionAttribute.FLAG.IgnoreSaveDB);
}
///
/// 订阅变量数值发生变化
///
private void SubscribeValueAction()
{
BeckhoffIoSubscribeUpdateVariable(AN_A_PINENABLE);
BeckhoffIoSubscribeUpdateVariable(AN_B_PINENABLE);
BeckhoffIoSubscribeUpdateVariable(AN_A_POUTENABLE);
BeckhoffIoSubscribeUpdateVariable(AN_B_POUTENABLE);
BeckhoffIoSubscribeUpdateVariable(CELL_FLOW);
BeckhoffIoSubscribeUpdateVariable(WH_CLAMP);
BeckhoffIoSubscribeUpdateVariable(WH_UNCLAMP);
BeckhoffIoSubscribeUpdateVariable(CELL_FLOW_VALVE);
BeckhoffCounterSubscribeUpdateVariable(AN_A_CELL_FLOW,ANACellFlow);
BeckhoffCounter anACellFlowCounter = BeckhoffCounterManager.Instance.GetBeckhoffCounter($"{Module}.{AN_A_CELL_FLOW}");
if(anACellFlowCounter!=null)
{
ANACellFlow.Period = anACellFlowCounter.Period;
}
BeckhoffCounterSubscribeUpdateVariable(AN_B_CELL_FLOW,ANBCellFlow);
BeckhoffCounter anBCellFlowCounter = BeckhoffCounterManager.Instance.GetBeckhoffCounter($"{Module}.{AN_B_CELL_FLOW}");
if (anACellFlowCounter != null)
{
ANBCellFlow.Period = anBCellFlowCounter.Period;
}
}
///
/// 订阅Operation
///
protected override void InitializeOperation()
{
base.InitializeOperation();
OP.Subscribe($"{Module}.ANAFillOn",AnSideAFillOn);
OP.Subscribe($"{Module}.ANAFillOff", AnSideAFillOff);
OP.Subscribe($"{Module}.ANBFillOn", AnSideBFillOn);
OP.Subscribe($"{Module}.ANBFillOff", AnSideBFillOff);
OP.Subscribe($"{Module}.ANADrainOn", AnSideADrainOn);
OP.Subscribe($"{Module}.ANADrainOff", AnSideADrainOff);
OP.Subscribe($"{Module}.ANBDrainOn", AnSideBDrainOn);
OP.Subscribe($"{Module}.ANBDrainOff", AnSideBDrainOff);
OP.Subscribe($"{Module}.WHClampOn", WHClampOn);
OP.Subscribe($"{Module}.WHClampOff", WHClampOff);
OP.Subscribe($"{Module}.WHUnclampOn", WHUnClampOn);
OP.Subscribe($"{Module}.WHUnclampOff", WHUnClampOff);
OP.Subscribe($"{Module}.CellFlowValveOn", CellFlowValveOn);
OP.Subscribe($"{Module}.CellFlowValveOff", CellFlowValveOff);
OP.Subscribe($"{Module}.WaferHolderClampOn", WaferHolderClampOn);
OP.Subscribe($"{Module}.WaferHolderUnclampOn", WaferHolderUnclampOn);
OP.Subscribe($"{Module}.WaferHolderDisconnect", WaferHolderDisConnect);
OP.Subscribe($"{Module}.A.Fill", ANSideAFillOperation);
OP.Subscribe($"{Module}.B.Fill", ANSideBFillOperation);
OP.Subscribe($"{Module}.A.Stop", ANSideAStopOperation);
OP.Subscribe($"{Module}.B.Stop", ANSideBStopOperation);
OP.Subscribe($"{Module}.A.Drain", ANSideADrainOperation);
OP.Subscribe($"{Module}.B.Drain", ANSideBDrainOperation);
}
///
/// 订阅IO变量
///
///
private void BeckhoffIoSubscribeUpdateVariable(string variable)
{
_variableInitializeDic[variable] = false;
IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
}
///
/// 更新变量数值
///
///
///
private void UpdateVariableValue(string variable, object value)
{
if (!_metalDeviceData.IsDataInitialized)
{
_metalDeviceData.IsDataInitialized = true;
}
PropertyInfo property = _metalDeviceData.GetType().GetProperty(variable);
if (property != null)
{
property.SetValue(_metalDeviceData, value);
}
if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
{
_variableInitializeDic[variable] = true;
}
if (variable == CELL_FLOW_VALVE)
{
bool bValue = (bool)value;
if (bValue)
{
_flowValveStopWatch.Restart();
}
}
}
///
/// 订阅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);
}
}
}
}
#region Fill
///
/// AN A面Fill On
///
///
///
///
public bool AnSideAFillOn(string cmd, object[] param)
{
string ioName= BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_PINENABLE}");
string countName= BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_CELL_FLOW}");
bool result= BeckhoffCounterManager.Instance.StartCounter(countName);
if (result)
{
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
else
{
return false;
}
}
///
/// AN A面Fill Off
///
///
///
///
public bool AnSideAFillOff(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_PINENABLE}");
string countName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_CELL_FLOW}");
bool result = BeckhoffCounterManager.Instance.StopCounter(countName);
if(result)
{
result= BeckhoffCounterManager.Instance.ResetCounter(countName,0);
if(result)
{
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
}
return false;
}
///
/// AN B面Fill On
///
///
///
///
public bool AnSideBFillOn(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_PINENABLE}");
string countName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_CELL_FLOW}");
bool result = BeckhoffCounterManager.Instance.StartCounter(countName);
if (result)
{
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
else
{
return false;
}
}
///
/// AN B面Fill Off
///
///
///
///
public bool AnSideBFillOff(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_PINENABLE}");
string countName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_CELL_FLOW}");
bool result = BeckhoffCounterManager.Instance.StopCounter(countName);
if (result)
{
result = BeckhoffCounterManager.Instance.ResetCounter(countName, 0);
if (result)
{
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
}
return false;
}
#endregion
#region Drain
///
/// AN A面Drain On
///
///
///
///
private bool AnSideADrainOn(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_POUTENABLE}");
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// AN A面Drain Off
///
///
///
///
public bool AnSideADrainOff(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_POUTENABLE}");
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
///
/// AN B面Drain On
///
///
///
///
private bool AnSideBDrainOn(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_POUTENABLE}");
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// AN A面Drain Off
///
///
///
///
public bool AnSideBDrainOff(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_POUTENABLE}");
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
#endregion
#region WH Clamp
///
/// WH Clamp On
///
///
///
///
private bool WHClampOn(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// WH Clamp Off
///
///
///
///
private bool WHClampOff(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
///
/// WH UnClamp On
///
///
///
///
private bool WHUnClampOn(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// WH UnClamp Off
///
///
///
///
private bool WHUnClampOff(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
///
/// Wafer Holder Clamp On
///
///
///
///
public bool WaferHolderClampOn(string cmd, object[] param)
{
string unclampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
bool result = IOModuleManager.Instance.WriteIoValue(unclampIOName, false);
if(result)
{
string clampIOName= BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
return IOModuleManager.Instance.WriteIoValue(clampIOName, true);
}
return false;
}
///
/// Wafer Holder Clamp On
///
///
///
///
public bool WaferHolderUnclampOn(string cmd, object[] param)
{
string clampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
bool result = IOModuleManager.Instance.WriteIoValue(clampIOName, false);
if (result)
{
string unclampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
return IOModuleManager.Instance.WriteIoValue(unclampIOName, true);
}
return false;
}
///
/// Wafer Holder Disconnect
///
///
///
///
public bool WaferHolderDisConnect(string cmd, object[] param)
{
string clampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
bool result = IOModuleManager.Instance.WriteIoValue(clampIOName, false);
if (result)
{
string unclampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
return IOModuleManager.Instance.WriteIoValue(unclampIOName, false);
}
return false;
}
#endregion
#region Cell Flow Valve
///
/// Cell Flow On
///
///
///
///
public bool CellFlowValveOn(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CELL_FLOW_VALVE}");
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// Cell Flow Off
///
///
///
///
public bool CellFlowValveOff(string cmd, object[] param)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CELL_FLOW_VALVE}");
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
#endregion
#region AN Fill
///
/// 阳极A面Fill
///
///
///
///
private bool ANSideAFillOperation(string cmd, object[] objects)
{
if(_currentANACellOperation!=ANCellOperation.None)
{
LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} current is {_currentANACellOperation},cannot execute AN Side A Fill");
return false;
}
bool result = _anANACellFillRoutine.Start() == RState.Running;
if (result)
{
_currentANACellOperation = ANCellOperation.Fill;
}
return result;
}
///
/// 阳极B面Fill
///
///
///
///
private bool ANSideBFillOperation(string cmd, object[] objects)
{
if (_currentANBCellOperation != ANCellOperation.None)
{
LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} current is {_currentANBCellOperation},cannot execute AN Side B Fill");
return false;
}
bool result = _anANBCellFillRoutine.Start() == RState.Running;
if (result)
{
_currentANBCellOperation = ANCellOperation.Fill;
}
return result;
}
#endregion
#region AN Drain
///
/// 阳极A面Drain
///
///
///
///
private bool ANSideADrainOperation(string cmd, object[] objects)
{
if (_currentANACellOperation != ANCellOperation.None)
{
LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} current is {_currentANACellOperation},cannot execute AN Side A Drain");
return false;
}
bool result = true;
CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
if(CheckOtherMetalDeviceDrainStatus(reservoirDevice,"A"))
{
return false;
}
if (reservoirDevice != null && reservoirDevice.ReservoirData.ANADrainPump == 0)
{
result = reservoirDevice.AnADrainPumpOn("", null);
}
if (result)
{
result = AnSideADrainOn("", null);
if (result)
{
ANACellFlow.Status = ANCellStatus.Emptying.ToString();
_anATotalFillFlow = 0;
_anADrainTime=DateTime.Now;
}
else
{
reservoirDevice.AnADrainPump(0);
}
}
return result;
}
///
/// 其他Metal Drain是否打开
///
///
///
///
private bool CheckOtherMetalDeviceDrainStatus(CompactMembranReservoirDevice reservoirDevice,string side)
{
if(reservoirDevice==null)
{
return false;
}
ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(reservoirDevice.Module);
if(reservoirItem!=null)
{
foreach(var item in reservoirItem.MetalCells)
{
if(item.ModuleName!=Module)
{
CompactMembranMetalDevice metalDevice = DEVICE.GetDevice(item.ModuleName);
if(metalDevice!=null)
{
if(side=="A"&&metalDevice.MetalDeviceData.ANAPoutEnable)
{
LOG.WriteLog(eEvent.ERR_METAL, Module, $"{item.ModuleName} A Drain is on");
return true;
}
if (side == "B" && metalDevice.MetalDeviceData.ANBPoutEnable)
{
LOG.WriteLog(eEvent.ERR_METAL, Module, $"{item.ModuleName} B Drain is on");
return true;
}
}
}
}
}
return false;
}
///
/// 阳极A面Drain
///
///
///
///
private bool ANSideBDrainOperation(string cmd, object[] objects)
{
if (_currentANBCellOperation != ANCellOperation.None)
{
LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} current is {_currentANBCellOperation},cannot execute AN Side A Drain");
return false;
}
bool result = true;
CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
if (CheckOtherMetalDeviceDrainStatus(reservoirDevice, "B"))
{
return false;
}
if(reservoirDevice!=null&&reservoirDevice.ReservoirData.ANBDrainPump==0)
{
result= reservoirDevice.AnBDrainPumpOn("", null);
}
if (result)
{
result = AnSideBDrainOn("", null);
if (result)
{
ANBCellFlow.Status = ANCellStatus.Emptying.ToString();
_anBTotalFillFlow = 0;
_anBDrainTime=DateTime.Now;
}
else
{
reservoirDevice.AnBDrainPump(0);
}
}
return result;
}
#endregion
#region AN Stop
///
/// 阳面A停止
///
///
///
///
private bool ANSideAStopOperation(string cmd, object[] objs)
{
CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
if (reservoirDevice != null)
{
if (reservoirDevice.ReservoirData.ANPump != 0)
{
reservoirDevice.AnPump(0);
}
if (reservoirDevice.ReservoirData.ANADrainPump != 0)
{
reservoirDevice.AnADrainPump(0);
}
}
if (MetalDeviceData.ANAPinEnable)
{
AnSideAFillOff("", null);
}
if (MetalDeviceData.ANAPoutEnable)
{
AnSideADrainOff("", null);
}
ANACellFlow.Status = ANCellStatus.Unknow.ToString();
_anATotalFillFlow = 0;
return true;
}
///
/// 阳面A停止
///
///
///
///
private bool ANSideBStopOperation(string cmd, object[] objs)
{
CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
if (reservoirDevice != null)
{
if (reservoirDevice.ReservoirData.ANPump != 0)
{
reservoirDevice.AnPump(0);
}
if(reservoirDevice.ReservoirData.ANBDrainPump!=0)
{
reservoirDevice.AnBDrainPump(0);
}
}
if(MetalDeviceData.ANBPinEnable)
{
AnSideBFillOff("", null);
}
if(MetalDeviceData.ANBPoutEnable)
{
AnSideBDrainOff("", null);
}
ANBCellFlow.Status = ANCellStatus.Unknow.ToString();
_anBTotalFillFlow = 0;
return true;
}
#endregion
#region Timer定时器
///
/// 定时器
///
///
public override bool OnTimer(int interval)
{
if (_currentANACellOperation == ANCellOperation.Fill)
{
SideFillRoutineMonitor(_anANACellFillRoutine, "A", ANACellFlow, ref _currentANACellOperation);
}
if (_currentANBCellOperation == ANCellOperation.Fill)
{
SideFillRoutineMonitor(_anANBCellFillRoutine, "B", ANBCellFlow, ref _currentANBCellOperation);
}
//正在Filing
if (ANACellFlow.Status == ANCellStatus.Filling.ToString())
{
JudgeFillFull(ANACellFlow,interval,ref _anATotalFillFlow);
}
if (ANBCellFlow.Status == ANCellStatus.Filling.ToString())
{
JudgeFillFull(ANBCellFlow,interval,ref _anBTotalFillFlow);
}
if (ANACellFlow.Status == ANCellStatus.Emptying.ToString())
{
JudgeDrainEmpty("A");
}
if (ANBCellFlow.Status == ANCellStatus.Emptying.ToString())
{
JudgeDrainEmpty("B");
}
return true;
}
///
/// 单面Fill Routine监控
///
///
///
///
private void SideFillRoutineMonitor(IRoutine routine, string side,CounterFlowData counterFlowData, ref ANCellOperation operation)
{
RState state = routine.Monitor();
if (state == RState.Failed || state == RState.Timeout)
{
CloseReservoirPumpAndMetalFill(side);
operation = ANCellOperation.None;
}
else if (state == RState.End)
{
counterFlowData.Status = ANCellStatus.Filling.ToString();
operation = ANCellOperation.None;
}
}
///
/// 判定是否fill Full
///
private void JudgeFillFull(CounterFlowData counterFlowData,int interval,ref double totalFillFlow)
{
double anodeFillVolume = SC.GetValue($"Metal.AnodeFillVolume");
totalFillFlow += counterFlowData.CounterValue / 60 * ((double)interval / 1000);
if (totalFillFlow >= anodeFillVolume)
{
counterFlowData.Status = "Full";
}
}
///
/// 判定是否Drain Empty
///
///
private void JudgeDrainEmpty(string side)
{
if (side == "A")
{
JudgeSideADrain(ANACellFlow, _anADrainTime);
if(ANACellFlow.Status==ANCellStatus.Empty.ToString())
{
CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
if (reservoirDevice != null)
{
reservoirDevice.AnADrainPump(0);
}
AnSideADrainOff("", null);
}
}
else
{
JudgeSideADrain(ANBCellFlow, _anBDrainTime);
if (ANBCellFlow.Status == ANCellStatus.Empty.ToString())
{
CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
if (reservoirDevice != null)
{
reservoirDevice.AnBDrainPump(0);
}
AnSideBDrainOff("", null);
}
}
}
///
/// 判定单面Drain的情况
///
///
///
private void JudgeSideADrain(CounterFlowData counterFlowData, DateTime drainDateTime)
{
double anodeDrainTime = SC.GetValue("Metal.AnodeDrainTime");
if (DateTime.Now.Subtract(drainDateTime).TotalMilliseconds >= anodeDrainTime * 1000)
{
counterFlowData.Status = ANCellStatus.Empty.ToString();
}
}
///
/// 关闭Reservoir Pump和Metal Fill
///
private void CloseReservoirPumpAndMetalFill(string side)
{
CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
if (reservoirDevice != null)
{
reservoirDevice.AnPump(0);
if (side == "A")
{
AnSideAFillOff("", null);
}
else
{
AnSideBDrainOff("", null);
}
}
}
///
/// 获取Reservoir设备
///
///
private CompactMembranReservoirDevice GetReservoirDevice()
{
string reservoir = ReservoirItemManager.Instance.GetReservoirByMetal(Module);
return DEVICE.GetDevice(reservoir);
}
#endregion
///
/// Enter Disabled Operation
///
///
public void EnterDisabledOperation()
{
ANSideAStopOperation("", null);
ANSideBStopOperation("", null);
if (_metalDeviceData.CellFlowValve)
{
CellFlowValveOff("", null);
}
}
#region 设备接口
public override void Monitor()
{
}
public override void Reset()
{
}
public override void Terminate()
{
}
#endregion
}
}