using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.RecipeCenter; 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.Persistent.Reservoirs; using MECF.Framework.Common.RecipeCenter; using MECF.Framework.Common.ToolLayout; using MECF.Framework.Common.TwinCat; using CyberX8_Core; using CyberX8_RT.Devices.Facilities; using CyberX8_RT.Devices.Metal; using CyberX8_RT.Modules.Reservoir; using System; using System.Collections.Generic; using System.Reflection; using CyberX8_RT.Modules; using System.Collections.ObjectModel; using CyberX8_RT.Devices.Dose; using CyberX8_RT.Modules.Metal; using CyberX8_RT.Devices.Temperature; using CyberX8_RT.Devices.PowerSupplier; using System.Linq; using CyberX8_RT.Devices.Safety; using MECF.Framework.Common.IOCore; namespace CyberX8_RT.Devices.Reservoir { public class StandardHotReservoirDevice : BaseDevice, IDevice { private enum ReservoirOperation { None, ManualDiReplen, AutoDiReplen } private enum DosingOperation { None, ManualDosing, AutoDosing, } #region 常量 private const string AUTO = "Auto"; private const string MANUAL = "Manual"; private const string DISABLE = "Disable"; private const string STRATUS = "Stratus"; private const string PERSISTENT_VALUE = "PersistentValue"; private const string FLOW = "Flow"; private const string HED_FLOW = "HedFlow"; private const string PH_FLOW_VALVE = "PHFlowValve"; private const string PH_VALUE = "PHValue"; private const string WATER_LEVEL = "WaterLevel"; private const string LOW_LEVEL = "LowLevel"; private const string HIGH_LEVEL = "HighLevel"; private const string DI_REPLEN = "DiReplen"; private const string RESERVOIRDEVICEDATA = "ReservoirDeviceData"; private const string REPLEN_LEVEL = "ReplenLevel"; private const double PUMP_SPEED_CONVERT = 0.0672; private const int ENABLE = 5; #endregion #region 内部变量 /// /// Level取样平均值 /// private double _avgLevel; /// /// AN Level取样队列 /// private Queue _LevelSamples; /// /// Level计算平均值取样数 /// private int levelSampleCount; /// /// Prewet 持久性数值对象 /// private ReservoirsPersistentValue _persistentValue; /// /// 定时器Job /// PeriodicJob _periodicJob = null; /// /// 变量是否初始化字典 /// private Dictionary _variableInitializeDic = new Dictionary(); /// /// Reservoir数据 /// private StandardHotReservoirData _reservoirData = new StandardHotReservoirData(); /// /// 当前操作 /// private ReservoirOperation _currentOperation = ReservoirOperation.None; /// /// 手动注水时间(秒) /// private int _manualReplenSecond = 0; /// /// Recipe /// private ResRecipe _resRecipe; /// /// 平均PH值 /// private double _avaragePH; /// /// PH Routine /// private StandardHotPHRoutine _phRoutine; /// /// PH Routine状态 /// private RState _phState=RState.Init; /// /// PH结束时间 /// private DateTime _phRoutineEndTime=DateTime.Now; /// /// Direplen 逻辑对象 /// private ReservoirDiReplenHelper _direplenHelper; /// /// Replen数量 /// private int _replenNum = 0; /// /// Dose Replen数据 /// private ReplenData[] _replenDatas; /// /// ReplenType /// private string _replenType; /// /// Replen Recipe集合 /// private RdsRecipe[] _rdsRecipe; /// /// DosingSystemHelper对象列表 /// private List _dosingSystemHelperLst; /// /// ReplenLevel 列表 /// private List _replenLevelLst; /// /// 当前操作 /// private List _currentDosingOperation; /// /// 配置的metal device集合 /// private ObservableCollection _metalDevices = new ObservableCollection(); /// /// Replen Persistent Value /// private Dictionary _replenPersistentValue = new Dictionary(); /// /// DosingCommonHelper /// private DosingCommonHelper _dosingCommonHelper; /// /// WarningFlag /// private List _isCAFlowRateWARN; /// /// CMM Flow High Error /// private double _reservoirCMMFlowHighError; /// /// CMM Flow Low Error /// private double _reservoirCMMFlowLowError; private bool _isTCControlWARN = false; private bool _isCMMPowerCurrentWARN = false; private bool _isCMMPowerFlowWARN = false; private bool _isExportCMMUsage = false; private bool _isAutoDIReplenError = false; #endregion #region 属性 /// /// 数据 /// public StandardHotReservoirData ReservoirData { get { return _reservoirData; } } /// /// Replen数据 /// public ReplenData[] ReplenDatas { get { return _replenDatas; } } /// /// DosingSystemHelper对象列表 /// public List DosingSystemHelpers { get { return _dosingSystemHelperLst; }} /// /// Replen数量 /// public int ReplenNum { get { return _replenNum; } } /// /// 操作模式 /// public string OperationMode { get { return _persistentValue.OperatingMode; } } /// /// 工程模式 /// public string EngineerMode { get { return _persistentValue.RecipeOperatingMode; } } /// /// 是否自动 /// public bool IsAuto { get { return _persistentValue.OperatingMode == AUTO; } } /// /// 是否需要补水 /// public bool NeedAutoDireplen { get { return GetNeedAutoDireplen(); } } /// /// 正在补水 /// public bool IsDireplenOn { get { return _reservoirData.DiReplen; } } /// /// 平均PH数值 /// public double AveragePH { get { return _avaragePH; } set { _avaragePH = value; } } /// /// 当前Recipe /// public ResRecipe Recipe { get { return _resRecipe; } } /// /// 当前Rds Recipe /// public RdsRecipe[] RdsRecipe { get { return _rdsRecipe; } } #endregion /// /// 构造函数 /// /// /// public StandardHotReservoirDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName) { levelSampleCount = SC.GetValue("Reservoir.LevelAvgSamples"); levelSampleCount = levelSampleCount == 0 ? 20 : levelSampleCount; _LevelSamples = new Queue(levelSampleCount); _periodicJob = new PeriodicJob(100, OnTimer, $"{Module}.OnTimer", true); _reservoirCMMFlowHighError = SC.GetValue("Reservoir.CMM.CMMFlowHighFault"); _reservoirCMMFlowLowError = SC.GetValue("Reservoir.CMM.CMMFlowLowFault"); } /// /// 定时器 /// /// private bool OnTimer() { //计算AN/CA level的平均值 if (ReservoirData != null) { //AN if (_LevelSamples.Count >= levelSampleCount) { _LevelSamples.Dequeue(); _LevelSamples.Enqueue(ReservoirData.Level); } else { _LevelSamples.Enqueue(ReservoirData.Level); } _avgLevel = _LevelSamples.Count > 0 ? _LevelSamples.Average() : 0; } foreach (StandardHotMetalDevice device in _metalDevices) { device.OnTimer(_periodicJob.Interval); } ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module); //报错停DosingSystem if (_replenType != "" && _replenNum != 0 && reservoirEntity != null && reservoirEntity.IsError) { for (int i = 0; i < _replenNum; i++) { string replenName = "Replen" + (i + 1).ToString(); if (_replenPersistentValue[replenName].IsDosingRunning) { _dosingSystemHelperLst[i].StopDosing(); _currentDosingOperation[i] = DosingOperation.None; } } } //触发水位过高或者过低将reservoir切成error if (!_reservoirData.LowLevel || ReservoirData.WaterLevel > SC.GetValue($"Reservoir.{Module}.HighLevel")) { if (!_reservoirData.LowLevel && !reservoirEntity.IsError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"WaterLevel low is Activate"); } if(ReservoirData.WaterLevel > SC.GetValue($"Reservoir.{Module}.HighLevel") && !reservoirEntity.IsError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"WaterLevel:{ReservoirData.WaterLevel} is larger than HighLevel Config:{SC.GetValue($"Reservoir.{Module}.HighLevel")}"); SystemFacilities systemFacilities = DEVICE.GetDevice("System.Facilities"); if (systemFacilities != null) { systemFacilities.DiFillDisableOperation("DIFillDisableOpeartion", null); systemFacilities.DiReplenDisableOperation("DiReplenDisableOperation", null); if (ReservoirData.DiReplen) { _currentOperation = ReservoirOperation.None; DIReplenOff("", null); } } } reservoirEntity.PostMsg(ReservoirMsg.Error); } if (!_reservoirData.LowLevel) //true是正常的 { ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module); foreach (var metalDevice in _metalDevices) { if (metalDevice.MetalDeviceData.Circulation) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Lowlevel was activate"); metalDevice.SwitchToBypass($"{metalDevice.Name}.SwitchToBypass", null); } if (metalDevice.MetalDeviceData.CellFlow > 0) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Lowlevel was activate"); metalDevice.PumpOff(); } //水位过低时将起对应的metal也要切成error MetalEntity metalEntity = Singleton.Instance.GetModule(metalDevice.DeviceID); if (metalEntity != null && !metalEntity.IsError) { metalEntity.PostMsg(MetalMsg.Error); } } //禁用TC if (!String.IsNullOrEmpty(reservoirItem.TCID)) { TemperatureController temperatureController = DEVICE.GetDevice(reservoirItem.TCID); if (temperatureController != null && temperatureController.TemperatureData.ControlOperationModel == 5) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Lowlevel was activate"); temperatureController.DisableOperation("", null); } } } //水位触发reservoir里面的high/low将对应的reservoir切成error if (_resRecipe != null && (ReservoirData.Level < _resRecipe.CALevelErrorLow || ReservoirData.Level > _resRecipe.CALevelErrorHigh)) { if (ReservoirData.Level < _resRecipe.CALevelErrorLow && !reservoirEntity.IsError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current level:{ReservoirData.Level} is lower than recipe's CA Errorlow paramater:{_resRecipe.CALevelErrorLow}"); } if (ReservoirData.Level > _resRecipe.CALevelErrorHigh && !reservoirEntity.IsError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current level:{ReservoirData.Level} is larger than recipe's CA Errorlow paramater:{_resRecipe.CALevelErrorHigh}"); } reservoirEntity.PostMsg(ReservoirMsg.Error); } //触发Safetyhigh将reservoir切成error SafetyDevice safetyDevice = DEVICE.GetDevice("Safety"); if (safetyDevice != null && safetyDevice.SafetyData.ReservoirHighLevel && !reservoirEntity.IsError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Safety high is Activate"); reservoirEntity.PostMsg(ReservoirMsg.Error); } //DIReplen _direplenHelper.MonitorPeriodTime(); if (_currentOperation == ReservoirOperation.ManualDiReplen && _reservoirData.DiReplen) { bool result = _direplenHelper.MonitorManualDiReplenComplete(_manualReplenSecond, DIReplenOff); if (result) { _currentOperation = ReservoirOperation.None; } } else if (_currentOperation == ReservoirOperation.AutoDiReplen && _reservoirData.DiReplen) { bool result = _direplenHelper.AutoDiReplenMonitorTimeOut(DIReplenOff); if (result) { _currentOperation = ReservoirOperation.None; } else { //按液位补水 result = _direplenHelper.AutoDiReplenMonitorComplete(_reservoirData.Level, _resRecipe.ReservoirCALevel, _resRecipe, DIReplenOff); if (result) { _currentOperation = ReservoirOperation.None; } } } if (reservoirEntity == null || !reservoirEntity.IsInitialized) { return true; } if (_persistentValue.OperatingMode == AUTO) { CAFlowRateCheck(); TemperatureCheck(); CMMPowerCheck(); //CMM用电量记录 if (_isExportCMMUsage && _persistentValue.CMMStartTime != DateTime.MinValue) { ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module); if (!string.IsNullOrEmpty(reservoirItem.CMMSupplyID) && _resRecipe != null && _resRecipe.CMMEnable) { CellPowerSupplier powerSupplier = DEVICE.GetDevice(reservoirItem.CMMSupplyID); double cmmUsage = powerSupplier.PowerSupplierData.Current * DateTime.Now.Subtract(_persistentValue.CMMStartTime).TotalHours; ReservoirUsageManager.Instance.UpdateReservoirCMMUsage(Module, Math.Round(cmmUsage, 3)); _persistentValue.CMMStartTime = DateTime.Now; ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); _isExportCMMUsage = false; } } } if (_phState == RState.Running) { _phState = _phRoutine.Monitor(); if (_phState == RState.End) { _phRoutineEndTime = DateTime.Now; } } else if (_phState != RState.Init) { double phUpdatePeriod = SC.GetValue("Reservoir.PHUpdatePeriod"); if (DateTime.Now.Subtract(_phRoutineEndTime).TotalMilliseconds >= phUpdatePeriod * 1000) { StartDetectPHValve(); } } if (_replenType != "" && _replenNum != 0) { //DosingSystem 状态监控 _dosingCommonHelper.DoseStatusMonitor(); //Dosing监控 if (_dosingCommonHelper.IsDosingSystemInitialized) { if (_replenPersistentValue["Replen1"].OperatingMode == "Manual") { //ManualDosing _dosingCommonHelper.ManualDoseSystemMonitor(); } if (_replenPersistentValue["Replen1"].OperatingMode == "Auto") { //AutoDosing _dosingCommonHelper.AutoDoseSystemMonitor(); } else { _dosingCommonHelper.CheckDoseOperation(); } } } return true; } /// /// 获取是否需要补水 /// /// private bool GetNeedAutoDireplen() { if (IsAuto&&_resRecipe!=null) { if (_resRecipe.DIReplenEnable && _resRecipe.DIReplenCurrentRate == 0 && _resRecipe.DIReplenTimeRate == 0) { double levelHysteresis = SC.GetValue("Reservoir.LevelHysteresis"); return ReservoirData.Level < _resRecipe.ReservoirCALevel - levelHysteresis; } return false; } else { return false; } } /// /// 初始化 /// /// public bool Initialize() { InitializeRoutine(); InitializeParameter(); SubscribeData(); InitializeOperation(); SubscribeValueAction(); return true; } /// /// 初始化routine /// private void InitializeRoutine() { _phRoutine = new StandardHotPHRoutine(Module); } /// /// 初始化参数 /// private void InitializeParameter() { _persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(Module.ToString()); if (_persistentValue == null) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module.ToString(), "Persistent Value Object is not exist"); } else { if (!string.IsNullOrEmpty(_persistentValue.Recipe)) { _resRecipe = RecipeFileManager.Instance.LoadGenericityRecipe(_persistentValue.Recipe); } _direplenHelper = new ReservoirDiReplenHelper(Module, _persistentValue); } ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module.ToString()); if (reservoirItem != null) { foreach (var item in reservoirItem.MetalCells) { if (item.ModuleName != Module) { StandardHotMetalDevice metalDevice = DEVICE.GetDevice(item.ModuleName); if (metalDevice != null) { _metalDevices.Add(metalDevice); } } } } _isCAFlowRateWARN = new List(new bool[_metalDevices.Count]); //DosingSystem数据初始化 _replenType = reservoirItem.ChemReplenType; _replenNum = reservoirItem.ChemReplenPumps; if (_replenType != "" && _replenNum != 0) { _replenDatas = new ReplenData[_replenNum]; _rdsRecipe = new RdsRecipe[_replenNum]; _replenLevelLst = new List(new bool[_replenNum]); _currentDosingOperation = new List(); for (int i = 0; i < _replenNum; i++) { string replenName = "Replen" + (i + 1).ToString(); _replenDatas[i] = new ReplenData(); _replenDatas[i].ReplenName = replenName; _replenDatas[i].RecipeName = ""; _replenDatas[i].BottleLevel = DosingSystemHelper.BottleLevelState.Empty.ToString(); _replenDatas[i].IsAutoDosingError = false; if(_dosingSystemHelperLst==null) _dosingSystemHelperLst = new List (); _dosingSystemHelperLst.Add(new DosingSystemHelper(Module, _replenDatas[i].ReplenName)); _currentDosingOperation.Add(DosingOperation.None); _replenPersistentValue[replenName] = ReplenPersistentManager.Instance.GetReplenPersistentValue(Module, replenName); } _dosingCommonHelper = new DosingCommonHelper(Module, _replenNum); } } /// /// 订阅数据 /// private void SubscribeData() { DATA.Subscribe($"{Module}.DIValveMaxOnTime", () => SC.GetValue($"Reservoir.{Module}.DIValveMaxOnTime")*60, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.IsManualReplen", () => { return _currentOperation == ReservoirOperation.ManualDiReplen; }, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.ReservoirData", () => _reservoirData, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.ReservoirAverageLevel", () => _avgLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _persistentValue,SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.ReplenPersistentValue", () => _replenPersistentValue, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.PHValue", () => _avaragePH, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.CurrentRecipe", () => _resRecipe, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.ReplenType", () => _replenType, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.ReplenNum", () => _replenNum, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.ReplenDatas", () => _replenDatas, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.DosingSystemState", () => _dosingCommonHelper != null ? _dosingCommonHelper.DosingSystemState : null, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.RecipeName", () => (_resRecipe != null ? _resRecipe.Ppid : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.HedFlow", () => _reservoirData.HedFlow, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.PHEnable",()=>_reservoirData.PHFlowValve, SubscriptionAttribute.FLAG.IgnoreSaveDB); } /// /// 初始化操作 /// private void InitializeOperation() { 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); OP.Subscribe($"{Module}.DiReplenOn", DIReplenOnOperation); OP.Subscribe($"{Module}.DiReplenOff", DIReplenOff); OP.Subscribe($"{Module}.ManualDiReplen", ManualDiReplen); OP.Subscribe($"{Module}.ResetTotalTime", ResetTotalTime); OP.Subscribe($"{Module}.LoadRecipe", LoadRecipeOperation); OP.Subscribe($"{Module}.LoadDosingRecipe", LoadDosingRecipeOperation); OP.Subscribe($"{Module}.ReplenPumpOn", ReplenPumpOnOperation); OP.Subscribe($"{Module}.ReplenPumpOff", ReplenPumpOffOperation); OP.Subscribe($"{Module}.SetPumpFactor", SetPumpFactor); OP.Subscribe($"{Module}.ManualDosing", ManualDosing); OP.Subscribe($"{Module}.StopManualDosing", StopManualDosing); OP.Subscribe($"{Module}.ResetBottleVolume", ResetBottleVolume); OP.Subscribe($"{Module}.DosingInitialize", DosingInitialize); } #region Operation /// /// 重置时长 /// /// /// /// private bool ResetTotalTime(string cmd, object[] objs) { _persistentValue.TotalReplen = 0; _persistentValue.LastTotalReplen = 0; ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); return true; } /// /// DisabledAction /// /// /// /// private bool DisabledOperation(string cmd, object[] args) { string currentOperation = "Disabled"; if (args.Length >= 1 && (bool)args[0]) { foreach(var replenData in ReplenDatas) { if (_replenPersistentValue != null && _replenPersistentValue[replenData.ReplenName] != null) { _replenPersistentValue[replenData.ReplenName].OperatingMode = currentOperation; ReplenPersistentManager.Instance.UpdatePersistentValue(Module, replenData.ReplenName); } } for (int i = 0; i < _replenNum; i++) { string replenName = "Replen" + (i + 1).ToString(); if (_replenPersistentValue[replenName].IsDosingRunning) { _dosingSystemHelperLst[i].StopDosing(); _currentDosingOperation[i] = DosingOperation.None; } } DosingEnterInit(); } else { if (_persistentValue != null) { ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module); if (_persistentValue.OperatingMode == "Auto" && reservoirEntity.IsMetalBusy) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} is Busy, can't change to disable mode"); return false; } foreach (var metalDevice in _metalDevices) { metalDevice.DisabledOperation("", null); MetalEntity metalEntity = Singleton.Instance.GetModule(metalDevice.Module); metalEntity.AbortRecipe(null); metalDevice.EnterDisabledOperation(); } EnterDisabledOperation(); if (_persistentValue.OperatingMode != "Disabled") reservoirEntity.EnterInit(); _persistentValue.OperatingMode = currentOperation; } ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); _currentOperation = ReservoirOperation.None; } return true; } /// /// ManualAction /// /// /// /// private bool ManualOperation(string cmd, object[] args) { string currentOperation = "Manual"; if (args.Length >= 1 && (bool)args[0]) { foreach (var replenData in ReplenDatas) { if (_replenPersistentValue != null && _replenPersistentValue[replenData.ReplenName] != null) { _replenPersistentValue[replenData.ReplenName].OperatingMode = currentOperation; ReplenPersistentManager.Instance.UpdatePersistentValue(Module, replenData.ReplenName); } } DosingEnterInit(); } else { ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module); if (reservoirEntity == null) return false; if (_persistentValue != null) { if (_persistentValue.OperatingMode == "Auto" && reservoirEntity.IsMetalBusy) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} is Busy, can't change to manual mode"); return false; } foreach (var metalDevice in _metalDevices) { metalDevice.ManualOperation("", null); } if (_persistentValue.OperatingMode != "Manual" && reservoirEntity != null) reservoirEntity.EnterInit(); _persistentValue.OperatingMode = currentOperation; } ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); _currentOperation = ReservoirOperation.None; } return true; } /// /// AutoAction /// /// /// /// private bool AutoOperation(string cmd, object[] args) { if (!_reservoirData.LowLevel) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Lowlevel was activate"); return false; } string currentOperation = "Auto"; if (args.Length >= 1 && (bool)args[0]) { foreach (var replenData in ReplenDatas) { if (_replenPersistentValue != null && _replenPersistentValue[replenData.ReplenName] != null) { _replenPersistentValue[replenData.ReplenName].OperatingMode = currentOperation; ReplenPersistentManager.Instance.UpdatePersistentValue(Module, replenData.ReplenName); } } DosingEnterInit(); } else { if (_persistentValue != null) { ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module); if (_persistentValue.OperatingMode != "Auto" && reservoirEntity != null) reservoirEntity.EnterInit(); _persistentValue.OperatingMode = currentOperation; } ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); } return true; } /// /// EngineeringModeAction /// /// /// /// private bool EngineeringModeOperation(string cmd, object[] args) { string currentRecipeOperation = "Engineering"; if (_persistentValue != null) { _persistentValue.RecipeOperatingMode = currentRecipeOperation; } ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); return true; } /// /// ProductionAction /// /// /// /// private bool ProductionModeOperation(string cmd, object[] args) { string currentRecipeOperation = "Production"; if (_persistentValue != null) { _persistentValue.RecipeOperatingMode = currentRecipeOperation; } ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); return true; } /// /// 加载Recipe /// /// /// /// private bool LoadRecipeOperation(string cmd, object[] args) { _persistentValue.Recipe = args[0].ToString(); string[] fileRoute = _persistentValue.Recipe.Split('\\'); string recipeRoute = ""; if (fileRoute.Length > 2) { recipeRoute = fileRoute[fileRoute.Length - 2]; } try { _resRecipe = RecipeFileManager.Instance.LoadGenericityRecipe(_persistentValue.Recipe); ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module.ToString()); LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Load {recipeRoute} Recipe {_resRecipe.Ppid} Success"); } catch { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Load {recipeRoute} Recipe {_persistentValue.Recipe} failed"); } return true; } /// /// DiReplen On /// /// /// /// public bool DIReplenOnOperation(string cmd, object[] args) { return DIReplenOn(true); } /// /// 自动注水 /// /// public bool DIReplenOn(bool showError) { if (ReservoirData.WaterLevel > SC.GetValue($"Reservoir.{Module}.HighLevel")) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Highlevel is activate"); return false; } if (!_reservoirData.LowLevel) //信号是相反的 { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"WaterLevel low is Activate"); return false; } bool preCondition = CheckPreDiReplenCondition(showError); if (!preCondition) { return false; } string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{DI_REPLEN}"); bool result = IOModuleManager.Instance.WriteIoValue(ioName, true); if (result) { _persistentValue.IsDiReplenOn = true; } return result; } /// /// 检验DiReplen前置条件 /// /// public bool CheckPreDiReplenCondition(bool showError) { if (!CheckFacilitiesDiReplenStatus()&&showError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Facilities DiReplen is Off"); return false; } SafetyDevice safetyDevice = DEVICE.GetDevice("Safety"); if (safetyDevice != null && safetyDevice.SafetyData.ReservoirHighLevel) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Safety high is Activate"); return false; } if (CheckOtherReservoirDiReplenStatus(showError)) { return false; } return true; } /// /// 检验总Di有没有开 /// /// private bool CheckFacilitiesDiReplenStatus() { SystemFacilities systemFacilities = DEVICE.GetDevice("System.Facilities"); if(systemFacilities!=null) { return systemFacilities.DIReplenEnable; } return false; } /// /// 检验是否其他Reservoir Direplen已经 /// /// private bool CheckOtherReservoirDiReplenStatus(bool showError) { List reservoirs = ReservoirItemManager.Instance.InstalledModules; foreach (string item in reservoirs) { if(item!=Module) { ReservoirItem reservoirItem=ReservoirItemManager.Instance.GetReservoirItem(item); if(reservoirItem.SubType==STRATUS) { StandardHotReservoirDevice tmpDevice = DEVICE.GetDevice(item); if(tmpDevice.ReservoirData.DiReplen && showError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{item} direplen valve is on"); return true; } } else { CompactMembranReservoirDevice tmpDevice = DEVICE.GetDevice(item); if(tmpDevice.ReservoirData.ANDiReplen&&showError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{item} ANDireplen valve is on"); return true; } if(tmpDevice.ReservoirData.CADiReplen && showError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{item} CADireplen valve is on"); return true; } } } } return false; } /// /// DiReplen Off /// /// /// /// private bool DIReplenOff(string cmd, object[] args) { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{DI_REPLEN}"); bool result= IOModuleManager.Instance.WriteIoValue(ioName, false); if(result) { _persistentValue.IsDiReplenOn = false; if(_currentOperation==ReservoirOperation.ManualDiReplen||_currentOperation==ReservoirOperation.AutoDiReplen) { _currentOperation = ReservoirOperation.None; _persistentValue.LastTotalReplen = _persistentValue.TotalReplen; ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); } } return result; } /// /// 手动注水 /// /// /// /// private bool ManualDiReplen(string cmd, object[] args) { if(_currentOperation!=ReservoirOperation.None) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"current operation is {_currentOperation},cannot execute ManualDireplen operation"); return false; } bool result = DIReplenOnOperation("", null); if(result) { _currentOperation = ReservoirOperation.ManualDiReplen; _persistentValue.DiReplenTime = DateTime.Now; ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); int.TryParse(args[0].ToString(), out _manualReplenSecond); } return result; } /// /// 自动注水 /// /// public bool AutoDireplen() { if (!_reservoirData.LowLevel && !_isAutoDIReplenError) { _isAutoDIReplenError = true; LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"LowLevel is activate,Can't AutoDireplen"); return false; } else { _isAutoDIReplenError = false; } if (_currentOperation != ReservoirOperation.None) { return false; } if(_resRecipe==null) { return false; } bool result = DIReplenOn(false); if(result) { _currentOperation = ReservoirOperation.AutoDiReplen; _persistentValue.DiReplenTime = DateTime.Now; } return result; } /// /// 启动PH检测 /// public bool StartDetectPHValve() { if(_persistentValue.OperatingMode==MANUAL) { return false; } _phState= _phRoutine.Start(); LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, "Start Detect PH"); return true; } /// /// 打开PH Valve /// /// public bool PHValveOn() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PH_FLOW_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, true); } /// /// 关闭PH Valve /// /// public bool PHValveOff() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PH_FLOW_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, false); } /// /// CAFlowRateCheck /// private void CAFlowRateCheck() { ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module); if (_resRecipe == null) return; for (int i = 0; i < _metalDevices.Count; i++) { StandardHotMetalDevice hotMetalDevice = _metalDevices[i]; if (hotMetalDevice != null && !hotMetalDevice.IsDisable && hotMetalDevice.IsAuto) { if (hotMetalDevice.MetalDeviceData == null || !hotMetalDevice.MetalDeviceData.Circulation) continue; if (!hotMetalDevice.FlowValveStable) continue; double cellFlow = hotMetalDevice.MetalDeviceData.CellFlow; if (cellFlow < _resRecipe.CAFlowRateErrorLow) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"cell {hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateErrorLow parameter:{_resRecipe.CAFlowRateErrorLow}"); reservoirEntity.PostMsg(ReservoirMsg.Error); } else if (cellFlow < _resRecipe.CAFlowRateWarningLow) { if (!_isCAFlowRateWARN[i]) { LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"cell {hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateWarningLow parameter:{_resRecipe.CAFlowRateWarningLow}"); _isCAFlowRateWARN[i] = true; } } else { _isCAFlowRateWARN[i] = false; } } } } /// /// Temperature Check /// private void TemperatureCheck() { ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module); ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module); TemperatureController temperatureController = DEVICE.GetDevice(reservoirItem.TCID); if (temperatureController == null || temperatureController.TemperatureData == null || _resRecipe == null || temperatureController.TemperatureData.ControlOperationModel != ENABLE) return; double tempValue = temperatureController.TemperatureData.ReserviorTemperature; if (tempValue > _resRecipe.TemperatureErrorHigh && !reservoirEntity.IsError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{temperatureController.Name} temperature:{tempValue} is over recipe's TemperatureErrorHigh parameter:{_resRecipe.TemperatureErrorHigh}"); reservoirEntity.PostMsg(ReservoirMsg.Error); } else if (tempValue < _resRecipe.TemperatureErrorLow && !reservoirEntity.IsError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{temperatureController.Name} temperature:{tempValue} is less than recipe's TemperatureErrorLow parameter:{_resRecipe.TemperatureErrorLow}"); reservoirEntity.PostMsg(ReservoirMsg.Error); } else if (tempValue > _resRecipe.TemperatureWarningHigh) { if (!_isTCControlWARN) { LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{temperatureController.Name} temperature:{tempValue} is over recipe's TemperatureWarningHigh parameter:{_resRecipe.TemperatureWarningHigh}"); _isTCControlWARN = true; } } else if (tempValue < _resRecipe.TemperatureWarningLow) { if (!_isTCControlWARN) { LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{temperatureController.Name} temperature:{tempValue} is less than recipe's TemperatureWarningLow parameter:{_resRecipe.TemperatureWarningLow}"); _isTCControlWARN = true; } } else { _isTCControlWARN = false; } } /// /// CMMPowerCheck /// private void CMMPowerCheck() { ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module); ReservoirItem _reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module.ToString()); if (!string.IsNullOrEmpty(_reservoirItem.CMMSupplyID)) { CellPowerSupplier _powerSupplier = DEVICE.GetDevice(_reservoirItem.CMMSupplyID); if (_powerSupplier == null || _powerSupplier.PowerSupplierData == null || _resRecipe == null || !_resRecipe.CMMEnable||!_powerSupplier.PowerSupplierData.Enabled || _powerSupplier.PowerSupplierData.Current == 0) return; //CMM Current Check double current = _powerSupplier.PowerSupplierData.Current; if (current > _resRecipe.CMMCurrentSetPoint * (1 + (double)_resRecipe.CMMCurrentFaultPercent / 100)) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{_powerSupplier.Name} current:{current} is over error upper limit:{_resRecipe.CMMCurrentSetPoint * (1 + (double)_resRecipe.CMMCurrentFaultPercent / 100)} based on recipe's CMMCurrentFaultPercent parameter:{_resRecipe.CMMCurrentFaultPercent} %"); reservoirEntity.PostMsg(ReservoirMsg.Error); if (_powerSupplier.PowerSupplierData.Enabled) { _powerSupplier.DisableOperation("", null); _persistentValue.CMMStartTime = DateTime.MinValue; ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); } } else if (current < _resRecipe.CMMCurrentSetPoint * (1 - (double)_resRecipe.CMMCurrentFaultPercent / 100)) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{_powerSupplier.Name} current:{current} is less than error lower limit:{_resRecipe.CMMCurrentSetPoint * (1 - (double)_resRecipe.CMMCurrentFaultPercent / 100)} based on recipe's CMMCurrentFaultPercent parameter:{_resRecipe.CMMCurrentFaultPercent}%"); reservoirEntity.PostMsg(ReservoirMsg.Error); if (_powerSupplier.PowerSupplierData.Enabled) { _powerSupplier.DisableOperation("", null); _persistentValue.CMMStartTime = DateTime.MinValue; ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module); } } else if (current > _resRecipe.CMMCurrentSetPoint * (1 + (double)_resRecipe.CMMCurrentWarningPercent / 100)) { if (!_isCMMPowerCurrentWARN) { LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{_powerSupplier.Name} current:{current} is over warning upper limit:{_resRecipe.CMMCurrentSetPoint * (1 + (double)_resRecipe.CMMCurrentWarningPercent / 100)} based on recipe's CMMCurrentWarningPercent parameter:{_resRecipe.CMMCurrentWarningPercent}%"); _isCMMPowerCurrentWARN = true; } } else if (current < _resRecipe.CMMCurrentSetPoint * (1 - (double)_resRecipe.CMMCurrentWarningPercent / 100)) { if (!_isCMMPowerCurrentWARN) { LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{_powerSupplier.Name} current:{current} is less than warning lower limit{_resRecipe.CMMCurrentSetPoint * (1 - (double)_resRecipe.CMMCurrentWarningPercent / 100)} based on recipe's CMMCurrentWarningPercent parameter:{_resRecipe.CMMCurrentWarningPercent}%"); _isCMMPowerCurrentWARN = true; } } else { _isCMMPowerCurrentWARN = false; } //CMM Voltage Check double voltage = _powerSupplier.PowerSupplierData.Voltage; if (voltage < _resRecipe.CMMMinVoltage) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{_powerSupplier.Name} voltage:{voltage} is less than recipe's CMMMinVoltage parameter:{_resRecipe.CMMMinVoltage}"); reservoirEntity.PostMsg(ReservoirMsg.Error); if (_powerSupplier.PowerSupplierData.Enabled) _powerSupplier.DisableOperation("", null); } //CMM Flow Check double flow = ReservoirData.Flow; double cmmFlowHighFault = SC.GetValue($"Reservoir.CMM.CMMFlowHighFault"); double cmmFlowHighWarning = SC.GetValue($"Reservoir.CMM.CMMFlowHighWarning"); double cmmFlowLowFault = SC.GetValue($"Reservoir.CMM.CMMFlowLowFault"); double cmmFlowLowWarning = SC.GetValue($"Reservoir.CMM.CMMFlowLowWarning"); if (flow < cmmFlowLowFault) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} CMM flow:{flow} is less than config item CMMFlowLowFault:{cmmFlowLowFault}"); if (_powerSupplier.PowerSupplierData.Enabled) _powerSupplier.DisableOperation("", null); reservoirEntity.PostMsg(ReservoirMsg.Error); } else if (flow < cmmFlowLowWarning) { if (!_isCMMPowerFlowWARN) { LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} CMM flow:{flow} is less than config item CMMFlowLowWarning:{cmmFlowLowWarning}"); _isCMMPowerFlowWARN = true; } } else if (flow > cmmFlowHighFault) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} CMM flow:{flow} is over config item CMMFlowHighFault:{cmmFlowLowFault}"); if(_powerSupplier.PowerSupplierData.Enabled) _powerSupplier.DisableOperation("", null); reservoirEntity.PostMsg(ReservoirMsg.Error); } else if (flow > cmmFlowHighWarning) { if (!_isCMMPowerFlowWARN) { LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} CMM flow:{flow} is over config item CMMFlowHighWarning:{cmmFlowLowWarning}"); _isCMMPowerFlowWARN = true; } } else { _isCMMPowerFlowWARN = false; } } } #region DosingSystem /// /// 加载Replen Recipe /// /// /// /// private bool LoadDosingRecipeOperation(string cmd, object[] args) { string replenName = args[1].ToString(); int replenID = int.Parse(args[1].ToString().Substring(6,1)); string replenRecipe = args[0].ToString(); _rdsRecipe[replenID-1] = RecipeFileManager.Instance.LoadGenericityRecipe(replenRecipe); _replenDatas[replenID-1].RecipeName = args[2].ToString(); LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Load Replen Recipe {_rdsRecipe[replenID-1].Ppid} Success"); return true; } #region Replen Pump /// /// Replen Pump On 操作(根据PumpFactor和InitialDosingSpeed调速) /// /// /// /// public bool ReplenPumpOnOperation(string cmd, object[] args) { string replenName = args[0].ToString(); int replenID = int.Parse(args[0].ToString().Substring(6, 1)); //加载InitialDosingSpeed double InitialDosingSpeed = 0; if (SC.ContainsItem($"Reservoir.{Module}.InitialDosingSpeed")) { InitialDosingSpeed = SC.GetValue($"Reservoir.{Module}.InitialDosingSpeed"); if(InitialDosingSpeed == 0) { _replenDatas[replenID - 1].ReplenPumpEnable = false; LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "InitialDosingSpeed is zero. Can't open replen pump"); return false; } } else { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Configuration item of InitialDosingSpeed doesn't exist!"); return false; } //加载ReplenPumpFactor double PumpFactor = 0; PumpFactor = _replenPersistentValue[replenName].ReplenPumpFactor; if(PumpFactor == 0) { _replenDatas[replenID - 1].ReplenPumpEnable = false; LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "PumpFactor is zero. Can't open replen pump"); return false; } //计算PumpSpeed(mL/min) double replenPumpSpeed = InitialDosingSpeed * PumpFactor; SCConfigItem item = SC.GetConfigItem($"Reservoir.{Module}.InitialDosingSpeed"); double speedMax = double.Parse(item.Max); if(replenPumpSpeed > speedMax) replenPumpSpeed = speedMax; bool result = ReplenPump(replenPumpSpeed / PUMP_SPEED_CONVERT, replenID); if (!result) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Opening replen{replenID} pump is failed"); _replenDatas[replenID - 1].ReplenPumpSpeed = 0; _replenDatas[replenID - 1].ReplenPumpEnable = false; return false; } _replenDatas[replenID - 1].ReplenPumpSpeed = replenPumpSpeed; _replenDatas[replenID - 1].ReplenPumpEnable = true; LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Replen{replenID} pump is opened"); return true; } /// /// Replen Pump Off操作 /// /// /// /// public bool ReplenPumpOffOperation(string cmd, object[] args) { string replenName = args[0].ToString(); int replenID = int.Parse(args[0].ToString().Substring(6, 1)); bool result = ReplenPump(0, replenID); if (!result) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Closing replen{replenID} pump is failed"); return false; } _replenDatas[replenID - 1].ReplenPumpSpeed = 0; _replenDatas[replenID - 1].ReplenPumpEnable = false; LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Replen{replenID} pump is closed"); return true; } /// /// Replen Pump WriteIOValue /// /// /// private bool ReplenPump(double speed, int replenNum) { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.Replen{replenNum}PumpSpeed"); return IOModuleManager.Instance.WriteIoValue(ioName, speed); } #endregion /// /// 设置PumpFactor /// /// /// /// public bool SetPumpFactor(string cmd, object[] args) { int replenID = int.Parse(args[0].ToString().Substring(6, 1)); double targetPumpFactor = (double)args[1]; _dosingSystemHelperLst[replenID-1].SetPumpfactor(targetPumpFactor); return true; } /// /// 手动Dosing /// /// /// /// private bool ManualDosing(string cmd, object[] args) { ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module); if (reservoirEntity == null || !_dosingCommonHelper.IsDosingSystemInitialized) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Dosing System is not initialized!"); return true; } string replenName = args[0].ToString(); int replenID = int.Parse(args[0].ToString().Substring(6, 1)); double manualDosingVolume = (double)args[1]; if(manualDosingVolume == 0) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Dosing Volume is zero, can't do manual dosing"); return false; } if (!CheckandUpdateBottleLevel(replenName, manualDosingVolume)) { return false; } if (_replenPersistentValue[replenName].IsDosingRunning) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Dosing is runnning, can't do manual dosing"); return false; } LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, "ManualDosing starts now"); _currentDosingOperation[replenID - 1] = DosingOperation.ManualDosing; bool result = _dosingSystemHelperLst[replenID-1].StartDosing(manualDosingVolume, false); return result; } /// /// 停止手动Dosing /// /// /// /// private bool StopManualDosing(string cmd, object[] args) { string replenName = args[0].ToString(); int replenID = int.Parse(args[0].ToString().Substring(6, 1)); if (!_replenPersistentValue[replenName].IsDosingRunning) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "ManualDosing is not running. Can't stop!"); } _currentDosingOperation[replenID - 1] = DosingOperation.None; bool result = _dosingSystemHelperLst[replenID - 1].StopDosing(); if (result) { LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, "ManualDosing has stopped now"); } return result; } /// /// 检查并更新BottleLevel状态 /// /// /// public bool CheckandUpdateBottleLevel(string replenName, double targetVolume = -1, bool isError = true) { int replenId = int.Parse(replenName.Substring(6, 1)); double remainVolume = _replenPersistentValue[replenName].RemainDosingVolume; bool result = true; if (ReservoirData.ReplenLevel[replenId - 1]) { ReplenDatas[replenId - 1].BottleLevel = DosingSystemHelper.BottleLevelState.Full.ToString(); if (targetVolume > remainVolume) { ReplenDatas[replenId - 1].BottleLevel = DosingSystemHelper.BottleLevelState.Warning.ToString(); if (isError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current Bottle is in Warning Level!"); } result = false; } } else { ReplenDatas[replenId - 1].BottleLevel = DosingSystemHelper.BottleLevelState.Empty.ToString(); if (isError) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Current Bottle is in Empty Level!"); } result = false; } return result; } /// /// Reset BottleVolume /// /// /// /// private bool ResetBottleVolume(string cmd, object[] args) { string replenName = args[0].ToString(); int replenID = int.Parse(args[0].ToString().Substring(6, 1)); if (SC.ContainsItem($"Reservoir.{Module}.BottleReserveVolume{replenID}")) { _replenPersistentValue[replenName].RemainDosingVolume = SC.GetValue($"Reservoir.{Module}.BottleReserveVolume{replenID}"); } ReplenPersistentManager.Instance.UpdatePersistentValue(Module, replenName); LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Bottle Reserve Volume of Replen{replenID} has been reset now"); return true; } /// /// DosingSystem初始化 /// /// /// /// private bool DosingInitialize(string cmd, object[] args) { ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(Module); if (reservoirEntity == null || !reservoirEntity.IsInitialized) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} is not initialized"); return false; } return _dosingCommonHelper.DosingInitialize(); ; } /// /// Enetr Init State /// /// /// /// private bool DosingEnterInit() { return _dosingCommonHelper.DosingEnterInit(); } #endregion /// /// Enter Disabled Operation /// private void EnterDisabledOperation() { ReservoirItem _reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module.ToString()); //关CMMPower if (!string.IsNullOrEmpty(_reservoirItem.CMMSupplyID)) { CellPowerSupplier powerSupplier = DEVICE.GetDevice(_reservoirItem.CMMSupplyID); if(powerSupplier != null && powerSupplier.PowerSupplierData.Enabled) powerSupplier.DisableOperation("", null); } //关TC if (!string.IsNullOrEmpty(_reservoirItem.TCID)) { TemperatureController temperatureController = DEVICE.GetDevice(_reservoirItem.TCID); if(temperatureController != null) temperatureController.DisableOperation("", null); } _phRoutine.Abort(); if (_reservoirData.PHFlowValve) { PHValveOff(); } if (_reservoirData.DiReplen) { DIReplenOff("", null); } } /// /// Set Export CMMUsage /// public void SetExportCMMUsage() { _isExportCMMUsage = true; } #endregion /// /// 订阅变量数值发生变化 /// private void SubscribeValueAction() { BeckhoffIoSubscribeUpdateVariable(FLOW); BeckhoffIoSubscribeUpdateVariable(HED_FLOW); BeckhoffIoSubscribeUpdateVariable(DI_REPLEN); BeckhoffIoSubscribeUpdateVariable(PH_FLOW_VALVE); BeckhoffIoSubscribeUpdateVariable(PH_VALUE); BeckhoffIoSubscribeUpdateVariable(WATER_LEVEL); BeckhoffIoSubscribeUpdateVariable(LOW_LEVEL); BeckhoffIoSubscribeUpdateVariable(HIGH_LEVEL); for(int i = 0;i < _replenNum;i++) { BeckhoffIoSubscribeUpdateVariable($"Replen{i+1}Level"); } } /// /// 订阅IO变量 /// /// private void BeckhoffIoSubscribeUpdateVariable(string variable) { _variableInitializeDic[variable] = false; IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue); } /// /// 更新变量数值 /// /// /// private void UpdateVariableValue(string variable, object value) { if (!ReservoirData.IsDataInitialized) { ReservoirData.IsDataInitialized = true; } PropertyInfo property = ReservoirData.GetType().GetProperty(variable); if (property != null) { property.SetValue(_reservoirData, value); if(variable==WATER_LEVEL) { string levelCurve = SC.GetStringValue($"Reservoir.{Module}.LevelCurve"); ReservoirData.Level = LevelCurveManager.Instance.CalculateLevelByWaterLevel(ReservoirData.WaterLevel, levelCurve); } } if (variable.Contains("Replen") && variable.Substring(0,6) == "Replen") { property = ReservoirData.GetType().GetProperty(REPLEN_LEVEL); _replenLevelLst[int.Parse(variable.Substring(6, 1)) - 1] = (bool)value; property.SetValue(_reservoirData, _replenLevelLst); } if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable]) { _variableInitializeDic[variable] = true; } } /// /// 是否所有IO变量初始化完成 /// /// private bool AllIoVariableInitialized() { foreach (string item in _variableInitializeDic.Keys) { if (!_variableInitializeDic[item]) { LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{item} is not initialized"); return false; } } return true; } public void Monitor() { } public void Reset() { } public void Terminate() { } } }