using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using CyberX8_Core; using CyberX8_RT.Modules.Reservoir; using CyberX8_RT.Modules.SRD; using MECF.Framework.Common.Beckhoff.ModuleIO; using MECF.Framework.Common.Persistent.Reservoirs; using MECF.Framework.Common.Persistent.Temperature; using MECF.Framework.Common.ProcessCell; using MECF.Framework.Common.RecipeCenter; using MECF.Framework.Common.ToolLayout; using MECF.Framework.Common.TwinCat; using System; using System.Net; using System.Reflection; namespace CyberX8_RT.Devices.Reservoir { public class DosingSystemHelper { #region 常量 public enum BottleLevelState { Empty, Full, Warning, } public enum DosingOperation { None, ManualDosing, AutoDosing, } #endregion #region 内部变量 /// /// ModuleName /// private string _moduleName; /// /// ReplenName /// private string _replenName; /// /// ReplenID /// private int _replenId; /// /// ReservoirDosingRoutine /// private ReservoirDosingRoutine _reservoirDosingRoutine; /// /// 当前加载Recipoe /// private RdsRecipe _currentRecipe; /// /// 当次自动补液体积 /// private double _autoDosingVolume; /// /// 最小补液体积 /// private double _minDoseAmount; /// /// Replen Persistent /// private ReplenPersistentValue _persistentValue; /// /// Reservoir Usage /// private ReservoirUsage _reservoirUsage; #endregion #region 属性 /// /// 当次自动补液体积 /// public double AutoDosingVolume { get { return _autoDosingVolume; } } /// /// Dosing状态 /// public RState DosingState { get { return _reservoirDosingRoutine.Monitor(); } } #endregion /// /// 构造函数 /// /// public DosingSystemHelper(string moduleName, string replenName) { _moduleName = moduleName; _replenName = replenName; _replenId = int.Parse(replenName.Substring(6, 1)); _persistentValue = ReplenPersistentManager.Instance.GetReplenPersistentValue(_moduleName, _replenName); _reservoirDosingRoutine = new ReservoirDosingRoutine(_moduleName,_replenName); } #region Operation /// /// 开始Dosing /// public bool StartDosing(double targetVolume, bool isAutoMode) { _persistentValue.IsDosingRunning = true; ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName); return _reservoirDosingRoutine.Start(targetVolume, isAutoMode) == RState.Running; } /// /// 停止Dosing /// public bool StopDosing() { _persistentValue.IsDosingRunning = false; ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName); _reservoirDosingRoutine.Abort(); return true; } /// /// Dosing超时监控 /// /// public bool DosingTimeOutMonitor() { RState result = _reservoirDosingRoutine.Monitor(); if(result == RState.Failed || result == RState.Timeout) { return false; } return true; } /// /// 监控AutoDose触发时机 /// /// public bool AutoDosingMonitor() { bool result = false; double targetVolume = 0; double currentDosingAmpHour = 0; _reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName); //最小补液体积 if (SC.ContainsItem($"Reservoir.{_moduleName}.InitialDosingSpeed")) { _minDoseAmount = SC.GetValue($"Reservoir.{_moduleName}.MinDoseAmount"); } //当前电量 if(_reservoirUsage != null) currentDosingAmpHour = _reservoirUsage.TotalUsage; //累计电量(Ah) double deltAmpHour = currentDosingAmpHour - _persistentValue.AutoDosingStartAmpHour; //累计时间(hr) double deltHour = DateTime.Now.Subtract(_persistentValue.AutoDosingStartTime).TotalHours; if (_currentRecipe != null) { if (_currentRecipe.ReplenEnable) { if (_currentRecipe.ReplenCurrentBased) { //基于电量计算DoseVolume targetVolume = deltAmpHour * _currentRecipe.ReplenCurrentBasedRate; _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2); //计算DoseVolume大于MinDoseAmount则开始补液 if (targetVolume > _minDoseAmount) { _autoDosingVolume = targetVolume; result = true; } } else if(_currentRecipe.ReplenTimeBased) { //基于时间计算DoseVolume targetVolume = deltHour / 24 * _currentRecipe.ReplenTimeBasedRate; _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2); //计算DoseVolume大于MinDoseAmount则开始补液 if (targetVolume > _minDoseAmount) { _autoDosingVolume = targetVolume; result = true; } } }else if (_currentRecipe.AutoDoseEnable) { _persistentValue.TargetDosingVolume = _minDoseAmount; if (_currentRecipe.AutoCurrentBased) { //累计电量大于AutoDosingStartAmpHour则开始补液 targetVolume = _minDoseAmount / _currentRecipe.AutoDoseFrequency * deltAmpHour; _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2); if (deltAmpHour > _currentRecipe.AutoDoseFrequency) { result = true; _autoDosingVolume = _minDoseAmount; } } else if (_currentRecipe.AutoTimeBased) { //累计时间大于AutoDoseIdleStartTime则开始补液 targetVolume = _minDoseAmount / _currentRecipe.AutoDoseIdleStartTime * deltHour; _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2); if (deltHour > _currentRecipe.AutoDoseIdleStartTime) { result = true; _autoDosingVolume = _minDoseAmount; } } } } ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName); return result; } /// /// 检查并加载Recipe /// /// /// public bool CheckandLoadRecipe(RdsRecipe recipe) { if (_currentRecipe == recipe) { return true; } else if (_currentRecipe == null) { _currentRecipe = recipe; return true; } else { _currentRecipe = recipe; return false; } } /// /// 记录AutoDosing开始时的时间和电量 /// public void RecordStartData() { _reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName); _persistentValue.AutoDosingStartTime = DateTime.Now; if(_reservoirUsage != null) _persistentValue.AutoDosingStartAmpHour = _reservoirUsage.TotalUsage; ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName); } /// /// 设置PumpFactor /// public void SetPumpfactor(double targetPumpFactor) { _persistentValue.ReplenPumpFactor = targetPumpFactor; ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName); } #endregion } }