using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.Beckhoff.AxisProvider;
using MECF.Framework.Common.Persistent.Reservoirs;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.ToolLayout;
using MECF.Framework.Common.Utilities;
using PunkHPX8_Core;
using PunkHPX8_RT.Devices.AXIS;
using PunkHPX8_RT.Devices.PlatingCell;
using PunkHPX8_RT.Devices.Reservoir;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PunkHPX8_RT.Modules.PlatingCell
{
public class PlatingCellCCRRoutine : RoutineBase, IRoutine
{
private enum CCRStep
{
CSRStart,
CSRClamshellClose,
CSROpenRinseValve,
CSRStartRotation,
CSRRinseMonitor,
CSRCloseRinseValve,
CSRSetDryRotationSpeed,
CSRCheckRotationStoped,
CCR1Start,
CCR1ClamshellOpen,
OpenCCR1Valve,
CCR1StartRotation,
CCR1CCRMonitor,
CCR1CloseCCRValve,
CCR1SetDryRotationSpeed,
CCR1CheckRotationStoped,
CCR2Start,
CCR2ClamshellOpen,
OpenCCR2Valve,
CCR2StartRotation,
CCR2CCRMonitor,
CCR2CloseCCRValve,
CCR2SetDryRotationSpeed,
CCR2CheckRotationStoped,
End
}
#region 常量
///
/// ROTATION电机转速比例
///
private const int SPEED_RATIO = 1;
#endregion
#region 内部变量
///
/// 设备对象
///
private PlatingCellDevice _platingCellDevice;
///
/// Rotation axis
///
private JetAxisBase _rotationAxis;
///
/// SRD rotation Provider对象
///
private BeckhoffProviderAxis _rotationProviderAxis;
///
/// startRotationTime,用于控制速度改变
///
private int _startRotationTime;
///
/// 当前执行到哪一步的显示
///
private string _currentStep;
///
/// 当前执行到哪一步的剩余时间
///
private double _timeRemain;
private bool _cSREnable;
private bool _cCR1Enable;
private bool _cCR2Enable;
private int _cSRRinseSpeed;
private int _cSRDrySpeed;
private double _cSRRinseTime;
private double _cSRDryTime;
private int _cCR1RinseSpeed;
private int _cCR1DrySpeed;
private double _cCR1RinseTime;
private double _cCR1DryTime;
private int _cCR2RinseSpeed;
private int _cCR2DrySpeed;
private double _cCR2RinseTime;
private double _cCR2DryTime;
///
/// CCR小步骤的启动时间
///
private DateTime _cSRStartTime;
private DateTime _cCR1StartTime;
private DateTime _cCR2StartTime;
#endregion
///
/// 构造函数
///
///
public PlatingCellCCRRoutine(string module) : base(module)
{
}
///
/// 中止
///
public void Abort()
{
Runner.Stop("CCR Manual Abort");
}
///
/// 监控
///
///
public RState Monitor()
{
CheckCurrentStepAndTimeRemain();
_platingCellDevice.UpdateStatus(_currentStep);
Runner.RunIf(CCRStep.CSRStart, _cSREnable , () => RecordCCRStepStartTime(out _cSRStartTime), _delay_1ms)
.RunIf(CCRStep.CSRClamshellClose, _cSREnable , () => _platingCellDevice.ClamShellClose(), CheckClamShellClosed, _delay_1ms)
.RunIf(CCRStep.CSROpenRinseValve, _cSREnable, OpenRinseValve, _delay_1ms)
.RunIf(CCRStep.CSRStartRotation, _cSREnable, () => CSRStartRotation(), _delay_1ms)
.WaitIf(CCRStep.CSRRinseMonitor, _cSREnable, MonitorCSRRinseRotationEndStatus)
.RunIf(CCRStep.CSRCloseRinseValve, _cSREnable, CloseRinseValve, _delay_1ms)
.RunIf(CCRStep.CSRSetDryRotationSpeed, _cSREnable, () => ChangeRotationSpeed(_cSRDrySpeed), _delay_1ms)
.WaitWithStopConditionIf(CCRStep.CSRCheckRotationStoped, _cSREnable, CheckRotationEndStatus, CheckRotationStopStatus)
.RunIf(CCRStep.CCR1Start, _cCR1Enable, () => RecordCCRStepStartTime(out _cCR1StartTime), _delay_1ms)
.RunIf(CCRStep.CCR1ClamshellOpen, _cCR1Enable, () => _platingCellDevice.ClamShellOpen(), CheckClamShellOpen, _delay_1ms)
.RunIf(CCRStep.OpenCCR1Valve, _cCR1Enable, OpenCCRValve, _delay_1ms)
.RunIf(CCRStep.CCR1StartRotation, _cCR1Enable, () => CCR1StartRotation(), _delay_1ms)
.WaitIf(CCRStep.CCR1CCRMonitor, _cCR1Enable, MonitorCCR1RotationEndStatus)
.RunIf(CCRStep.CCR1CloseCCRValve, _cCR1Enable, CloseCCRValve, _delay_1ms)
.RunIf(CCRStep.CCR1SetDryRotationSpeed, _cCR1Enable, () => ChangeRotationSpeed(_cCR1DrySpeed), _delay_1ms)
.WaitWithStopConditionIf(CCRStep.CCR1CheckRotationStoped, _cCR1Enable, CheckRotationEndStatus, CheckRotationStopStatus)
.RunIf(CCRStep.CCR2Start, _cCR2Enable, () => RecordCCRStepStartTime(out _cCR2StartTime), _delay_1ms)
.RunIf(CCRStep.CCR2ClamshellOpen, _cCR2Enable, () => _platingCellDevice.ClamShellOpen(), CheckClamShellOpen, _delay_1ms)
.RunIf(CCRStep.OpenCCR2Valve, _cCR2Enable, OpenCCRValve, _delay_1ms)
.RunIf(CCRStep.CCR2StartRotation, _cCR2Enable, () => CCR2StartRotation(), _delay_1ms)
.WaitIf(CCRStep.CCR2CCRMonitor, _cCR2Enable, MonitorCCR2RotationEndStatus)
.RunIf(CCRStep.CCR2CloseCCRValve, _cCR2Enable, CloseCCRValve, _delay_1ms)
.RunIf(CCRStep.CCR2SetDryRotationSpeed, _cCR2Enable, () => ChangeRotationSpeed(_cCR2DrySpeed), _delay_1ms)
.WaitWithStopConditionIf(CCRStep.CCR2CheckRotationStoped, _cCR2Enable, CheckRotationEndStatus, CheckRotationStopStatus)
.End(CCRStep.End, NullFun, _delay_1ms);
return Runner.Status;
}
///
/// 记录ccr step 起始时间
///
///
///
private bool RecordCCRStepStartTime(out DateTime dateTime)
{
dateTime = DateTime.Now;
return true;
}
///
/// 判断当前处于ccr的哪一步
///
private void CheckCurrentStepAndTimeRemain()
{
string currentStep = Runner.CurrentStep.ToString();
if (currentStep.Contains("CSR"))
{
_currentStep ="CSR Rinse/Dry";
_timeRemain = _cSRRinseTime + _cSRDryTime - (DateTime.Now - _cSRStartTime).TotalSeconds > 0 ? _cSRRinseTime + _cSRDryTime - (DateTime.Now - _cSRStartTime).TotalSeconds : 0;
}
else if (currentStep.Contains("CCR1"))
{
_currentStep = "CCR Cycle1 Rinse/Dry";
_timeRemain = _cCR1RinseTime + _cCR1DryTime - (DateTime.Now - _cCR1StartTime).TotalSeconds > 0 ? _cCR1RinseTime + _cCR1DryTime - (DateTime.Now - _cCR1StartTime).TotalSeconds : 0;
}
else if (currentStep.Contains("CCR2"))
{
_currentStep = "CCR Cycle2 Rinse/Dry";
_timeRemain = _cCR2RinseTime + _cCR2DryTime - (DateTime.Now - _cCR2StartTime).TotalSeconds > 0 ? _cCR2RinseTime + _cCR2DryTime - (DateTime.Now - _cCR2StartTime).TotalSeconds : 0;
}
else
{
_currentStep = "End";
_timeRemain = 0;
}
_platingCellDevice.UpdateCCRTimeRemain(_timeRemain);
}
///
/// 打开CCR valve
///
///
private bool OpenCCRValve()
{
return _platingCellDevice.CCREnableAction();
}
///
/// 关闭CCR valve
///
///
private bool CloseCCRValve()
{
return _platingCellDevice.CCRDisableAction();
}
///
/// 打开Rinse valve
///
///
private bool OpenRinseValve()
{
return _platingCellDevice.RinseEnableAction();
}
///
/// 关闭Rinse valve
///
///
private bool CloseRinseValve()
{
return _platingCellDevice.RinseDisableAction();
}
///
/// 检查ClamShell是否closed
///
///
private bool CheckClamShellClosed()
{
return _platingCellDevice.PlatingCellDeviceData.ClamShellClose;
}
///
/// 检查ClamShell是否Open
///
///
private bool CheckClamShellOpen()
{
return !_platingCellDevice.PlatingCellDeviceData.ClamShellClose;
}
///
/// 检验Rotation是否停止
///
///
private bool CheckRotationEndStatus()
{
if (!_rotationAxis.IsRun && _rotationAxis.Status == RState.End)
{
return true;
}
return false;
}
///
/// 检验Rotation停止状态
///
///
private bool CheckRotationStopStatus()
{
if (_rotationAxis.Status == RState.Failed || _rotationAxis.Status == RState.Timeout)
{
NotifyError(eEvent.ERR_PLATINGCELL, $"{Module}.Rotation is failed", 0);
return true;
}
return false;
}
///
/// CSR阶段rotation开始旋转
///
///
///
private bool CSRStartRotation()
{
double _scale = _rotationProviderAxis.ScaleFactor;
//rinse 目标位置
double rinsePosition = _cSRRinseTime * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cSRRinseSpeed);
//dry目标位置
double dryPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cSRDrySpeed) * _cSRDryTime;
int targetPosition = (int)Math.Round((rinsePosition + dryPosition ) * _scale, 0);
int rotationSpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cSRRinseSpeed), 0);
//启动先用rinse的speed,时间到了转成用dry的speed
bool result = _rotationAxis.ProfilePosition(targetPosition, rotationSpeed * SPEED_RATIO, 0, 0);
if (!result)
{
NotifyError(eEvent.ERR_PLATINGCELL, "Start Rotation is failed", 0);
return false;
}
LOG.WriteLog(eEvent.INFO_PLATINGCELL, Module, "Start CSR Step Rinse Rotation");
//Rinse开始时间
_startRotationTime = Environment.TickCount;
return true;
}
///
/// WaterFlow End Monitor
///
///
private bool MonitorCSRRinseRotationEndStatus()
{
int ticks = Environment.TickCount - _startRotationTime;
if (ticks >= _cSRRinseTime * 1000)
{
return true;
}
return false;
}
///
/// CCR1阶段rotation开始旋转
///
///
///
private bool CCR1StartRotation()
{
double _scale = _rotationProviderAxis.ScaleFactor;
//rinse 目标位置
double rinsePosition = _cCR1RinseTime * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR1RinseSpeed);
//dry目标位置
double dryPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR1DrySpeed) * _cCR1DryTime;
int targetPosition = (int)Math.Round((rinsePosition + dryPosition) * _scale, 0);
int rotationSpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR1RinseSpeed), 0);
//启动先用rinse的speed,时间到了转成用dry的speed
bool result = _rotationAxis.ProfilePosition(targetPosition, rotationSpeed * SPEED_RATIO, 0, 0);
if (!result)
{
NotifyError(eEvent.ERR_PLATINGCELL, "Start Rotation is failed", 0);
return false;
}
LOG.WriteLog(eEvent.INFO_PLATINGCELL, Module, "Start CCR1 Step Rinse Rotation");
//Rinse开始时间
_startRotationTime = Environment.TickCount;
return true;
}
///
/// CCR1 WaterFlow End Monitor
///
///
private bool MonitorCCR1RotationEndStatus()
{
int ticks = Environment.TickCount - _startRotationTime;
if (ticks >= _cCR1RinseTime * 1000)
{
return true;
}
return false;
}
///
/// CCR2阶段rotation开始旋转
///
///
///
private bool CCR2StartRotation()
{
double _scale = _rotationProviderAxis.ScaleFactor;
//rinse 目标位置
double rinsePosition = _cCR2RinseTime * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR2RinseSpeed);
//dry目标位置
double dryPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR2DrySpeed) * _cCR2DryTime;
int targetPosition = (int)Math.Round((rinsePosition + dryPosition) * _scale, 0);
int rotationSpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR2RinseSpeed), 0);
//启动先用rinse的speed,时间到了转成用dry的speed
bool result = _rotationAxis.ProfilePosition(targetPosition, rotationSpeed * SPEED_RATIO, 0, 0);
if (!result)
{
NotifyError(eEvent.ERR_PLATINGCELL, "Start Rotation is failed", 0);
return false;
}
LOG.WriteLog(eEvent.INFO_PLATINGCELL, Module, "Start CCR2 Step Rinse Rotation");
//Rinse开始时间
_startRotationTime = Environment.TickCount;
return true;
}
///
/// CCR2 WaterFlow End Monitor
///
///
private bool MonitorCCR2RotationEndStatus()
{
int ticks = Environment.TickCount - _startRotationTime;
if (ticks >= _cCR2RinseTime * 1000)
{
return true;
}
return false;
}
///
/// 改变速度
///
///
///
private bool ChangeRotationSpeed(int speed)
{
double _scale = _rotationProviderAxis.ScaleFactor;
speed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(speed), 0);
return _rotationAxis.ChangeSpeed(speed);
}
///
/// 启动
///
///
///
public RState Start(params object[] objs)
{
_platingCellDevice = DEVICE.GetDevice(Module);
_cSREnable = SC.GetValue("PlatingCell.CSR.CSREnable");
_cCR1Enable = SC.GetValue("PlatingCell.CCR1.CCR1Enable");
_cCR2Enable = SC.GetValue("PlatingCell.CCR2.CCR2Enable");
_cSRRinseSpeed = SC.GetValue("PlatingCell.CSR.RinseSpeed");
_cSRDrySpeed = SC.GetValue("PlatingCell.CSR.DrySpeed");
_cSRRinseTime = SC.GetValue("PlatingCell.CSR.RinseTime");
_cSRDryTime = SC.GetValue("PlatingCell.CSR.DryTime");
_cCR1RinseSpeed = SC.GetValue("PlatingCell.CCR1.RinseSpeed");
_cCR1DrySpeed = SC.GetValue("PlatingCell.CCR1.DrySpeed");
_cCR1RinseTime = SC.GetValue("PlatingCell.CCR1.RinseTime");
_cCR1DryTime = SC.GetValue("PlatingCell.CCR1.DryTime");
_cCR2RinseSpeed = SC.GetValue("PlatingCell.CCR2.RinseSpeed");
_cCR2DrySpeed = SC.GetValue("PlatingCell.CCR2.DrySpeed");
_cCR2RinseTime = SC.GetValue("PlatingCell.CCR2.RinseTime");
_cCR2DryTime = SC.GetValue("PlatingCell.CCR2.DryTime");
_rotationAxis = DEVICE.GetDevice($"{Module}.Rotation");
_rotationProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{Module}.Rotation");
if (_rotationProviderAxis == null)
{
NotifyError(eEvent.ERR_SRD, $"{Module}.Rotation Provider is not exist", 0);
return RState.Failed;
}
return Runner.Start(Module, "Start Reservoir Initialize");
}
}
}