DosingSystemHelper.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. using Aitex.Core.RT.Device;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.SCCore;
  4. using Aitex.Core.Util;
  5. using CyberX8_Core;
  6. using CyberX8_RT.Modules.Reservoir;
  7. using CyberX8_RT.Modules.SRD;
  8. using MECF.Framework.Common.Beckhoff.ModuleIO;
  9. using MECF.Framework.Common.Persistent.Reservoirs;
  10. using MECF.Framework.Common.Persistent.Temperature;
  11. using MECF.Framework.Common.ProcessCell;
  12. using MECF.Framework.Common.RecipeCenter;
  13. using MECF.Framework.Common.ToolLayout;
  14. using MECF.Framework.Common.TwinCat;
  15. using System;
  16. using System.Net;
  17. using System.Reflection;
  18. namespace CyberX8_RT.Devices.Reservoir
  19. {
  20. public class DosingSystemHelper
  21. {
  22. #region 常量
  23. public enum BottleLevelState
  24. {
  25. Empty,
  26. Full,
  27. Warning,
  28. }
  29. public enum DosingOperation
  30. {
  31. None,
  32. ManualDosing,
  33. AutoDosing,
  34. }
  35. #endregion
  36. #region 内部变量
  37. /// <summary>
  38. /// ModuleName
  39. /// </summary>
  40. private string _moduleName;
  41. /// <summary>
  42. /// ReplenName
  43. /// </summary>
  44. private string _replenName;
  45. /// <summary>
  46. /// ReplenID
  47. /// </summary>
  48. private int _replenId;
  49. /// <summary>
  50. /// ReservoirDosingRoutine
  51. /// </summary>
  52. private ReservoirDosingRoutine _reservoirDosingRoutine;
  53. /// <summary>
  54. /// 当前加载Recipoe
  55. /// </summary>
  56. private RdsRecipe _currentRecipe;
  57. /// <summary>
  58. /// 当次自动补液体积
  59. /// </summary>
  60. private double _autoDosingVolume;
  61. /// <summary>
  62. /// 最小补液体积
  63. /// </summary>
  64. private double _minDoseAmount;
  65. /// <summary>
  66. /// Replen Persistent
  67. /// </summary>
  68. private ReplenPersistentValue _persistentValue;
  69. /// <summary>
  70. /// Reservoir Usage
  71. /// </summary>
  72. private ReservoirUsage _reservoirUsage;
  73. #endregion
  74. #region 属性
  75. /// <summary>
  76. /// 当次自动补液体积
  77. /// </summary>
  78. public double AutoDosingVolume { get { return _autoDosingVolume; } }
  79. /// <summary>
  80. /// Dosing状态
  81. /// </summary>
  82. public RState DosingState { get { return _reservoirDosingRoutine.Monitor(); } }
  83. #endregion
  84. /// <summary>
  85. /// 构造函数
  86. /// </summary>
  87. /// <param name="moduleName"></param>
  88. public DosingSystemHelper(string moduleName, string replenName)
  89. {
  90. _moduleName = moduleName;
  91. _replenName = replenName;
  92. _replenId = int.Parse(replenName.Substring(6, 1));
  93. _persistentValue = ReplenPersistentManager.Instance.GetReplenPersistentValue(_moduleName, _replenName);
  94. _reservoirDosingRoutine = new ReservoirDosingRoutine(_moduleName,_replenName);
  95. }
  96. #region Operation
  97. /// <summary>
  98. /// 开始Dosing
  99. /// </summary>
  100. public bool StartDosing(double targetVolume, bool isAutoMode)
  101. {
  102. _persistentValue.IsDosingRunning = true;
  103. ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);
  104. return _reservoirDosingRoutine.Start(targetVolume, isAutoMode) == RState.Running;
  105. }
  106. /// <summary>
  107. /// 停止Dosing
  108. /// </summary>
  109. public bool StopDosing()
  110. {
  111. _persistentValue.IsDosingRunning = false;
  112. ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);
  113. _reservoirDosingRoutine.Abort();
  114. return true;
  115. }
  116. /// <summary>
  117. /// Dosing超时监控
  118. /// </summary>
  119. /// <returns></returns>
  120. public bool DosingTimeOutMonitor()
  121. {
  122. RState result = _reservoirDosingRoutine.Monitor();
  123. if(result == RState.Failed || result == RState.Timeout)
  124. {
  125. return false;
  126. }
  127. return true;
  128. }
  129. /// <summary>
  130. /// 监控AutoDose触发时机
  131. /// </summary>
  132. /// <returns></returns>
  133. public bool AutoDosingMonitor()
  134. {
  135. bool result = false;
  136. double targetVolume = 0;
  137. double currentDosingAmpHour = 0;
  138. _reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName);
  139. //最小补液体积
  140. if (SC.ContainsItem($"Reservoir.{_moduleName}.InitialDosingSpeed"))
  141. {
  142. _minDoseAmount = SC.GetValue<double>($"Reservoir.{_moduleName}.MinDoseAmount");
  143. }
  144. //当前电量
  145. if(_reservoirUsage != null) currentDosingAmpHour = _reservoirUsage.TotalUsage;
  146. //累计电量(Ah)
  147. double deltAmpHour = currentDosingAmpHour - _persistentValue.AutoDosingStartAmpHour;
  148. //累计时间(hr)
  149. double deltHour = DateTime.Now.Subtract(_persistentValue.AutoDosingStartTime).TotalHours;
  150. if (_currentRecipe != null)
  151. {
  152. if (_currentRecipe.ReplenEnable)
  153. {
  154. if (_currentRecipe.ReplenCurrentBased)
  155. {
  156. //基于电量计算DoseVolume
  157. targetVolume = deltAmpHour * _currentRecipe.ReplenCurrentBasedRate;
  158. _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
  159. //计算DoseVolume大于MinDoseAmount则开始补液
  160. if (targetVolume > _minDoseAmount)
  161. {
  162. _autoDosingVolume = targetVolume;
  163. result = true;
  164. }
  165. }
  166. else if(_currentRecipe.ReplenTimeBased)
  167. {
  168. //基于时间计算DoseVolume
  169. targetVolume = deltHour / 24 * _currentRecipe.ReplenTimeBasedRate;
  170. _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
  171. //计算DoseVolume大于MinDoseAmount则开始补液
  172. if (targetVolume > _minDoseAmount)
  173. {
  174. _autoDosingVolume = targetVolume;
  175. result = true;
  176. }
  177. }
  178. }else if (_currentRecipe.AutoDoseEnable)
  179. {
  180. _persistentValue.TargetDosingVolume = _minDoseAmount;
  181. if (_currentRecipe.AutoCurrentBased)
  182. {
  183. //累计电量大于AutoDosingStartAmpHour则开始补液
  184. targetVolume = _minDoseAmount / _currentRecipe.AutoDoseFrequency * deltAmpHour;
  185. _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
  186. if (deltAmpHour > _currentRecipe.AutoDoseFrequency)
  187. {
  188. result = true;
  189. _autoDosingVolume = _minDoseAmount;
  190. }
  191. }
  192. else if (_currentRecipe.AutoTimeBased)
  193. {
  194. //累计时间大于AutoDoseIdleStartTime则开始补液
  195. targetVolume = _minDoseAmount / _currentRecipe.AutoDoseIdleStartTime * deltHour;
  196. _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
  197. if (deltHour > _currentRecipe.AutoDoseIdleStartTime)
  198. {
  199. result = true;
  200. _autoDosingVolume = _minDoseAmount;
  201. }
  202. }
  203. }
  204. }
  205. ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);
  206. return result;
  207. }
  208. /// <summary>
  209. /// 检查并加载Recipe
  210. /// </summary>
  211. /// <param name="recipe"></param>
  212. /// <returns></returns>
  213. public bool CheckandLoadRecipe(RdsRecipe recipe)
  214. {
  215. if (_currentRecipe == recipe)
  216. {
  217. return true;
  218. }
  219. else if (_currentRecipe == null)
  220. {
  221. _currentRecipe = recipe;
  222. return true;
  223. }
  224. else
  225. {
  226. _currentRecipe = recipe;
  227. return false;
  228. }
  229. }
  230. /// <summary>
  231. /// 记录AutoDosing开始时的时间和电量
  232. /// </summary>
  233. public void RecordStartData()
  234. {
  235. _reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName);
  236. _persistentValue.AutoDosingStartTime = DateTime.Now;
  237. if(_reservoirUsage != null) _persistentValue.AutoDosingStartAmpHour = _reservoirUsage.TotalUsage;
  238. ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);
  239. }
  240. /// <summary>
  241. /// 设置PumpFactor
  242. /// </summary>
  243. public void SetPumpfactor(double targetPumpFactor)
  244. {
  245. _persistentValue.ReplenPumpFactor = targetPumpFactor;
  246. ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);
  247. }
  248. #endregion
  249. }
  250. }