IoCylinder.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. using System;
  2. using System.Xml;
  3. using Aitex.Core.Common.DeviceData;
  4. using Aitex.Core.RT.DataCenter;
  5. using Aitex.Core.RT.Event;
  6. using Aitex.Core.RT.IOCore;
  7. using Aitex.Core.RT.Log;
  8. using Aitex.Core.RT.OperationCenter;
  9. using Aitex.Core.Util;
  10. namespace Aitex.Core.RT.Device.Unit
  11. {
  12. public class IoCylinder : BaseDevice, IDevice
  13. {
  14. private DIAccessor _diON;
  15. private DIAccessor _diOFF;
  16. private DOAccessor _doON;
  17. private DOAccessor _doOFF;
  18. private CylinderState _operation;
  19. private DeviceTimer _timer = new DeviceTimer();
  20. private R_TRIG _trigReset = new R_TRIG();
  21. private R_TRIG _trigError = new R_TRIG();
  22. public bool EnableOpen { get; set; }
  23. public bool EnableClose { get; set; }
  24. public int SetPoint
  25. {
  26. get
  27. {
  28. if (_doON.Value && _doOFF.Value) return (int)CylinderState.Error;
  29. if (_doON.Value && !_doOFF.Value) return (int)CylinderState.Open;
  30. if (!_doON.Value && _doOFF.Value) return (int)CylinderState.Close;
  31. if (!_doON.Value && !_doOFF.Value) return (int)CylinderState.Unknown;
  32. return (int)CylinderState.Unknown;
  33. }
  34. }
  35. public CylinderState State
  36. {
  37. get
  38. {
  39. if (_diON != null && _diOFF != null)
  40. {
  41. if (ONFeedback && _diOFF.Value)
  42. return CylinderState.Error;
  43. if (ONFeedback && !_diOFF.Value)
  44. return CylinderState.Open;
  45. if (!ONFeedback && _diOFF.Value)
  46. return CylinderState.Close;
  47. if (!ONFeedback && !_diOFF.Value)
  48. return CylinderState.Unknown;
  49. }
  50. return CylinderState.Unknown;
  51. }
  52. }
  53. public bool ONFeedback
  54. {
  55. get { return _diON != null && _diON.Value; }
  56. }
  57. public bool OFFFeedback
  58. {
  59. get { return _diOFF != null && _diOFF.Value; }
  60. }
  61. public bool ONSetPoint
  62. {
  63. get
  64. {
  65. return _doON != null && _doON.Value;
  66. }
  67. set
  68. {
  69. if (_doON != null && _doON.Check(value, out _))
  70. _doON.Value = value;
  71. }
  72. }
  73. public bool OFFSetPoint
  74. {
  75. get
  76. {
  77. return _doOFF != null && _doOFF.Value;
  78. }
  79. set
  80. {
  81. if (_doOFF != null && _doOFF.Check(value, out _))
  82. _doOFF.Value = value;
  83. }
  84. }
  85. private AITCylinderData DeviceData
  86. {
  87. get
  88. {
  89. AITCylinderData deviceData = new AITCylinderData
  90. {
  91. Module = Module,
  92. DeviceName = Name,
  93. DeviceSchematicId = DeviceID,
  94. DisplayName = Display,
  95. OpenFeedback = ONFeedback,
  96. CloseFeedback = OFFFeedback,
  97. OpenSetPoint = ONSetPoint,
  98. CloseSetPoint = OFFSetPoint
  99. };
  100. return deviceData;
  101. }
  102. }
  103. //public int Status
  104. //{
  105. // get
  106. // {
  107. // if (OpenFeedback && _diClosed.Value)
  108. // return (int)CylinderState.Error;
  109. // if (OpenFeedback && !_diClosed.Value)
  110. // return (int)CylinderState.Open;
  111. // if (!OpenFeedback && _diClosed.Value)
  112. // return (int)CylinderState.Close;
  113. // if (!OpenFeedback && !_diClosed.Value)
  114. // return (int)CylinderState.Unknown;
  115. // return (int)CylinderState.Unknown;
  116. // }
  117. //}
  118. public IoCylinder(string module, XmlElement node, string ioModule = "")
  119. {
  120. base.Module = module;
  121. base.Name = node.GetAttribute("id");
  122. base.Display = node.GetAttribute("display");
  123. base.DeviceID = node.GetAttribute("schematicId");
  124. _diON = ParseDiNode("diON", node, ioModule);
  125. _diOFF = ParseDiNode("diOFF", node, ioModule);
  126. _doON = ParseDoNode("doON", node, ioModule);
  127. _doOFF = ParseDoNode("doOFF", node, ioModule);
  128. }
  129. public bool Initialize()
  130. {
  131. DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
  132. OP.Subscribe($"{Module}.{Name}.{AITCylinderOperation.Open}", InvokeOpenCylinder);
  133. OP.Subscribe($"{Module}.{Name}.{AITCylinderOperation.Close}", InvokeCloseCylinder);
  134. DEVICE.Register($"{Module}.{Name}.{AITCylinderOperation.Open}", (out string reason, int time, object[] param) =>
  135. {
  136. bool ret = SetCylinder(true, out reason);
  137. if (ret)
  138. {
  139. reason = string.Format("Open Cylinder {0}", Name);
  140. return true;
  141. }
  142. return false;
  143. });
  144. DEVICE.Register($"{Module}.{Name}.{AITCylinderOperation.Close}", (out string reason, int time, object[] param) =>
  145. {
  146. bool ret = SetCylinder(false, out reason);
  147. if (ret)
  148. {
  149. reason = string.Format("Close Cylinder {0}", Name);
  150. return true;
  151. }
  152. return false;
  153. });
  154. return true;
  155. }
  156. private bool InvokeOpenCylinder(string arg1, object[] arg2)
  157. {
  158. string reason;
  159. if (!SetCylinder(true, out reason))
  160. {
  161. EV.PostWarningLog(Module, $"Can not open cylinder {Module}.{Name}, {reason}");
  162. return false;
  163. }
  164. EV.PostInfoLog(Module, $"Open cylinder {Module}.{Name}");
  165. return true;
  166. }
  167. private bool InvokeCloseCylinder(string arg1, object[] arg2)
  168. {
  169. string reason;
  170. if (!SetCylinder(false, out reason))
  171. {
  172. EV.PostWarningLog(Module, $"Can not close cylinder {Module}.{Name}, {reason}");
  173. return false;
  174. }
  175. EV.PostInfoLog(Module, $"Close cylinder {Module}.{Name}");
  176. return true;
  177. }
  178. public void Terminate()
  179. {
  180. OFFSetPoint = false;
  181. ONSetPoint = false;
  182. }
  183. public bool SetCylinder(bool isOpen, out string reason)
  184. {
  185. reason = "";
  186. ONSetPoint = isOpen;
  187. OFFSetPoint = !isOpen;
  188. _operation = isOpen ? CylinderState.Open : CylinderState.Close;
  189. _timer.Start(1000 * 60 * 3);
  190. return true;
  191. }
  192. public void Monitor()
  193. {
  194. try
  195. {
  196. if (_timer.IsTimeout())
  197. {
  198. _timer.Stop();
  199. if (State != _operation)
  200. {
  201. if (_operation == CylinderState.Open)
  202. {
  203. string reason;
  204. if (!_doON.Check(true, out reason))
  205. EV.PostMessage(Module, EventEnum.DefaultAlarm, "Open Cylinder Failed for interlock, " + reason);
  206. else
  207. EV.PostMessage(Module, EventEnum.DefaultAlarm, "Cylinder hold close status");
  208. }
  209. else
  210. {
  211. string reason;
  212. if (!_doON.Check(false, out reason))
  213. EV.PostMessage(Module, EventEnum.DefaultAlarm, "Close Cylinder Failed for interlock, " + reason);
  214. else
  215. EV.PostMessage(Module, EventEnum.DefaultAlarm, "Cylinder hold open status");
  216. }
  217. }
  218. _operation = (CylinderState)SetPoint;
  219. }
  220. else if (_timer.IsIdle())
  221. {
  222. _trigReset.CLK = SetPoint != (int)_operation; // fire event only check at first, SetPoint set by interlock
  223. if (_trigReset.Q)
  224. {
  225. if (_operation == CylinderState.Open)
  226. {
  227. string reason;
  228. if (!_doON.Check(true, out reason))
  229. EV.PostMessage(Module, EventEnum.SwInterlock, Module, string.Format("Cylinder {0} was {1},Reason:{2}", Display, "Close", reason));
  230. else
  231. EV.PostMessage(Module, EventEnum.SwInterlock, Module, string.Format("Cylinder {0} was {1},Reason {2}", Display, "Close", "PLC kept"));
  232. }
  233. else
  234. {
  235. string reason;
  236. if (!_doON.Check(false, out reason))
  237. EV.PostMessage(Module, EventEnum.SwInterlock, Module, string.Format("Cylinder {0} was {1},Reason:{2}", Display, "Open", reason));
  238. else
  239. EV.PostMessage(Module, EventEnum.SwInterlock, Module, string.Format("Cylinder {0} was {1},Reason {2}", Display, "Open", "PLC Kept"));
  240. }
  241. _operation = (CylinderState)SetPoint;
  242. }
  243. }
  244. _trigError.CLK = State == CylinderState.Error;
  245. if (_trigError.Q)
  246. {
  247. EV.PostMessage(Module, EventEnum.DefaultAlarm, "Cylinder in error status");
  248. }
  249. if ((SetPoint == (int)State) && (SetPoint == (int)CylinderState.Open || SetPoint == (int)CylinderState.Close))
  250. {
  251. OFFSetPoint = false;
  252. ONSetPoint = false;
  253. }
  254. }
  255. catch (Exception ex)
  256. {
  257. LOG.Write(ex);
  258. }
  259. }
  260. public void Reset()
  261. {
  262. _trigReset.RST = true;
  263. _trigError.RST = true;
  264. }
  265. }
  266. }