using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.TwinCat;
using CyberX8_Core;
using System;
using System.Collections.Generic;
using Aitex.Core.Util;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.PUF
{
public class PufVacuum : BaseDevice, IDevice
{
#region 常量
private const string CHUCKA_VAC = "ChuckAVac";
private const string CHUCKB_VAC = "ChuckBVac";
private const string CHUCKA_RELEASE = "ChuckARelease";
private const string CHUCKB_RELEASE = "ChuckBRelease";
private const string CHUCKA_VACUUM_STATUS = "ChuckAVacuumStatus";
private const string CHUCKB_VACUUM_STATUS = "ChuckBVacuumStaus";
private const string CHUCKA = "ChuckA";
private const string CHUCKB = "ChuckB";
private const string VACUUM_LEAK = "VacuumLeak";
#endregion
#region 内部变量
private bool _chuckAWaferPresent;
private bool _chuckBWaferPresent;
private bool _chuckAReleased;
private bool _chuckBReleased;
private double _chuckAValue;
private double _chuckBValue;
private double _chuckVacuumCloseLimit;
private double _chuckVacuumOpenLimit;
private double _chuckVacuumWaferAbsent;
private double _chuckVacuumWaferPresent;
private string _chuckAVacuumStatus = "";
private string _chuckBVacuumStatus = "";
private DateTime _leakADateTime = DateTime.Now;
private System.Timers.Timer _leakATimer;
private DateTime _leakBDateTime = DateTime.Now;
private System.Timers.Timer _leakBTimer;
///
/// 变量是否初始化字典
///
private Dictionary _variableInitializeDic = new Dictionary();
///
/// 首次加载数据成功
///
private bool _firstLoad = false;
#endregion
#region 属性
///
/// ChuckA Wafer Present状态
///
public bool ChuckAWaferPresent
{
get { return _chuckAWaferPresent; }
set { _chuckAWaferPresent = value; }
}
///
/// ChuckB Wafer Present
///
public bool ChuckBWaferPresent
{
get { return _chuckBWaferPresent; }
set { _chuckBWaferPresent = value; }
}
///
/// Side A Vacuum状态
///
public string ChuckAVacuumStatus
{
get { return _chuckAVacuumStatus; }
}
///
/// Side B Vacuum状态
///
public string ChuckBVacuumStatus
{
get { return _chuckBVacuumStatus; }
}
///
/// Side B 是否关闭真空
///
public bool ISChuckBReleased
{
get { return _chuckBReleased; }
}
///
/// Side A是否关闭真空
///
public bool IsChuckAReleased
{
get { return _chuckAReleased; }
}
///
/// 所有io变量是否初始化
///
public bool IOInitialized { get { return AllIoVariableInitialized(); } }
#endregion
#region 事件
public event EventHandler OnVacuumLeak;
public event EventHandler OnVacuumResume;
#endregion
///
/// 构造函数
///
///
public PufVacuum(string moduleName):base(moduleName,"Vacuum","Vacuum","Vacuum")
{
LoadConfigParameter();
_leakATimer = new System.Timers.Timer(500);
_leakATimer.Elapsed += LeakATimer_Elapsed;
_leakBTimer=new System.Timers.Timer(500);
_leakBTimer.Elapsed += LeakBTimer_Elapsed;
}
///
/// 加载配置参数
///
private void LoadConfigParameter()
{
_chuckVacuumCloseLimit = SC.GetValue($"{Module}.ChuckVacuumCloseLimit");
_chuckVacuumOpenLimit = SC.GetValue($"{Module}.ChuckVacuumOpenLimit");
_chuckVacuumWaferAbsent = SC.GetValue($"{Module}.ChuckVacuumWaferAbsent");
_chuckVacuumWaferPresent = SC.GetValue($"{Module}.ChuckVacuumWaferPresent");
}
///
/// Leak定时器
///
///
///
///
private void LeakATimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if(DateTime.Now.Subtract(_leakADateTime).TotalSeconds>=2)
{
_chuckAVacuumStatus = VACUUM_LEAK;
LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckA vacuum leak");
if (OnVacuumLeak != null)
{
OnVacuumLeak(this, Module);
}
_leakATimer.Stop();
}
}
///
/// LeakB定时器
///
///
///
///
private void LeakBTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (DateTime.Now.Subtract(_leakBDateTime).TotalSeconds >= 2)
{
_chuckBVacuumStatus = VACUUM_LEAK;
LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckB vacuum leak");
if (OnVacuumLeak != null)
{
OnVacuumLeak(this, Module);
}
_leakBTimer.Stop();
}
}
///
/// 初始化
///
///
public bool Initialize()
{
SubscribeData();
InitializeOperation();
SubscribeValueAction();
return true;
}
///
/// 初始化操作
///
private void InitializeOperation()
{
OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumAOn}", VaccumAOnOperation);
OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumBOn}", VaccumBOnOperation);
}
///
/// 订阅变量数值发生变化
///
private void SubscribeValueAction()
{
BeckhoffIoSubscribeUpdateVariable(CHUCKA_VAC);
BeckhoffIoSubscribeUpdateVariable(CHUCKB_VAC);
BeckhoffIoSubscribeUpdateVariable(CHUCKA_RELEASE);
BeckhoffIoSubscribeUpdateVariable(CHUCKB_RELEASE);
}
///
/// 订阅IO变量
///
///
private void BeckhoffIoSubscribeUpdateVariable(string variable)
{
_variableInitializeDic[variable] = false;
IOModuleManager.Instance.SubscribeModuleVariable($"{Module}", variable, UpdateVariableValue);
}
///
/// 是否所有IO变量初始化完成
///
///
private bool AllIoVariableInitialized()
{
foreach (string item in _variableInitializeDic.Keys)
{
if (!_variableInitializeDic[item])
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{item} is not initialized");
return false;
}
}
return true;
}
///
/// 订阅数据
///
private void SubscribeData()
{
DATA.Subscribe($"{Module}.{CHUCKA_RELEASE}", () => _chuckAReleased,SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.{CHUCKB_RELEASE}", () => _chuckBReleased, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.{CHUCKA_VAC}", () => _chuckAValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.{CHUCKB_VAC}", () => _chuckBValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.{CHUCKA_VACUUM_STATUS}", () => _chuckAVacuumStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.{CHUCKB_VACUUM_STATUS}", () => _chuckBVacuumStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB);
}
/// 更新变量数值
///
///
///
private void UpdateVariableValue(string variable, object value)
{
if(!_firstLoad)
{
_firstLoad = true;
VacuumAOn();
VacuumBOn();
}
if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
{
_variableInitializeDic[variable] = true;
}
if (variable == $"{CHUCKA_RELEASE}")
{
_chuckAReleased = (bool)value;
var item = JudgeWaferPresent(_chuckAValue, _chuckAReleased, CHUCKA);
_chuckAWaferPresent = item.Item1;
_chuckAVacuumStatus = item.Item2;
if (_chuckAVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK)
{
_leakADateTime = DateTime.Now;
_leakATimer.Start();
}
else if (item.Item2 != VACUUM_LEAK)
{
_leakBTimer.Stop();
}
}
else if(variable==$"{CHUCKB_RELEASE}")
{
_chuckBReleased=(bool)value;
var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB);
if (_chuckBVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK)
{
_leakBDateTime = DateTime.Now;
_leakBTimer.Start();
}
else if (item.Item2 != VACUUM_LEAK)
{
_leakBTimer.Stop();
}
_chuckBWaferPresent = item.Item1;
_chuckBVacuumStatus = item.Item2;
}
else if(variable==$"{CHUCKA_VAC}")
{
_chuckAValue = (double)value;
var item = JudgeWaferPresent(_chuckAValue, _chuckAReleased, CHUCKA);
if(_chuckAVacuumStatus!= VACUUM_LEAK&&item.Item2== VACUUM_LEAK)
{
_leakADateTime = DateTime.Now;
_leakATimer.Start();
}
else if (item.Item2 != VACUUM_LEAK)
{
_leakATimer.Stop();
}
_chuckAWaferPresent =item.Item1;
_chuckAVacuumStatus=item.Item2;
}
else if(variable==$"{CHUCKB_VAC}")
{
_chuckBValue=(double)value;
var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB);
if (_chuckBVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK)
{
_leakBDateTime = DateTime.Now;
_leakBTimer.Start();
}
else if(item.Item2!=VACUUM_LEAK)
{
_leakBTimer.Stop();
}
_chuckBWaferPresent = item.Item1;
_chuckBVacuumStatus = item.Item2;
}
}
///
/// 判定Wafer Present
///
///
///
///
private (bool,string) JudgeWaferPresent(double chuckValue,bool chuckRelease,string chuck)
{
LoadConfigParameter();
if (!chuckRelease)
{
if(chuckValue < _chuckVacuumWaferPresent)
{
ResumeVacuum();
return (true,"WaferPresent");
}
else if( chuckValue > _chuckVacuumWaferAbsent)
{
ResumeVacuum();
return (false,"WaferAbsent");
}
else
{
return (false,"InvalidData");
}
}
else
{
if(chuckValue<=_chuckVacuumCloseLimit)
{
return (false,"VacuumLeak");
}
else if(chuckValue<=_chuckVacuumOpenLimit)
{
ResumeVacuum();
return (false, "VacuumOff");
}
else
{
ResumeVacuum();
return (false, "");
}
}
}
///
/// 故障恢复
///
private void ResumeVacuum()
{
if (OnVacuumResume != null)
{
OnVacuumResume(this, Module);
}
}
///
/// VacuumAOn操作
///
///
///
///
private bool VaccumAOnOperation(string cmd, object[] args)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");
if(!string.IsNullOrEmpty(ioName))
{
IOModuleManager.Instance.WriteIoValue(ioName, args[1]);
}
return true;
}
///
/// VacuumBOn操作
///
///
///
///
private bool VaccumBOnOperation(string cmd, object[] args)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");
if (!string.IsNullOrEmpty(ioName))
{
IOModuleManager.Instance.WriteIoValue(ioName, args[1]);
}
return true;
}
///
/// VacuumA关闭
///
public bool VacuumAOff()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");
if (!string.IsNullOrEmpty(ioName))
{
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
return false;
}
///
/// VacuumB关闭
///
public bool VacuumBOff()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");
if (!string.IsNullOrEmpty(ioName))
{
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
return false;
}
///
/// VacuumA打开
///
public bool VacuumAOn()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");
if (!string.IsNullOrEmpty(ioName))
{
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
return false;
}
///
/// VacuumB打开
///
public bool VacuumBOn()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");
if (!string.IsNullOrEmpty(ioName))
{
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
return false;
}
///
/// 监控
///
public void Monitor()
{
}
///
/// 重置
///
public void Reset()
{
}
///
/// 中止
///
public void Terminate()
{
}
}
}