using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Beckhoff.ModuleIO; using MECF.Framework.Common.CommonData.Reservoir; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Persistent.Reservoirs; using MECF.Framework.Common.Persistent.Temperature; using MECF.Framework.Common.TwinCat; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace PunkHPX8_RT.Devices.Reservoir { public class DMReservoirDevice : ReservoirDevice { #region 常量 private const string AN_PUMP = "ANPump"; #endregion #region 内部变量 /// /// 默认泵速 /// private double _anPumpSpeed = 5000; /// /// an泵速Helper /// private ReservoirANPumpSpeedHelper _anPumpSpeedHelper; #endregion #region 属性 /// /// 检验阳极是否highlevel /// public bool IsANHighLevel { get { return _reservoirData.AnTowerHigh; } } /// /// 检验阳极是否lowlevel /// public bool IsANLowLevel { get { return _reservoirData.AnTowerLow; } } /// /// 阳极是否需要补水 /// public bool AnNeedDireplen { get { return CheckANNeedDiReplen(); } } #endregion #region Trigger /// /// low WaterLevel trigger /// private R_TRIG _anWaterLevelLowerTrigger = new R_TRIG(); /// /// low WaterLevel trigger /// private R_TRIG _anWaterLevelHighTrigger = new R_TRIG(); #endregion /// /// 构造函数 /// /// public DMReservoirDevice(string moduleName) : base(moduleName) { _anPumpSpeedHelper = new ReservoirANPumpSpeedHelper(Module, this); } /// /// 订阅变量 /// protected override void SubscribeValueAction() { base.SubscribeValueAction(); IoSubscribeUpdateVariable(AN_DI_REPLEN); IoSubscribeUpdateVariable(AN_FLOW); IoSubscribeUpdateVariable(AN_PUMP_ENABLE); IoSubscribeUpdateVariable(AN_PUMP_SPEED); IoSubscribeUpdateVariable(DEGAS_ENABLE); } /// /// 订阅Data /// protected override void SubscribeData() { base.SubscribeData(); DATA.Subscribe($"{Module}.IsManualANReplen", () => { return _currentDireplenOperation == DiReplenOperation.ManualANDiReplen; }, SubscriptionAttribute.FLAG.IgnoreSaveDB); } /// /// 订阅Operation /// protected override void InitializeOperation() { base.InitializeOperation(); OP.Subscribe($"{Module}.ANPumpEnable", AnPumpOnOperation); OP.Subscribe($"{Module}.ANPumpSpeed", ANPumpSpeedOperation); OP.Subscribe($"{Module}.ANPumpDisable", AnPumpOffOperation); OP.Subscribe($"{Module}.ANIsolationOn", (cmd, para) => { return ANIsolationOn(); }); OP.Subscribe($"{Module}.ANIsolationOff", (cmd, para) => { return ANIsolationOff(); }); OP.Subscribe($"{Module}.ManualANDiReplen", ManualANDiReplen); } #region AnPump /// /// AN Pump调速 /// /// /// /// private bool ANPumpSpeedOperation(string cmd, object[] args) { double anMaxPumpSpeed = 0; if (SC.ContainsItem("Reservoir.ANMaxPumpSpeed")) { anMaxPumpSpeed = SC.GetValue("Reservoir.ANMaxPumpSpeed"); } if (double.TryParse(args[0].ToString(), out double speed)) { _anPumpSpeed = speed; if (_anPumpSpeed > anMaxPumpSpeed) { LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"AN pump speed:{_anPumpSpeed} is over AN max pump speed {anMaxPumpSpeed}!"); return false; } return AnPumpSpeed(_anPumpSpeed); } else { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{args[0]} is nor invalid speed"); return false; } } /// /// 设置AN泵速 /// /// /// public bool AnPumpSpeed(double anPumpSpeed) { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_PUMP_SPEED}"); return BeckhoffIOManager.Instance.WriteIoValue(ioName, anPumpSpeed); } /// /// 阳极Pump On /// /// /// /// public bool AnPumpOnOperation(string cmd, object[] args) { double caPumpSpeed = SC.GetValue("Reservoir.ANDefaultPumpSpeed"); bool result = AnPumpSpeed(caPumpSpeed); if (result) { string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_PUMP_ENABLE}"); return BeckhoffIOManager.Instance.WriteIoValue(enableIOName, true); } else { return false; } } /// /// 阳极Pump Off /// /// /// /// private bool AnPumpOffOperation(string cmd, object[] args) { return AnPumpOff(); } /// /// 关闭阳极Pump /// /// public bool AnPumpOff() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_PUMP_ENABLE}"); return BeckhoffIOManager.Instance.WriteIoValue(ioName, false); } /// /// ANIsolationOn /// /// public bool ANIsolationOn() { return WriteVariableValue(AN_ISOLATION, true); } /// /// ANIsolationOff /// /// public bool ANIsolationOff() { return WriteVariableValue(AN_ISOLATION, false); } #endregion protected override void AutoMonitor() { base.AutoMonitor(); if (_persistentValue.OperatingMode == AUTO) { _anPumpSpeedHelper.Monitor(_resRecipe); } } /// /// 水位监控 /// protected override void WaterLevelMonitor() { base.WaterLevelMonitor(); //增加AN tower监控逻辑 _anWaterLevelLowerTrigger.CLK = _reservoirData.AnTowerLow; _anWaterLevelHighTrigger.CLK = _reservoirData.AnTowerHigh; if (_anWaterLevelLowerTrigger.Q && !Recipe.ANDIReplenEnable) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"AN tower low is activate and recipe ANDIReplenEnable is false"); } if (_anWaterLevelHighTrigger.Q && !Recipe.ANDIReplenEnable) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"AN tower high is activate and recipe ANDIReplenEnable is false"); } } /// /// 补水监控,用于关闭自动补水 /// protected override void AutoDireplenMonitor() { base.AutoDireplenMonitor(); if (_currentDireplenOperation == DiReplenOperation.ManualANDiReplen) { bool result = _direplenHelper.MonitorManualDiReplenComplete(_manualReplenSecond, ANDiReplenOff, ref _isDIReplenMaxTimeOut); if (result) { _currentDireplenOperation = DiReplenOperation.None; } } if (_currentDireplenOperation == DiReplenOperation.AutoANDiReplen) { AutoANDiReplenMonitor(ANDiReplenOff, _resRecipe.ANDIReplenEnable, _resRecipe.ANDIReplenTimeRate, _resRecipe.ANDIReplenCurrentRate); } } /// /// 阳极DI Replen On /// /// /// /// private bool ANDiReplenOnOperation(string cmd, object[] args) { return ANDiReplenOn(); } /// /// 阳极DI Replen On /// /// /// private bool ANDiReplenOn() { bool preCondition = CheckPreDiReplenCondition(); if (!preCondition) { return false; } if (IsANHighLevel) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"ANHighLevel is activate,Can't do AN_DIReple"); return false; } if (IsANLowLevel) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"ANLowLevel is activate,Can't do AN_DIReple"); return false; } if (ReservoirData.CaDiReplen) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "CADiReplen is on"); return false; } string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_DI_REPLEN}"); return BeckhoffIOManager.Instance.WriteIoValue(ioName, true); } /// /// 阳极DI Replen Off /// /// /// /// private bool ANDiReplenOff(string cmd, object[] args) { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_DI_REPLEN}"); bool result = BeckhoffIOManager.Instance.WriteIoValue(ioName, false); if (result) { _persistentValue.IsDiReplenOn = false; if (_currentDireplenOperation == DiReplenOperation.ManualANDiReplen || _currentDireplenOperation == DiReplenOperation.AutoANDiReplen) { _currentDireplenOperation = DiReplenOperation.None; _persistentValue.LastTotalReplen = _persistentValue.TotalReplen; ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); } } return result; } /// /// 手动阳极注水 /// /// /// /// private bool ManualANDiReplen(string cmd, object[] args) { return ManualDiReplen(ANDiReplenOnOperation, DiReplenOperation.ManualANDiReplen, args[0].ToString()); } /// /// 检验阳极是否需要补水 /// /// private bool CheckANNeedDiReplen() { if (IsAuto && _resRecipe != null) { if (_resRecipe.ANDIReplenEnable && _resRecipe.ANDIReplenCurrentRate == 0 && _resRecipe.ANDIReplenTimeRate == 0) { return _reservoirData.AnTowerLow; } return false; } else { return false; } } /// /// 阳极自动注水 /// /// public bool AutoANDiReplen() { return AutoDireplen(ANDiReplenOn, DiReplenOperation.AutoANDiReplen); } /// /// 阳极自动注水监控 /// /// /// /// private void AutoANDiReplenMonitor(Func direplenOff, bool replenEnable, int direplenTimeRate, int direplenCurrentRate) { //判断是否注水超时(包括单次和累计) bool result = _direplenHelper.AutoDiReplenMonitorTimeOut(direplenOff, ref _isDIReplenMaxTimeOut, ref _isDIReplenPerfillTimeOut); if (result) { _currentDireplenOperation = DiReplenOperation.None; } else { //按液位补水 result = AutoANDiReplenMonitorComplete(replenEnable, direplenTimeRate, direplenCurrentRate, direplenOff); if (result) { _currentDireplenOperation = DiReplenOperation.None; } } } /// /// 阳极自动注水是否结束 /// /// /// /// /// /// private bool AutoANDiReplenMonitorComplete(bool replenEnable, int direplenTimeRate, int direplenCurrentRate, Func direplenOffAction) { if (replenEnable && direplenTimeRate == 0 && direplenCurrentRate == 0 && ReservoirData.AnTowerHigh) { LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, "Auto AN DiReplen complete"); bool result = direplenOffAction("", null); if (result) { _persistentValue.LastTotalReplen = _persistentValue.TotalReplen; _persistentValue.IsDiReplenOn = false; ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); return result; } } return false; } } }