using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using CyberX8_Core;
using CyberX8_RT.Devices.Dose;
using CyberX8_RT.Modules;
using CyberX8_RT.Modules.Reservoir;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.IOCore;
using MECF.Framework.Common.Persistent.Reservoirs;
using MECF.Framework.Common.ProcessCell;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.ToolLayout;
using MECF.Framework.Common.TwinCat;
using System;
using System.Reflection;
using System.Windows;
using static CyberX8_RT.Devices.Reservoir.DosingSystemHelper;
namespace CyberX8_RT.Devices.Reservoir
{
public class CrossDoseHelper
{
#region 常量
public enum CrossDoseOperation
{
None,
ManualDosing,
AutoDosing,
}
///
/// 补液体积(固定10mL)
///
private const double DOSING_VOLUME = 10;
#endregion
#region 内部变量
///
/// ModuleName
///
private string _moduleName;
///
/// ANTransferPumpOnRoutine
///
private ANTransferPumpOnRoutine _anTransferPumpOnRoutine;
///
/// CrossDoseResetRoutine
///
private CrossDoseResetRoutine _crossDoseResetRoutine;
///
/// ReservoirsPersistentValue
///
private ReservoirsPersistentValue _persistentValue;
///
/// CompactMembranReservoirDevice
///
private CompactMembranReservoirDevice _cmReservoirDevice;
///
/// CrossDoseVolume
///
private double _crossDoseVolume;
///
/// 当前CrossDose模式
///
private CrossDoseOperation _currentCrossDoseOperation;
///
/// Reservoir Usage
///
private ReservoirUsage _reservoirUsage;
private bool _flag;
#endregion
#region 属性
///
/// 当前Dose模式
///
public CrossDoseOperation CurrentDoseOperation{ get {return _currentCrossDoseOperation; } }
///
/// CrossDose当前的RState
///
public RState CrossDoseState { get { return _anTransferPumpOnRoutine.CurrentState; } }
///
/// ResetRoutine当前的RState
///
public RState ResetState { get { return _crossDoseResetRoutine.CurrentState; } }
#endregion
public CrossDoseHelper(string moduleName)
{
_moduleName = moduleName;
_anTransferPumpOnRoutine = new ANTransferPumpOnRoutine(_moduleName);
_crossDoseResetRoutine = new CrossDoseResetRoutine(_moduleName);
_persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(_moduleName);
_cmReservoirDevice = DEVICE.GetDevice($"{_moduleName}");
_currentCrossDoseOperation = CrossDoseOperation.None;
}
#region Operation
///
/// 开始Dosing
///
///
public bool StartDosing(double crossDoseVolume)
{
_crossDoseVolume = crossDoseVolume;
return _anTransferPumpOnRoutine.Start(crossDoseVolume) == RState.Running;
}
///
/// 停止Dosing
///
///
public bool HaltDosing()
{
_anTransferPumpOnRoutine.Abort();
EnterError();
return true;
}
///
/// CrossDosing监控
///
public void CrossDoseStatusMonitor()
{
RState result = _anTransferPumpOnRoutine.Monitor();
//监控Pump
if (result == RState.Failed || result == RState.Timeout)
{
EnterError();
LOG.WriteLog(eEvent.WARN_RESERVOIR, _moduleName, "Open AN Transfer Pump failed");
_cmReservoirDevice.InitializeCrossDose(false);
}
}
///
/// 自动CrossDose监控
///
public void AutoCrossDoseMonitor(bool isInitialized)
{
if (!isInitialized)
{
if (!_flag)
{
LOG.WriteLog(eEvent.WARN_RESERVOIR, _moduleName, "Please initialize Cross Dose");
_flag = true;
}
return;
}
_flag = false;
if (_cmReservoirDevice.Recipe != null && (_cmReservoirDevice.Recipe.CurrentBased || _cmReservoirDevice.Recipe.TimeBased))
{
//非AutoDosing模式下进入AutoDosing模式,并记录开始数据
if (_currentCrossDoseOperation != CrossDoseOperation.AutoDosing)
{
LOG.WriteLog(eEvent.INFO_RESERVOIR, _moduleName, $"Timing of AutoCrossDose has started now");
RecordStartData();
SetAutoDoseOperation();
}
else
{
//AutoDosing模式下,若上一次Dosing完成则再次记录数据
if (_persistentValue.AutoCrossDoseStartTime == DateTime.MinValue && _persistentValue.AutoCrossDoseStartAmpHour == 0)
{
LOG.WriteLog(eEvent.INFO_RESERVOIR, _moduleName, $"Timing of AutoCrossDose has started again now");
RecordStartData();
}
}
}
else
{
ResetDoseOperation();
}
//AutoDosing监控
if (CrossDoseState != RState.Running && _currentCrossDoseOperation == CrossDoseOperation.AutoDosing && AutoDosingMonitor())
{
StartDosing(DOSING_VOLUME);
}
}
///
/// CrossDoseOperation状态监控
///
public bool CrossDoseOperationMonitor()
{
if (_currentCrossDoseOperation == CrossDoseOperation.ManualDosing && CrossDoseState != RState.Running)
{
_currentCrossDoseOperation = CrossDoseOperation.None;
}
if (_currentCrossDoseOperation == CrossDoseOperation.AutoDosing)
{
_currentCrossDoseOperation = CrossDoseOperation.None;
}
return true;
}
///
/// 自动补液触发时机判断
///
///
private bool AutoDosingMonitor()
{
ResRecipe recipe = _cmReservoirDevice.Recipe;
bool result = false;
double targetVolume = 0;
double currentDosingAmpHour = 0;
_reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName);
//当前电量
if (_reservoirUsage != null) currentDosingAmpHour = _reservoirUsage.TotalUsage;
//累计电量(Ah)
double deltAmpHour = currentDosingAmpHour - _persistentValue.AutoCrossDoseStartAmpHour;
//累计时间(Day)
double deltDay = DateTime.Now.Subtract(_persistentValue.AutoCrossDoseStartTime).TotalDays;
if (recipe.CurrentBased)
{
//基于电量补液
targetVolume = deltAmpHour * recipe.CrossDoseCurrentRate;
_persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
if (targetVolume >= DOSING_VOLUME)
{
result = true;
}
}
else if (recipe.TimeBased)
{
//基于时间则开始补液
targetVolume = deltDay * recipe.CrossDoseTimeRate;
_persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
if (targetVolume >= DOSING_VOLUME)
{
result = true;
}
}
ReservoirsPersistentManager.Instance.UpdatePersistentValue(_moduleName);
return result;
}
///
/// 设置手动Dose模式
///
public void SetManualDoseOperation()
{
_currentCrossDoseOperation = CrossDoseOperation.ManualDosing;
}
///
/// 设置自动Dose模式
///
public void SetAutoDoseOperation()
{
_currentCrossDoseOperation = CrossDoseOperation.AutoDosing;
}
///
/// 重置Dose模式
///
public void ResetDoseOperation()
{
_currentCrossDoseOperation = CrossDoseOperation.None;
}
///
/// EnterError
///
private bool EnterError()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{_moduleName}.TransferPumpExecute");
bool result = IOModuleManager.Instance.WriteIoValue(ioName, false);
if (!result)
{
return false;
}
ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{_moduleName}.TransferPumpEnable");
result = IOModuleManager.Instance.WriteIoValue(ioName, false);
if (!result)
{
return false;
}
if (!_cmReservoirDevice.CrossDoseOff("", null))
{
LOG.WriteLog(eEvent.WARN_RESERVOIR, _moduleName, $"Close CrossDose Valve failed");
return false;
}
return true;
}
///
/// 记录AutoCrossDose开始时的时间和电量
///
private void RecordStartData()
{
_reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName);
_persistentValue.AutoCrossDoseStartTime = DateTime.Now;
if (_reservoirUsage != null) _persistentValue.AutoCrossDoseStartAmpHour = _reservoirUsage.TotalUsage;
ReservoirsPersistentManager.Instance.UpdatePersistentValue(_moduleName);
}
///
/// 设置PumpFactor
///
public void SetPumpfactor(double targetPumpFactor)
{
_persistentValue.CrossDosePumpFactor = targetPumpFactor;
ReservoirsPersistentManager.Instance.UpdatePersistentValue(_moduleName);
}
///
/// Reset Start
///
public bool ResetCrossDose()
{
return _crossDoseResetRoutine.Start() == RState.Running;
}
///
/// Reset Start Monitor
///
///
public bool ResetCrossDoseMonitor()
{
RState result = _crossDoseResetRoutine.Monitor();
if (result == RState.Failed || result == RState.Timeout)
{
LOG.WriteLog(eEvent.WARN_RESERVOIR, _moduleName, "Reset Cross Dose failed");
return false;
}
return result == RState.End;
}
#endregion
}
}