AutoManager.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. using System;
  2. using System.Threading;
  3. using GSG.NET.Concurrent;
  4. using GSG.NET.Logging;
  5. using OHV.Common.Shareds;
  6. using VehicleControlSystem.ControlLayer.IO;
  7. using Prism.Events;
  8. using OHV.SqliteDAL;
  9. using OHV.Common.Model;
  10. using OHV.Common.Events;
  11. using VehicleControlSystem.ControlLayer;
  12. using GSG.NET.Utils;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. namespace VehicleControlSystem.Managers
  16. {
  17. /// <summary>
  18. /// Vehicle 전체 상태를 관리.
  19. /// </summary>
  20. public class AutoManager : IDisposable
  21. {
  22. static Logger logger = Logger.GetLogger();
  23. Thread threadWorker = null;
  24. bool isThreadAlive = false;
  25. IIO iO = null;
  26. private bool isErrorProcessing = false;
  27. public bool IsErrorProcessing
  28. {
  29. get { return this.isErrorProcessing; }
  30. set
  31. {
  32. if ( this.isErrorProcessing == value ) return;
  33. this.isErrorProcessing = value;
  34. if ( value )
  35. {
  36. //if ( this.activeAlarm == null ) return;
  37. //this.OnOccurAlarm?.BeginInvoke( this.activeAlarm.AlarmId, null, null );
  38. }
  39. else
  40. {
  41. this.ActiveAlarms.ForEach( x =>
  42. {
  43. this.OnClearAlarm?.BeginInvoke( x.AlarmId, null, null );
  44. } );
  45. this.ActiveAlarms.Clear();
  46. //if ( this.activeAlarm == null ) return;
  47. //this.OnClearAlarm?.BeginInvoke( this.activeAlarm.AlarmId, null, null );
  48. //this.activeAlarm = null;
  49. this.BuzzerOnOff( false );
  50. }
  51. }
  52. }
  53. public event Action<int> OnOccurAlarm;
  54. public event Action<int> OnClearAlarm;
  55. Alarm activeAlarm = null;
  56. //Alarm List
  57. List<Alarm> Alarms { get; set; }
  58. //현재 발생 된 알람 리스트
  59. List<Alarm> ActiveAlarms { get; set; }
  60. IEventAggregator eventAggregator = null;
  61. SqliteManager sql = null;
  62. private eOperatationMode operationMode;
  63. public eOperatationMode OperationModeProperty
  64. {
  65. get { return operationMode; }
  66. set
  67. {
  68. if ( operationMode == value ) return;
  69. operationMode = value;
  70. logger.D( $"[AutoManager] OperationMode - {value}" );
  71. this.OnOperationModeChanged?.Invoke( value );
  72. if ( value == eOperatationMode.AutoMode )
  73. this.iO.OutputOff( "OUT_TEACH_MODE" );
  74. else
  75. this.iO.OutputOn( "OUT_TEACH_MODE" );
  76. }
  77. }
  78. public event Action<eOperatationMode> OnOperationModeChanged;
  79. private eAutoModeState autoModeState;
  80. public eAutoModeState AutoModeStateProperty
  81. {
  82. get { return autoModeState; }
  83. set
  84. {
  85. if ( autoModeState == value ) return;
  86. autoModeState = value;
  87. logger.D( $"[AutoManager] AutoModeState - {value}" );
  88. switch ( value )
  89. {
  90. case eAutoModeState.ErrorStop:
  91. this.LampStateProperty = eLampState.Alarm;
  92. break;
  93. case eAutoModeState.StartRun:
  94. this.LampStateProperty = eLampState.AutoRunNChargingFull;
  95. break;
  96. case eAutoModeState.Run:
  97. this.LampStateProperty = eLampState.AutoRunNChargingFull;
  98. break;
  99. case eAutoModeState.Stop:
  100. this.LampStateProperty = eLampState.Alarm;
  101. break;
  102. case eAutoModeState.WaitStop:
  103. this.LampStateProperty = eLampState.Alarm;
  104. break;
  105. default:
  106. break;
  107. }
  108. }
  109. }
  110. private eLampState lampState = eLampState.None;
  111. public eLampState LampStateProperty
  112. {
  113. get { return lampState; }
  114. set
  115. {
  116. if ( lampState == value ) return;
  117. lampState = value;
  118. this.LampStateChange( value );
  119. }
  120. }
  121. private eBuzzerKind buzzerState;
  122. public eBuzzerKind BuzzerStateProperty
  123. {
  124. get { return buzzerState; }
  125. set { buzzerState = value; }
  126. }
  127. public AutoManager( IIO io, IEventAggregator ea, SqliteManager sql, List<Alarm> al )
  128. {
  129. this.iO = io;
  130. this.eventAggregator = ea;
  131. this.sql = sql;
  132. this.Alarms = al;
  133. }
  134. #region Vehicle Events
  135. private void Vehicle_OnChargingFull()
  136. {
  137. if ( this.OperationModeProperty == eOperatationMode.AutoMode )
  138. LampStateChange( eLampState.AutoRunNChargingFull );
  139. else
  140. LampStateChange( eLampState.Alarm );
  141. }
  142. private void Vehicle_OnCharging()
  143. {
  144. LampStateChange( eLampState.Charging );
  145. }
  146. private void Vehicle_OnMoveFinish()
  147. {
  148. BuzzerOnOff( false );
  149. logger.D( "Vehicle Move Finish" );
  150. }
  151. private void Vehicle_OnMoving()
  152. {
  153. BuzzerOnOff( true, eBuzzerKind.Moving );
  154. logger.D( "Vehicle Moving" );
  155. }
  156. private void Vehicle_OnMoveReady()
  157. {
  158. BuzzerOnOff( true, eBuzzerKind.StartWarn );
  159. logger.D( "Vehicle Move Ready" );
  160. }
  161. #endregion
  162. public void Init( Vehicle vehicle )
  163. {
  164. this.OperationModeProperty = eOperatationMode.ManualMode;
  165. this.AutoModeStateProperty = eAutoModeState.Stop;
  166. this.isThreadAlive = true;
  167. this.threadWorker = ThreadUtils.Invoke( this.ThreadWork );
  168. vehicle.OnMoveReady += Vehicle_OnMoveReady;
  169. vehicle.OnMoving += Vehicle_OnMoving;
  170. vehicle.OnMoveFinish += Vehicle_OnMoveFinish;
  171. vehicle.OnCharging += Vehicle_OnCharging;
  172. vehicle.OnChargingFull += Vehicle_OnChargingFull;
  173. }
  174. #region Lamp & Buzzer
  175. void LampStateChange( eLampState state )
  176. {
  177. this.iO.OutputOff( "OUT_TOWER_LAMP_RED" );
  178. this.iO.OutputOff( "OUT_TOWER_LAMP_GREEN" );
  179. switch ( state )
  180. {
  181. case eLampState.Alarm:
  182. this.iO.OutputOn( "OUT_TOWER_LAMP_RED" );
  183. break;
  184. case eLampState.Charging:
  185. this.iO.OutputOn( "OUT_TOWER_LAMP_RED" );
  186. this.iO.OutputOn( "OUT_TOWER_LAMP_GREEN" );
  187. break;
  188. case eLampState.AutoRunNChargingFull:
  189. this.iO.OutputOn( "OUT_TOWER_LAMP_GREEN" );
  190. //Blue 없음
  191. //this.iO.OutputOff("OUT_TOWER_LAMP_BLUE");
  192. break;
  193. default:
  194. break;
  195. }
  196. }
  197. void BuzzerOnOff( bool isOn, eBuzzerKind kind = eBuzzerKind.Alarm )
  198. {
  199. this.iO.OutputOff( "OUT_BUZZER_00" );
  200. this.iO.OutputOff( "OUT_BUZZER_01" );
  201. this.iO.OutputOff( "OUT_BUZZER_02" );
  202. if ( !isOn )
  203. return;
  204. switch ( kind )
  205. {
  206. case eBuzzerKind.Alarm:
  207. this.iO.OutputOn( "OUT_BUZZER_00" );
  208. break;
  209. case eBuzzerKind.StartWarn:
  210. this.iO.OutputOn( "OUT_BUZZER_01" );
  211. break;
  212. case eBuzzerKind.Moving:
  213. this.iO.OutputOn( "OUT_BUZZER_02" );
  214. break;
  215. default:
  216. break;
  217. }
  218. }
  219. #endregion
  220. void ThreadWork()
  221. {
  222. while ( this.isThreadAlive )
  223. {
  224. try
  225. {
  226. Thread.Sleep( 5 );
  227. DoWork();
  228. }
  229. catch ( Exception ex )
  230. {
  231. logger.E( $"{GetType().Name} - Thread Exception : {ex.StackTrace}" );
  232. }
  233. }
  234. logger.D( "[AutoManager] - Work Thread Dispose" );
  235. }
  236. public void DoWork()
  237. {
  238. switch ( this.OperationModeProperty )
  239. {
  240. case eOperatationMode.ManualMode:
  241. break;
  242. case eOperatationMode.AutoMode:
  243. switch ( this.AutoModeStateProperty )
  244. {
  245. case eAutoModeState.ErrorStop:
  246. this.AutoModeStateProperty = eAutoModeState.WaitStop;
  247. break;
  248. case eAutoModeState.WaitStop:
  249. this.AutoModeStateProperty = eAutoModeState.Stop;
  250. break;
  251. case eAutoModeState.Stop:
  252. this.OperationModeProperty = eOperatationMode.ManualMode;
  253. break;
  254. case eAutoModeState.StartRun:
  255. this.AutoModeStateProperty = eAutoModeState.Run;
  256. break;
  257. case eAutoModeState.Run:
  258. break;
  259. default:
  260. break;
  261. }
  262. break;
  263. case eOperatationMode.InitialMode:
  264. break;
  265. default:
  266. break;
  267. }
  268. }
  269. public void ProcessAlarm( int alarmID )
  270. {
  271. this.AutoModeStateProperty = eAutoModeState.ErrorStop;
  272. this.LampStateProperty = eLampState.Alarm;
  273. this.BuzzerStateProperty = eBuzzerKind.Alarm;
  274. HisAlarm hisAlarm = new HisAlarm();
  275. var alarm = this.Alarms.Where( x => x.AlarmId == alarmID ).FirstOrDefault();
  276. if ( alarm == null )
  277. {
  278. hisAlarm.AlarmId = alarmID;
  279. hisAlarm.Text = "Not Define Alarm";
  280. alarm = new Alarm();
  281. alarm.AlarmId = alarmID;
  282. alarm.Text = "Not Define Alarm";
  283. logger.E( $"[{this.GetType().Name}] - Not Define Alarm No {alarmID}" );
  284. }
  285. else
  286. {
  287. hisAlarm.AlarmId = alarmID;
  288. hisAlarm.Text = alarm.Name + " - " + alarm.Text;
  289. hisAlarm.Solution = alarm.Solution;
  290. //hisAlarm.Alarm = alarm;
  291. }
  292. sql.HisAlarmDAL.Insert( hisAlarm );
  293. logger.I( $"[Alarm Occur] - ID : {alarmID} / Text : {hisAlarm.Text}" );
  294. this.ActiveAlarms.Add( alarm );
  295. this.OnOccurAlarm?.BeginInvoke( alarm.AlarmId, null, null );
  296. //UI 로는 처음 발생한 Error 만 전송한다.
  297. if ( IsErrorProcessing )
  298. return;
  299. this.BuzzerOnOff( true, eBuzzerKind.Alarm );
  300. this.sql.CommandDAL.Clean();
  301. this.sql.SubCmdDAL.Clean();
  302. this.activeAlarm = ObjectCopyUtils.DeepClone<Alarm>( alarm );
  303. IsErrorProcessing = true;
  304. var msg = new GUIMessageEventArgs
  305. {
  306. Kind = GUIMessageEventArgs.eGUIMessageKind.ModelPropertyChange,
  307. MessageKey = MessageKey.Alarm,
  308. MessageText = hisAlarm.Text,
  309. Args = hisAlarm,
  310. };
  311. this.eventAggregator.GetEvent<GUIMessagePubSubEvent>().Publish( msg );
  312. }
  313. #region IDisposable Support
  314. private bool disposedValue = false; // 중복 호출을 검색하려면
  315. protected virtual void Dispose( bool disposing )
  316. {
  317. if ( !disposedValue )
  318. {
  319. if ( disposing )
  320. {
  321. // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다.
  322. this.isThreadAlive = false;
  323. if ( !this.threadWorker.Join( 3000 ) )
  324. ThreadUtils.Kill( this.threadWorker );
  325. }
  326. // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다.
  327. // TODO: 큰 필드를 null로 설정합니다.
  328. disposedValue = true;
  329. }
  330. }
  331. // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다.
  332. // ~AutoManager()
  333. // {
  334. // // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
  335. // Dispose(false);
  336. // }
  337. // 삭제 가능한 패턴을 올바르게 구현하기 위해 추가된 코드입니다.
  338. public void Dispose()
  339. {
  340. // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
  341. Dispose( true );
  342. // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다.
  343. // GC.SuppressFinalize(this);
  344. }
  345. #endregion
  346. }
  347. }