EPDDevice.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Security;
  5. using System.ServiceModel;
  6. using System.Text;
  7. using Aitex.Core.RT.DataCenter;
  8. using Aitex.Core.RT.Device;
  9. using Aitex.Core.RT.Event;
  10. using Aitex.Core.RT.Log;
  11. using Aitex.Core.RT.OperationCenter;
  12. using Aitex.Core.RT.SCCore;
  13. using Aitex.Core.Util;
  14. using Aitex.Core.WCF;
  15. using EPInterface;
  16. using EPInterface.Data;
  17. using EPInterface.Datas;
  18. using Venus_RT.Devices;
  19. namespace Aitex.RT.Device.Custom
  20. {
  21. public class EPDDevice : JetEPDBase
  22. {
  23. private PeriodicJob _monitorThead;
  24. private R_TRIG _triggerConnected = new R_TRIG();
  25. private R_TRIG _triggerNotConnected = new R_TRIG();
  26. private int _channel;
  27. private string _channelStatus;
  28. private object _lockerTrigger = new object();
  29. private bool _isEnd = false;
  30. public bool IsEnd
  31. {
  32. get
  33. {
  34. return _isEnd;
  35. }
  36. }
  37. public bool IsConnected
  38. {
  39. get
  40. {
  41. return _triggerConnected.M;
  42. }
  43. }
  44. private int _connectionCounter = 0;
  45. public EPDDevice(string module, string name)// :
  46. // base(module, name, name, name)
  47. {
  48. }
  49. public override bool Initialize()
  50. {
  51. _channel = SC.GetValue<int>($"{Module}.{Name}.ChannelNumber");
  52. DATA.Subscribe($"{Module}.{Name}.IsConnected", ()=> IsConnected);
  53. DATA.Subscribe($"{Module}.{Name}.CurrentChannel", () => _channel);
  54. DATA.Subscribe($"{Module}.{Name}.ChannelStatus", () => _channelStatus);
  55. OP.Subscribe($"{Module}.{Name}.SetConfig", (out string reason, int time, object[] args) => {
  56. if (!IsConnected)
  57. {
  58. LOG.Write(eEvent.WARN_ENDPOINT, Module, $"{Module} {Name} not connected, can not set config");
  59. reason = $"{Module} {Name} not connected, can not set config";
  60. return false;
  61. }
  62. _isEnd = false;
  63. StepStart(args[1].ToString(), Convert.ToInt32(args[0]));
  64. reason = "";
  65. return true;
  66. });
  67. _monitorThead = new PeriodicJob(100, OnTimer, "EPDMonitor", true);
  68. EPDCallbackClient.Instance.Notify += Instance_Notify;
  69. EPDCallbackClient.Instance.Trigger += Instance_Trigger;
  70. return true;
  71. }
  72. public override void RecipeStart(string recipeName)
  73. {
  74. if (!IsConnected)
  75. {
  76. LOG.Write( eEvent.ERR_ENDPOINT, Module, "EPD not connected, call recipe start ignored");
  77. return;
  78. }
  79. EV.PostInfoLog(Module, $"{Module} {Name}, Notify EPD recipe {recipeName} start");
  80. EPDClient.Instance.Service.RecipeStart(_channel, recipeName);
  81. }
  82. public override void RecipeStop()
  83. {
  84. if (!IsConnected)
  85. {
  86. LOG.Write(eEvent.ERR_ENDPOINT, Module, "EPD not connected, call recipe start ignored");
  87. return;
  88. }
  89. EV.PostInfoLog(Module, $"{Module} {Name}, Notify EPD recipe stopped");
  90. EPDClient.Instance.Service.RecipeStop(_channel);
  91. }
  92. /*
  93. * ExposureTime=222;WaveLengthA=2;BinningA=3;WaveLengthB=4;BinningB=6;WaveLengthC=5;BinningC=8;
  94. * WaveLengthD=7;BinningD=9;Fd=1;PrefilterTime=2;PostfilterTime=3;AlgorithmType=Valley;
  95. * Criteria=4;DelayTime=5;ValidationTime=6;ValidationValue=7;
  96. * TimeWindow=8;MinimalTime=9;PostponeTime=10;Control=11;Normalization=12;
  97. * EnablePostponePercent=True;EnableCriterialPercent=True;
  98. * TriggerMode=System.Windows.Controls.ComboBoxItem: Event;IsFaultIfNoTrigger=True;
  99. */
  100. public override void StepStart(string config, int index)
  101. {
  102. if (!IsConnected)
  103. {
  104. LOG.Write(eEvent.ERR_ENDPOINT, Module, "EPD not connected, call step start ignored");
  105. return;
  106. }
  107. EV.PostInfoLog(Module, $"{Module} {Name}, Notify EPD recipe step {index+1} start");
  108. EV.PostInfoLog(Module, $"{Module} {Name}, EPD config {config}");
  109. try
  110. {
  111. EPDConfig epd = new EPDConfig();
  112. epd.nParameterCount = 1;
  113. string[] items = config.Split(';');
  114. foreach (var item in items)
  115. {
  116. if (string.IsNullOrEmpty(item))
  117. continue;
  118. string[] pairs = item.Split('=');
  119. if (pairs.Length != 2)
  120. continue;
  121. switch (pairs[0])
  122. {
  123. case "ExposureTime":
  124. epd.Columns[0].nCCDExposureTime = int.Parse(pairs[1]);
  125. break;
  126. case "WaveLengthA":
  127. epd.Columns[0].nWaveLength[0] = ushort.Parse(pairs[1]);
  128. break;
  129. case "BinningA":
  130. epd.Columns[0].nBinning[0] = ushort.Parse(pairs[1]);
  131. break;
  132. case "WaveLengthB":
  133. epd.Columns[0].nWaveLength[1] = ushort.Parse(pairs[1]);
  134. break;
  135. case "BinningB":
  136. epd.Columns[0].nBinning[1] = ushort.Parse(pairs[1]);
  137. break;
  138. case "WaveLengthC":
  139. epd.Columns[0].nWaveLength[2] = ushort.Parse(pairs[1]);
  140. break;
  141. case "BinningC":
  142. epd.Columns[0].nBinning[2] = ushort.Parse(pairs[1]);
  143. break;
  144. case "WaveLengthD":
  145. epd.Columns[0].nWaveLength[3] = ushort.Parse(pairs[1]);
  146. break;
  147. case "BinningD":
  148. epd.Columns[0].nBinning[3] = ushort.Parse(pairs[1]);
  149. break;
  150. case "Fd":
  151. epd.Columns[0].cFunc = pairs[1];
  152. break;
  153. case "PrefilterTime":
  154. epd.Columns[0].nPreFilterTime = int.Parse(pairs[1]);
  155. break;
  156. case "PostfilterTime":
  157. epd.Columns[0].nPostFilterTime = int.Parse(pairs[1]);
  158. break;
  159. case "AlgorithmType":
  160. epd.Columns[0].algorithmType = MapType(pairs[1]);
  161. break;
  162. case "Criteria":
  163. epd.Columns[0].nCriteria = float.Parse(pairs[1]);
  164. break;
  165. case "DelayTime":
  166. epd.Columns[0].nDelayTime = int.Parse(pairs[1]);
  167. break;
  168. case "ValidationTime":
  169. epd.Columns[0].nValidationTime = int.Parse(pairs[1]);
  170. break;
  171. case "ValidationValue":
  172. epd.Columns[0].nValidationValue = int.Parse(pairs[1]);
  173. break;
  174. case "TimeWindow":
  175. epd.Columns[0].nTimeWindow = int.Parse(pairs[1]);
  176. break;
  177. case "MinimalTime":
  178. epd.Columns[0].nMinimalTime = int.Parse(pairs[1]);
  179. break;
  180. case "PostponeTime":
  181. epd.Columns[0].nPostponeTime = int.Parse(pairs[1]);
  182. break;
  183. case "Control":
  184. epd.Columns[0].bControl = Convert.ToBoolean(pairs[1]);
  185. break;
  186. case "Normalization":
  187. epd.Columns[0].bNormalization = Convert.ToBoolean(pairs[1]);
  188. break;
  189. case "EnablePostponePercent":
  190. epd.Columns[0].bPostponePercent = Convert.ToBoolean(pairs[1]);
  191. break;
  192. case "EnableCriterialPercent":
  193. epd.Columns[0].bCriteriaPercent = Convert.ToBoolean(pairs[1]);
  194. break;
  195. case "EnableEventTrigger":
  196. epd.Columns[0].bEvtTrigger = Convert.ToBoolean(pairs[1]);
  197. break;
  198. }
  199. }
  200. EPDClient.Instance.Service.StartByConfig(_channel, index, $"step{index}", epd);
  201. }
  202. catch (Exception ex)
  203. {
  204. LOG.WriteExeption(ex);
  205. }
  206. }
  207. private AlgorithmType MapType(string type)
  208. {
  209. switch (type)
  210. {
  211. case "Unknown": return AlgorithmType.ALG_NONE;
  212. case "Above_ABS_Value": return AlgorithmType.ALG_RISE_VALUE;
  213. case "Below_ABS_Value": return AlgorithmType.ALG_FALL_VALUE;
  214. case "Drop_Percent": return AlgorithmType.ALG_FALL_PERCENT;
  215. case "Up_Percent": return AlgorithmType.ALG_RISE_PERCENT;
  216. case "Range_In": return AlgorithmType.ALG_RANGE_IN;
  217. case "Gradient": return AlgorithmType.ALG_GRADIENT;
  218. case "Peek": return AlgorithmType.ALG_PEAK;
  219. case "Valley": return AlgorithmType.ALG_VALLEY;
  220. case "Min_Drop_Percent": return AlgorithmType.ALG_MIN_FALL_PERCENT;
  221. case "Min_Up_Percent": return AlgorithmType.ALG_MIN_RISE_PERCENT;
  222. case "Max_Drop_Percent": return AlgorithmType.ALG_MAX_FALL_PERCENT;
  223. case "Max_Up_Percent": return AlgorithmType.ALG_MAX_RISE_PERCENT;
  224. case "Rise_Fall": return AlgorithmType.ALG_RISE_FALL;
  225. case "Fall_Rise": return AlgorithmType.ALG_FALL_RISE;
  226. }
  227. return AlgorithmType.ALG_NONE;
  228. }
  229. public override void StepStop()
  230. {
  231. if (!IsConnected)
  232. {
  233. LOG.Write(eEvent.ERR_ENDPOINT, Module, "EPD not connected, call step stop ignored");
  234. return;
  235. }
  236. EV.PostInfoLog(Module, $"{Module} {Name}, Notify EPD recipe step stopped");
  237. EPDClient.Instance.Service.Stop(_channel);
  238. }
  239. private bool OnTimer()
  240. {
  241. try
  242. {
  243. bool retryConnect = false;
  244. lock (_lockerTrigger)
  245. {
  246. retryConnect = _triggerConnected.M;
  247. if (!_triggerConnected.M)
  248. {
  249. //if (_enableRetry)
  250. {
  251. retryConnect = true;
  252. }
  253. }
  254. if (retryConnect)
  255. {
  256. _connectionCounter++;
  257. if (_connectionCounter > 10000)
  258. _connectionCounter = 1;
  259. _triggerConnected.CLK = _connectionCounter== EPDClient.Instance.Service.Heartbeat(_connectionCounter);
  260. _triggerNotConnected.CLK = !_triggerConnected.M;
  261. if (_triggerConnected.Q)
  262. {
  263. EPDCallbackClient.Instance.Init();
  264. EV.PostInfoLog(Module, $"{Module} {Name}, EPD Connected");
  265. }
  266. if (_triggerConnected.M)
  267. {
  268. _channelStatus = EPDClient.Instance.Service.QueryState(_channel).ToString();
  269. }
  270. if (_triggerNotConnected.Q)
  271. {
  272. EPDCallbackClient.Instance.Stop();
  273. EV.PostWarningLog(Module, $"{Module} {Name}, EPD disconnected");
  274. }
  275. }
  276. }
  277. }
  278. catch (Exception ex)
  279. {
  280. LOG.WriteExeption(ex);
  281. }
  282. return true;
  283. }
  284. private void Instance_Notify(int channel, string e)
  285. {
  286. if (_channel != channel)
  287. return;
  288. EV.PostInfoLog(Module, $"{Module} {Name}, EPD Feedback:{e}");
  289. }
  290. private void Instance_Trigger(int channel, TriggerEventArgs e)
  291. {
  292. if (_channel != channel)
  293. return;
  294. _isEnd = true;
  295. EV.PostInfoLog(Module, $"{Module} {Name}, EPD: {e.Channel}.{e.Name} Triggered");
  296. }
  297. public override void Monitor()
  298. {
  299. }
  300. public override void Terminate()
  301. {
  302. }
  303. public override void Reset()
  304. {
  305. lock (_lockerTrigger)
  306. {
  307. if (!_triggerConnected.M)
  308. {
  309. _triggerConnected.RST = true;
  310. _triggerNotConnected.RST = true;
  311. }
  312. }
  313. }
  314. }
  315. public class EPDCallbackClient : Singleton<EPDCallbackClient>, IEPDCallback
  316. {
  317. public event Action<int, string> Notify;
  318. public event Action<int, TriggerEventArgs> Trigger;
  319. private EPDCallbackServiceClient _service;
  320. public EPDCallbackClient()
  321. {
  322. _service = new EPDCallbackServiceClient(this);
  323. }
  324. public void Init()
  325. {
  326. _service.Register();
  327. }
  328. public void Stop()
  329. {
  330. _service.UnRegister();
  331. }
  332. //public void OnNotify(string channel, string message)
  333. //{
  334. //}
  335. //public void OnTrigger(string channel, string name, long ticket)
  336. //{
  337. //}
  338. public void OnNotify(int channel, EPDEventType EventType, string message)
  339. {
  340. Notify?.Invoke(channel, $"{EventType}:{message}");
  341. }
  342. public void OnTrigger(int channel, string name, long ticket)
  343. {
  344. Trigger?.Invoke(channel, new TriggerEventArgs() { Channel = channel, Name = name, Ticket = ticket });
  345. }
  346. }
  347. public class TriggerEventArgs
  348. {
  349. public int Channel { get; set; }
  350. public string Name { get; set; }
  351. public long Ticket { get; set; }
  352. }
  353. public class EPDCallbackServiceClient : DuplexChannelServiceClientWrapper<IEPDCallbackService>
  354. {
  355. private Guid _clientId = Guid.Empty;
  356. public EPDCallbackServiceClient(IEPDCallback callback) : base(new InstanceContext(callback), "Client_IEPDCallbackService", "IEPDCallbackService")
  357. {
  358. }
  359. public void Register()
  360. {
  361. if (_clientId != Guid.Empty)
  362. UnRegister();
  363. _clientId = Guid.NewGuid();
  364. Invoke(x => x.Register(_clientId));
  365. }
  366. public void UnRegister()
  367. {
  368. Invoke(x => x.UnRegister(_clientId));
  369. }
  370. }
  371. }