Scheduler.cs 11 KB

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