HoribaConnection.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. using Aitex.Core.RT.Device;
  2. using Aitex.Core.RT.Event;
  3. using Aitex.Core.RT.Log;
  4. using Aitex.Core.RT.SCCore;
  5. using Aitex.Core.Util;
  6. using MECF.Framework.Common.Communications;
  7. using MECF.Framework.Common.Device.Bases;
  8. using MECF.Framework.Common.Equipment;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.IO.Ports;
  12. using System.Linq;
  13. using System.Threading;
  14. namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.MFCs.HoribaMFC
  15. {
  16. public class HoribaMessage : BinaryMessage
  17. {
  18. public string DeviceAddress { get; set; }
  19. public string Action { get; set; }
  20. public string Parameter { get; set; }
  21. public int DataLength { get; set; }
  22. public string ErrorText { get; set; }
  23. public byte[] Datas { get; set; }
  24. }
  25. public class HoribaConnection : SerialPortConnectionBase
  26. {
  27. private const int STX = 0x02;
  28. private const int ETX = 0x03;
  29. private const int NAK = 0x15;
  30. private List<byte> _lstCacheBuffer = new List<byte>();
  31. private PeriodicJob _thread;
  32. private bool _activeMonitorStatus;
  33. private R_TRIG _trigWarningMessage = new R_TRIG();
  34. private R_TRIG _trigCommunicationError = new R_TRIG();
  35. private R_TRIG _trigRetryConnect = new R_TRIG();
  36. private LinkedList<HandlerBase> _lstHandler = new LinkedList<HandlerBase>();
  37. private object _locker = new object();
  38. private bool _enableLog = true;
  39. private bool _isFirstTime = true;
  40. private int _reconnectCount = 0;
  41. private DeviceTimer _QueryScaleTimer = new DeviceTimer();
  42. private readonly int _QueryScaleInterval = 3000;
  43. private List<MfcBase> MFCList = new List<MfcBase>();
  44. private Dictionary<string, string> _slaveAddress = new Dictionary<string, string>();
  45. public event Action<string, float> OnFlowReadout; // address, data
  46. public event Action<string, string> OnUnitReadout; // address, unit
  47. private string _scRoot;
  48. public HoribaConnection(string module, string name, string scRoot) : base(SC.GetStringValue($"{scRoot}.Address"), 38400, 7, Parity.Odd, StopBits.One, "\r", false)
  49. {
  50. _activeMonitorStatus = true;
  51. Module = module;
  52. Name = name;
  53. _scRoot = scRoot;
  54. _enableLog = SC.GetValue<bool>($"{_scRoot}.EnableLogMessage");
  55. EnableLog(_enableLog);
  56. if (Connect())
  57. {
  58. EV.PostInfoLog(Module, $"{Module}.{Name} connected");
  59. }
  60. Thread.Sleep(2000);
  61. if (SC.ContainsItem("System.IsSimulatorMode") && SC.GetValue<bool>("System.IsSimulatorMode"))
  62. _thread = new PeriodicJob(200, OnTimer, $"{Module}.{Name} MonitorHandler", true);
  63. else
  64. _thread = new PeriodicJob(100, OnTimer, $"{Module}.{Name} MonitorHandler", true);
  65. }
  66. public string Module { get; set; }
  67. public string Name { get; set; }
  68. private bool OnTimer()
  69. {
  70. try
  71. {
  72. MonitorTimeout();
  73. if (!IsConnected || IsCommunicationError)
  74. {
  75. _trigRetryConnect.CLK = !IsConnected;
  76. if (_trigRetryConnect.Q)
  77. {
  78. EV.PostAlarmLog(Module, $"Disconnect with {Module}.{Name} {SC.GetStringValue($"{_scRoot}.Address")}");
  79. _reconnectCount = 0;
  80. }
  81. if (_reconnectCount <= SC.GetValue<int>($"{_scRoot}.ReconnectCount"))
  82. {
  83. //SetPortAddress(SC.GetStringValue($"{Module}.MFCSerialPortName"));
  84. Connect();
  85. Thread.Sleep(2000);
  86. if (IsConnected)
  87. {
  88. Reset();
  89. EV.PostInfoLog(Module, $"Reconnect with {Module}.{Name} {SC.GetStringValue($"{_scRoot}.Address")} successed");
  90. }
  91. else
  92. {
  93. EV.PostWarningLog(Module, $"Can not connect with {Module}.{Name} {SC.GetStringValue($"{_scRoot}.Address")}, retry {_reconnectCount}");
  94. Thread.Sleep(1000);
  95. }
  96. }
  97. lock (_locker)
  98. {
  99. _lstHandler.Clear();
  100. _reconnectCount++;
  101. }
  102. return true;
  103. }
  104. HandlerBase handler = null;
  105. if (!IsBusy)
  106. {
  107. lock (_locker)
  108. {
  109. if (_lstHandler.Count == 0 && _activeMonitorStatus)
  110. {
  111. foreach (var key in _slaveAddress.Keys)
  112. {
  113. _lstHandler.AddLast(new HoribaMFCQueryFlow(this, _slaveAddress[key]));
  114. if (_QueryScaleTimer.IsTimeout())
  115. _lstHandler.AddLast(new HoribaMFCQueryScale(this, _slaveAddress[key]));
  116. if (_isFirstTime)
  117. {
  118. _lstHandler.AddLast(new HoribaMFCQueryScale(this, _slaveAddress[key]));
  119. _lstHandler.AddLast(new HoribaMFCSetDigitalMode(this, _slaveAddress[key]));
  120. }
  121. }
  122. if (_QueryScaleTimer.IsTimeout())
  123. _QueryScaleTimer.Start(_QueryScaleInterval);
  124. _isFirstTime = false;
  125. }
  126. if (_lstHandler.Count > 0)
  127. {
  128. handler = _lstHandler.First.Value;
  129. _lstHandler.RemoveFirst();
  130. }
  131. }
  132. if (handler != null)
  133. {
  134. Execute(handler);
  135. }
  136. }
  137. EnableLog(_enableLog);
  138. _trigCommunicationError.CLK = IsCommunicationError;
  139. if (_trigCommunicationError.Q)
  140. {
  141. EV.PostAlarmLog(Module, $"{Module}.{Name} communication error");
  142. }
  143. }
  144. catch (Exception ex)
  145. {
  146. LOG.Write(ex);
  147. }
  148. return true;
  149. }
  150. public void AddHandler(HandlerBase handler)
  151. {
  152. lock (_locker)
  153. {
  154. _lstHandler.AddLast(handler);
  155. }
  156. }
  157. public void AddMFC(MfcBase mfc)
  158. {
  159. MFCList.Add(mfc);
  160. }
  161. public void AddSlaveAddress(string name, string address)
  162. {
  163. _slaveAddress.Add(name, address.PadLeft(2, '0'));
  164. }
  165. public void SetFlow(string address, float flow)
  166. {
  167. lock (_locker)
  168. {
  169. _lstHandler.AddLast(new HoribaMFCSetFlow(this, address, flow));
  170. }
  171. }
  172. public void NoteFlowReadout(string address, float flow)
  173. {
  174. if (OnFlowReadout != null)
  175. OnFlowReadout(address, flow);
  176. }
  177. public void NoteUnitReadout(string address, string unit)
  178. {
  179. if (OnUnitReadout != null)
  180. OnUnitReadout(address, unit);
  181. }
  182. public void Reset()
  183. {
  184. _trigWarningMessage.RST = true;
  185. SetCommunicationError(false, "");
  186. _trigCommunicationError.RST = true;
  187. _enableLog = SC.GetValue<bool>($"{_scRoot}.EnableLogMessage");
  188. _trigRetryConnect.RST = true;
  189. _reconnectCount = 0;
  190. }
  191. public override bool SendMessage(byte[] message)
  192. {
  193. _lstCacheBuffer.Clear();
  194. return base.SendMessage(message);
  195. }
  196. public void Terminate()
  197. {
  198. }
  199. public void SetError(byte[] content)
  200. {
  201. string reason = System.Text.Encoding.ASCII.GetString(content);
  202. _trigWarningMessage.CLK = true;
  203. if (_trigWarningMessage.Q)
  204. {
  205. EV.PostWarningLog(Module, $"{Module}.{Name} error, {reason}");
  206. }
  207. }
  208. protected override MessageBase ParseResponse(byte[] rawMessage)
  209. {
  210. _lstCacheBuffer.AddRange(rawMessage);
  211. byte[] temps = _lstCacheBuffer.ToArray();
  212. HoribaMessage msg = new HoribaMessage();
  213. msg.IsResponse = false;
  214. msg.IsAck = false;
  215. msg.IsComplete = false;
  216. msg.RawMessage = _lstCacheBuffer.ToArray();
  217. if (_lstCacheBuffer.Count < 4 || _lstCacheBuffer[_lstCacheBuffer.Count - 2] != ETX)
  218. return msg;
  219. if (temps.Length > 0 && (int)temps[0] == NAK)
  220. {
  221. LOG.Error($"NAK, " + temps);
  222. msg.IsNak = true;
  223. return msg;
  224. }
  225. if (temps.Length < 4)
  226. {
  227. LOG.Error($"text length check failed");
  228. msg.IsFormatError = true;
  229. return msg;
  230. }
  231. if ((int)temps[0] != STX)
  232. {
  233. LOG.Error($"text check STX failed");
  234. msg.IsFormatError = true;
  235. return msg;
  236. }
  237. int etxIndex = 0;
  238. foreach (var item in temps)
  239. {
  240. if ((int)item == ETX)
  241. break;
  242. etxIndex++;
  243. }
  244. if (etxIndex >= temps.Length)
  245. {
  246. LOG.Error($"text check ETX failed");
  247. msg.IsFormatError = true;
  248. return msg;
  249. }
  250. msg.DataLength = etxIndex - 1;
  251. msg.Datas = new byte[etxIndex - 1];
  252. ///STX msg ETX BCC
  253. Array.Copy(temps, 1, msg.Datas, 0, etxIndex - 1);
  254. var bcc = (int)temps[etxIndex + 1];
  255. int checkBCC = 0;
  256. foreach (var item in msg.Datas)
  257. {
  258. checkBCC += (int)item;
  259. }
  260. checkBCC += ETX;
  261. if (checkBCC % 128 != bcc)
  262. {
  263. LOG.Error($"check BCC failed");
  264. msg.IsFormatError = true;
  265. return msg;
  266. }
  267. msg.IsResponse = true;
  268. msg.IsAck = true;
  269. msg.IsComplete = true;
  270. return msg;
  271. }
  272. }
  273. }