Scheduler.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using GSG.NET.Concurrent;
  9. using GSG.NET.Logging;
  10. using GSG.NET.Utils;
  11. using OHV.Common.Events;
  12. using OHV.Common.Model;
  13. using OHV.SqliteDAL;
  14. using Prism.Events;
  15. namespace VehicleControlSystem.Managers
  16. {
  17. public class Scheduler : IDisposable
  18. {
  19. static Logger logger = Logger.GetLogger();
  20. private List<Command> commands;
  21. public List<Command> CommandsList
  22. {
  23. get { return commands; }
  24. set { commands = value; }
  25. }
  26. Thread thread = null;
  27. bool isThreadAlive = false;
  28. IEventAggregator eventAggregator;
  29. AutoManager autoManager;
  30. SqliteManager sql = null;
  31. public event Action<Command> OnMaualAddedCommand;
  32. public Scheduler( IEventAggregator ea, AutoManager autoManager, SqliteManager sqlite )
  33. {
  34. this.CommandsList = new List<Command>();
  35. eventAggregator = ea;// CommonServiceLocator.ServiceLocator.Current.GetInstance<IEventAggregator>();
  36. eventAggregator.GetEvent<VCSMessagePubSubEvent>().Subscribe( OnReceivedMessageEvent );
  37. this.autoManager = autoManager;
  38. this.sql = sqlite;
  39. }
  40. private void OnReceivedMessageEvent( VCSMessageEventArgs obj )
  41. {
  42. if ( obj.Kind == VCSMessageEventArgs.eVCSMessageKind.ReqAddCommand )
  43. {
  44. //var vInof = sql.VehicleInfoDAL.GetInfo();
  45. //if ( vInof.VehicleState == OHV.Common.Shareds.eVehicleState.Move )
  46. // this.sql.CommandDAL.Clean();
  47. this.AddCommand( obj.Command );
  48. if ( obj.Command.ByWho == OHV.Common.Shareds.eCommandByWho.LocalSystem || obj.Command.ByWho == OHV.Common.Shareds.eCommandByWho.LocalOverWrite )
  49. this.OnMaualAddedCommand?.BeginInvoke( obj.Command, null, null );
  50. }
  51. //var m = new GUIMessageEventArgs() { MessageText = obj.MessageText, MessageKey = obj.MessageKey };
  52. //m.Command = ObjectCopyUtils.DeepClone(obj.Command);
  53. //GUIMessagePublish(m);
  54. }
  55. void GUIMessagePublish( GUIMessageEventArgs args )
  56. {
  57. eventAggregator.GetEvent<GUIMessagePubSubEvent>().Publish( args );
  58. }
  59. public void Init()
  60. {
  61. this.isThreadAlive = true;
  62. this.thread = ThreadUtils.Invoke( this.ExcuteCommand );
  63. }
  64. public bool AddCommand( Command cmd )
  65. {
  66. try
  67. {
  68. this.sql.CommandDAL.Add( cmd );
  69. }
  70. catch ( Exception ex )
  71. {
  72. logger.E( ex );
  73. return false;
  74. }
  75. return true;
  76. }
  77. bool RemoveCommand( Command cmd )
  78. {
  79. if ( !this.CommandsList.Remove( cmd ) )
  80. {
  81. logger.D( $"Scheduler - [Command] : RemoveCommand fail ID-{cmd.CommandID} / Result-{cmd.Result} " );
  82. return false;
  83. }
  84. logger.D( $"Scheduler - [Command] : RemoveCommand OK ID-{cmd.CommandID} / Result-{cmd.Result} " );
  85. return true;
  86. }
  87. void ExcuteCommand()
  88. {
  89. while ( isThreadAlive )
  90. {
  91. Thread.Sleep( 500 );
  92. try
  93. {
  94. var state = this.autoManager.OperationModeProperty;
  95. switch ( state )
  96. {
  97. case OHV.Common.Shareds.eOperatationMode.ManualMode:
  98. break;
  99. case OHV.Common.Shareds.eOperatationMode.AutoMode:
  100. {
  101. switch ( this.autoManager.AutoModeStateProperty )
  102. {
  103. case OHV.Common.Shareds.eAutoModeState.ErrorStop:
  104. break;
  105. case OHV.Common.Shareds.eAutoModeState.StartRun:
  106. break;
  107. case OHV.Common.Shareds.eAutoModeState.Run:
  108. Command cmd = sql.CommandDAL.GetCmd();
  109. if ( cmd == null ) continue;
  110. DoWork( cmd );
  111. break;
  112. case OHV.Common.Shareds.eAutoModeState.Stop:
  113. break;
  114. default:
  115. break;
  116. }
  117. }
  118. break;
  119. case OHV.Common.Shareds.eOperatationMode.InitialMode:
  120. break;
  121. default:
  122. break;
  123. }
  124. }
  125. catch ( Exception ex )
  126. {
  127. logger.E( ex );
  128. }
  129. }
  130. logger.D("[Scheduler] - Command Thread Dispose");
  131. }
  132. private void DoWork( Command cmd )
  133. {
  134. switch ( cmd.State )
  135. {
  136. case OHV.Common.Shareds.eCommandState.Queued:
  137. if ( sql.SubCmdDAL.Count <= 0 ) //
  138. {
  139. switch ( cmd.Type )
  140. {
  141. case OHV.Common.Shareds.eCommandType.Move:
  142. case OHV.Common.Shareds.eCommandType.MoveNLoad:
  143. case OHV.Common.Shareds.eCommandType.MoveNUnload:
  144. case OHV.Common.Shareds.eCommandType.Charging:
  145. CreateSubCommand( cmd, SubCmd.eType.Move );
  146. break;
  147. default:
  148. break;
  149. }
  150. this.sql.CommandDAL.UpdateState( cmd.CommandID, OHV.Common.Shareds.eCommandState.Processing );
  151. }
  152. break;
  153. case OHV.Common.Shareds.eCommandState.Processing:
  154. {
  155. var subCmd = sql.SubCmdDAL.GetSubCmd();
  156. if ( subCmd == null ) // Move 명령을 수행 완료 했다고 판단.
  157. {
  158. if ( cmd.IsSecondCommanded )
  159. {
  160. sql.CommandDAL.UpdateState( cmd.CommandID, OHV.Common.Shareds.eCommandState.Complete );
  161. break;
  162. }
  163. if ( cmd.Type == OHV.Common.Shareds.eCommandType.MoveNLoad )
  164. {
  165. if ( this.CreateSubCommand( cmd, SubCmd.eType.Load ) )
  166. cmd.IsSecondCommanded = true;
  167. break;
  168. }
  169. else if ( cmd.Type == OHV.Common.Shareds.eCommandType.MoveNUnload )
  170. {
  171. if ( this.CreateSubCommand( cmd, SubCmd.eType.Unload ) )
  172. cmd.IsSecondCommanded = true;
  173. break;
  174. }
  175. else if ( cmd.Type == OHV.Common.Shareds.eCommandType.Charging )
  176. {
  177. if ( this.CreateSubCommand( cmd, SubCmd.eType.Charge ) )
  178. cmd.IsSecondCommanded = true;
  179. break;
  180. }
  181. else //Move Command complete
  182. {
  183. sql.CommandDAL.UpdateState( cmd.CommandID, OHV.Common.Shareds.eCommandState.Complete );
  184. break;
  185. }
  186. }
  187. else
  188. {
  189. if ( subCmd.CmdID.Equals( cmd.CommandID ) ) //진행중 판단
  190. break;
  191. }
  192. }
  193. break;
  194. case OHV.Common.Shareds.eCommandState.Complete:
  195. sql.CommandDAL.Delete( cmd );
  196. break;
  197. default:
  198. break;
  199. }
  200. }
  201. private bool CreateSubCommand( Command cmd, SubCmd.eType type )
  202. {
  203. //명령을 만들기 전에 Vehicle 의 상태를 확인하여 만들자.
  204. switch ( type )
  205. {
  206. case SubCmd.eType.Move:
  207. break;
  208. case SubCmd.eType.Load:
  209. break;
  210. case SubCmd.eType.Unload:
  211. break;
  212. case SubCmd.eType.Charge:
  213. break;
  214. default:
  215. break;
  216. }
  217. var sub = new SubCmd
  218. {
  219. CmdType = SubCmd.eCmdType.Auto,
  220. Type = type,
  221. TargetID = cmd.TargetID,
  222. CmdID = cmd.CommandID,
  223. };
  224. sql.SubCmdDAL.Add( sub );
  225. logger.I( $"{sub.ID} Sub Command Create - Type={sub.Type}, TargetID={sub.TargetID}, CommandID={sub.CmdID}" );
  226. return true;
  227. }
  228. #region IDisposable Support
  229. private bool disposedValue = false; // 중복 호출을 검색하려면
  230. protected virtual void Dispose( bool disposing )
  231. {
  232. if ( !disposedValue )
  233. {
  234. if ( disposing )
  235. {
  236. // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다.
  237. this.isThreadAlive = false;
  238. if ( !this.thread.Join( 3000 ) )
  239. ThreadUtils.Kill( this.thread );
  240. }
  241. // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다.
  242. // TODO: 큰 필드를 null로 설정합니다.
  243. disposedValue = true;
  244. }
  245. }
  246. // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다.
  247. // ~Scheduler()
  248. // {
  249. // // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
  250. // Dispose(false);
  251. // }
  252. // 삭제 가능한 패턴을 올바르게 구현하기 위해 추가된 코드입니다.
  253. public void Dispose()
  254. {
  255. // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
  256. Dispose( true );
  257. // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다.
  258. // GC.SuppressFinalize(this);
  259. }
  260. #endregion
  261. }
  262. }