| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- using System;
- using System.Threading;
- using GSG.NET.Concurrent;
- using GSG.NET.Logging;
- using OHV.Common.Shareds;
- using VehicleControlSystem.ControlLayer.IO;
- using Prism.Events;
- using OHV.SqliteDAL;
- using OHV.Common.Model;
- using OHV.Common.Events;
- using VehicleControlSystem.ControlLayer;
- using GSG.NET.Utils;
- using System.Collections.Generic;
- using System.Linq;
- using GSG.NET.LINQ;
- namespace VehicleControlSystem.Managers
- {
- /// <summary>
- /// Vehicle 전체 상태를 관리.
- /// </summary>
- public class AutoManager : IDisposable
- {
- static Logger logger = Logger.GetLogger();
- Thread threadWorker = null;
- bool isThreadAlive = false;
- IIO iO = null;
- private bool isErrorProcessing = false;
- public bool IsErrorProcessing
- {
- get { return this.isErrorProcessing; }
- set
- {
- //if (this.isErrorProcessing == value) return;
- this.isErrorProcessing = value;
- if (value)
- {
- //if ( this.activeAlarm == null ) return;
- //this.OnOccurAlarm?.BeginInvoke( this.activeAlarm.AlarmId, null, null );
- }
- else
- {
- this.ActiveAlarms.ForEach(x =>
- {
- this.OnClearAlarm?.Invoke(x.AlarmId);
- var al = ObjectCopyUtils.DeepClone<Alarm>(x);
- var args = new ActiveAlarmEventArgs(al, false);
- this.eventAggregator.GetEvent<ActiveAlarmPubSubEvent>().Publish(args);
- });
- this.ActiveAlarms.Clear();
- //if ( this.activeAlarm == null ) return;
- //this.OnClearAlarm?.BeginInvoke( this.activeAlarm.AlarmId, null, null );
- //this.activeAlarm = null;
- this.BuzzerOnOff(false);
- }
- }
- }
- private bool isBlockedMoving = false;
- public bool IsBlockedMoving //210812 Kkm
- {
- get { return this.isBlockedMoving; }
- set
- {
- if (this.isBlockedMoving == value) return;
- this.isBlockedMoving = value;
- if (value)
- {
- this.BuzzerOnOff(false); //Kkm Blocked 상태는 무조건 Off
- this.LampStateChange(eLampState.Blocked);
- }
- else
- {
- this.BuzzerOnOff(true, eBuzzerKind.Moving);
- this.LampStateChange(eLampState.AutoRunNChargingFull);
- }
- }
- }
- public event Action<int> OnOccurAlarm;
- public event Action<int> OnClearAlarm;
- Alarm activeAlarm = null;
- //Alarm List
- List<Alarm> Alarms { get; set; }
- //현재 발생 된 알람 리스트
- public List<Alarm> ActiveAlarms { get; set; }
- IEventAggregator eventAggregator = null;
- SqliteManager sql = null;
- private eOperatationMode operationMode;
- public eOperatationMode OperationModeProperty
- {
- get { return operationMode; }
- set
- {
- if (operationMode == value) return;
- operationMode = value;
- logger.D($"[AutoManager] OperationMode - {value}");
- this.OnOperationModeChanged?.Invoke(value);
- if (value == eOperatationMode.AutoMode)
- this.iO.OutputOff("OUT_TEACH_MODE");
- else
- this.iO.OutputOn("OUT_TEACH_MODE");
- }
- }
- public event Action<eOperatationMode> OnOperationModeChanged;
- private eAutoModeState autoModeState;
- public eAutoModeState AutoModeStateProperty
- {
- get { return autoModeState; }
- set
- {
- if (autoModeState == value) return;
- autoModeState = value;
- logger.D($"[AutoManager] AutoModeState - {value}");
- switch (value)
- {
- case eAutoModeState.ErrorStop:
- this.LampStateProperty = eLampState.Alarm;
- break;
- case eAutoModeState.StartRun:
- this.LampStateProperty = eLampState.AutoRunNChargingFull;
- break;
- case eAutoModeState.Run:
- this.LampStateProperty = eLampState.AutoRunNChargingFull;
- break;
- case eAutoModeState.Stop:
- this.LampStateProperty = eLampState.Manual;
- break;
- case eAutoModeState.WaitStop:
- this.LampStateProperty = eLampState.Manual;
- break;
- default:
- break;
- }
- }
- }
- private eLampState lampState = eLampState.None;
- public eLampState LampStateProperty
- {
- get { return lampState; }
- set
- {
- if (lampState == value) return;
- lampState = value;
- this.LampStateChange(value);
- }
- }
- private eBuzzerKind buzzerState;
- public eBuzzerKind BuzzerStateProperty
- {
- get { return buzzerState; }
- set { buzzerState = value; }
- }
- Vehicle vehicle = null;
- public AutoManager(IIO io, IEventAggregator ea, SqliteManager sql, List<Alarm> al)
- {
- this.iO = io;
- this.eventAggregator = ea;
- this.sql = sql;
- this.Alarms = al;
- this.ActiveAlarms = new List<Alarm>();
- }
- #region Vehicle Events
- private void Vehicle_OnChargingFull()
- {
- if (this.OperationModeProperty == eOperatationMode.AutoMode)
- LampStateChange(eLampState.AutoRunNChargingFull);
- else
- LampStateChange(eLampState.Manual);
- }
- private void Vehicle_OnCharging()
- {
- LampStateChange(eLampState.Charging);
- }
- private void Vehicle_OnMoveFinish()
- {
- BuzzerOnOff(false);
- logger.D("Vehicle Move Finish");
- }
- private void Vehicle_OnMoving()
- {
- BuzzerOnOff(true, eBuzzerKind.Moving);
- logger.D("Vehicle Moving");
- }
- private void Vehicle_OnMoveReady()
- {
- BuzzerOnOff(true, eBuzzerKind.StartWarn);
- logger.D("Vehicle Move Ready");
- }
- #endregion
- public void Init(Vehicle vehicle)
- {
- this.OperationModeProperty = eOperatationMode.ManualMode;
- this.AutoModeStateProperty = eAutoModeState.Stop;
- this.isThreadAlive = true;
- this.threadWorker = ThreadUtils.Invoke(this.ThreadWork);
- this.vehicle = vehicle;
- this.vehicle.OnMoveReady += Vehicle_OnMoveReady;
- this.vehicle.OnMoving += Vehicle_OnMoving;
- this.vehicle.OnMoveFinish += Vehicle_OnMoveFinish;
- this.vehicle.OnCharging += Vehicle_OnCharging;
- this.vehicle.OnChargingFull += Vehicle_OnChargingFull;
- }
- #region Lamp & Buzzer
- void LampStateChange(eLampState state)
- {
- this.iO.OutputOff("OUT_TOWER_LAMP_RED");
- this.iO.OutputOff("OUT_TOWER_LAMP_GREEN");
- switch (state)
- {
- case eLampState.Manual:
- case eLampState.Alarm:
- this.iO.OutputOn("OUT_TOWER_LAMP_RED");
- break;
- case eLampState.Charging:
- this.iO.OutputOn("OUT_TOWER_LAMP_RED");
- this.iO.OutputOn("OUT_TOWER_LAMP_GREEN");
- break;
- case eLampState.AutoRunNChargingFull:
- this.iO.OutputOn("OUT_TOWER_LAMP_GREEN");
- break;
- case eLampState.Blocked: //210812 Kkm 진행 막혀있는 상태 시 Buzzer 및 Lamp 상태 변경
- this.iO.OutputOn("OUT_TOWER_LAMP_RED");
- this.iO.OutputOn("OUT_TOWER_LAMP_GREEN");
- break;
- default:
- break;
- }
- }
- void BuzzerOnOff(bool isOn, eBuzzerKind kind = eBuzzerKind.Alarm)
- {
- this.iO.OutputOff("OUT_BUZZER_00");
- this.iO.OutputOff("OUT_BUZZER_01");
- this.iO.OutputOff("OUT_BUZZER_02");
- if (!isOn)
- return;
- //21.09.16. Kang. 주행중 Buzzer 사용 선택.
- if (kind == eBuzzerKind.Moving)
- {
- var useMovingBuzzer = sql.ConfigDal.Get(_ => _.ID.Equals(ConstString.UseMovingBuzzer)).FirstOrDefault();
- if (useMovingBuzzer != null)
- {
- if (useMovingBuzzer.Value.FwIntOf() <= 0)
- return;
- }
- }
- switch (kind)
- {
- case eBuzzerKind.Alarm:
- this.iO.OutputOn("OUT_BUZZER_00");
- break;
- case eBuzzerKind.StartWarn:
- this.iO.OutputOn("OUT_BUZZER_01");
- break;
- case eBuzzerKind.Moving:
- this.iO.OutputOn("OUT_BUZZER_02");
- break;
- //case eBuzzerKind.Blocked: //210812 Kkm 진행 막혀있는 상태 시 Buzzer 및 Lamp 상태 변경
- // break;
- default:
- break;
- }
- }
- #endregion
- void ThreadWork()
- {
- Thread.CurrentThread.Name = $"{this.GetType().Name}-Work";
- while (this.isThreadAlive)
- {
- try
- {
- Thread.Sleep(100);
- DoWork();
- }
- catch (Exception ex)
- {
- logger.E($"{GetType().Name} - Thread Exception : {ex.StackTrace}");
- }
- }
- logger.D("[AutoManager] - Work Thread Dispose");
- }
- public void DoWork()
- {
- switch (this.OperationModeProperty)
- {
- case eOperatationMode.ManualMode:
- break;
- case eOperatationMode.AutoMode:
- switch (this.AutoModeStateProperty)
- {
- case eAutoModeState.ErrorStop:
- this.AutoModeStateProperty = eAutoModeState.WaitStop;
- break;
- case eAutoModeState.WaitStop:
- this.AutoModeStateProperty = eAutoModeState.Stop;
- break;
- case eAutoModeState.Stop:
- if (IsAllProcessStop())
- {
- //TODO: 여기서 메인명령을 정리하자.
- this.sql.SubCmdDAL.Clean();
- this.sql.CommandDAL.Clean();
- this.OperationModeProperty = eOperatationMode.ManualMode;
- }
- break;
- case eAutoModeState.StartRun:
- if (IsAllProcessStart())
- this.AutoModeStateProperty = eAutoModeState.Run;
- break;
- case eAutoModeState.Run:
- break;
- default:
- break;
- }
- break;
- case eOperatationMode.InitialMode:
- break;
- default:
- break;
- }
- }
- public void ProcessAlarm(int alarmID)
- {
- HisAlarm hisAlarm = new HisAlarm();
- var alarm = this.Alarms.Where(x => x.AlarmId == alarmID).FirstOrDefault();
- if (alarm == null)
- {
- hisAlarm.AlarmId = alarmID;
- hisAlarm.Text = "Not Define Alarm";
- alarm = new Alarm();
- alarm.AlarmId = alarmID;
- alarm.Level = eAlarmLevel.Fault;
- alarm.Text = "Not Define Alarm";
- logger.E($"[{this.GetType().Name}] - Alarm Process / Not Define Alarm No {alarmID}");
- }
- else
- {
- hisAlarm.AlarmId = alarmID;
- hisAlarm.Text = alarm.Name + " - " + alarm.Text;
- hisAlarm.Solution = alarm.Solution;
- }
- //Add History
- sql.HisAlarmDAL.Insert(hisAlarm);
- logger.I($"[Alarm Occur] - ID : {alarmID} / Text : {hisAlarm.Text}");
-
- if (this.ActiveAlarms == null)
- return;
- if (!this.ActiveAlarms.Any(x => x.AlarmId == alarmID))
- {
- //OCS Report
- this.OnOccurAlarm?.Invoke(alarm.AlarmId);
- var cloneAlarm = ObjectCopyUtils.DeepClone<Alarm>(alarm);
- this.activeAlarm = cloneAlarm;
- this.ActiveAlarms.Add(cloneAlarm); //Clear 보고를 위한 List Add
- var args = new ActiveAlarmEventArgs(cloneAlarm);
- this.eventAggregator.GetEvent<ActiveAlarmPubSubEvent>().Publish(args);
- }
- if (alarm.Level == eAlarmLevel.Warn)
- return;
- this.AutoModeStateProperty = eAutoModeState.ErrorStop;
- this.LampStateProperty = eLampState.Alarm;
- this.BuzzerStateProperty = eBuzzerKind.Alarm;
- this.BuzzerOnOff(true, eBuzzerKind.Alarm);
- this.sql.CommandDAL.Clean();
- this.sql.SubCmdDAL.Clean();
- //UI 로는 처음 발생한 Error 만 전송한다.
- if (IsErrorProcessing)
- return;
- IsErrorProcessing = true;
- var msg = new GUIMessageEventArgs
- {
- Kind = GUIMessageEventArgs.eGUIMessageKind.ModelPropertyChange,
- MessageKey = MessageKey.Alarm,
- MessageText = hisAlarm.Text,
- Args = hisAlarm,
- };
- this.eventAggregator.GetEvent<GUIMessagePubSubEvent>().Publish(msg);
- }
- /// <summary>
- /// Alarm Clear 를 여기서 모아서 하자.
- /// </summary>
- /// <param name="alarmID"></param>
- public void ClearAlarm(int alarmID)
- {
- var alarm = this.ActiveAlarms.FirstOrDefault(x => x.AlarmId == alarmID);
- if (alarm == null)
- return;
- this.ActiveAlarms.Remove(alarm);
- logger.I($"[{this.GetType().Name}] - Alarm Clear [{alarmID}]");
- this.OnClearAlarm?.Invoke(alarm.AlarmId);
- var al = ObjectCopyUtils.DeepClone<Alarm>(alarm);
- var args = new ActiveAlarmEventArgs(al, false);
- this.eventAggregator.GetEvent<ActiveAlarmPubSubEvent>().Publish(args);
- }
- bool IsAllProcessStop()
- {
- if (vehicle.IsAutoRun)
- return false;
- return true;
- }
- bool IsAllProcessStart()
- {
- return vehicle.IsAutoRun;
- }
- #region IDisposable Support
- private bool disposedValue = false; // 중복 호출을 검색하려면
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다.
- this.isThreadAlive = false;
- if (!this.threadWorker.Join(3000))
- ThreadUtils.Kill(this.threadWorker);
- }
- // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다.
- // TODO: 큰 필드를 null로 설정합니다.
- disposedValue = true;
- }
- }
- // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다.
- // ~AutoManager()
- // {
- // // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
- // Dispose(false);
- // }
- // 삭제 가능한 패턴을 올바르게 구현하기 위해 추가된 코드입니다.
- public void Dispose()
- {
- // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
- Dispose(true);
- // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다.
- // GC.SuppressFinalize(this);
- }
- #endregion
- }
- }
|