DMReservoirDevice.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. using Aitex.Core.RT.Log;
  2. using Aitex.Core.RT.OperationCenter;
  3. using Aitex.Core.RT.SCCore;
  4. using Aitex.Core.Util;
  5. using MECF.Framework.Common.Beckhoff.ModuleIO;
  6. using MECF.Framework.Common.CommonData.Reservoir;
  7. using MECF.Framework.Common.Equipment;
  8. using MECF.Framework.Common.Persistent.Reservoirs;
  9. using MECF.Framework.Common.Persistent.Temperature;
  10. using MECF.Framework.Common.TwinCat;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. namespace PunkHPX8_RT.Devices.Reservoir
  17. {
  18. public class DMReservoirDevice : ReservoirDevice
  19. {
  20. #region 常量
  21. private const string AN_PUMP = "ANPump";
  22. #endregion
  23. #region 内部变量
  24. /// <summary>
  25. /// 默认泵速
  26. /// </summary>
  27. private double _anPumpSpeed = 5000;
  28. #endregion
  29. #region 属性
  30. /// <summary>
  31. /// 检验阳极是否highlevel
  32. /// </summary>
  33. public bool IsANHighLevel { get { return _reservoirData.AnTowerHigh; } }
  34. /// <summary>
  35. /// 检验阳极是否lowlevel
  36. /// </summary>
  37. public bool IsANLowLevel { get { return _reservoirData.AnTowerLow; } }
  38. #endregion
  39. #region Trigger
  40. /// <summary>
  41. /// low WaterLevel trigger
  42. /// </summary>
  43. private R_TRIG _anWaterLevelLowerTrigger = new R_TRIG();
  44. /// <summary>
  45. /// low WaterLevel trigger
  46. /// </summary>
  47. private R_TRIG _anWaterLevelHighTrigger = new R_TRIG();
  48. #endregion
  49. /// <summary>
  50. /// 构造函数
  51. /// </summary>
  52. /// <param name="moduleName"></param>
  53. public DMReservoirDevice(string moduleName) : base(moduleName)
  54. {
  55. }
  56. /// <summary>
  57. /// 订阅变量
  58. /// </summary>
  59. protected override void SubscribeValueAction()
  60. {
  61. base.SubscribeValueAction();
  62. IoSubscribeUpdateVariable(AN_DI_REPLEN);
  63. IoSubscribeUpdateVariable(AN_FLOW);
  64. IoSubscribeUpdateVariable(AN_PUMP_ENABLE);
  65. IoSubscribeUpdateVariable(AN_PUMP_SPEED);
  66. IoSubscribeUpdateVariable(DEGAS_ENABLE);
  67. }
  68. /// <summary>
  69. /// 订阅Operation
  70. /// </summary>
  71. protected override void InitializeOperation()
  72. {
  73. base.InitializeOperation();
  74. OP.Subscribe($"{Module}.ANPumpEnable", AnPumpOnOperation);
  75. OP.Subscribe($"{Module}.ANPumpSpeed", ANPumpSpeedOperation);
  76. OP.Subscribe($"{Module}.ANPumpDisable", AnPumpOffOperation);
  77. OP.Subscribe($"{Module}.ANIsolationOn", (cmd, para) => { return ANIsolationOn(); });
  78. OP.Subscribe($"{Module}.ANIsolationOff", (cmd, para) => { return ANIsolationOff(); });
  79. }
  80. #region AnPump
  81. /// <summary>
  82. /// AN Pump调速
  83. /// </summary>
  84. /// <param name="cmd"></param>
  85. /// <param name="args"></param>
  86. /// <returns></returns>
  87. private bool ANPumpSpeedOperation(string cmd, object[] args)
  88. {
  89. double anMaxPumpSpeed = 0;
  90. if (SC.ContainsItem("Reservoir.ANMaxPumpSpeed"))
  91. {
  92. anMaxPumpSpeed = SC.GetValue<double>("Reservoir.ANMaxPumpSpeed");
  93. }
  94. if (double.TryParse(args[0].ToString(), out double speed))
  95. {
  96. _anPumpSpeed = speed;
  97. if (_anPumpSpeed > anMaxPumpSpeed)
  98. {
  99. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"AN pump speed:{_anPumpSpeed} is over AN max pump speed {anMaxPumpSpeed}!");
  100. return false;
  101. }
  102. return AnPumpSpeed(_anPumpSpeed);
  103. }
  104. else
  105. {
  106. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{args[0]} is nor invalid speed");
  107. return false;
  108. }
  109. }
  110. /// <summary>
  111. /// 设置AN泵速
  112. /// </summary>
  113. /// <param name="caPumpSpeed"></param>
  114. /// <returns></returns>
  115. public bool AnPumpSpeed(double anPumpSpeed)
  116. {
  117. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_PUMP_SPEED}");
  118. return BeckhoffIOManager.Instance.WriteIoValue(ioName, anPumpSpeed);
  119. }
  120. /// <summary>
  121. /// 阳极Pump On
  122. /// </summary>
  123. /// <param name="cmd"></param>
  124. /// <param name="args"></param>
  125. /// <returns></returns>
  126. public bool AnPumpOnOperation(string cmd, object[] args)
  127. {
  128. double caPumpSpeed = SC.GetValue<double>("Reservoir.ANDefaultPumpSpeed");
  129. bool result = AnPumpSpeed(caPumpSpeed);
  130. if (result)
  131. {
  132. string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_PUMP_ENABLE}");
  133. return BeckhoffIOManager.Instance.WriteIoValue(enableIOName, true);
  134. }
  135. else
  136. {
  137. return false;
  138. }
  139. }
  140. /// <summary>
  141. /// 阳极Pump Off
  142. /// </summary>
  143. /// <param name="cmd"></param>
  144. /// <param name="args"></param>
  145. /// <returns></returns>
  146. private bool AnPumpOffOperation(string cmd, object[] args)
  147. {
  148. return AnPumpOff();
  149. }
  150. /// <summary>
  151. /// 关闭阳极Pump
  152. /// </summary>
  153. /// <returns></returns>
  154. public bool AnPumpOff()
  155. {
  156. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_PUMP_ENABLE}");
  157. return BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
  158. }
  159. /// <summary>
  160. /// ANIsolationOn
  161. /// </summary>
  162. /// <returns></returns>
  163. public bool ANIsolationOn()
  164. {
  165. return WriteVariableValue(AN_ISOLATION, true);
  166. }
  167. /// <summary>
  168. /// ANIsolationOff
  169. /// </summary>
  170. /// <returns></returns>
  171. public bool ANIsolationOff()
  172. {
  173. return WriteVariableValue(AN_ISOLATION, false);
  174. }
  175. #endregion
  176. /// <summary>
  177. /// 水位监控
  178. /// </summary>
  179. protected override void WaterLevelMonitor()
  180. {
  181. base.WaterLevelMonitor();
  182. //增加AN tower监控逻辑
  183. _anWaterLevelLowerTrigger.CLK = _reservoirData.AnTowerLow;
  184. _anWaterLevelHighTrigger.CLK = _reservoirData.AnTowerHigh;
  185. if (_anWaterLevelLowerTrigger.Q && !Recipe.ANDIReplenEnable)
  186. {
  187. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"AN tower low is activate and recipe ANDIReplenEnable is false");
  188. //若recipe允许补水且res auto ,需要启动阳极自动补水
  189. }
  190. if (_anWaterLevelHighTrigger.Q && !Recipe.ANDIReplenEnable)
  191. {
  192. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"AN tower high is activate and recipe ANDIReplenEnable is false");
  193. }
  194. }
  195. /// <summary>
  196. /// 补水监控
  197. /// </summary>
  198. protected override void AutoDireplenMonitor()
  199. {
  200. base.AutoDireplenMonitor();
  201. }
  202. /// <summary>
  203. /// 阳极DI Replen On
  204. /// </summary>
  205. /// <param name="cmd"></param>
  206. /// <param name="args"></param>
  207. /// <returns></returns>
  208. private bool ANDiReplenOnOperation(string cmd, object[] args)
  209. {
  210. return ANDiReplenOn();
  211. }
  212. /// <summary>
  213. /// 阳极DI Replen On
  214. /// </summary>
  215. /// <param name="showError"></param>
  216. /// <returns></returns>
  217. private bool ANDiReplenOn()
  218. {
  219. bool preCondition = CheckPreDiReplenCondition();
  220. if (!preCondition)
  221. {
  222. return false;
  223. }
  224. if (IsANHighLevel)
  225. {
  226. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"ANHighLevel is activate,Can't do AN_DIReple");
  227. return false;
  228. }
  229. if (IsANLowLevel)
  230. {
  231. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"ANLowLevel is activate,Can't do AN_DIReple");
  232. return false;
  233. }
  234. if (ReservoirData.CaDiReplen)
  235. {
  236. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "CADiReplen is on");
  237. return false;
  238. }
  239. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_DI_REPLEN}");
  240. return BeckhoffIOManager.Instance.WriteIoValue(ioName, true);
  241. }
  242. /// <summary>
  243. /// 阳极DI Replen Off
  244. /// </summary>
  245. /// <param name="cmd"></param>
  246. /// <param name="args"></param>
  247. /// <returns></returns>
  248. private bool ANDiReplenOff(string cmd, object[] args)
  249. {
  250. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_DI_REPLEN}");
  251. bool result = BeckhoffIOManager.Instance.WriteIoValue(ioName, false);
  252. if (result)
  253. {
  254. _persistentValue.IsDiReplenOn = false;
  255. if (_currentDireplenOperation == DiReplenOperation.ManualANDiReplen || _currentDireplenOperation == DiReplenOperation.AutoANDiReplen)
  256. {
  257. _currentDireplenOperation = DiReplenOperation.None;
  258. _persistentValue.LastTotalReplen = _persistentValue.TotalReplen;
  259. ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
  260. }
  261. }
  262. return result;
  263. }
  264. /// <summary>
  265. /// 手动阳极注水
  266. /// </summary>
  267. /// <param name="cmd"></param>
  268. /// <param name="args"></param>
  269. /// <returns></returns>
  270. private bool ManualANDiReplen(string cmd, object[] args)
  271. {
  272. return ManualDiReplen(ANDiReplenOnOperation, DiReplenOperation.ManualANDiReplen, args[0].ToString());
  273. }
  274. }
  275. }