|
@@ -2,17 +2,29 @@
|
|
using Aitex.Core.RT.Device;
|
|
using Aitex.Core.RT.Device;
|
|
using Aitex.Core.RT.Log;
|
|
using Aitex.Core.RT.Log;
|
|
using Aitex.Core.RT.OperationCenter;
|
|
using Aitex.Core.RT.OperationCenter;
|
|
|
|
+using Aitex.Core.RT.RecipeCenter;
|
|
|
|
+using Aitex.Core.RT.SCCore;
|
|
using Aitex.Core.Util;
|
|
using Aitex.Core.Util;
|
|
|
|
+using MECF.Framework.Common.Alarm;
|
|
|
|
+using MECF.Framework.Common.Beckhoff.ModuleIO;
|
|
using MECF.Framework.Common.CommonData.Reservoir;
|
|
using MECF.Framework.Common.CommonData.Reservoir;
|
|
using MECF.Framework.Common.IOCore;
|
|
using MECF.Framework.Common.IOCore;
|
|
using MECF.Framework.Common.Persistent.Reservoirs;
|
|
using MECF.Framework.Common.Persistent.Reservoirs;
|
|
|
|
+using MECF.Framework.Common.RecipeCenter;
|
|
|
|
+using MECF.Framework.Common.ToolLayout;
|
|
using MECF.Framework.Common.TwinCat;
|
|
using MECF.Framework.Common.TwinCat;
|
|
using MECF.Framework.Common.Utilities;
|
|
using MECF.Framework.Common.Utilities;
|
|
|
|
+using PunkHPX8_Core;
|
|
|
|
+using PunkHPX8_RT.Devices.Facilities;
|
|
|
|
+using PunkHPX8_RT.Devices.Safety;
|
|
|
|
+using PunkHPX8_RT.Devices.Temperature;
|
|
using PunkHPX8_RT.Modules;
|
|
using PunkHPX8_RT.Modules;
|
|
|
|
+using PunkHPX8_RT.Modules.Reservoir;
|
|
using System;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Reflection;
|
|
|
|
+using System.ServiceModel.Security;
|
|
using System.Text;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
@@ -67,6 +79,63 @@ namespace PunkHPX8_RT.Devices.Reservoir
|
|
/// 定时器
|
|
/// 定时器
|
|
/// </summary>
|
|
/// </summary>
|
|
private PeriodicJob _periodicJob;
|
|
private PeriodicJob _periodicJob;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 阴极Pump速度
|
|
|
|
+ /// </summary>
|
|
|
|
+ private double _caPumpSpeed = 0;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Return Valve比例
|
|
|
|
+ /// </summary>
|
|
|
|
+ private double _returnValvePercent = 0.5;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// CA Level取样平均值
|
|
|
|
+ /// </summary>
|
|
|
|
+ private double _avgCALevel;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// CA Level取样队列
|
|
|
|
+ /// </summary>
|
|
|
|
+ private Queue<double> _CALevelSamples;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// CA level计算平均值取样数
|
|
|
|
+ /// </summary>
|
|
|
|
+ private int _levelSampleCount;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Recipe
|
|
|
|
+ /// </summary>
|
|
|
|
+ private ResRecipe _resRecipe;
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 累计补水是否超时
|
|
|
|
+ /// </summary>
|
|
|
|
+ private bool _isDIReplenMaxTimeOut = false;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 单次补水是否超时
|
|
|
|
+ /// </summary>
|
|
|
|
+ private bool _isDIReplenPerfillTimeOut = false;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 注水Helper
|
|
|
|
+ /// </summary>
|
|
|
|
+ private ReservoirDiReplenHelper _direplenHelper;
|
|
|
|
+ #endregion
|
|
|
|
+
|
|
|
|
+ #region Trigger
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// low WaterLevel trigger
|
|
|
|
+ /// </summary>
|
|
|
|
+ private R_TRIG _caWaterLevelLowerTrigger=new R_TRIG();
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// low WaterLevel trigger
|
|
|
|
+ /// </summary>
|
|
|
|
+ private R_TRIG _caWaterLevelHighTrigger = new R_TRIG();
|
|
|
|
+
|
|
|
|
+ #endregion
|
|
|
|
+
|
|
|
|
+ #region 共享变量
|
|
|
|
+ protected DiReplenOperation _currentDireplenOperation = DiReplenOperation.None;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 手动注水时间(秒)
|
|
|
|
+ /// </summary>
|
|
|
|
+ protected int _manualReplenSecond = 0;
|
|
#endregion
|
|
#endregion
|
|
|
|
|
|
#region 属性
|
|
#region 属性
|
|
@@ -87,6 +156,18 @@ namespace PunkHPX8_RT.Devices.Reservoir
|
|
/// 数据
|
|
/// 数据
|
|
/// </summary>
|
|
/// </summary>
|
|
public ReservoirData ReservoirData { get { return _reservoirData; } }
|
|
public ReservoirData ReservoirData { get { return _reservoirData; } }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 检验阴极是否highlevel
|
|
|
|
+ /// </summary>
|
|
|
|
+ public bool IsCAHighLevel { get { return CheckCAHighLevelStatus(); } }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 检验阴极是否lowlevel
|
|
|
|
+ /// </summary>
|
|
|
|
+ public bool IsCALowLevel { get { return CheckCALowLevelStatus(); } }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 当前Recipe
|
|
|
|
+ /// </summary>
|
|
|
|
+ public ResRecipe Recipe { get { return _resRecipe; } }
|
|
#endregion
|
|
#endregion
|
|
/// <summary>
|
|
/// <summary>
|
|
/// 构造函数
|
|
/// 构造函数
|
|
@@ -95,6 +176,9 @@ namespace PunkHPX8_RT.Devices.Reservoir
|
|
/// <param name="name"></param>
|
|
/// <param name="name"></param>
|
|
public ReservoirDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
|
|
public ReservoirDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
|
|
{
|
|
{
|
|
|
|
+ _levelSampleCount = SC.GetValue<int>("Reservoir.LevelAvgSamples");
|
|
|
|
+ _levelSampleCount = _levelSampleCount == 0 ? 20 : _levelSampleCount;
|
|
|
|
+ _CALevelSamples = new Queue<double>(_levelSampleCount);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// <summary>
|
|
/// 初始化
|
|
/// 初始化
|
|
@@ -120,6 +204,16 @@ namespace PunkHPX8_RT.Devices.Reservoir
|
|
{
|
|
{
|
|
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module.ToString(), "Persistent Value Object is not exist");
|
|
LOG.WriteLog(eEvent.ERR_RESERVOIR, Module.ToString(), "Persistent Value Object is not exist");
|
|
}
|
|
}
|
|
|
|
+ _persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(Module);
|
|
|
|
+ if (_persistentValue == null)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Persistent Value Object is not exist");
|
|
|
|
+ }
|
|
|
|
+ if (!string.IsNullOrEmpty(_persistentValue.Recipe))
|
|
|
|
+ {
|
|
|
|
+ _resRecipe = RecipeFileManager.Instance.LoadGenericityRecipe<ResRecipe>(_persistentValue.Recipe);
|
|
|
|
+ }
|
|
|
|
+ _direplenHelper = new ReservoirDiReplenHelper(Module, _persistentValue);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// <summary>
|
|
/// 初始化Routine
|
|
/// 初始化Routine
|
|
@@ -139,13 +233,16 @@ namespace PunkHPX8_RT.Devices.Reservoir
|
|
/// <summary>
|
|
/// <summary>
|
|
/// 初始化Operation
|
|
/// 初始化Operation
|
|
/// </summary>
|
|
/// </summary>
|
|
- private void InitializeOperation()
|
|
|
|
|
|
+ protected virtual void InitializeOperation()
|
|
{
|
|
{
|
|
OP.Subscribe($"{Module}.DisabledAction", DisabledOperation);
|
|
OP.Subscribe($"{Module}.DisabledAction", DisabledOperation);
|
|
OP.Subscribe($"{Module}.ManualAction", ManualOperation);
|
|
OP.Subscribe($"{Module}.ManualAction", ManualOperation);
|
|
OP.Subscribe($"{Module}.AutoAction", AutoOperation);
|
|
OP.Subscribe($"{Module}.AutoAction", AutoOperation);
|
|
OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation);
|
|
OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation);
|
|
- OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation);
|
|
|
|
|
|
+ OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation);
|
|
|
|
+ OP.Subscribe($"{Module}.CAPumpOn", CAPumpOn);
|
|
|
|
+ OP.Subscribe($"{Module}.CAPumpSpeed", CAPumpSpeedOperation);
|
|
|
|
+ OP.Subscribe($"{Module}.CAPumpOff", CAPumpOff);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// <summary>
|
|
/// 订阅变量数值发生变化
|
|
/// 订阅变量数值发生变化
|
|
@@ -189,6 +286,11 @@ namespace PunkHPX8_RT.Devices.Reservoir
|
|
if (property != null)
|
|
if (property != null)
|
|
{
|
|
{
|
|
property.SetValue(_reservoirData, value);
|
|
property.SetValue(_reservoirData, value);
|
|
|
|
+ if (variable == CA_WATER_LEVEL)
|
|
|
|
+ {
|
|
|
|
+ string caLevelCurve = SC.GetStringValue($"Reservoir.{Module}.CALevelCurve");
|
|
|
|
+ ReservoirData.CaLevel = LevelCurveManager.Instance.CalculateLevelByWaterLevel(ReservoirData.CaWaterLevel, caLevelCurve);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
|
|
if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
|
|
{
|
|
{
|
|
@@ -201,8 +303,170 @@ namespace PunkHPX8_RT.Devices.Reservoir
|
|
/// <returns></returns>
|
|
/// <returns></returns>
|
|
protected virtual bool OnTimer()
|
|
protected virtual bool OnTimer()
|
|
{
|
|
{
|
|
|
|
+ CalculateCALevel();
|
|
|
|
+ WaterLevelMonitor();
|
|
|
|
+ DireplenMonitor();
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
+ #region timer
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 计算CA
|
|
|
|
+ /// </summary>
|
|
|
|
+ private void CalculateCALevel()
|
|
|
|
+ {
|
|
|
|
+ if (ReservoirData != null)
|
|
|
|
+ {
|
|
|
|
+ if (_CALevelSamples.Count >= _levelSampleCount)
|
|
|
|
+ {
|
|
|
|
+ _CALevelSamples.Dequeue();
|
|
|
|
+ _CALevelSamples.Enqueue(ReservoirData.CaLevel);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ _CALevelSamples.Enqueue(ReservoirData.CaLevel);
|
|
|
|
+ }
|
|
|
|
+ _avgCALevel = _CALevelSamples.Count > 0 ? _CALevelSamples.Average() : 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// WaterLevel监控
|
|
|
|
+ /// </summary>
|
|
|
|
+ protected virtual void WaterLevelMonitor()
|
|
|
|
+ {
|
|
|
|
+ _caWaterLevelLowerTrigger.CLK = IsCALowLevel;
|
|
|
|
+ if (_caWaterLevelLowerTrigger.Q)
|
|
|
|
+ {
|
|
|
|
+ ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
|
|
|
|
+
|
|
|
|
+ string reason = $"Current CAWaterlevel:{ReservoirData.CaWaterLevel} is lower than CALowLevel Config:{SC.GetValue<double>($"Reservoir.{Module}.CALowLevel")}";
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, reason);
|
|
|
|
+ CALowLevelOperation();
|
|
|
|
+ if (reservoirEntity.IsAuto && !AlarmListManager.Instance.IsContainDataError(Module, "CAWaterLevel"))
|
|
|
|
+ {
|
|
|
|
+ AlarmListManager.Instance.AddDataError(Module,
|
|
|
|
+ $"CAWaterLevel", $"Current CAWaterlevel:{ReservoirData.CaWaterLevel} is lower than CALowLevel Config:{SC.GetValue<double>($"Reservoir.{Module}.CALowLevel")}");
|
|
|
|
+ }
|
|
|
|
+ if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _caWaterLevelLowerTrigger.CLK = IsCAHighLevel;
|
|
|
|
+ if (_caWaterLevelHighTrigger.Q)
|
|
|
|
+ {
|
|
|
|
+ HighLevelOperation();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// CA Low Level触发对应操作
|
|
|
|
+ /// </summary>
|
|
|
|
+ private void CALowLevelOperation()
|
|
|
|
+ {
|
|
|
|
+ ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module);
|
|
|
|
+ if (_reservoirData.CaPumpEnable)
|
|
|
|
+ {
|
|
|
|
+ CAPumpOff("", null);
|
|
|
|
+ }
|
|
|
|
+ //禁用TC
|
|
|
|
+ if (!string.IsNullOrEmpty(reservoirItem.TCID))
|
|
|
|
+ {
|
|
|
|
+ TemperatureController temperatureController = DEVICE.GetDevice<TemperatureController>(reservoirItem.TCID);
|
|
|
|
+ if (temperatureController != null && temperatureController.TemperatureData.ControlOperationModel == (int)TemperatureEnumData.ENABLE)
|
|
|
|
+ {
|
|
|
|
+ temperatureController.DisableOperation("", null);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
|
|
|
|
+
|
|
|
|
+ if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// High Level Common Operation
|
|
|
|
+ /// </summary>
|
|
|
|
+ private void HighLevelOperation()
|
|
|
|
+ {
|
|
|
|
+ ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
|
|
|
|
+ SystemFacilities systemFacilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
|
|
|
|
+ if (systemFacilities != null)
|
|
|
|
+ {
|
|
|
|
+ if (systemFacilities.DIFillEnable) systemFacilities.DiFillDisableOperation("DIFillDisableOpeartion", null);
|
|
|
|
+ if (systemFacilities.DIReplenEnable) systemFacilities.DiReplenDisableOperation("DiReplenDisableOperation", null);
|
|
|
|
+
|
|
|
|
+ if (_reservoirData.CaDiReplen)
|
|
|
|
+ {
|
|
|
|
+ _currentDireplenOperation = DiReplenOperation.None;
|
|
|
|
+ CADiReplenOff("", null);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (!reservoirEntity.IsError) reservoirEntity.PostMsg(ReservoirMsg.Error);
|
|
|
|
+ if (reservoirEntity.IsAuto && !AlarmListManager.Instance.IsContainDataError(Module, "CAWaterLevel"))
|
|
|
|
+ {
|
|
|
|
+ AlarmListManager.Instance.AddDataError(Module,
|
|
|
|
+ $"CAWaterLevel", $"Current CAWaterlevel:{ReservoirData.CaWaterLevel} is large than CAHighLevel Config:{SC.GetValue<double>($"Reservoir.{Module}.CAHighLevel")}");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Direplen监控
|
|
|
|
+ /// </summary>
|
|
|
|
+ private void DireplenMonitor()
|
|
|
|
+ {
|
|
|
|
+ var facilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
|
|
|
|
+ //补水监控
|
|
|
|
+ if (_direplenHelper != null)
|
|
|
|
+ {
|
|
|
|
+ _direplenHelper.MonitorPeriodTime(ref _isDIReplenMaxTimeOut);
|
|
|
|
+ if (!_isDIReplenMaxTimeOut && !_isDIReplenPerfillTimeOut && facilities.DIFillEnable)
|
|
|
|
+ {
|
|
|
|
+ AutoDireplenMonitor();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 自动补水
|
|
|
|
+ /// </summary>
|
|
|
|
+ protected virtual void AutoDireplenMonitor()
|
|
|
|
+ {
|
|
|
|
+ if (_currentDireplenOperation == DiReplenOperation.ManualCADiReplen)
|
|
|
|
+ {
|
|
|
|
+ bool result = _direplenHelper.MonitorManualDiReplenComplete(_manualReplenSecond, CADiReplenOff, ref _isDIReplenMaxTimeOut);
|
|
|
|
+ if (result)
|
|
|
|
+ {
|
|
|
|
+ _currentDireplenOperation = DiReplenOperation.None;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (_currentDireplenOperation == DiReplenOperation.AutoCADiReplen)
|
|
|
|
+ {
|
|
|
|
+ AutoDiReplenMonitor(CADiReplenOff, _reservoirData.CaLevel, _resRecipe.ReservoirCALevel, _resRecipe.DIReplenEnable,
|
|
|
|
+ _resRecipe.DIReplenTimeRate, _resRecipe.DIReplenCurrentRate);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 自动注水监控
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="direplenOff"></param>
|
|
|
|
+ /// <param name="level"></param>
|
|
|
|
+ /// <param name="recipeLevel"></param>
|
|
|
|
+ private void AutoDiReplenMonitor(Func<string, object[], bool> direplenOff, double level, double recipeLevel, bool replenEnable,
|
|
|
|
+ int direplenTimeRate, int direplenCurrentRate)
|
|
|
|
+ {
|
|
|
|
+ bool result = _direplenHelper.AutoDiReplenMonitorTimeOut(direplenOff, ref _isDIReplenMaxTimeOut, ref _isDIReplenPerfillTimeOut);
|
|
|
|
+ if (result)
|
|
|
|
+ {
|
|
|
|
+ _currentDireplenOperation = DiReplenOperation.None;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ //按液位补水
|
|
|
|
+ result = _direplenHelper.AutoDiReplenMonitorComplete(level, recipeLevel, replenEnable, direplenTimeRate, direplenCurrentRate, direplenOff);
|
|
|
|
+ if (result)
|
|
|
|
+ {
|
|
|
|
+ _currentDireplenOperation = DiReplenOperation.None;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #endregion
|
|
|
|
|
|
#region Mode switch
|
|
#region Mode switch
|
|
/// <summary>
|
|
/// <summary>
|
|
@@ -298,6 +562,395 @@ namespace PunkHPX8_RT.Devices.Reservoir
|
|
public void Monitor()
|
|
public void Monitor()
|
|
{
|
|
{
|
|
}
|
|
}
|
|
|
|
+ #region CA Pump
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// CA Pump调速
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="args"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool CAPumpSpeedOperation(string cmd, object[] args)
|
|
|
|
+ {
|
|
|
|
+ double caMaxPumpSpeed = 0;
|
|
|
|
+ if (SC.ContainsItem("Reservoir.CAMaxPumpSpeed"))
|
|
|
|
+ {
|
|
|
|
+ caMaxPumpSpeed = SC.GetValue<double>("Reservoir.CAMaxPumpSpeed");
|
|
|
|
+ }
|
|
|
|
+ if (double.TryParse(args[0].ToString(), out double speed))
|
|
|
|
+ {
|
|
|
|
+ _caPumpSpeed = speed;
|
|
|
|
+ if (_caPumpSpeed > caMaxPumpSpeed)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.WARN_METAL, Module, $"CA pump speed:{_caPumpSpeed} is over CA max pump speed {caMaxPumpSpeed}!");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ return CAPumpSpeed(_caPumpSpeed);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_METAL, Module, $"{args[0]} is nor invalid speed");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 设置阴极泵速
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="caPumpSpeed"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public bool CAPumpSpeed(double caPumpSpeed)
|
|
|
|
+ {
|
|
|
|
+ string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_SPEED}");
|
|
|
|
+ return BeckhoffIOManager.Instance.WriteIoValue(ioName, caPumpSpeed);
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 阴极Pump On
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="args"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool CAPumpOn(string cmd, object[] args)
|
|
|
|
+ {
|
|
|
|
+ double caPumpSpeed = SC.GetValue<double>("Reservoir.CADefaultPumpSpeed");
|
|
|
|
+ bool result = CAPumpSpeed(caPumpSpeed);
|
|
|
|
+ if (result)
|
|
|
|
+ {
|
|
|
|
+ string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_ENABLE}");
|
|
|
|
+ return BeckhoffIOManager.Instance.WriteIoValue(enableIOName, true);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 阴极Pump Off
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="args"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool CAPumpOff(string cmd, object[] args)
|
|
|
|
+ {
|
|
|
|
+ string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_PUMP_ENABLE}");
|
|
|
|
+ return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #endregion
|
|
|
|
+
|
|
|
|
+ #region Return Valve
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Return Valve
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="args"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool ReturnValvePercentOperation(string cmd, object[] args)
|
|
|
|
+ {
|
|
|
|
+ if (double.TryParse(args[0].ToString(), out double percent))
|
|
|
|
+ {
|
|
|
|
+ _returnValvePercent = percent;
|
|
|
|
+ return CAPumpSpeed(_caPumpSpeed);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_METAL, Module, $"{args[0]} is nor invalid speed");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 设置比例
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="caPumpSpeed"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public bool ReturnValvePercent(double percent)
|
|
|
|
+ {
|
|
|
|
+ string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RETURN_VALVE_PERCENT}");
|
|
|
|
+ return BeckhoffIOManager.Instance.WriteIoValue(ioName, percent);
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Return Valve On
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="args"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool ReturnValveOn(string cmd, object[] args)
|
|
|
|
+ {
|
|
|
|
+ double percent = SC.GetValue<double>("Reservoir.ReturnOpenDefaultPercentage");
|
|
|
|
+ bool result = ReturnValvePercent(percent);
|
|
|
|
+ if (result)
|
|
|
|
+ {
|
|
|
|
+ string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RETURN_VALVE}");
|
|
|
|
+ return BeckhoffIOManager.Instance.WriteIoValue(enableIOName, true);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Return Valve Off
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="args"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool ReturnValveOff(string cmd, object[] args)
|
|
|
|
+ {
|
|
|
|
+ string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RETURN_VALVE}");
|
|
|
|
+ return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #endregion
|
|
|
|
+
|
|
|
|
+ #region CA DiReplen
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 阴极DI Replen On
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="args"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool CADiReplenOnOperation(string cmd, object[] args)
|
|
|
|
+ {
|
|
|
|
+ return CADiReplenOn();
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 阴极DI Replen On
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="showError"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool CADiReplenOn()
|
|
|
|
+ {
|
|
|
|
+ bool preCondition = CheckPreDiReplenCondition();
|
|
|
|
+ if (!preCondition)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (IsCAHighLevel)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CAHighLevel is activate,Can't do CA_DIReple");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (IsCALowLevel)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CALowLevel is activate,Can't do CA_DIReple");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (ReservoirData.AnDiReplen)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "ANDiReplen is on");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_DI_REPLEN}");
|
|
|
|
+ return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 阴极DI Replen Off
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="args"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool CADiReplenOff(string cmd, object[] args)
|
|
|
|
+ {
|
|
|
|
+ string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CA_DI_REPLEN}");
|
|
|
|
+ bool result = BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
|
|
|
|
+ if (result)
|
|
|
|
+ {
|
|
|
|
+ _persistentValue.IsDiReplenOn = false;
|
|
|
|
+ if (_currentDireplenOperation == DiReplenOperation.ManualCADiReplen || _currentDireplenOperation == DiReplenOperation.AutoCADiReplen)
|
|
|
|
+ {
|
|
|
|
+ _currentDireplenOperation = DiReplenOperation.None;
|
|
|
|
+ _persistentValue.LastTotalReplen = _persistentValue.TotalReplen;
|
|
|
|
+ ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 检验DiReplen前置条件
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public bool CheckPreDiReplenCondition()
|
|
|
|
+ {
|
|
|
|
+ if (!CheckFacilitiesDiReplenStatus())
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Facilities DiReplen is Off, can't start auto diReplen");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ SafetyDevice safetyDevice = DEVICE.GetDevice<SafetyDevice>("Safety");
|
|
|
|
+ if (safetyDevice != null && safetyDevice.SafetyData.Reservoir1CALevelHigh)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Safety high is Activate, can't start auto diReplen");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (CheckOtherReservoirDiReplenStatus())
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 检验总Di有没有开
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool CheckFacilitiesDiReplenStatus()
|
|
|
|
+ {
|
|
|
|
+ SystemFacilities systemFacilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
|
|
|
|
+ if (systemFacilities != null)
|
|
|
|
+ {
|
|
|
|
+ return systemFacilities.DIReplenEnable;
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 检验是否其他Reservoir Direplen已经
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ protected bool CheckOtherReservoirDiReplenStatus()
|
|
|
|
+ {
|
|
|
|
+ List<string> reservoirs = ReservoirItemManager.Instance.InstalledModules;
|
|
|
|
+ foreach (string item in reservoirs)
|
|
|
|
+ {
|
|
|
|
+ if (item != Module)
|
|
|
|
+ {
|
|
|
|
+ ReservoirDevice tmpDevice = DEVICE.GetDevice<ReservoirDevice>(item);
|
|
|
|
+ if (tmpDevice.ReservoirData.CaDiReplen)
|
|
|
|
+ {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(item);
|
|
|
|
+ if (reservoirItem.SubType == ReservoirType.DegasMembrance.ToString())
|
|
|
|
+ {
|
|
|
|
+ if (tmpDevice.ReservoirData.AnDiReplen)
|
|
|
|
+ {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ #endregion
|
|
|
|
+
|
|
|
|
+ #region DiReplen Operation
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 重置时长
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="objs"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool ResetTotalTime(string cmd, object[] objs)
|
|
|
|
+ {
|
|
|
|
+ _isDIReplenMaxTimeOut = false;
|
|
|
|
+ _persistentValue.TotalReplen = 0;
|
|
|
|
+ _persistentValue.LastTotalReplen = 0;
|
|
|
|
+ ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 手动阴极注水
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="cmd"></param>
|
|
|
|
+ /// <param name="args"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool ManualCADiReplen(string cmd, object[] args)
|
|
|
|
+ {
|
|
|
|
+ return ManualDiReplen(CADiReplenOnOperation, DiReplenOperation.ManualCADiReplen, args[0].ToString());
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 手动注水
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="direplenOn"></param>
|
|
|
|
+ /// <param name="direplenOperation"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ private bool ManualDiReplen(Func<string, object[], bool> direplenOn, DiReplenOperation direplenOperation, string timeLength)
|
|
|
|
+ {
|
|
|
|
+ if (_currentDireplenOperation != DiReplenOperation.None)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"current operation is {_currentDireplenOperation},cannot execute {direplenOperation}");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
|
|
|
|
+ if (!reservoirEntity.IsInitialized)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} is not initialized. Can't start DiReplen");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (_isDIReplenMaxTimeOut)
|
|
|
|
+ {
|
|
|
|
+ double diValveMaxOnTime = SC.GetValue<double>($"Reservoir.{Module}.DIValveMaxOnTime");
|
|
|
|
+ LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"Direplen time over conifg's DIValveMaxOnTime:{diValveMaxOnTime} min");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (_isDIReplenPerfillTimeOut)
|
|
|
|
+ {
|
|
|
|
+ double diValveMaxOnTimePerFill = SC.GetValue<double>($"Reservoir.{Module}.DIValveMaxOnTimePerFill");
|
|
|
|
+ LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"Direplen time over conifg's DIValveMaxOnTimePerFill:{diValveMaxOnTimePerFill} min");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ bool result = direplenOn("", null);
|
|
|
|
+ if (result)
|
|
|
|
+ {
|
|
|
|
+ _currentDireplenOperation = direplenOperation;
|
|
|
|
+ _persistentValue.DiReplenTime = DateTime.Now;
|
|
|
|
+ ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
|
|
|
|
+ int.TryParse(timeLength, out _manualReplenSecond);
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 阴极自动流水
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ public bool AutoCADiReplen()
|
|
|
|
+ {
|
|
|
|
+ if (IsCALowLevel)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"CALowLevel is activate,Can't AutoANDireplen");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ return AutoDireplen(CADiReplenOn, DiReplenOperation.AutoCADiReplen);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 自动注水
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ protected bool AutoDireplen(Func<bool> direplenOn, DiReplenOperation reservoirOperation)
|
|
|
|
+ {
|
|
|
|
+ if (_currentDireplenOperation != DiReplenOperation.None)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"current operation is {_currentDireplenOperation},cannot execute {reservoirOperation}");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (_resRecipe == null)
|
|
|
|
+ {
|
|
|
|
+ LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"recipe is null");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ bool result = direplenOn();
|
|
|
|
+ if (result)
|
|
|
|
+ {
|
|
|
|
+ _currentDireplenOperation = reservoirOperation;
|
|
|
|
+ _persistentValue.DiReplenTime = DateTime.Now;
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ #endregion
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 检验阴极是否highlevel
|
|
|
|
+ /// </summary>
|
|
|
|
+ public bool CheckCAHighLevelStatus()
|
|
|
|
+ {
|
|
|
|
+ return ReservoirData.CaWaterLevel > SC.GetValue<double>($"Reservoir.{Module}.CAHighLevel") ? true : false;
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 检验阴极是否lowlevel
|
|
|
|
+ /// </summary>
|
|
|
|
+ public bool CheckCALowLevelStatus()
|
|
|
|
+ {
|
|
|
|
+ return ReservoirData.CaWaterLevel < SC.GetValue<double>($"Reservoir.{Module}.CALowLevel") ? true : false;
|
|
|
|
+ }
|
|
|
|
|
|
public void Reset()
|
|
public void Reset()
|
|
{
|
|
{
|
|
@@ -306,5 +959,14 @@ namespace PunkHPX8_RT.Devices.Reservoir
|
|
public void Terminate()
|
|
public void Terminate()
|
|
{
|
|
{
|
|
}
|
|
}
|
|
|
|
+ protected enum DiReplenOperation
|
|
|
|
+ {
|
|
|
|
+ None,
|
|
|
|
+ ManualANDiReplen,
|
|
|
|
+ ManualCADiReplen,
|
|
|
|
+ AutoANDiReplen,
|
|
|
|
+ AutoCADiReplen
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
}
|
|
}
|