IOManager.cs 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing.Drawing2D;
  4. using System.Linq;
  5. using System.Xml;
  6. using Aitex.Common.Util;
  7. using Aitex.Core.RT.DataCenter;
  8. using Aitex.Core.RT.Event;
  9. using Aitex.Core.RT.IOCore;
  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 MECF.Framework.RT.Core.IoProviders;
  15. using CyberX8_Core;
  16. namespace MECF.Framework.Common.IOCore
  17. {
  18. public class IoManager : Singleton<IoManager>, IIoBuffer
  19. {
  20. private Dictionary<string, DIAccessor> _diMap = new Dictionary<string, DIAccessor>();
  21. private Dictionary<string, DOAccessor> _doMap = new Dictionary<string, DOAccessor>();
  22. private Dictionary<string, AIAccessor> _aiMap = new Dictionary<string, AIAccessor>();
  23. private Dictionary<string, AOAccessor> _aoMap = new Dictionary<string, AOAccessor>();
  24. private Dictionary<string, Dictionary<int, bool[]>> _diBuffer = new Dictionary<string, Dictionary<int, bool[]>>();
  25. private Dictionary<string, Dictionary<int, bool[]>> _doBuffer = new Dictionary<string, Dictionary<int, bool[]>>();
  26. private Dictionary<string, Dictionary<int, short[]>> _aiBuffer = new Dictionary<string, Dictionary<int, short[]>>();
  27. private Dictionary<string, Dictionary<int, short[]>> _aoBuffer = new Dictionary<string, Dictionary<int, short[]>>();
  28. private Dictionary<string, List<DIAccessor>> _diList = new Dictionary<string, List<DIAccessor>>();
  29. private Dictionary<string, List<DOAccessor>> _doList = new Dictionary<string, List<DOAccessor>>();
  30. private Dictionary<string, List<AIAccessor>> _aiList = new Dictionary<string, List<AIAccessor>>();
  31. private Dictionary<string, List<AOAccessor>> _aoList = new Dictionary<string, List<AOAccessor>>();
  32. private Dictionary<string, List<NotifiableIoItem>> _ioItemList = new Dictionary<string, List<NotifiableIoItem>>();
  33. private PeriodicJob _monitorThread;
  34. public void Initialize(string interlockConfigFile)
  35. {
  36. string reason = string.Empty;
  37. if (!InterlockManager.Instance.Initialize(interlockConfigFile, _doMap, _diMap, out reason))
  38. {
  39. throw new Exception(string.Format("interlock define file found error: \r\n {0}", reason));
  40. }
  41. _monitorThread = new PeriodicJob(200, OnTimer, "IO Monitor Thread", true);
  42. }
  43. public void Initialize()
  44. {
  45. string reason = string.Empty;
  46. string installedModules = SC.GetStringValue("System.InstalledModules");
  47. string[] ary= installedModules.Split(',');
  48. List<string> strList = new List<string>(ary);
  49. string[] pms = { "PMA", "PMB", "PMC", "PMD" };
  50. for (int i = 0; i < pms.Length; i++)
  51. {
  52. string pmName = pms[i];
  53. if (installedModules.Contains(pmName))
  54. {
  55. JetChamber jetChamber = (JetChamber)SC.GetValue<int>($"{pmName}.ChamberType");
  56. var InterlockPMConfigFile = PathManager.GetCfgDir() + "PM" + "\\" + jetChamber.ToString() + "\\" + $"{jetChamber.ToString()}Interlock.xml";
  57. if (!InterlockManager.Instance.Initialize(pmName, InterlockPMConfigFile, _doMap, _diMap, out reason))
  58. {
  59. throw new Exception(string.Format($"{pmName} interlock define file found error: \r\n {reason}"));
  60. }
  61. }
  62. }
  63. if (installedModules.Contains("SETM"))
  64. {
  65. var InterlockTMConfigFile = PathManager.GetCfgDir() + "TM" + "\\" + "SETMInterlock.xml";
  66. if (!InterlockManager.Instance.Initialize("TM", InterlockTMConfigFile, _doMap, _diMap, out reason))
  67. {
  68. throw new Exception(string.Format("TM interlock define file found error: \r\n {0}", reason));
  69. }
  70. }
  71. if (strList.Contains("TM"))
  72. {
  73. var InterlockTMConfigFile = PathManager.GetCfgDir() + "TM" + "\\" + "TMInterlock.xml";
  74. if (!InterlockManager.Instance.Initialize("TM", InterlockTMConfigFile, _doMap, _diMap, out reason))
  75. {
  76. throw new Exception(string.Format("TM interlock define file found error: \r\n {0}", reason));
  77. }
  78. }
  79. _monitorThread = new PeriodicJob(200, OnTimer, "IO Monitor Thread", true);
  80. }
  81. private bool OnTimer()
  82. {
  83. try
  84. {
  85. InterlockManager.Instance.Monitor();
  86. }
  87. catch (Exception ex)
  88. {
  89. LOG.WriteExeption(ex);
  90. }
  91. return true;
  92. }
  93. internal List<Tuple<int, int, string>> GetIONameList(string group, IOType ioType)
  94. {
  95. return null;
  96. }
  97. public bool CanSetDo(string doName, bool onOff, out string reason)
  98. {
  99. return InterlockManager.Instance.CanSetDo(doName, onOff, out reason);
  100. }
  101. public List<DIAccessor> GetDIList(string source)
  102. {
  103. return _diList.ContainsKey(source) ? _diList[source] : null;
  104. }
  105. public List<DOAccessor> GetDOList(string source)
  106. {
  107. return _doList.ContainsKey(source) ? _doList[source] : null;
  108. }
  109. public List<AIAccessor> GetAIList(string source)
  110. {
  111. return _aiList.ContainsKey(source) ? _aiList[source] : null;
  112. }
  113. public List<AOAccessor> GetAOList(string source)
  114. {
  115. return _aoList.ContainsKey(source) ? _aoList[source] : null;
  116. }
  117. public IoManager()
  118. {
  119. //OP.Subscribe("System.SetDoValue", InvokeSetDo);
  120. //OP.Subscribe("System.SetAoValue", InvokeSetAo);
  121. //OP.Subscribe("System.SetAoValue32", InvokeSetAo32);
  122. //OP.Subscribe("System.SetDoValueWithPrivoder", InvokeSetDoWithPrivoder);
  123. //OP.Subscribe("System.SetAoValueWithPrivoder", InvokeSetAoWithPrivoder);
  124. //OP.Subscribe("System.SetAiBuffer", InvokeSetAiBuffer);
  125. //OP.Subscribe("System.SetDiBuffer", InvokeSetDiBuffer);
  126. }
  127. private bool InvokeSetDo(string arg1, object[] args)
  128. {
  129. string name = (string) args[0];
  130. bool setpoint = (bool) args[1];
  131. string reason;
  132. if (!CanSetDo(name, setpoint, out reason))
  133. {
  134. EV.PostWarningLog("System", $"Can not set DO {name} to {setpoint}, {reason}");
  135. return false;
  136. }
  137. DOAccessor do1 = GetIO<DOAccessor>(name);
  138. if (do1 == null)
  139. {
  140. EV.PostWarningLog("System", $"Can not set DO {name} to {setpoint}, not defined do");
  141. return false;
  142. }
  143. if (!do1.SetValue(setpoint, out reason))
  144. {
  145. EV.PostWarningLog("System", $"Can not set DO {name} to {setpoint}, {reason}");
  146. return false;
  147. }
  148. EV.PostInfoLog("System", $"Change DO {name} to {setpoint}");
  149. return true;
  150. }
  151. private bool InvokeSetAo(string arg1, object[] args)
  152. {
  153. string name = (string)args[0];
  154. short setpoint = (short)args[1];
  155. AOAccessor io = GetIO<AOAccessor>(name);
  156. if (io == null)
  157. {
  158. EV.PostWarningLog("System", $"Can not set AO {name} to {setpoint}, not defined do");
  159. return false;
  160. }
  161. io.Value = setpoint;
  162. EV.PostInfoLog("System", $"Change AO {name} to {setpoint}");
  163. return true;
  164. }
  165. private bool InvokeSetAo32(string arg1, object[] args)
  166. {
  167. string name = (string)args[0];
  168. float setpoint = (float)args[1];
  169. AOAccessor io = GetIO<AOAccessor>(name);
  170. if (io == null)
  171. {
  172. EV.PostWarningLog("System", $"Can not set AO {name} to {setpoint}, not defined do");
  173. return false;
  174. }
  175. byte[] flow = BitConverter.GetBytes(setpoint);
  176. int index = io.Index;
  177. Int16 value1= BitConverter.ToInt16(flow, 0);
  178. io.Buffer[index] = value1;
  179. if (io.Index < io.Buffer.Length - 1)
  180. {
  181. Int16 value2 = BitConverter.ToInt16(flow, 2);
  182. io.Buffer[index + 1] = value2;
  183. }
  184. EV.PostInfoLog("System", $"Change AO {name} to {setpoint}");
  185. return true;
  186. }
  187. private bool InvokeSetDoWithPrivoder(string arg1, object[] args)
  188. {
  189. string provider = (string)args[0];
  190. int offset = (int)args[1];
  191. string name = (string)args[2];
  192. bool setpoint = (bool)args[3];
  193. string reason;
  194. if (!CanSetDo(name, setpoint, out reason))
  195. {
  196. EV.PostWarningLog("System", $"Can not set DO {provider}.{name} to {setpoint}, {reason}");
  197. return false;
  198. }
  199. var doList = GetDOList(provider);
  200. if(doList == null)
  201. {
  202. EV.PostWarningLog("System", $"Can not set DO {provider}.{name} to {setpoint}, {reason}");
  203. return false;
  204. }
  205. var doAccessor = doList.FirstOrDefault(x => x.Name == name);
  206. if(doAccessor == default(DOAccessor))
  207. {
  208. EV.PostWarningLog("System", $"Can not set DO {provider}.{name} to {setpoint}, {reason}");
  209. return false;
  210. }
  211. if (!doAccessor.SetValue(setpoint, out reason))
  212. {
  213. EV.PostWarningLog("System", $"Can not set DO {provider}.{name} to {setpoint}, {reason}");
  214. return false;
  215. }
  216. EV.PostInfoLog("System", $"Change DO {provider}.{name} to {setpoint}");
  217. return true;
  218. }
  219. private bool InvokeSetAiBuffer(string arg1, object[] args)
  220. {
  221. string provider = (string)args[0];
  222. int offset = (int)args[1];
  223. short[] buffer = (short [])args[2];
  224. SetAiBuffer(provider, offset, buffer);
  225. return true;
  226. }
  227. private bool InvokeSetDiBuffer(string arg1, object[] args)
  228. {
  229. string provider = (string)args[0];
  230. int offset = (int)args[1];
  231. bool[] buffer = (bool[])args[2];
  232. SetDiBuffer(provider, offset, buffer);
  233. return true;
  234. }
  235. private bool InvokeSetAoWithPrivoder(string arg1, object[] args)
  236. {
  237. string provider = (string)args[0];
  238. int offset = (int)args[1];
  239. string name = (string)args[2];
  240. float setpoint = (float)args[3];
  241. string reason = "";
  242. var aoList = GetAOList(provider);
  243. if (aoList == null)
  244. {
  245. EV.PostWarningLog("System", $"Can not set AO {provider}.{name} to {setpoint}, {reason}");
  246. return false;
  247. }
  248. var aoAccessor = aoList.FirstOrDefault(x => x.Name == name);
  249. if (aoAccessor == default(AOAccessor))
  250. {
  251. EV.PostWarningLog("System", $"Can not set AO {provider}.{name} to {setpoint}, {reason}");
  252. return false;
  253. }
  254. aoAccessor.Value = (short)setpoint;
  255. EV.PostInfoLog("System", $"Change DO {provider}.{name} to {setpoint}");
  256. return true;
  257. }
  258. public T GetIO<T>(string name) where T : class
  259. {
  260. if (typeof(T) == typeof(DIAccessor) && _diMap.ContainsKey(name))
  261. {
  262. return _diMap[name] as T;
  263. }
  264. if (typeof(T) == typeof(DOAccessor) && _doMap.ContainsKey(name))
  265. {
  266. return _doMap[name] as T;
  267. }
  268. if (typeof(T) == typeof(AIAccessor) && _aiMap.ContainsKey(name))
  269. {
  270. return _aiMap[name] as T;
  271. }
  272. if (typeof(T) == typeof(AOAccessor) && _aoMap.ContainsKey(name))
  273. {
  274. return _aoMap[name] as T;
  275. }
  276. return null;
  277. }
  278. public Dictionary<int, bool[]> GetDiBuffer(string source)
  279. {
  280. if (_diBuffer.ContainsKey(source))
  281. {
  282. return _diBuffer[source];
  283. }
  284. return null;
  285. }
  286. public Dictionary<int, bool[]> GetDoBuffer(string source)
  287. {
  288. if (_doBuffer.ContainsKey(source))
  289. {
  290. return _doBuffer[source];
  291. }
  292. return null;
  293. }
  294. public Dictionary<int, short[]> GetAiBuffer(string source)
  295. {
  296. if (_aiBuffer.ContainsKey(source))
  297. {
  298. return _aiBuffer[source];
  299. }
  300. return null;
  301. }
  302. public Dictionary<int, short[]> GetAoBuffer(string source)
  303. {
  304. if (_aoBuffer.ContainsKey(source))
  305. {
  306. return _aoBuffer[source];
  307. }
  308. return null;
  309. }
  310. public void SetDiBuffer(string source, int offset, bool[] buffer)
  311. {
  312. if (_diBuffer.ContainsKey(source) && _diBuffer[source].ContainsKey(offset))
  313. {
  314. for (int i = 0; i < buffer.Length && i < _diBuffer[source][offset].Length; i++)
  315. {
  316. _diBuffer[source][offset][i] = buffer[i];
  317. }
  318. }
  319. }
  320. public void SetAiBuffer(string source, int offset, short[] buffer, int skipSize = 0)
  321. {
  322. if (_aiBuffer.ContainsKey(source) && _aiBuffer[source].ContainsKey(offset))
  323. {
  324. for (int i = 0; i < buffer.Length && i < _aiBuffer[source][offset].Length; i++)
  325. {
  326. _aiBuffer[source][offset][i + skipSize] = buffer[i];
  327. }
  328. }
  329. }
  330. public void SetDoBuffer(string source, int offset, bool[] buffer)
  331. {
  332. if (_doBuffer.ContainsKey(source) && _doBuffer[source].ContainsKey(offset))
  333. {
  334. for (int i = 0; i < buffer.Length && i < _doBuffer[source][offset].Length; i++)
  335. {
  336. _doBuffer[source][offset][i] = buffer[i];
  337. }
  338. }
  339. }
  340. public void SetAoBuffer(string source, int offset, short[] buffer)
  341. {
  342. if (_aoBuffer.ContainsKey(source) && _aoBuffer[source].ContainsKey(offset))
  343. {
  344. for (int i = 0; i < buffer.Length && i < _aoBuffer[source][offset].Length; i++)
  345. {
  346. _aoBuffer[source][offset][i] = buffer[i];
  347. }
  348. }
  349. }
  350. //spin recipe set
  351. public void SetAoBuffer(string source, int offset, short[] buffer, int bufferStartIndex)
  352. {
  353. if (_aoBuffer.ContainsKey(source) && _aoBuffer[source].ContainsKey(offset) && _aoBuffer[source][offset].Length > bufferStartIndex)
  354. {
  355. for (int i = 0; i < buffer.Length && bufferStartIndex + i < _aoBuffer[source][offset].Length; i++)
  356. {
  357. _aoBuffer[source][offset][bufferStartIndex + i] = buffer[i];
  358. }
  359. }
  360. }
  361. public void SetBufferBlock(string provider, List<IoBlockItem> lstBlocks)
  362. {
  363. foreach (var ioBlockItem in lstBlocks)
  364. {
  365. switch (ioBlockItem.Type)
  366. {
  367. case IoType.AI:
  368. if (!_aiBuffer.ContainsKey(provider))
  369. {
  370. _aiBuffer[provider] = new Dictionary<int, short[]>();
  371. }
  372. if (!_aiBuffer[provider].ContainsKey(ioBlockItem.Offset))
  373. {
  374. _aiBuffer[provider][ioBlockItem.Offset] = new short[ioBlockItem.Size];
  375. }
  376. break;
  377. case IoType.AO:
  378. if (!_aoBuffer.ContainsKey(provider))
  379. {
  380. _aoBuffer[provider] = new Dictionary<int, short[]>();
  381. }
  382. if (!_aoBuffer[provider].ContainsKey(ioBlockItem.Offset))
  383. {
  384. _aoBuffer[provider][ioBlockItem.Offset] = new short[ioBlockItem.Size];
  385. }
  386. break;
  387. case IoType.DI:
  388. if (!_diBuffer.ContainsKey(provider))
  389. {
  390. _diBuffer[provider] = new Dictionary<int, bool[]>();
  391. }
  392. if (!_diBuffer[provider].ContainsKey(ioBlockItem.Offset))
  393. {
  394. _diBuffer[provider][ioBlockItem.Offset] = new bool[ioBlockItem.Size];
  395. }
  396. break;
  397. case IoType.DO:
  398. if (!_doBuffer.ContainsKey(provider))
  399. {
  400. _doBuffer[provider] = new Dictionary<int, bool[]>();
  401. }
  402. if (!_doBuffer[provider].ContainsKey(ioBlockItem.Offset))
  403. {
  404. _doBuffer[provider][ioBlockItem.Offset] = new bool[ioBlockItem.Size];
  405. }
  406. break;
  407. }
  408. }
  409. }
  410. List<NotifiableIoItem> SubscribeDiData()
  411. {
  412. List<NotifiableIoItem> result = new List<NotifiableIoItem>();
  413. foreach (var ioDefine in _diMap)
  414. {
  415. NotifiableIoItem di = new NotifiableIoItem()
  416. {
  417. Address = ioDefine.Value.Addr,
  418. Name = ioDefine.Value.Name,
  419. Description = ioDefine.Value.Description,
  420. Index = ioDefine.Value.Index,
  421. BoolValue = ioDefine.Value.Value,
  422. Provider = ioDefine.Value.Provider,
  423. BlockOffset = ioDefine.Value.BlockOffset,
  424. BlockIndex = ioDefine.Value.Index,
  425. };
  426. result.Add(di);
  427. }
  428. return result;
  429. }
  430. List<NotifiableIoItem> SubscribeDoData()
  431. {
  432. List<NotifiableIoItem> result = new List<NotifiableIoItem>();
  433. foreach (var ioDefine in _doMap)
  434. {
  435. NotifiableIoItem io = new NotifiableIoItem()
  436. {
  437. Address = ioDefine.Value.Addr,
  438. Name = ioDefine.Value.Name,
  439. Description = ioDefine.Value.Description,
  440. Index = ioDefine.Value.Index,
  441. BoolValue = ioDefine.Value.Value,
  442. Provider = ioDefine.Value.Provider,
  443. BlockOffset = ioDefine.Value.BlockOffset,
  444. BlockIndex = ioDefine.Value.Index,
  445. };
  446. result.Add(io);
  447. }
  448. return result;
  449. }
  450. List<NotifiableIoItem> SubscribeAiData()
  451. {
  452. List<NotifiableIoItem> result = new List<NotifiableIoItem>();
  453. foreach (var ioDefine in _aiMap)
  454. {
  455. NotifiableIoItem di = new NotifiableIoItem()
  456. {
  457. Address = ioDefine.Value.Addr,
  458. Name = ioDefine.Value.Name,
  459. Description = ioDefine.Value.Description,
  460. Index = ioDefine.Value.Index,
  461. ShortValue = ioDefine.Value.Value,
  462. Provider = ioDefine.Value.Provider,
  463. BlockOffset = ioDefine.Value.BlockOffset,
  464. BlockIndex = ioDefine.Value.Index,
  465. };
  466. result.Add(di);
  467. }
  468. return result;
  469. }
  470. List<NotifiableIoItem> SubscribeAoData()
  471. {
  472. List<NotifiableIoItem> result = new List<NotifiableIoItem>();
  473. foreach (var ioDefine in _aoMap)
  474. {
  475. NotifiableIoItem ao = new NotifiableIoItem()
  476. {
  477. Address = ioDefine.Value.Addr,
  478. Name = ioDefine.Value.Name,
  479. Description = ioDefine.Value.Description,
  480. Index = ioDefine.Value.Index,
  481. ShortValue = ioDefine.Value.Value,
  482. Provider = ioDefine.Value.Provider,
  483. BlockOffset = ioDefine.Value.BlockOffset,
  484. BlockIndex = ioDefine.Value.Index,
  485. };
  486. result.Add(ao);
  487. }
  488. return result;
  489. }
  490. public void SetIoMap(string provider, int blockOffset, List<DIAccessor> ioList)
  491. {
  492. SubscribeIoItemList(provider);
  493. var scConfig = SC.GetConfigItem("System.IsIgnoreSaveDB");
  494. var isIgnoreSaveDB = scConfig != null && scConfig.BoolValue;
  495. foreach (var accessor in ioList)
  496. {
  497. accessor.Provider = provider;
  498. accessor.BlockOffset = blockOffset;
  499. _diMap[accessor.Name] = accessor;
  500. if (!_diList.ContainsKey(provider))
  501. _diList[provider] = new List<DIAccessor>();
  502. _diList[provider].Add(accessor);
  503. _ioItemList[$"{provider}.DIItemList"].Add(new NotifiableIoItem()
  504. {
  505. Address = accessor.Addr,
  506. Name = accessor.Name,
  507. Description = accessor.Description,
  508. Index = accessor.Index,
  509. Provider = provider,
  510. BlockOffset = blockOffset,
  511. BlockIndex = accessor.BlockOffset,
  512. });
  513. if (isIgnoreSaveDB)
  514. {
  515. DATA.Subscribe($"IO.{accessor.Name}", () => accessor.Value, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  516. }
  517. else
  518. {
  519. DATA.Subscribe($"IO.{accessor.Name}", () => accessor.Value);
  520. }
  521. }
  522. }
  523. public void SetIoMap(string provider, int blockOffset, List<DOAccessor> ioList)
  524. {
  525. SubscribeIoItemList(provider);
  526. var scConfig = SC.GetConfigItem("System.IsIgnoreSaveDB");
  527. var isIgnoreSaveDB = scConfig != null && scConfig.BoolValue;
  528. foreach (var accessor in ioList)
  529. {
  530. accessor.Provider = provider;
  531. accessor.BlockOffset = blockOffset;
  532. _doMap[accessor.Name] = accessor;
  533. if (!_doList.ContainsKey(provider))
  534. _doList[provider] = new List<DOAccessor>();
  535. _doList[provider].Add(accessor);
  536. _ioItemList[$"{provider}.DOItemList"].Add(new NotifiableIoItem()
  537. {
  538. Address = accessor.Addr,
  539. Name = accessor.Name,
  540. Description = accessor.Description,
  541. Index = accessor.Index,
  542. Provider = provider,
  543. BlockOffset = blockOffset,
  544. BlockIndex = accessor.BlockOffset,
  545. });
  546. if (isIgnoreSaveDB)
  547. {
  548. DATA.Subscribe($"IO.{accessor.Name}", () => accessor.Value, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  549. }
  550. else
  551. {
  552. DATA.Subscribe($"IO.{accessor.Name}", () => accessor.Value);
  553. }
  554. }
  555. }
  556. public void SetIoMap(string provider, int blockOffset, List<AIAccessor> ioList)
  557. {
  558. SubscribeIoItemList(provider);
  559. var scConfig = SC.GetConfigItem("System.IsIgnoreSaveDB");
  560. var isIgnoreSaveDB = scConfig != null && scConfig.BoolValue;
  561. foreach (var accessor in ioList)
  562. {
  563. accessor.Provider = provider;
  564. accessor.BlockOffset = blockOffset;
  565. _aiMap[accessor.Name] = accessor;
  566. if (!_aiList.ContainsKey(provider))
  567. _aiList[provider] = new List<AIAccessor>();
  568. _aiList[provider].Add(accessor);
  569. _ioItemList[$"{provider}.AIItemList"].Add(new NotifiableIoItem()
  570. {
  571. Address = accessor.Addr,
  572. Name = accessor.Name,
  573. Description = accessor.Description,
  574. Index = accessor.Index,
  575. Provider = provider,
  576. BlockOffset = blockOffset,
  577. BlockIndex = accessor.BlockOffset,
  578. });
  579. if (isIgnoreSaveDB)
  580. {
  581. DATA.Subscribe($"IO.{accessor.Name}", () => accessor.Value, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  582. DATA.Subscribe($"IO32.{accessor.Name}", () =>
  583. {
  584. if (accessor.Index < accessor.Buffer.Length - 1)
  585. {
  586. byte[] high = BitConverter.GetBytes(accessor.Buffer[accessor.Index]);
  587. byte[] low = BitConverter.GetBytes(accessor.Buffer[accessor.Index + 1]);
  588. return BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  589. }
  590. else
  591. {
  592. return accessor.Value;
  593. }
  594. }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  595. }
  596. else
  597. {
  598. DATA.Subscribe($"IO.{accessor.Name}", () => accessor.Value);
  599. DATA.Subscribe($"IO32.{accessor.Name}", () =>
  600. {
  601. if (accessor.Index < accessor.Buffer.Length - 1)
  602. {
  603. byte[] high = BitConverter.GetBytes(accessor.Buffer[accessor.Index]);
  604. byte[] low = BitConverter.GetBytes(accessor.Buffer[accessor.Index + 1]);
  605. return BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  606. }
  607. else
  608. {
  609. return accessor.Value;
  610. }
  611. });
  612. }
  613. }
  614. }
  615. public void SetIoMap(string provider, int blockOffset, List<AOAccessor> ioList)
  616. {
  617. SubscribeIoItemList(provider);
  618. var scConfig = SC.GetConfigItem("System.IsIgnoreSaveDB");
  619. var isIgnoreSaveDB = scConfig != null && scConfig.BoolValue;
  620. foreach (var accessor in ioList)
  621. {
  622. accessor.Provider = provider;
  623. accessor.BlockOffset = blockOffset;
  624. _aoMap[accessor.Name] = accessor;
  625. if (!_aoList.ContainsKey(provider))
  626. _aoList[provider] = new List<AOAccessor>();
  627. _aoList[provider].Add(accessor);
  628. _ioItemList[$"{provider}.AOItemList"].Add(new NotifiableIoItem()
  629. {
  630. Address = accessor.Addr,
  631. Name = accessor.Name,
  632. Description = accessor.Description,
  633. Index = accessor.Index,
  634. Provider = provider,
  635. BlockOffset = blockOffset,
  636. BlockIndex = accessor.BlockOffset,
  637. });
  638. if (isIgnoreSaveDB)
  639. {
  640. DATA.Subscribe($"IO.{accessor.Name}", () => accessor.Value,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  641. DATA.Subscribe($"IO32.{accessor.Name}", () =>
  642. {
  643. if (accessor.Index < accessor.Buffer.Length - 1)
  644. {
  645. byte[] high = BitConverter.GetBytes(accessor.Buffer[accessor.Index]);
  646. byte[] low = BitConverter.GetBytes(accessor.Buffer[accessor.Index + 1]);
  647. return BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  648. }
  649. else
  650. {
  651. return accessor.Value;
  652. }
  653. }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  654. }
  655. else
  656. {
  657. DATA.Subscribe($"IO.{accessor.Name}", () => accessor.Value);
  658. DATA.Subscribe($"IO32.{accessor.Name}", () =>
  659. {
  660. if (accessor.Index < accessor.Buffer.Length - 1)
  661. {
  662. byte[] high = BitConverter.GetBytes(accessor.Buffer[accessor.Index]);
  663. byte[] low = BitConverter.GetBytes(accessor.Buffer[accessor.Index + 1]);
  664. return BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  665. }
  666. else
  667. {
  668. return accessor.Value;
  669. }
  670. });
  671. }
  672. }
  673. }
  674. public void SetIoMap(string provider, int blockOffset, string xmlPathFile, string module="")
  675. {
  676. SubscribeIoItemList(provider);
  677. XmlDocument xml = new XmlDocument();
  678. xml.Load(xmlPathFile);
  679. XmlNodeList lstDi = xml.SelectNodes("IO_DEFINE/Dig_In/DI_ITEM");
  680. var scConfig = SC.GetConfigItem("System.IsIgnoreSaveDB");
  681. var isIgnoreSaveDB = scConfig == null ? false : scConfig.BoolValue;
  682. //<DI_ITEM Index="0" Name="" BufferOffset="0" Addr="0" Description=""/>
  683. List<DIAccessor> diList = new List<DIAccessor>();
  684. foreach (var diItem in lstDi)
  685. {
  686. XmlElement element = diItem as XmlElement;
  687. if (element == null)
  688. continue;
  689. string index = element.GetAttribute("Index");
  690. string bufferOffset = element.GetAttribute("BufferOffset");
  691. if (string.IsNullOrEmpty(bufferOffset))
  692. bufferOffset = index;
  693. string name = element.GetAttribute("Name");
  694. string address = element.GetAttribute("Addr");
  695. string description = element.GetAttribute("Description");
  696. if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(index) || string.IsNullOrEmpty(bufferOffset))
  697. continue;
  698. name = name.Trim();
  699. index = index.Trim();
  700. bufferOffset = bufferOffset.Trim();
  701. string moduleName = string.IsNullOrEmpty(module) ? name : $"{module}.{name}";
  702. int intIndex;
  703. if (!int.TryParse(index, out intIndex))
  704. continue;
  705. int intBufferOffset;
  706. if (!int.TryParse(bufferOffset, out intBufferOffset))
  707. continue;
  708. if (!_diBuffer.ContainsKey(provider) || !_diBuffer[provider].ContainsKey(blockOffset))
  709. {
  710. throw new Exception("Not defined DI buffer from IO provider, " + provider);
  711. }
  712. DIAccessor diAccessor = new DIAccessor(moduleName, intBufferOffset, _diBuffer[provider][blockOffset], _diBuffer[provider][blockOffset]);
  713. diAccessor.IoTableIndex = intIndex;
  714. diAccessor.Addr = address;
  715. diAccessor.Provider = provider;
  716. diAccessor.BlockOffset = blockOffset;
  717. diAccessor.Description = description;
  718. diList.Add(diAccessor);
  719. _diMap[moduleName] = diAccessor;
  720. if (!_diList.ContainsKey(provider))
  721. _diList[provider] = new List<DIAccessor>();
  722. _diList[provider].Add(diAccessor);
  723. _ioItemList[$"{provider}.DIItemList"].Add(new NotifiableIoItem()
  724. {
  725. Address = address,
  726. Name = moduleName,
  727. Description = description,
  728. Index = intIndex,
  729. Provider = provider,
  730. BlockOffset = blockOffset,
  731. BlockIndex = intIndex,
  732. });
  733. if (isIgnoreSaveDB)
  734. {
  735. DATA.Subscribe($"IO.{moduleName}", () => diAccessor.Value, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  736. }
  737. else
  738. {
  739. DATA.Subscribe($"IO.{moduleName}", () => diAccessor.Value);
  740. }
  741. }
  742. XmlNodeList lstDo = xml.SelectNodes("IO_DEFINE/Dig_Out/DO_ITEM");
  743. // < DO_ITEM Index = "0" BufferOffset="0" Name = "" Addr = "0" Description = "" />
  744. foreach (var doItem in lstDo)
  745. {
  746. XmlElement element = doItem as XmlElement;
  747. if (element == null)
  748. continue;
  749. string index = element.GetAttribute("Index");
  750. string bufferOffset = element.GetAttribute("BufferOffset");
  751. if (string.IsNullOrEmpty(bufferOffset))
  752. bufferOffset = index;
  753. string name = element.GetAttribute("Name");
  754. string address = element.GetAttribute("Addr");
  755. string description = element.GetAttribute("Description");
  756. if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(index) || string.IsNullOrEmpty(bufferOffset))
  757. continue;
  758. name = name.Trim();
  759. index = index.Trim();
  760. bufferOffset = bufferOffset.Trim();
  761. string moduleName = string.IsNullOrEmpty(module) ? name : $"{module}.{name}";
  762. int intIndex;
  763. if (!int.TryParse(index, out intIndex))
  764. continue;
  765. int intBufferOffset;
  766. if (!int.TryParse(bufferOffset, out intBufferOffset))
  767. continue;
  768. if (!_doBuffer.ContainsKey(provider) || !_doBuffer[provider].ContainsKey(blockOffset))
  769. {
  770. throw new Exception("Not defined DO buffer from IO provider, " + provider);
  771. }
  772. DOAccessor doAccessor = new DOAccessor(moduleName, intBufferOffset, _doBuffer[provider][blockOffset]);
  773. _doMap[moduleName] = doAccessor;
  774. doAccessor.IoTableIndex = intIndex;
  775. doAccessor.Addr = address;
  776. doAccessor.Provider = provider;
  777. doAccessor.BlockOffset = blockOffset;
  778. doAccessor.Description = description;
  779. if (!_doList.ContainsKey(provider))
  780. _doList[provider] = new List<DOAccessor>();
  781. _doList[provider].Add(doAccessor);
  782. _ioItemList[$"{provider}.DOItemList"].Add(new NotifiableIoItem()
  783. {
  784. Address = address,
  785. Name = moduleName,
  786. Description = description,
  787. Index = intIndex,
  788. Provider = provider,
  789. BlockOffset = blockOffset,
  790. BlockIndex = intIndex,
  791. });
  792. if (isIgnoreSaveDB)
  793. {
  794. DATA.Subscribe($"IO.{moduleName}", () => doAccessor.Value,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  795. }
  796. else
  797. {
  798. DATA.Subscribe($"IO.{moduleName}", () => doAccessor.Value);
  799. }
  800. }
  801. XmlNodeList lstAo = xml.SelectNodes("IO_DEFINE/Ana_Out/AO_ITEM");
  802. // < AO_ITEM Index = "0" BufferOffset="0" Name = "" Addr = "0" Description = "" />
  803. foreach (var aoItem in lstAo)
  804. {
  805. XmlElement element = aoItem as XmlElement;
  806. if (element == null)
  807. continue;
  808. string index = element.GetAttribute("Index");
  809. string bufferOffset = element.GetAttribute("BufferOffset");
  810. if (string.IsNullOrEmpty(bufferOffset))
  811. bufferOffset = index;
  812. string name = element.GetAttribute("Name");
  813. string address = element.GetAttribute("Addr");
  814. string description = element.GetAttribute("Description");
  815. if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(index) || string.IsNullOrEmpty(bufferOffset))
  816. continue;
  817. name = name.Trim();
  818. index = index.Trim();
  819. bufferOffset = bufferOffset.Trim();
  820. string moduleName = string.IsNullOrEmpty(module) ? name : $"{module}.{name}";
  821. int intIndex;
  822. if (!int.TryParse(index, out intIndex))
  823. continue;
  824. int intBufferOffset;
  825. if (!int.TryParse(bufferOffset, out intBufferOffset))
  826. continue;
  827. if (!_aoBuffer.ContainsKey(provider) || !_aoBuffer[provider].ContainsKey(blockOffset))
  828. {
  829. throw new Exception("Not defined AO buffer from IO provider, " + provider);
  830. }
  831. AOAccessor aoAccessor = new AOAccessor(moduleName, intBufferOffset, _aoBuffer[provider][blockOffset]);
  832. _aoMap[moduleName] = aoAccessor;
  833. aoAccessor.IoTableIndex = intIndex;
  834. aoAccessor.Addr = address;
  835. aoAccessor.Provider = provider;
  836. aoAccessor.BlockOffset = blockOffset;
  837. aoAccessor.Description = description;
  838. if (!_aoList.ContainsKey(provider))
  839. _aoList[provider] = new List<AOAccessor>();
  840. _aoList[provider].Add(aoAccessor);
  841. _ioItemList[$"{provider}.AOItemList"].Add(new NotifiableIoItem()
  842. {
  843. Address = address,
  844. Name = moduleName,
  845. Description = description,
  846. Index = intIndex,
  847. Provider = provider,
  848. BlockOffset = blockOffset,
  849. BlockIndex = intIndex,
  850. });
  851. if (isIgnoreSaveDB)
  852. {
  853. DATA.Subscribe($"IO.{moduleName}", () => aoAccessor.Value,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  854. DATA.Subscribe($"IO32.{moduleName}", () =>
  855. {
  856. if (aoAccessor.Index < aoAccessor.Buffer.Length - 1)
  857. {
  858. byte[] high = BitConverter.GetBytes(aoAccessor.Buffer[aoAccessor.Index]);
  859. byte[] low = BitConverter.GetBytes(aoAccessor.Buffer[aoAccessor.Index + 1]);
  860. return BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  861. }
  862. else
  863. {
  864. return aoAccessor.Value;
  865. }
  866. },SubscriptionAttribute.FLAG.IgnoreSaveDB);
  867. }
  868. else
  869. {
  870. DATA.Subscribe($"IO.{moduleName}", () => aoAccessor.Value);
  871. DATA.Subscribe($"IO32.{moduleName}", () =>
  872. {
  873. if (aoAccessor.Index < aoAccessor.Buffer.Length - 1)
  874. {
  875. byte[] high = BitConverter.GetBytes(aoAccessor.Buffer[aoAccessor.Index]);
  876. byte[] low = BitConverter.GetBytes(aoAccessor.Buffer[aoAccessor.Index + 1]);
  877. return BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  878. }
  879. else
  880. {
  881. return aoAccessor.Value;
  882. }
  883. });
  884. }
  885. }
  886. XmlNodeList lstAi = xml.SelectNodes("IO_DEFINE/Ana_In/AI_ITEM");
  887. // < AO_ITEM Index = "0" BufferOffset="0" Name = "" Addr = "0" Description = "" />
  888. foreach (var aiItem in lstAi)
  889. {
  890. XmlElement element = aiItem as XmlElement;
  891. if (element == null)
  892. continue;
  893. string index = element.GetAttribute("Index");
  894. string bufferOffset = element.GetAttribute("BufferOffset");
  895. if (string.IsNullOrEmpty(bufferOffset))
  896. bufferOffset = index;
  897. string name = element.GetAttribute("Name");
  898. string address = element.GetAttribute("Addr");
  899. string description = element.GetAttribute("Description");
  900. if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(index) || string.IsNullOrEmpty(bufferOffset))
  901. continue;
  902. name = name.Trim();
  903. index = index.Trim();
  904. bufferOffset = bufferOffset.Trim();
  905. string moduleName = string.IsNullOrEmpty(module) ? name : $"{module}.{name}";
  906. int intIndex;
  907. if (!int.TryParse(index, out intIndex))
  908. continue;
  909. int intBufferOffset;
  910. if (!int.TryParse(bufferOffset, out intBufferOffset))
  911. continue;
  912. if (!_aiBuffer.ContainsKey(provider) || !_aiBuffer[provider].ContainsKey(blockOffset))
  913. {
  914. throw new Exception("Not defined AI buffer from IO provider, " + provider);
  915. }
  916. AIAccessor aiAccessor = new AIAccessor(moduleName, intBufferOffset, _aiBuffer[provider][blockOffset]);
  917. _aiMap[moduleName] = aiAccessor;
  918. aiAccessor.IoTableIndex = intIndex;
  919. aiAccessor.Addr = address;
  920. aiAccessor.Provider = provider;
  921. aiAccessor.BlockOffset = blockOffset;
  922. aiAccessor.Description = description;
  923. if (!_aiList.ContainsKey(provider))
  924. _aiList[provider] = new List<AIAccessor>();
  925. _aiList[provider].Add(aiAccessor);
  926. _ioItemList[$"{provider}.AIItemList"].Add(new NotifiableIoItem()
  927. {
  928. Address = address,
  929. Name = moduleName,
  930. Description = description,
  931. Index = intIndex,
  932. Provider = provider,
  933. BlockOffset = blockOffset,
  934. BlockIndex = intIndex,
  935. });
  936. if (isIgnoreSaveDB)
  937. {
  938. DATA.Subscribe($"IO.{moduleName}", () => aiAccessor.Value, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  939. DATA.Subscribe($"IO32.{moduleName}", () =>
  940. {
  941. if (aiAccessor.Index < aiAccessor.Buffer.Length - 1)
  942. {
  943. byte[] high = BitConverter.GetBytes(aiAccessor.Buffer[aiAccessor.Index]);
  944. byte[] low = BitConverter.GetBytes(aiAccessor.Buffer[aiAccessor.Index + 1]);
  945. return BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  946. }
  947. else
  948. {
  949. return aiAccessor.Value;
  950. }
  951. }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  952. }
  953. else
  954. {
  955. DATA.Subscribe($"IO.{moduleName}", () => aiAccessor.Value);
  956. DATA.Subscribe($"IO32.{moduleName}", () =>
  957. {
  958. if (aiAccessor.Index < aiAccessor.Buffer.Length - 1)
  959. {
  960. byte[] high = BitConverter.GetBytes(aiAccessor.Buffer[aiAccessor.Index]);
  961. byte[] low = BitConverter.GetBytes(aiAccessor.Buffer[aiAccessor.Index + 1]);
  962. return BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  963. }
  964. else
  965. {
  966. return aiAccessor.Value;
  967. }
  968. });
  969. }
  970. }
  971. }
  972. public void SetIoMap(string provider, Dictionary<int, string> ioMappingPathFile)
  973. {
  974. foreach (var map in ioMappingPathFile)
  975. {
  976. SetIoMap(provider, map.Key, map.Value);
  977. }
  978. DATA.Subscribe(provider, "DIList", SubscribeDiData);
  979. DATA.Subscribe(provider, "DOList", SubscribeDoData);
  980. DATA.Subscribe(provider, "AIList", SubscribeAiData);
  981. DATA.Subscribe(provider, "AOList", SubscribeAoData);
  982. }
  983. public void SetIoMapByModule(string provider, int offset, string ioMappingPathFile, string module)
  984. {
  985. SetIoMap(provider, offset, ioMappingPathFile, module);
  986. DATA.Subscribe(provider, "DIList", SubscribeDiData);
  987. DATA.Subscribe(provider, "DOList", SubscribeDoData);
  988. DATA.Subscribe(provider, "AIList", SubscribeAiData);
  989. DATA.Subscribe(provider, "AOList", SubscribeAoData);
  990. }
  991. private void SubscribeIoItemList(string provider)
  992. {
  993. string diKey = $"{provider}.DIItemList";
  994. if (!_ioItemList.ContainsKey(diKey))
  995. {
  996. _ioItemList[diKey] = new List<NotifiableIoItem>();
  997. DATA.Subscribe(diKey, () => _ioItemList[diKey]);
  998. }
  999. string doKey = $"{provider}.DOItemList";
  1000. if (!_ioItemList.ContainsKey(doKey))
  1001. {
  1002. _ioItemList[doKey] = new List<NotifiableIoItem>();
  1003. DATA.Subscribe(doKey, () => _ioItemList[doKey]);
  1004. }
  1005. string aiKey = $"{provider}.AIItemList";
  1006. if (!_ioItemList.ContainsKey(aiKey))
  1007. {
  1008. _ioItemList[aiKey] = new List<NotifiableIoItem>();
  1009. DATA.Subscribe(aiKey, () => _ioItemList[aiKey]);
  1010. }
  1011. string aoKey = $"{provider}.AOItemList";
  1012. if (!_ioItemList.ContainsKey(aoKey))
  1013. {
  1014. _ioItemList[aoKey] = new List<NotifiableIoItem>();
  1015. DATA.Subscribe(aoKey, () => _ioItemList[aoKey]);
  1016. }
  1017. }
  1018. }
  1019. }