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()
{
}
}
}