EzIO.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. using GSG.NET.Concurrent;
  2. using GSG.NET.Excel;
  3. using GSG.NET.Logging;
  4. using GSG.NET.Quartz;
  5. using GSG.NET.Utils;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Threading;
  10. using VehicleControlSystem.ControlLayer.Lib.EziPlusE;
  11. namespace VehicleControlSystem.ControlLayer.IO
  12. {
  13. public partial class EzIO : IIO, IDisposable
  14. {
  15. #region Bit Mask
  16. public readonly uint[] bitOnMask =
  17. {
  18. 0x00000001, 0x00000002, 0x00000004, 0x00000008,
  19. 0x00000010, 0x00000020, 0x00000040, 0x00000080,
  20. 0x00000100, 0x00000200, 0x00000400, 0x00000800,
  21. 0x00001000, 0x00002000, 0x00004000, 0x00008000,
  22. 0x00010000, 0x00020000, 0x00040000, 0x00080000,
  23. 0x00100000, 0x00200000, 0x00400000, 0x00800000,
  24. 0x01000000, 0x02000000, 0x04000000, 0x08000000,
  25. 0x10000000, 0x20000000, 0x40000000, 0x80000000
  26. };
  27. public readonly uint[] bitOffMask =
  28. {
  29. 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFB, 0xFFFFFFF7,
  30. 0xFFFFFFEF, 0xFFFFFFDF, 0xFFFFFFBF, 0xFFFFFF7F,
  31. 0xFFFFFEFF, 0xFFFFFDFF, 0xFFFFFBFF, 0xFFFFF7FF,
  32. 0xFFFFEFFF, 0xFFFFDFFF, 0xFFFFBFFF, 0xFFFF7FFF,
  33. 0xFFFEFFFF, 0xFFFDFFFF, 0xFFFBFFFF, 0xFFF7FFFF,
  34. 0xFFEFFFFF, 0xFFDFFFFF, 0xFFBFFFFF, 0xFF7FFFFF,
  35. 0xFEFFFFFF, 0xFDFFFFFF, 0xFBFFFFFF, 0xF7FFFFFF,
  36. 0xEFFFFFFF, 0xDFFFFFFF, 0xBFFFFFFF, 0x7FFFFFFF
  37. };
  38. public readonly uint[] servoAmpInputBitOnMask =
  39. {
  40. 0x04000000, 0x08000000, 0x10000000, 0x20000000,
  41. 0x40000000, 0x80000000, 0x00400000, 0x00800000,
  42. 0x01000000
  43. };
  44. public readonly uint[] servoAmpOutputBitMask =
  45. {
  46. 0x00008000, 0x00010000, 0x00020000, 0x00040000,
  47. 0x00080000, 0x00100000, 0x00200000, 0x00400000,
  48. 0x00800000
  49. };
  50. #endregion
  51. static Logger logger = Logger.GetLogger();
  52. bool IsThreadAlive = true;
  53. public List<EzBoard> BoardList = new List<EzBoard>();
  54. List<BitBlock> _inPutIOList = null;
  55. public List<BitBlock> InPutIOList
  56. {
  57. get => this._inPutIOList;
  58. }
  59. List<BitBlock> _outPutIOList = null;
  60. public List<BitBlock> OutPutIOList
  61. {
  62. get => this._outPutIOList;
  63. }
  64. UInt16[] _incomingBuffer;
  65. UInt16[] _outcomingBuffer;
  66. Thread _readThread;
  67. ThreadCancel threadCancel = new ThreadCancel();
  68. bool isConnectError = false;
  69. public bool IsConnectError
  70. {
  71. get => this.isConnectError;
  72. set
  73. {
  74. if ( this.isConnectError == value )
  75. return;
  76. this.isConnectError = value;
  77. if ( isConnectError )
  78. this.qQ.Enqueue( new QoDiconnected() {Arg0 = "EzIO" } );
  79. else
  80. this.qQ.Enqueue( new QoConnected() {Arg0 = "EzIO" } );
  81. }
  82. }
  83. TsMap<string, SyncObject> ddWaitChgBlock = new TsMap<string, SyncObject>();
  84. #region Pull Thread
  85. public TsQueue<QueueObject> qQ = new TsQueue<QueueObject>( 512 );
  86. public Thread pullThread;
  87. #endregion
  88. #region public Method
  89. public int GetBit( uint usIOAddr, bool pbval )
  90. {
  91. throw new NotImplementedException();
  92. }
  93. public int GetBit( string strIOAddr, bool pbVal )
  94. {
  95. throw new NotImplementedException();
  96. }
  97. public int GetByte( uint usIOAddr, byte pcValue )
  98. {
  99. throw new NotImplementedException();
  100. }
  101. public int GetByte( string strIOAddr, byte pcValue )
  102. {
  103. throw new NotImplementedException();
  104. }
  105. public int GetWord( uint usIOAddr, short pwValue )
  106. {
  107. throw new NotImplementedException();
  108. }
  109. public int GetWord( string strIOAddr, short pwValue )
  110. {
  111. throw new NotImplementedException();
  112. }
  113. public int Initialize( List<EzBoard> ezBoards )
  114. {
  115. this.BoardList = ezBoards;
  116. this._incomingBuffer = new ushort[ezBoards.Count];
  117. this._outcomingBuffer = new ushort[ezBoards.Count];
  118. this.IsThreadAlive = true;
  119. _readThread = new Thread( this.IOThread );
  120. this._readThread.IsBackground = true;
  121. this._readThread.Start();
  122. return 0;
  123. }
  124. #endregion
  125. public bool IsDeviceOpened()
  126. {
  127. throw new NotImplementedException();
  128. }
  129. public bool IsOff( uint usIOAddr )
  130. {
  131. throw new NotImplementedException();
  132. }
  133. public bool IsOff( string ioTag, bool isInput = true )
  134. {
  135. BitBlock bit = null;
  136. if ( isInput )
  137. bit = this._inPutIOList.Where( x => ioTag.Equals( x.Tag ) ).FirstOrDefault();
  138. else
  139. bit = this._outPutIOList.Where( x => ioTag.Equals( x.Tag ) ).FirstOrDefault();
  140. return !bit.IsBitOn;
  141. }
  142. public bool IsOn( uint usIOAddr )
  143. {
  144. throw new NotImplementedException();
  145. }
  146. //public int IsOn( string strIOAddr, bool pbVal )
  147. //{
  148. // var io = this._inPutIOList.Where( x => strIOAddr.Equals( x.Tag ) ).FirstOrDefault();
  149. // if( io == null )
  150. // return -1;
  151. // else
  152. // {
  153. // }
  154. // return 0;
  155. //}
  156. public bool IsOn( string ioTag, bool isInput = true )
  157. {
  158. BitBlock bit = null;
  159. if ( isInput )
  160. bit = this._inPutIOList.Where( x => ioTag.Equals( x.Tag ) ).FirstOrDefault();
  161. else
  162. bit = this._outPutIOList.Where( x => ioTag.Equals( x.Tag ) ).FirstOrDefault();
  163. return bit.IsBitOn;
  164. }
  165. public bool WaitChangeInputIO( bool exp, int timeout, string tag )
  166. {
  167. if ( exp == IsOn( tag ) )
  168. return true;
  169. Assert.IsFalse( ddWaitChgBlock.ContainsKey( tag ), "WaitChg InputIO already waiting:{0}", tag );
  170. try
  171. {
  172. var so = new SyncObject { };
  173. ddWaitChgBlock.Add( tag, so );
  174. so.Lock();
  175. return so.Await( timeout );
  176. }
  177. finally
  178. {
  179. this.ddWaitChgBlock.Remove( tag );
  180. }
  181. }
  182. public int LoadIOMap( string strFileName )
  183. {
  184. var bl = new ExcelMapper( strFileName ).Fetch<EzBoard>( "BOARD" ).ToList();
  185. this.BoardList = bl;
  186. var il = new ExcelMapper( strFileName ).Fetch<BitBlock>( "IN_IO" ).ToList();
  187. var inputIO = il.Where( x => !string.IsNullOrEmpty( x.Tag ) ).ToList();
  188. this._inPutIOList = inputIO;
  189. var ol = new ExcelMapper( strFileName ).Fetch<BitBlock>( "OUT_IO" ).ToList();
  190. var outputIO = ol.Where( x => !string.IsNullOrEmpty( x.Tag ) ).ToList();
  191. this._outPutIOList = outputIO;
  192. return 0;
  193. }
  194. public int OutputOff( uint usIOAddr )
  195. {
  196. throw new NotImplementedException();
  197. }
  198. public int OutputOff( string strIOAddr )
  199. {
  200. int result = 0;
  201. var outIO = this._outPutIOList.Where( x => strIOAddr.Equals( x.Tag ) ).FirstOrDefault();
  202. var boardType = this.BoardList.Where( x => x.BoardID == outIO.BoardNo ).FirstOrDefault().Type;
  203. uint bitMask = 0;
  204. if ( boardType == E_EzboardType.Servo )
  205. {
  206. bitMask = this.servoAmpOutputBitMask[outIO.Index];
  207. result = EziMOTIONPlusELib.FAS_SetIOOutput( outIO.BoardNo, 0, bitMask );
  208. }
  209. else
  210. {
  211. bitMask = bitOnMask[outIO.Index];
  212. result = EziMOTIONPlusELib.FAS_SetOutput( outIO.BoardNo, 0, bitMask );
  213. }
  214. return result;
  215. }
  216. public int OutputOn( uint usIOAddr )
  217. {
  218. //var outIO = this._inPutIOList.Where( x => strIOAddr.Equals( x.Tag ) ).FirstOrDefault();
  219. //EziMOTIONPlusELib.FAS_SetIOOutput( boardNo, writeMask, 0 );
  220. return 0;
  221. }
  222. public int OutputOn( string outputTag )
  223. {
  224. int result = 0;
  225. var outIO = this._outPutIOList.Where( x => outputTag.Equals( x.Tag ) ).FirstOrDefault();
  226. var boardType = this.BoardList.Where( x => x.BoardID == outIO.BoardNo ).FirstOrDefault().Type;
  227. uint bitMask = 0;
  228. if ( boardType == E_EzboardType.Servo )
  229. {
  230. bitMask = this.servoAmpOutputBitMask[outIO.Index];
  231. result = EziMOTIONPlusELib.FAS_SetIOOutput( outIO.BoardNo, bitMask, 0 );
  232. }
  233. else
  234. {
  235. bitMask = bitOnMask[outIO.Index];
  236. result = EziMOTIONPlusELib.FAS_SetOutput( outIO.BoardNo, bitMask, 0 );
  237. }
  238. return result;
  239. }
  240. #region 일정시간 이후 동작 구현
  241. void WriteOutputOn( string outputTag )
  242. {
  243. int result = 0;
  244. var outIO = this._outPutIOList.Where( x => outputTag.Equals( x.Tag ) ).FirstOrDefault();
  245. var boardType = this.BoardList.Where( x => x.BoardID == outIO.BoardNo ).FirstOrDefault().Type;
  246. uint bitMask = 0;
  247. if ( boardType == E_EzboardType.Servo )
  248. {
  249. bitMask = this.servoAmpOutputBitMask[outIO.Index];
  250. result = EziMOTIONPlusELib.FAS_SetIOOutput( outIO.BoardNo, bitMask, 0 );
  251. }
  252. else
  253. {
  254. bitMask = bitOnMask[outIO.Index];
  255. result = EziMOTIONPlusELib.FAS_SetOutput( outIO.BoardNo, bitMask, 0 );
  256. }
  257. }
  258. void WriteOutputOff( string strIOAddr )
  259. {
  260. int result = 0;
  261. var outIO = this._outPutIOList.Where( x => strIOAddr.Equals( x.Tag ) ).FirstOrDefault();
  262. var boardType = this.BoardList.Where( x => x.BoardID == outIO.BoardNo ).FirstOrDefault().Type;
  263. uint bitMask = 0;
  264. if ( boardType == E_EzboardType.Servo )
  265. {
  266. bitMask = this.servoAmpOutputBitMask[outIO.Index];
  267. result = EziMOTIONPlusELib.FAS_SetIOOutput( outIO.BoardNo, 0, bitMask );
  268. }
  269. else
  270. {
  271. bitMask = bitOnMask[outIO.Index];
  272. result = EziMOTIONPlusELib.FAS_SetOutput( outIO.BoardNo, 0, bitMask );
  273. }
  274. }
  275. public void WriteOutputIO( string tag, bool on, int after = 0 )
  276. {
  277. if ( on )
  278. {
  279. if ( after > 0 )
  280. TimerUtils.Once( after, WriteOutputOn, tag );
  281. else
  282. WriteOutputOn( tag );
  283. }
  284. else
  285. {
  286. if ( after > 0 )
  287. TimerUtils.Once( after, WriteOutputOff, tag );
  288. else
  289. WriteOutputOff( tag );
  290. }
  291. }
  292. #endregion
  293. public int OutputToggle( uint usIOAddr )
  294. {
  295. throw new NotImplementedException();
  296. }
  297. public int OutputToggle( string strIOAddr )
  298. {
  299. throw new NotImplementedException();
  300. }
  301. public int PutByte( uint usIOAddr, byte pcValue )
  302. {
  303. throw new NotImplementedException();
  304. }
  305. public int PutByte( string strIOAddr, byte pcValue )
  306. {
  307. throw new NotImplementedException();
  308. }
  309. public int PutWord( uint usIOAddr, short pwValue )
  310. {
  311. throw new NotImplementedException();
  312. }
  313. public int PutWord( string strIOAddr, short pwValue )
  314. {
  315. throw new NotImplementedException();
  316. }
  317. #region Thread
  318. public void RunIOThread()
  319. {
  320. try
  321. {
  322. ThreadStart();
  323. }
  324. catch ( Exception )
  325. {
  326. }
  327. finally
  328. {
  329. }
  330. }
  331. public void ThreadStart()
  332. {
  333. this.threadCancel.AddGo( new Action( this.IOThread ) );
  334. this.threadCancel.AddGo( new Action( this.PullQueueThread ) );
  335. //this.IsThreadAlive = true;
  336. //this._readThread = ThreadUtils.Invoke( IOThread );
  337. //this.pullThread = ThreadUtils.Invoke( PullQueueThread );
  338. }
  339. void IOThread()
  340. {
  341. var sTime = SwUtils.CurrentTimeMillis;
  342. while ( !this.threadCancel.Canceled )
  343. {
  344. Thread.Sleep( 5 );
  345. try
  346. {
  347. if ( !IsConnetedAllBoard() )
  348. {
  349. if ( !ConnectAllBoard() )
  350. {
  351. IsConnectError = true;
  352. }
  353. Thread.Sleep( 1000 );
  354. continue;
  355. }
  356. IsConnectError = false;
  357. ReadBoardIO();
  358. //Console.WriteLine( $"Read Time - { SwUtils.Elapsed( sTime ) } mm" );
  359. //sTime = SwUtils.CurrentTimeMillis;
  360. }
  361. catch ( Exception ex )
  362. {
  363. logger.E( $"Exception [EzIO IORead Thread] - {ex.StackTrace}" );
  364. }
  365. }
  366. logger.D( "[EzIO] - Dispose" );
  367. }
  368. void ReadBoardIO()
  369. {
  370. foreach ( var board in this.BoardList )
  371. {
  372. if ( !IsConnetedBoard( board.BoardID ) )
  373. continue;
  374. switch ( board.Type )
  375. {
  376. case E_EzboardType.Servo:
  377. {
  378. uint axisDIn = 0, axisDOut = 0, axisStatus = 0;
  379. int cmdPos = 0, actPos = 0, posErr = 0, actVel = 0;
  380. ushort posItemNo = 0;
  381. if ( EziMOTIONPlusELib.FAS_GetAllStatus( board.BoardID, ref axisDIn, ref axisDOut, ref axisStatus,
  382. ref cmdPos, ref actPos, ref posErr, ref actVel, ref posItemNo ) == EziMOTIONPlusELib.FMM_OK )
  383. {
  384. //if ( this._inPutIOList.Where( x => x.BoardNo == board.BoardID ).Count() <= 0 ) break;
  385. var input = this._inPutIOList.Where( x => x.BoardNo == board.BoardID ).ToList();
  386. input.ForEach( i =>
  387. {
  388. var isOn = Convert.ToBoolean( axisDIn & this.servoAmpInputBitOnMask[i.Index] ) ? true : false;
  389. if ( i.IsBitOn != isOn )
  390. i.IsChanged = true;
  391. i.IsBitOn = isOn;
  392. } );
  393. var output = this._outPutIOList.Where( x => x.BoardNo == board.BoardID ).ToList();
  394. output.ForEach( o =>
  395. {
  396. var isOn = Convert.ToBoolean( axisDOut & this.servoAmpOutputBitMask[o.Index] ) ? true : false;
  397. if ( o.IsBitOn != isOn )
  398. o.IsChanged = true;
  399. o.IsBitOn = isOn;
  400. } );
  401. }
  402. }
  403. break;
  404. case E_EzboardType.IOInput:
  405. {
  406. uint inValue = 0, latchValue = 0;
  407. int result = EziMOTIONPlusELib.FMM_OK;
  408. result = EziMOTIONPlusELib.FAS_GetInput( board.BoardID, ref inValue, ref latchValue );
  409. if ( result == EziMOTIONPlusELib.FMM_OK )
  410. {
  411. var input = this._inPutIOList.Where( x => x.BoardNo == board.BoardID ).ToList();
  412. input.ForEach( i =>
  413. {
  414. var isOn = Convert.ToBoolean( inValue & this.bitOnMask[i.Index] ) ? true : false;
  415. if ( i.IsBitOn != isOn )
  416. i.IsChanged = true;
  417. i.IsBitOn = isOn;
  418. } );
  419. }
  420. else
  421. logger.E( $"EzIO - [{board.BoardID}] Read Fail Error Code {result}" );
  422. }
  423. break;
  424. case E_EzboardType.IOOutput:
  425. {
  426. uint outValue = 0, outStatus = 0;
  427. int result = EziMOTIONPlusELib.FMM_OK;
  428. result = EziMOTIONPlusELib.FAS_GetOutput( board.BoardID, ref outValue, ref outStatus );
  429. if ( result == EziMOTIONPlusELib.FMM_OK )
  430. {
  431. var output = this._outPutIOList.Where( x => x.BoardNo == board.BoardID ).ToList();
  432. output.ForEach( o =>
  433. {
  434. var isOn = Convert.ToBoolean( outValue & this.bitOnMask[o.Index] ) ? true : false;
  435. if ( o.IsBitOn != isOn )
  436. o.IsChanged = true;
  437. o.IsBitOn = isOn;
  438. } );
  439. }
  440. else
  441. logger.E( $"EzIO - [{board.BoardID}] Read Fail Error Code {result}" );
  442. }
  443. break;
  444. default:
  445. break;
  446. }
  447. }
  448. FireChangedIO();
  449. }
  450. void FireChangedIO()
  451. {
  452. this.InPutIOList.ForEach( i =>
  453. {
  454. if ( i.IsChanged )
  455. {
  456. i.IsChanged = false;
  457. var clone = ObjectCopyUtils.DeepClone<BitBlock>( i );
  458. this.qQ.Enqueue( new QoChangedIO { Arg0 = clone } );
  459. NotifySyncBit( clone );
  460. }
  461. } );
  462. this.OutPutIOList.ForEach( o =>
  463. {
  464. if ( o.IsChanged )
  465. {
  466. o.IsChanged = false;
  467. var clone = ObjectCopyUtils.DeepClone<BitBlock>( o );
  468. this.qQ.Enqueue( new QoChangedIO { Arg0 = clone } );
  469. }
  470. } );
  471. }
  472. void PullQueueThread()
  473. {
  474. while ( !this.threadCancel.Canceled )
  475. {
  476. try
  477. {
  478. var o = qQ.Dequeue();
  479. if ( o is QoConnected )
  480. DelegateUtils.Invoke( OnContd, o.Arg0 );
  481. else if ( o is QoDiconnected )
  482. DelegateUtils.Invoke( OnDiscontd, o.Arg0 );
  483. else if ( o is QoChangedIO )
  484. DelegateUtils.Invoke( OnChangedIO, o.Arg0 );
  485. else if ( o is QoWriteIO )
  486. DelegateUtils.Invoke( OnWriteIO, o.Arg0 );
  487. else if ( o is QoLog )
  488. DelegateUtils.Invoke( OnLog, o.Arg0, o.Arg1 );
  489. else if ( o is QoDispose )
  490. break;
  491. else
  492. Assert.Fail( "Unk Object {0}", o );
  493. }
  494. catch ( ThreadAbortException )
  495. {
  496. }
  497. catch ( Exception e )
  498. {
  499. logger.E( e );
  500. }
  501. }
  502. logger.D( "[EzIO] - PullQueue Thread Dispose" );
  503. }
  504. #endregion
  505. /// <summary>
  506. /// InputIO 변경 알림
  507. /// </summary>
  508. /// <param name="block"></param>
  509. void NotifySyncBit( BitBlock block )
  510. {
  511. if ( ddWaitChgBlock.ContainsKey( block.Tag ) )
  512. {
  513. var so = ddWaitChgBlock[block.Tag];
  514. so.Expect = block;
  515. so.Notify();
  516. }
  517. }
  518. bool IsConnetedBoard( int boardNo )
  519. {
  520. return EziMOTIONPlusELib.FAS_IsSlaveExist( boardNo ) == 1;
  521. }
  522. bool IsConnetedAllBoard()
  523. {
  524. foreach ( var b in this.BoardList )
  525. {
  526. if ( !IsConnetedBoard( b.BoardID ) )
  527. {
  528. this.qQ.Clear();//연결이 끊어지면 내용을 삭제.
  529. return false;
  530. }
  531. }
  532. return true;
  533. }
  534. bool ConnectAllBoard()
  535. {
  536. foreach ( var b in this.BoardList )
  537. {
  538. if ( IsConnetedBoard( b.BoardID ) )
  539. continue;
  540. var addr = b.IPAddress.Split( '.' );
  541. byte boardNo = Convert.ToByte( addr[3] );
  542. if ( EziMOTIONPlusELib.FAS_Connect( (byte)192, (byte)168, (byte)0, boardNo, b.BoardID ) != EziMOTIONPlusELib.FMM_OK )
  543. {
  544. logger.E( $"EzIO - Connect Fail {b.BoardID}" );
  545. return false;
  546. }
  547. }
  548. return true;
  549. }
  550. public int Terminate()
  551. {
  552. this.threadCancel.Cancel();
  553. this.qQ.Enqueue( new QoDispose() );
  554. //this.IsThreadAlive = false;
  555. //if ( this._readThread != null && this._readThread.IsAlive )
  556. //{
  557. // if ( !this._readThread.Join( 3000 ) )
  558. // this._readThread.Abort();
  559. //}
  560. LockUtils.Wait( 100 );
  561. this.threadCancel.StopWaitAll();
  562. this.BoardList.ForEach( b =>
  563. {
  564. EziMOTIONPlusELib.FAS_Close( b.BoardID );
  565. } );
  566. return 0;
  567. }
  568. public int Initialize()
  569. {
  570. throw new NotImplementedException();
  571. }
  572. int GetModuleAndBitNoByAddress( uint usIOAddr, out int boardNo, out int bitNo )
  573. {
  574. long nOffset = 0;
  575. long nCount = 0;
  576. long nAddress = usIOAddr;
  577. int INPUT_ORIGIN = 1000;
  578. int OUTPUT_ORIGIN = 2000;
  579. boardNo = 0;
  580. bitNo = 0;
  581. if ( usIOAddr < OUTPUT_ORIGIN )
  582. {
  583. nOffset = usIOAddr - INPUT_ORIGIN;
  584. for ( int nModNo = 0; nModNo < this.BoardList.Count; nModNo++ )
  585. {
  586. // Get Input CH Count Using Module ID
  587. //AxdInfoGetInputCount( nModNo, nCount );
  588. if ( nOffset - nCount < 0 )
  589. {
  590. boardNo = nModNo;
  591. bitNo = (int)nOffset;
  592. return 0;
  593. }
  594. nOffset -= nCount;
  595. }
  596. }
  597. else
  598. {
  599. nOffset = usIOAddr - OUTPUT_ORIGIN;
  600. for ( int nModNo = 0; nModNo < this.BoardList.Count; nModNo++ )
  601. {
  602. // Get Output CH Count Using Module ID
  603. //AxdInfoGetOutputCount( nModNo, nCount );
  604. if ( nOffset - nCount < 0 )
  605. {
  606. boardNo = nModNo;
  607. bitNo = (int)nOffset;
  608. return 0;
  609. }
  610. nOffset -= nCount;
  611. }
  612. }
  613. return 0;
  614. }
  615. public void TestEqueue()
  616. {
  617. var o = this.OutPutIOList.Where( x => x.Tag.Equals( "OUT_OBSTRUCTION_PATTERN_00" ) ).Single();
  618. o.IsChanged = false;
  619. var clone = ObjectCopyUtils.DeepClone<BitBlock>( o );
  620. this.qQ.Enqueue( new QoChangedIO { Arg0 = clone } );
  621. }
  622. #region IDisposable Support
  623. private bool disposedValue = false; // 중복 호출을 검색하려면
  624. protected virtual void Dispose( bool disposing )
  625. {
  626. if ( !disposedValue )
  627. {
  628. if ( disposing )
  629. {
  630. // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다.
  631. if ( this.pullThread != null )
  632. {
  633. this.IsThreadAlive = false;
  634. if ( !this.pullThread.Join( 2000 ) && this.pullThread.IsAlive )
  635. {
  636. this.pullThread.Abort();
  637. }
  638. this.pullThread = null;
  639. }
  640. ThreadUtils.Kill( this.pullThread );
  641. Terminate(); //Board Close
  642. }
  643. // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다.
  644. // TODO: 큰 필드를 null로 설정합니다.
  645. disposedValue = true;
  646. }
  647. }
  648. // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다.
  649. // ~EzIO()
  650. // {
  651. // // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
  652. // Dispose(false);
  653. // }
  654. // 삭제 가능한 패턴을 올바르게 구현하기 위해 추가된 코드입니다.
  655. public void Dispose()
  656. {
  657. // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
  658. Dispose( true );
  659. // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다.
  660. // GC.SuppressFinalize(this);
  661. }
  662. #endregion
  663. }
  664. }