| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 | using Aitex.Core.RT.Device;using Aitex.Core.RT.Log;using Aitex.Core.RT.Routine;using Aitex.Core.RT.SCCore;using PunkHPX8_Core;using PunkHPX8_RT.Devices.Reservoir;using MECF.Framework.Common.Persistent.Reservoirs;using MECF.Framework.Common.RecipeCenter;using MECF.Framework.Common.Routine;using System;namespace PunkHPX8_RT.Modules.Reservoir{    public class ReservoirDosingRoutine : RoutineBase, IRoutine    {        private enum DosingStep        {            Dosing_Check_Status,            Dosing_Dispensing,            Dosing_Wait_Complete,            Dosing_Done,            End        }        #region 内部变量        /// <summary>        /// 模块名称        /// </summary>        private string _moduleName;        /// <summary>        /// Replen名称        /// </summary>        private string _replenName;        /// <summary>        /// Replen ID        /// </summary>        private int _replenId;        /// <summary>        /// 本次需要补充的液体体积(mL)        /// </summary>        private double _targetVolume;        /// <summary>        /// RDS Recipe        /// </summary>        private RdsRecipe _rdsRecipe;        /// <summary>        /// 补液开始时间(ms)        /// </summary>        private int _dosingStartTime;        /// <summary>        /// 补液需要消耗的时间(ms)        /// </summary>        private int _dosingTime;        /// <summary>        /// InitialDosingSpeed(mL/min)        /// </summary>        private double _initialDosingSpeed;        /// <summary>        /// Replen Persistent Value        /// </summary>        private ReplenPersistentValue _persistentValue;        /// <summary>        /// 是否为Auto模式        /// </summary>        private bool _isAutoMode;        /// <summary>        /// Dosing超时时间        /// </summary>        private int _dosingOutTime;        #endregion        #region 属性        /// <summary>        /// 状态        /// </summary>        public string State { get { return Runner.CurrentStep.ToString(); } }        #endregion        /// <summary>        /// 构造函数        /// </summary>        /// <param name="name"></param>        public ReservoirDosingRoutine(string module, string replenName) : base(module)        {            _moduleName = module;            _replenName = replenName;            _replenId = int.Parse(_replenName.Substring(6, 1));        }        public void Abort()        {            Runner.Stop($"{_moduleName}_{_replenName} Stop Dosing");        }        public RState Monitor()        {            Runner.Run(DosingStep.Dosing_Check_Status, CheckStatus, _delay_1ms)                .Run(DosingStep.Dosing_Dispensing, Dispensing, _delay_1ms)                .WaitWithStopCondition(DosingStep.Dosing_Wait_Complete, WaitCompleteEndStatus, WaitCompleteErrorStatus, _dosingTime + _dosingOutTime)                .End(DosingStep.Dosing_Done, DoneOperation, _delay_1ms);            return Runner.Status;        }        /// <summary>        /// 启动        /// </summary>        /// <param name="objs"></param>        /// <returns></returns>        public RState Start(params object[] objs)        {            _targetVolume = (double)objs[0];            _isAutoMode = (bool)objs[1];            //加载持久化文件            _persistentValue = ReplenPersistentManager.Instance.GetReplenPersistentValue(_moduleName, _replenName);            if (_persistentValue == null)            {                LOG.WriteLog(eEvent.ERR_RESERVOIR, _moduleName, "Replen Persistent Value Object is not exist");                return RState.Failed;            }                //手动模式下无需Recipe            if (_isAutoMode && _rdsRecipe == null)            {                LOG.WriteLog(eEvent.ERR_RESERVOIR, _moduleName, "RDS recipe is null");                return RState.Failed;            }            if (SC.ContainsItem($"Reservoir.{_moduleName}.DosingOutTime"))            {                _dosingOutTime = (int)SC.GetValue<double>($"Reservoir.{_moduleName}.DosingOutTime") * 60 * 1000;            }            return Runner.Start(_moduleName +"_"+_replenName, "Dosing");        }        #region Operation                      /// <summary>        /// Check Status        /// </summary>        /// <param name="param"></param>        /// <returns></returns>        private bool CheckStatus()        {            return true;        }        /// <summary>        /// Dispensing        /// </summary>        /// <param name="param"></param>        /// <returns></returns>        private bool Dispensing()        {            //计算Dosing时间            if (SC.ContainsItem($"Reservoir.{_moduleName}.InitialDosingSpeed"))            {                _initialDosingSpeed = SC.GetValue<double>($"Reservoir.{_moduleName}.InitialDosingSpeed");                                double pumpFactor = _persistentValue.ReplenPumpFactor;                double adjustSpeed = pumpFactor * _initialDosingSpeed;                SCConfigItem item = SC.GetConfigItem($"Reservoir.{Module}.InitialDosingSpeed");                double speedMax = double.Parse(item.Max);                if(adjustSpeed > speedMax)                {                    _dosingTime = (int)((pumpFactor * _targetVolume / speedMax) * 60 * 1000);                    _initialDosingSpeed = speedMax / pumpFactor;                }                else                {                    _dosingTime = (int)((_targetVolume / _initialDosingSpeed) * 60 * 1000);                }                                                             }            //记录Dosing开始时刻            _dosingStartTime = Environment.TickCount;            //打开Replen Pump            Object[] args = new object[1];            args[0] = _replenName;            return true;        }                      /// <summary>        ///  WaitComplete End        /// </summary>        /// <returns></returns>        private bool WaitCompleteEndStatus()        {            int tick = Environment.TickCount - _dosingStartTime;            //更新实时DosingVolume            _persistentValue.CurrentDosingVolume = Math.Round(tick * (_initialDosingSpeed / 1000 / 60), 2);            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);            if (tick >= _dosingTime)            {                //关闭Replen Pump                Object[] args = new object[1];                args[0] = _replenName;                return true;            }            return false;        }        /// <summary>        ///  WaitComplete Error        /// </summary>        /// <returns></returns>        private bool WaitCompleteErrorStatus()        {            return false;        }        /// <summary>        /// Done Operation        /// </summary>        /// <param name="param"></param>        /// <returns></returns>        private bool DoneOperation()        {            //数据清零                       _persistentValue.CurrentDosingVolume = 0;            _persistentValue.IsDosingRunning = false;            _persistentValue.AutoDosingStartAmpHour = 0;            _persistentValue.AutoDosingStartTime = DateTime.MinValue;            _persistentValue.RemainDosingVolume = Math.Round(_persistentValue.RemainDosingVolume - _targetVolume, 2);            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);            _targetVolume = 0;            _dosingTime = 0;            _dosingStartTime = 0;            return true;        }                #endregion    }}
 |