PLCEntity.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using Aitex.Core.RT.Fsm;
  5. using Aitex.Core.RT.IOCore;
  6. using Aitex.Core.Util;
  7. using Aitex.Core.RT.Log;
  8. namespace Aitex.Core.RT.PLC
  9. {
  10. public class PLCEntityT<T, TBuffer, TInput, TOutput> : Entity
  11. where T : IDataDevice, new()
  12. where TBuffer : IDataBuffer<TInput, TOutput>, new()
  13. where TInput : struct
  14. where TOutput : struct
  15. {
  16. private T device = default(T);
  17. private Dictionary<string, TBuffer> _buffers = new Dictionary<string,TBuffer>();
  18. //retry
  19. private int error = 0;
  20. private int retryWaitTime = 100;
  21. private int retryTimes = 10;
  22. private R_TRIG errTrig = new R_TRIG();
  23. public enum STATE
  24. {
  25. INIT,
  26. RUNNING,
  27. ERROR, //
  28. };
  29. public enum MSG
  30. {
  31. INIT,
  32. ERROR,
  33. RECOVERY,
  34. RESET,
  35. };
  36. public PLCEntityT()
  37. {
  38. Running = false;
  39. device = new T();
  40. foreach (var type in device.GetTypes())
  41. {
  42. _buffers[type] = new TBuffer();
  43. }
  44. fsm = new StateMachine<PLCEntityT<T, TBuffer, TInput, TOutput>>("PLC", (int)STATE.INIT, 100);
  45. EnterExitTransition<STATE, MSG>(STATE.INIT, null, MSG.INIT, null);
  46. Transition(STATE.INIT, MSG.INIT, OpenDevice, STATE.RUNNING);
  47. Transition(STATE.RUNNING, FSM_MSG.TIMER, Run, STATE.RUNNING);
  48. Transition(STATE.RUNNING, MSG.RESET, Reset, STATE.RUNNING);
  49. Transition(STATE.ERROR, FSM_MSG.TIMER, Retry, STATE.RUNNING);
  50. Transition(STATE.ERROR, MSG.RECOVERY, Recovery, STATE.INIT);
  51. AnyStateTransition(MSG.ERROR, Error, STATE.ERROR);
  52. errTrig.CLK = false;
  53. }
  54. #region FSM Function
  55. private bool OpenDevice(object[] objs)
  56. {
  57. Running = false;
  58. if (!device.Open())
  59. {
  60. PostMsg<MSG>(MSG.ERROR);
  61. return false; //don't change state
  62. }
  63. return true;
  64. }
  65. private bool Run(object[] objs)
  66. {
  67. try
  68. {
  69. foreach (var type in device.GetTypes())
  70. {
  71. try
  72. {
  73. if (!device.IsOpen(type))
  74. {
  75. device.Open(type);
  76. continue;
  77. }
  78. object obj = device.Read<TInput>(type);
  79. if (obj == null)
  80. {
  81. throw new Exception();
  82. }
  83. _buffers[type].Input = (TInput)obj;
  84. Singleton<IOGroupManager>.Instance.Update(type, _buffers[type]);
  85. if (device.Write(type, _buffers[type].Output))
  86. {
  87. errTrig.CLK = false;
  88. error = 0;
  89. }
  90. }
  91. catch (Exception ex)
  92. {
  93. device.Close(type);
  94. LOG.Write(ex);
  95. }
  96. }
  97. }
  98. catch (Exception ex)
  99. {
  100. errTrig.CLK = true;
  101. if (errTrig.Q)
  102. {
  103. LOG.Write(ex);
  104. }
  105. }
  106. Running = true;
  107. return true;
  108. }
  109. private bool Error(object[] objs)
  110. {
  111. //add log
  112. if (error++ > retryTimes || !device.IsOpened)
  113. {
  114. PostMsg(MSG.RECOVERY);
  115. }
  116. return true;
  117. }
  118. private bool Retry(object[] objs)
  119. {
  120. //add log
  121. int elapsed = fsm.ElapsedTime;
  122. if (elapsed > retryWaitTime)
  123. {
  124. return true;
  125. }
  126. return false;
  127. }
  128. //关闭连接
  129. private bool Recovery(object[] objs)
  130. {
  131. device.Close();
  132. return true;
  133. }
  134. private bool Reset(object[] objs)
  135. {
  136. errTrig.RST = true;
  137. return true;
  138. }
  139. #endregion
  140. }
  141. }