using Aurora; using Aurora.Api; using Aurora.Api.Manager; using Aurora.Framework.Alarm; using AuroraPLC; using System; using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using WeldingCommon.Devices; using WeldingCommon.Sequences; using static WeldingCommon.Devices.PLCController; namespace WeldingCommon.Alarm { public class AlarmManager { private static readonly Logger AlarmLog = new Logger("ALARM"); protected static AlarmManager _Instance; protected static IAuroraEnvironment _AuroraEnv; public readonly IAlarmService _AlarmService; private readonly IDeviceManager _DeviceManager; private static PLCController _Plc; public AlarmManager(IAuroraEnvironment aurora) { _AuroraEnv = aurora; _AlarmService = aurora.AlarmService; _DeviceManager = aurora.DeviceManager; _Plc = _DeviceManager.GetDevice(CommonDeviceIds.PLCDevice) as PLCController; // Reset Alarm Event Subscribe > Clear All Device Alarms // TODO:: Check when event below generated. If event does not generated, remove. aurora.EventObservable.AsObservable(AuroraSysEvent.SYS_ALARM_RESET_ALL_ALARM) .Select(msg => msg.Param) .Subscribe(ClearAllAlarm); aurora.EventObservable.AsObservable(AuroraSysEvent.SYS_ALARM_RESET_ALARM) .Select(msg => msg.Param) .Subscribe(ClearAlarm); aurora.EventObservable.AsObservable(CommonEventIds.EVENT_RESET_ALL_ALARMS_REQUEST) .Select(msg => msg.Param) .Subscribe(ClearAllAlarmRequest); } public static void Init(IAuroraEnvironment aurora) { if (_Instance == null) { _Instance = new AlarmManager(aurora); } } private void ClearAlarm(object obj) { //각 Alarm별 clear 처리를 따로 해줘야 할까 ? } private void ClearAllAlarm(object mAlarmList) { if (!(mAlarmList is List alarmList)) { return; } //_Plc?.WriteBit(_Plc.LightAlarmStatusAddr, false); //_Plc?.WriteBit(_Plc.HeavyAlarmStatusAddr, false); } private void ClearAllAlarmRequest(object obj) { Application.Current.Dispatcher.InvokeAsync(() => _Instance._AlarmService.ClearAllAlarm()); //_Plc?.WriteBit(_Plc.LightAlarmStatusAddr, false); //_Plc?.WriteBit(_Plc.HeavyAlarmStatusAddr, false); } public static bool Alarm(int code, bool isLog = true, bool useReport = true) { // 모든 Alarm 은 띄워 줌 if (!_Instance._AlarmService.GetCurrentAlarmCodes().Contains(code)) { _Instance._AlarmService.SetAlarm(code, useReport); AlarmDescription alarm = _Instance._AlarmService.GetAlarmDescription(code); if (isLog) { if (alarm.Level == AlarmLevel.H) { AlarmLog.E($"Code : {code} , Description : {alarm.Name}"); } else { AlarmLog.W($"Code : {code} , Description : {alarm.Name}"); } } ////PLC의 중알람의 경우 PC에서 Dialog만 발생하고 Alarm 중알람 Word를 써주지 않는다 //if (alarm.Level == AlarmLevel.H && alarm.Unit == "PLC") { // return true; //} //if (alarm.Level == AlarmLevel.H) { // _Plc?.WriteBit(_Plc.HeavyAlarmStatusAddr, true); //} else { // _Plc?.WriteBit(_Plc.LightAlarmStatusAddr, true); //} return true; } return false; } public static bool ChangeAlarmDescription(int code, string description, bool isLog = true, bool useReport = true) { // 중복 알람은 로그로 남기지 않도록 하는 코드 if (IsOccuredAlarm(code)) return true; AlarmDescription alarm = _Instance._AlarmService.GetAlarmDescription(code); alarm.Description = description; // 모든 Alarm 은 띄워 줌 if (!_Instance._AlarmService.GetCurrentAlarmCodes().Contains(code)) { _Instance._AlarmService.SetAlarm(code, useReport); if (isLog) { if (alarm.Level == AlarmLevel.H) { AlarmLog.E($"Code : {code} , Description : {alarm.Name}"); } else { AlarmLog.W($"Code : {code} , Description : {alarm.Name}"); } } ////PLC의 중알람의 경우 PC에서 Dialog만 발생하고 Alarm 중알람 Word를 써주지 않는다 //if (alarm.Level == AlarmLevel.H && alarm.Unit == "PLC") { // return true; //} //if (alarm.Level == AlarmLevel.H) { // _Plc?.WriteBit(_Plc.HeavyAlarmStatusAddr, true); //} else { // _Plc?.WriteBit(_Plc.LightAlarmStatusAddr, true); //} return true; } return false; } public static void StopCommonSequenceByAlarm(int code) { AlarmDescription alarm = _Instance._AlarmService.GetAlarmDescription(code); // 바로 Sequence 를 정지해야 하는 경우 발생할 수 있음. // 불필요 할까?? Device 의 상태에 따라서 멈춰야 하는 Sequence 가 다를 수도 있다. // 만약에 Sequence 가 종료되었을 때, pass, fail 여부에 따라 다를 지도. if (alarm.Level == AlarmLevel.H) { StopSequence(CommonSequenceIds.SeqMarkGrid); StopSequence(CommonSequenceIds.SeqScannerCalibration); StopSequence(CommonSequenceIds.SeqReceiveCellInfo); StopSequence(CommonSequenceIds.SeqReportCellResult); StopSequence(CommonSequenceIds.SeqScoutFlyingVision); StopSequence(CommonSequenceIds.SeqScoutNormal); StopSequence(CommonSequenceIds.SeqUploadWeldingList); StopSequence(CommonSequenceIds.SeqTeachingRun); //26.04.15 추가 StopSequence(CommonSequenceIds.SeqAutoRunACS); } } protected static void StopSequence(string sequenceId) { if (_AuroraEnv.SequenceEntry[sequenceId].RunState == SequenceRunState.Running) { _AuroraEnv.SequenceEntry[sequenceId].EmergencyStop(); AlarmLog.I($"{_AuroraEnv.SequenceEntry[sequenceId]} EmergencyStop"); } } // 공통부. 현재 발생한 중알람 여부 조회 public static bool HasAlarmLevelHigh() { try { if (ApplicationExt.IsSimulation) return false; var alarmList = _Instance._AlarmService.GetCurrentAlarmCodes(); if (alarmList.Count > 0) { foreach (var item in alarmList) { if (IsAlarmLevelHigh(item)) { return true; } } } return false; } catch (Exception ex) { AlarmLog.E($"{ex.Message} Exception Accured"); return false; } } public static bool IsAlarmLevelHigh(int item) { var desc = _Instance._AlarmService.GetAlarmDescription(item); if (desc != null) { if (desc.Level == AlarmLevel.H) { return true; } } else { // Alarm Description을 알 수 없는 경우 : 위험할 수 있으니 일단 H로 취급 return true; } return false; } public static bool HasAlarmLevelLow() { var alarmList = _Instance._AlarmService.GetCurrentAlarmCodes(); if (alarmList.Count > 0) { foreach (var item in alarmList) { if (IsAlarmLevelLow(item)) { return true; } } } return false; } public static bool IsAlarmLevelLow(int item) { var desc = _Instance._AlarmService.GetAlarmDescription(item); if (desc != null) { if (desc.Level == AlarmLevel.L) { return true; } } else { // Alarm Description을 알 수 없는 경우 : 위험할 수 있으니 일단 H로 취급 return true; } return false; } public static bool IsOccuredAlarm(int AlarmCode) { var CurAlarmList = _Instance._AlarmService.GetCurrentAlarmCodes(); if (CurAlarmList.FirstOrDefault(x => x == AlarmCode) != 0) return true; return false; } public static bool IsPlcEmoAlarm() { if (_Plc == null) return false; else return _Plc.ReadBit(eCommonBitInput.PLC_EMO_STATUS).data; } public static bool IsPlcDoorOpen() { if (_Plc == null) return false; else return _Plc.ReadBit(eCommonBitInput.PLC_DOOR_INTERLOCK).data; } } }