| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 | 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 内部变量        /// <summary>        /// ModuleName        /// </summary>        private string _moduleName;        /// <summary>        /// ReplenName        /// </summary>        private string _replenName;        /// <summary>        /// ReplenID        /// </summary>        private int _replenId;        /// <summary>        /// ReservoirDosingRoutine        /// </summary>        private ReservoirDosingRoutine _reservoirDosingRoutine;                /// <summary>        /// 当前加载Recipoe        /// </summary>        private RdsRecipe _currentRecipe;        /// <summary>        /// 当次自动补液体积        /// </summary>        private double _autoDosingVolume;        /// <summary>        /// 最小补液体积        /// </summary>        private double _minDoseAmount;        /// <summary>        /// Replen Persistent        /// </summary>        private ReplenPersistentValue _persistentValue;        /// <summary>        /// Reservoir Usage        /// </summary>        private ReservoirUsage _reservoirUsage;        #endregion        #region 属性        /// <summary>        /// 当次自动补液体积        /// </summary>        public double AutoDosingVolume { get { return _autoDosingVolume; } }        /// <summary>        /// Dosing状态        /// </summary>        public RState DosingState { get { return _reservoirDosingRoutine.Monitor(); } }                #endregion        /// <summary>        /// 构造函数        /// </summary>        /// <param name="moduleName"></param>        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        /// <summary>        /// 开始Dosing        /// </summary>        public bool StartDosing(double targetVolume, bool isAutoMode)         {            _persistentValue.IsDosingRunning = true;            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);            return _reservoirDosingRoutine.Start(targetVolume, isAutoMode) == RState.Running;                  }        /// <summary>        /// 停止Dosing        /// </summary>        public bool StopDosing()        {            _persistentValue.IsDosingRunning = false;            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);                        _reservoirDosingRoutine.Abort();            return true;        }          /// <summary>        /// Dosing超时监控        /// </summary>        /// <returns></returns>        public bool DosingTimeOutMonitor()        {            RState result = _reservoirDosingRoutine.Monitor();            if(result == RState.Failed || result == RState.Timeout)            {                return false;            }            return true;        }        /// <summary>        /// 监控AutoDose触发时机        /// </summary>        /// <returns></returns>        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<double>($"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;        }        /// <summary>        /// 检查并加载Recipe        /// </summary>        /// <param name="recipe"></param>        /// <returns></returns>        public bool CheckandLoadRecipe(RdsRecipe recipe)        {            if (_currentRecipe == recipe)            {                return true;            }            else if (_currentRecipe == null)            {                _currentRecipe = recipe;                return true;            }            else            {                _currentRecipe = recipe;                return false;            }        }        /// <summary>        /// 记录AutoDosing开始时的时间和电量        /// </summary>        public void RecordStartData()        {            _reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName);            _persistentValue.AutoDosingStartTime = DateTime.Now;            if(_reservoirUsage != null) _persistentValue.AutoDosingStartAmpHour = _reservoirUsage.TotalUsage;            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);        }        /// <summary>        /// 设置PumpFactor        /// </summary>        public void SetPumpfactor(double targetPumpFactor)        {            _persistentValue.ReplenPumpFactor = targetPumpFactor;            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);        }                #endregion            }}
 |