using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.CommonData.Dryer;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Persistent.Dryer;
using MECF.Framework.Common.TwinCat;
using MECF.Framework.Common.Utilities;
using CyberX8_Core;
using CyberX8_RT.Devices.Facilities;
using System.Collections.Generic;
using System.Reflection;
using CyberX8_RT.Modules.Dryer;
using CyberX8_RT.Modules;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.Dryer
{
public class DryerDevice : BaseDevice, IDevice
{
#region 常量
private const string POWER_CONTROL = "PowerControl";
private const string EXHAUST_PRESSURE = "ExhaustPressure";
private const string BLOWER_HIGH = "BlowerHigh";
private const string EXHAUST_LIMIT_DATA = "ExhaustLimitData";
private const string EXHAUST_PRESSURE_VALUE = "ExhaustPressure";
private const string COMMON_DATA = "CommonData";
private const string PERSISTENT_VALUE = "PersistentValue";
#endregion
///
/// Dryer操作枚举
///
private enum DryerCommonOperation
{
None,
ControlPowerOn,
ControlPowerOff,
BlowerHigh,
BlowerLow
}
#region 内部变量
///
/// 公用数据
///
private DryerCommonData _dryerCommonData;
///
/// 状态
///
private RState _status;
///
/// 当前操作
///
private DryerCommonOperation _currentOperation;
///
/// Blower High Routine
///
private DryerBlowerHighRoutine _blowerHighRoutine;
///
/// ByPass
///
private bool _byPass = false;
///
/// Facilities
///
private SystemFacilities _facilities;
///
/// 变量是否初始化字典
///
private Dictionary _variableInitializeDic = new Dictionary();
///
/// 定时器Job
///
PeriodicJob _periodicJob = null;
///
/// Dryer 持久性数值对象
///
private DryerPersistentValue _dryerPersistentValue;
#endregion
#region 属性
///
/// 公用数据对象
///
public DryerCommonData CommonData { get { return _dryerCommonData; } }
///
/// 所有io变量是否初始化
///
public bool IOInitialized { get { return IOVariableDictionaryUtil.AllIoVariableInitialized(eEvent.ERR_DRYER,Module,_variableInitializeDic); } }
///
/// 状态
///
public RState Status { get { return _status; } }
///
/// ByPass
///
public bool Bypass { get { return _byPass; } }
///
/// FacilityCommonLimitData
///
public CommonLimitData FacilityCommonLimitData { get { return _facilities.GetCommonLimitDataByName(EXHAUST_PRESSURE_VALUE); } }
#endregion
///
/// 构造函数
///
///
///
public DryerDevice(string moduleName) : base(moduleName, moduleName,moduleName,moduleName)
{
_periodicJob = new PeriodicJob(100, OnTimer, $"{Module}.OnTimer", true);
_dryerCommonData = new DryerCommonData();
}
///
/// 初始化
///
///
public bool Initialize()
{
InitializeRoutine();
SubscribeData();
SubscribeValueAction();
InitializeOperation();
return true;
}
///
/// 初始化Routine
///
private void InitializeRoutine()
{
_blowerHighRoutine = new DryerBlowerHighRoutine(Module, this);
}
///
/// 订阅数据
///
private void SubscribeData()
{
_dryerPersistentValue = DryerPersistentManager.Instance.GetDryerPersistentValue(Module);
if (_dryerPersistentValue == null)
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, "Persistent Value Object is not exist");
}
DATA.Subscribe($"{Module}.{EXHAUST_LIMIT_DATA}", ()=>GetExhaustLimitData(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.{COMMON_DATA}", () => CommonData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _dryerPersistentValue,SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.ExhaustPressure",()=>CommonData.ExhaustPressure, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PowerControl", () => CommonData.PowerControl, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.BlowerHigh", () => CommonData.BlowerHigh, SubscriptionAttribute.FLAG.IgnoreSaveDB);
}
///
/// 获取Exhaust Limit 数据
///
///
private CommonLimitData GetExhaustLimitData()
{
if (_facilities == null)
{
_facilities = DEVICE.GetDevice("System.Facilities");
}
if (_facilities == null)
{
return null;
}
return _facilities.GetCommonLimitDataByName(EXHAUST_PRESSURE_VALUE);
}
///
/// 订阅变量数值发生变化
///
private void SubscribeValueAction()
{
_variableInitializeDic[POWER_CONTROL] = false;
IOModuleManager.Instance.SubscribeModuleVariable(Module, POWER_CONTROL, UpdateVariableValue);
_variableInitializeDic[BLOWER_HIGH] = false;
IOModuleManager.Instance.SubscribeModuleVariable(Module, BLOWER_HIGH, UpdateVariableValue);
_variableInitializeDic[EXHAUST_PRESSURE] = false;
IOModuleManager.Instance.SubscribeModuleVariable(Module, EXHAUST_PRESSURE, UpdateVariableValue);
}
/// 更新变量数值
///
///
///
private void UpdateVariableValue(string variable, object value)
{
if (!CommonData.IsDataInitialized)
{
CommonData.IsDataInitialized = true;
}
PropertyInfo property = CommonData.GetType().GetProperty(variable);
if (property != null)
{
property.SetValue(CommonData, value);
}
if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
{
_variableInitializeDic[variable] = true;
}
if(variable==BLOWER_HIGH)
{
if (CommonData.BlowerHigh)
{
DryerAutoOff.Instance.Stop();
}
else if(CommonData.PowerControl)
{
DryerAutoOff.Instance.Start();
}
}
else if(variable==POWER_CONTROL)
{
if (CommonData.PowerControl)
{
DryerAutoOff.Instance.Start();
}
else
{
DryerAutoOff.Instance.Stop();
}
}
}
///
/// 初始化操作
///
private void InitializeOperation()
{
OP.Subscribe($"{Module}.PowerControlOn", PowerControlOnAction);
OP.Subscribe($"{Module}.PowerControlOff", PowerControlOffAction);
OP.Subscribe($"{Module}.BlowerHigh",BlowerHighAction);
OP.Subscribe($"{Module}.BlowerLow", BlowerLowOnAction);
OP.Subscribe($"{Module}.ByPass", (cmd, args) => { _byPass = (bool)args[0]; return true; });
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);
}
///
/// 定时器
///
///
private bool OnTimer()
{
if (_status == RState.Running)
{
if (_currentOperation != DryerCommonOperation.None)
{
IRoutine routine = GetCurrentRoutine(_currentOperation);
if (routine != null)
{
CheckRoutineState(routine, _currentOperation);
}
else
{
EndOperation(RState.End);
}
}
}
return true;
}
#region Action
#region Power Control
///
/// Power Control On操作
///
private bool PowerControlOnAction(string cmd, object[] args)
{
return PowerControlOn();
}
///
/// Power Control Off操作
///
private bool PowerControlOffAction(string cmd, object[] args)
{
return PowerControlOff();
}
///
/// Power Control On
///
///
public bool PowerControlOn()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{POWER_CONTROL}");
bool result= IOModuleManager.Instance.WriteIoValue(ioName, true);
if (result)
{
LOG.WriteLog(eEvent.INFO_DRYER, Module, "Power Control On Success");
}
return result;
}
///
/// Power Control Off
///
///
public bool PowerControlOff()
{
//检验任一HVD处于High On状态
if(CheckDryersIsInBlowerHigh())
{
return false;
}
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{POWER_CONTROL}");
bool result = IOModuleManager.Instance.WriteIoValue(ioName, false);
if(result)
{
LOG.WriteLog(eEvent.INFO_DRYER, Module, "Power Control Off Success");
}
return result;
}
///
/// 检验是否Dryers是否有处于BlowerHigh状态
///
///
public bool CheckDryersIsInBlowerHigh(bool error=true)
{
bool dryer1High = CheckDryerModuleIsInBlowerHigh(ModuleName.Dryer1);
eEvent eEvent = eEvent.ERR_DRYER;
if(!error)
{
eEvent = eEvent.INFO_DRYER;
}
if(dryer1High)
{
LOG.WriteLog(eEvent, Module, "Dryer1 is high on");
return true;
}
bool dryer2High = CheckDryerModuleIsInBlowerHigh(ModuleName.Dryer2);
if (dryer2High)
{
LOG.WriteLog(eEvent, Module, "Dryer2 is high on");
return true;
}
bool dryer3High = CheckDryerModuleIsInBlowerHigh(ModuleName.Dryer3);
if (dryer3High)
{
LOG.WriteLog(eEvent, Module, "Dryer3 is high on");
return true;
}
return false;
}
///
/// 检验Dryer模块是否处于Blower High
///
///
///
private bool CheckDryerModuleIsInBlowerHigh(ModuleName moduleName)
{
if (ModuleHelper.IsInstalled(moduleName))
{
DryerDevice dryerDevice1 = DEVICE.GetDevice(moduleName.ToString());
if (dryerDevice1 != null)
{
if (dryerDevice1.CommonData.BlowerHigh)
{
return true;
}
}
}
return false;
}
#endregion
#region Blower High
///
/// Blow High动作
///
///
///
///
public bool BlowerHighAction(string cmd, object[] args)
{
if(JudgeRunningState(DryerCommonOperation.BlowerHigh))
{
return false;
}
if(CheckDryerModulePowerOff(ModuleHelper.Converter(Module)))
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{Module} is Power off");
return false;
}
_currentOperation = DryerCommonOperation.BlowerHigh;
_status = _blowerHighRoutine.Start(_byPass);
return _status == RState.Running;
}
///
/// Blower High On
///
///
public bool BlowerHighOn()
{
if(CheckDryerModulePowerOff(ModuleHelper.Converter(Module)))
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{Module} is Power off");
return false;
}
CommonLimitData commonLimitData = GetExhaustLimitData();
if (commonLimitData.IsWarning || commonLimitData.IsError)
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, "Exhuast Pressure is Abnormal");
return false;
}
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{BLOWER_HIGH}");
bool result = IOModuleManager.Instance.WriteIoValue(ioName, true);
if (result)
{
LOG.WriteLog(eEvent.INFO_DRYER, Module, "Blower High On Success");
}
return result;
}
///
/// 检验Dryer模块是否处于PowerOff
///
///
///
private bool CheckDryerModulePowerOff(ModuleName moduleName)
{
if (ModuleHelper.IsInstalled(moduleName))
{
DryerDevice dryerDevice1 = DEVICE.GetDevice(moduleName.ToString());
if (dryerDevice1 != null)
{
if (dryerDevice1.IOInitialized&&!dryerDevice1.CommonData.PowerControl)
{
return true;
}
}
}
return false;
}
///
/// 检验是否Dryers是否有处于BlowerHigh状态
///
///
private bool CheckDryersPowerOff()
{
bool dryer1High = CheckDryerModulePowerOff(ModuleName.Dryer1);
if (dryer1High)
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, "Dryer1 is power off");
return true;
}
bool dryer2High = CheckDryerModulePowerOff(ModuleName.Dryer2);
if (dryer2High)
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, "Dryer2 is power off");
return true;
}
bool dryer3High = CheckDryerModulePowerOff(ModuleName.Dryer3);
if (dryer3High)
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, "Dryer3 is power off");
return true;
}
return false;
}
#endregion
#region Blower Low
///
/// Blower Low On Action
///
///
///
///
private bool BlowerLowOnAction(string cmd, object[] args)
{
return BlowerLowOn();
}
///
/// Blower Low On
///
///
public bool BlowerLowOn()
{
//High off
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{BLOWER_HIGH}");
bool result= IOModuleManager.Instance.WriteIoValue(ioName, false);
if(result)
{
string controlPowerOnName= BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{POWER_CONTROL}");
result= IOModuleManager.Instance.WriteIoValue(controlPowerOnName, true);
}
return result;
}
#endregion
///
/// 判定运行状态
///
///
private bool JudgeRunningState(DryerCommonOperation operation)
{
if (_status == RState.Running)
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{Module} current execute {_currentOperation},cannot {operation}");
return true;
}
return false;
}
#endregion
///
/// 获取当前操作对应的Routine
///
///
///
private IRoutine GetCurrentRoutine(DryerCommonOperation currentOperation)
{
switch (currentOperation)
{
case DryerCommonOperation.BlowerHigh:
return _blowerHighRoutine;
default:
return null;
}
}
///
/// 检验Routine状态
///
///
///
private void CheckRoutineState(IRoutine routine, DryerCommonOperation currentOperation)
{
RState state = routine.Monitor();
if (state == RState.End)
{
EndOperation(RState.End);
}
else if (state == RState.Failed || state == RState.Timeout)
{
LOG.WriteLog(eEvent.ERR_DRYER, $"{Module}", $"{currentOperation} error");
EndOperation(RState.Failed);
}
}
///
/// 结束操作
///
private void EndOperation(RState state)
{
_status = state;
_currentOperation = DryerCommonOperation.None;
}
///
/// DisabledAction
///
///
///
///
private bool DisabledOperation(string cmd, object[] args)
{
string currentOperation = "Disabled";
DryerEntity dryerEntity = Singleton.Instance.GetModule(Module);
if(dryerEntity == null || _dryerPersistentValue == null) return false;
if (_dryerPersistentValue.OperatingMode != "Disabled") dryerEntity.EnterInit();
_dryerPersistentValue.OperatingMode = currentOperation;
DryerPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
///
/// ManualAction
///
///
///
///
private bool ManualOperation(string cmd, object[] args)
{
string currentOperation = "Manual";
DryerEntity dryerEntity = Singleton.Instance.GetModule(Module);
if (dryerEntity == null || _dryerPersistentValue == null) return false;
if(_dryerPersistentValue.OperatingMode == "Auto" && dryerEntity.IsBusy)
{
LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{Module} is Busy, can't change to manual mode");
return false;
}
if (_dryerPersistentValue.OperatingMode != "Manual") dryerEntity.EnterInit();
_dryerPersistentValue.OperatingMode = currentOperation;
DryerPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
///
/// AutoAction
///
///
///
///
private bool AutoOperation(string cmd, object[] args)
{
string currentOperation = "Auto";
DryerEntity dryerEntity = Singleton.Instance.GetModule(Module);
if (dryerEntity == null || _dryerPersistentValue == null) return false;
if (_dryerPersistentValue.OperatingMode != "Auto") dryerEntity.EnterInit();
_dryerPersistentValue.OperatingMode= currentOperation;
DryerPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
///
/// EngineeringModeAction
///
///
///
///
private bool EngineeringModeOperation(string cmd, object[] args)
{
string currentRecipeOperation = "Engineering";
_dryerPersistentValue.RecipeOperatingMode = currentRecipeOperation;
DryerPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
///
/// ProductionAction
///
///
///
///
private bool ProductionModeOperation(string cmd, object[] args)
{
string currentRecipeOperation = "Production";
_dryerPersistentValue.RecipeOperatingMode= currentRecipeOperation;
DryerPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
#region 设备接口
///
/// 监控
///
public void Monitor()
{
}
public void Reset()
{
}
///
/// 中止
///
public void Terminate()
{
_periodicJob.Stop(false);
}
#endregion
}
}