using Aurora.Api; using AuroraChiller; using AuroraIO; using AuroraLaser; using AuroraLaser.Trumpf; using AuroraLaserScanner; using AuroraLBAD; using AuroraOCT; using ILSOS_PrismaticScanner.Alarm; using ILSOS_PrismaticScanner.Device; using ILSOS_PrismaticScanner.Device.IO; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using WeldingCommon.Alarm; using WeldingCommon.Settings; using static AuroraIO.AJINEXTEK.AjinIO.IOModuleInfo; using static ILSOS_PrismaticScanner.Device.IO.PAIX_PrismaticScanner; using static ILSOS_PrismaticScanner.Device.PLCControllerPrismaticScanner; namespace WeldingCommon.Sequences { class SeqAlarmMonitor { const string SEQ_START = "SEQ START"; // 딱 한번 Sequence 진입 시에만 실행될 Node const string SEQ_LoopFirst = "SEQ Loop First"; const string SEQ_WAIT_TIME = "SEQ Wait Time"; //const string SEQ_LoopLast = "SEQ Loop Last"; public const string CHECK_ALARM_PLC = "Check Alarm PLC"; public const string CHECK_ALARM_SCANNER = "Check Alarm Scanner"; public const string CHECK_ALARM_LASER = "Check Alarm Laser"; public const string CHECK_ALARM_LBAD = "Check Alarm LBAD"; public const string CHECK_ALARM_OCT = "Check Alarm OCT"; public const string CHECK_ALARM_CHILLER = "Check Alarm Chiller"; public const string CHECK_ALARM_LEAK_SENSOR = "Check Alarm LeakSensor"; public const string CHECK_ALARM_IO_BOARD = "Check Alarm IOBoard"; private static SequenceSetting _SequenceSetting; private static PLCControllerPrismaticScanner _Plc; private static Scanner _Scanner; private static Laser _Laser; private static LaserTruFiber _LaserTruFiber; private static PAIX_PrismaticScanner _IO; private static SmcChiller _Chiller; private static OCT _OCT; private static LBAD _LBAD; public const int TIMEOUT_PLC_LIVE_CHECK = 2000; // msec public SequenceBuilder Builder() { SequenceBuilder sb = new SequenceBuilder(1000, true); sb.AddAction(SEQ_START, StartNode); sb.AddDecision(SEQ_LoopFirst, LoopFirstNode); sb.AddAction(SEQ_WAIT_TIME, WaitTime); sb.AddAction(CHECK_ALARM_PLC, CheckAlarmPLC); sb.AddAction(CHECK_ALARM_SCANNER, CheckAlarmScanner); sb.AddAction(CHECK_ALARM_LASER, CheckAlarmLaser); sb.AddAction(CHECK_ALARM_LBAD, CheckAlarmLBAD); sb.AddAction(CHECK_ALARM_OCT, CheckAlarmOCT); sb.AddAction(CHECK_ALARM_CHILLER, CheckAlarmChiller); sb.AddAction(CHECK_ALARM_LEAK_SENSOR, CheckAlarmLeakSensor); sb.AddAction(CHECK_ALARM_IO_BOARD, CheckAlarmIOBoard); //sb.AddAction(SEQ_LoopLast, LoopLastNode); sb.Flows(sb.Init > sb[SEQ_START] > sb[SEQ_LoopFirst] > sb[SEQ_WAIT_TIME] > sb[CHECK_ALARM_PLC] > sb[CHECK_ALARM_SCANNER] > sb[CHECK_ALARM_LASER] > sb[CHECK_ALARM_LBAD] > sb[CHECK_ALARM_OCT] > sb[CHECK_ALARM_CHILLER] > sb[CHECK_ALARM_LEAK_SENSOR] > sb[CHECK_ALARM_IO_BOARD] //> sb[SEQ_LoopLast] > sb[SEQ_LoopFirst]); > sb[SEQ_LoopFirst]); sb.Flows(sb[SEQ_LoopFirst] > sb.Final); sb.OnStopped(OnStopped); sb.OnForceError(OnForceError); //sb.Draw("AlarmMonitor.pdf"); return sb; } private static SequenceActionResult StartNode(SequenceContext context, string id, SequenceActionResult param) { _SequenceSetting = context.GetSetting(CommonSettingIds.Sequence); InitDev(context); return SequenceAction.Ok(); } private static void InitDev(SequenceContext context) { if (_SequenceSetting.PlcActivated) _Plc = context.Devices[CommonDeviceIds.PLCDevice] as PLCControllerPrismaticScanner; if (_SequenceSetting.ScannerActivated) _Scanner = context.GetLaserScanner(); if (_SequenceSetting.LaserActivated) { _Laser = context.GetLaser(); _LaserTruFiber = _Laser.getCore() as LaserTruFiber; } if (_SequenceSetting.LbadActivated) _LBAD = context.GetLBAD(); if (_SequenceSetting.OctActivated) _OCT = context.GetOCT(); if (_SequenceSetting.ChillerActivated) _Chiller = context.GetChiller(); // Scanner, Laser, LBAD, OCT, Chiller, LeakSensor 는 IO 로도 상태 check 할 수 있음. if (_SequenceSetting.ScannerActivatedWithIO || _SequenceSetting.LaserActivatedWithIO || _SequenceSetting.LbadActivatedWithIO || _SequenceSetting.OctActivatedWithIO || _SequenceSetting.ChillerActivatedWithIO || _SequenceSetting.LeakSensorActivatedWithIO) { _IO = context.GetIOUnit() as PAIX_PrismaticScanner; } } private static string LoopFirstNode(SequenceContext context, string id, ICollection branches, SequenceActionResult param) { while (!context.Stopped) { //_SequenceSetting = context.GetSetting(CommonSettingIds.Sequence); return SEQ_WAIT_TIME; } return SeqNodeIds.FINAL; } private static SequenceActionResult WaitTime(SequenceContext context, string id, SequenceActionResult param) { return SequenceAction.Ok(); } private static SequenceActionResult CheckAlarmPLC(SequenceContext context, string id, SequenceActionResult param) { if (_Plc == null || _SequenceSetting.PlcActivated == false) { return SequenceAction.Ok(); } if (_Plc.IsSimul) { return SequenceAction.Ok(); } if (!_Plc.IsActivated) { // 임시 주석 //AlarmManager.Alarm(AlaramCode_PrismaticScanner.ALARM_DEVICE_PLC_DEACTIVATED); } else { if (_SequenceSetting.PlcActivatedLive) { //PLC Live Check 시간은 확인 필요 Stopwatch sw = Stopwatch.StartNew(); while (!context.Stopped) { if (_Plc.ReadBit(eBitInput.PLC_LIVE_STATUS).data) { break; } if (sw.ElapsedMilliseconds > TIMEOUT_PLC_LIVE_CHECK) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_PLC_DISCONNECT); break; } Thread.Sleep(10); } } // EMO check 는 항상 해야 함. if (_Plc.ReadBit(PLCControllerPrismaticScanner.eBitInput.PLC_EMO_STATUS).data) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_PLC_EMO); _Laser.LaserOff(); } if (_Plc.ReadBit(PLCControllerPrismaticScanner.eBitInput.PLC_LIGHT_ALARM_STATUS).data) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_PLC_Light); } if (_Plc.ReadBit(PLCControllerPrismaticScanner.eBitInput.PLC_HEAVY_ALARM_STATUS).data) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_PLC_Heavy); } bool boolian = _Plc.ReadBit(PLCControllerPrismaticScanner.eBitInput.PLC_DOOR_INTERLOCK).data; if (boolian) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_PLC_DOOR_INTERLOCK); } } return SequenceAction.Ok(); } private static SequenceActionResult CheckAlarmScanner(SequenceContext context, string id, SequenceActionResult param) { if (_Scanner == null || _SequenceSetting.ScannerActivated == false) { return SequenceAction.Ok(); } if (_Scanner.IsSimul) { return SequenceAction.Ok(); } if (!_Scanner.IsActivated) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_SCANNER_DEACTIVATED); } else { var lastErrorcode = _Scanner.GetLastError(); //Scanner의 activate 상태를 체크하면.. 수동상태에서 디바이스를 deactivaed시키면 알람 발생하므로 조건문 변경 필요 if (lastErrorcode != 0) { AlarmManager.ChangeAlarmDescription(AlarmCode_PrismaticScanner.ALARM_DEVICE_SCANNER_ERROR, $"Scanner Error Code : {lastErrorcode} Check Scanner Error Status"); } // TODO: Scanner 는 Alarm 과 연결되어 있지 않음. 알람 추가되었을 시에 어떤 IO 를 check 하지?? } return SequenceAction.Ok(); } private static SequenceActionResult CheckAlarmLaser(SequenceContext context, string id, SequenceActionResult param) { if (_Laser == null || _SequenceSetting.LaserActivated == false) { return SequenceAction.Ok(); } if (_Laser.IsSimul) { return SequenceAction.Ok(); } if (!_Laser.IsActivated) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_LASER_DEACTIVATED); } else { if (!_Laser.GetConnected()) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LASER_DISCONNECT); } if (_SequenceSetting.LaserActivatedWithIO && CheckDeviceIO()) { //Laser Disconnect Check 조건문 변경 필요 if (!_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LaserAssigned))) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LASER_DISCONNECT); } if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LaserError))) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LASER_ERROR); } if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.Warning))) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LASER_WARNING); } //Laser EMO IO Map 확인 필요 if (!_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LaserEMO_1)) || !_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LaserEMO_2))) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LASER_EMO); } } else { _LaserTruFiber = _Laser.getCore() as LaserTruFiber; //// Laser OPCUA로 연결한 경우 //#region 26.04.14 삭제 할 것 if (_LaserTruFiber == null) return SequenceAction.Ok();; // 강제 OK //#endregion if (_LaserTruFiber.GetEStopOpen()) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LASER_EMO); } if (_LaserTruFiber.GetFaultLaser()) { string alarmCode = $"{Convert.ToString(_LaserTruFiber.GetLastMessageCompID(), 16).ToUpper().PadLeft(2, '0')}{Convert.ToString(_LaserTruFiber.GetLastMessageCompNum(), 16).ToUpper().PadLeft(2, '0')} {Convert.ToString(_LaserTruFiber.GetLastMessageMsgCode(), 16).ToUpper().PadLeft(2, '0')}"; string alarmDescription = $" {_LaserTruFiber.GetLastMessageShortText()}"; AlarmManager.ChangeAlarmDescription(AlarmCode_PrismaticScanner.ALARM_DEVICE_LASER_ERROR_MSG, alarmCode + alarmDescription); } else if (_LaserTruFiber.GetMonitoring()) { string alarmCode = $"{Convert.ToString(_LaserTruFiber.GetLastMessageCompID(), 16).ToUpper().PadLeft(2, '0')}{Convert.ToString(_LaserTruFiber.GetLastMessageCompNum(), 16).ToUpper().PadLeft(2, '0')} {Convert.ToString(_LaserTruFiber.GetLastMessageMsgCode(), 16).ToUpper().PadLeft(2, '0')}"; string alarmDescription = $" {_LaserTruFiber.GetLastMessageShortText()}"; AlarmManager.ChangeAlarmDescription(AlarmCode_PrismaticScanner.ALARM_DEVICE_LASER_WARNING_MSG, alarmCode + alarmDescription); } } } return SequenceAction.Ok(); } private static SequenceActionResult CheckAlarmLBAD(SequenceContext context, string id, SequenceActionResult param) { if (_LBAD == null || _SequenceSetting.LbadActivated == false) { return SequenceAction.Ok(); } if (_LBAD.IsSimul) { return SequenceAction.Ok(); } if (!_LBAD.IsActivated) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_LBAD_DEACTIVATED); } else { // TODO: ReadyByAuto 는 Auto 돌렸을 때, Sequence 안뜨도록 하는 로직 이라고 함. 이 부분 수정이 필요 할 듯. // 이게 Sequence 안에서 Try 하면서 계속 붙이는 부분과 관련이 있는 듯함. if (_LBAD.GetReadybyAuto()) { if (!_LBAD.GetConnected()) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_LBAD_DISCONNECT); } // TODO: 이건 바로 밖의 else 부분으로 빼야 할 지도, Device check 와 IO 로 check 는 다르므로 if (_SequenceSetting.LbadActivatedWithIO && CheckDeviceIO()) { if (!_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LBADReadyStatus))) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LBAD_ERROR); } } } } return SequenceAction.Ok(); } private static SequenceActionResult CheckAlarmOCT(SequenceContext context, string id, SequenceActionResult param) { if (_OCT == null || _SequenceSetting.OctActivated == false) { return SequenceAction.Ok(); } if (_OCT.IsSimul) { return SequenceAction.Ok(); } if (!_OCT.IsActivated) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_OCT_DEACTIVATED); } else { if (!_OCT.GetConnected()) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_OCT_DISCONNECT); } if (_SequenceSetting.OctActivatedWithIO && CheckDeviceIO()) { if (!_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LDDError))) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_OCT_ERROR); } } } return SequenceAction.Ok(); } private static SequenceActionResult CheckAlarmChiller(SequenceContext context, string id, SequenceActionResult param) { if (_Chiller == null || _SequenceSetting.ChillerActivated == false) { return SequenceAction.Ok(); } if (_Chiller.IsSimul) { return SequenceAction.Ok(); } if (!_Chiller.IsActivated) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_CHILLER_DEACTIVATED); } else { if (!_Chiller.GetConnected()) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_CHILLER_DISCONNECT); } if (_Chiller.GetChillerRunningFlag()) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_CHILLER_ERROR); } if (_SequenceSetting.ChillerActivatedWithIO && CheckDeviceIO()) { // TODO: IO 로 Chiller check 하는 것이 있으면 추가 } } return SequenceAction.Ok(); } private static SequenceActionResult CheckAlarmLeakSensor(SequenceContext context, string id, SequenceActionResult param) { if (_SequenceSetting.LeakSensorActivatedWithIO && CheckDeviceIO()) { //Leak Sensor IO Map 추가 필요 if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LeakSensorHead))) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LEAK_SENSOR_DETECT_SCANNER); } if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LeakSensorChiller))) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LEAK_SENSOR_DETECT_CHILLER); } } return SequenceAction.Ok(); } private static SequenceActionResult CheckAlarmIOBoard(SequenceContext context, string id, SequenceActionResult param) { if (!CheckDeviceIO()) return SequenceAction.Ok(); if (!_IO.ReadDiBit(ePrismaticDIAddress.CCCAPASSYLaserMC1ON)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_CCCAPASSYLaserMC1ON); if (!_IO.ReadDiBit(ePrismaticDIAddress.CCCAPASSYLaserMC2ON)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_CCCAPASSYLaserMC2ON); if (_IO.ReadDiBit(ePrismaticDIAddress.BOXTempAlarm)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_BOXTempAlarm); if (!_IO.ReadDiBit(ePrismaticDIAddress.CCCAPChillerLeakSensor)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_CCCAPChillerLeakSensor); if (_IO.ReadDiBit(ePrismaticDIAddress.FanAlarm1)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_FanAlarm1); if (_IO.ReadDiBit(ePrismaticDIAddress.FanAlarm2)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_FanAlarm2); if (_IO.ReadDiBit(ePrismaticDIAddress.FanAlarm3)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_FanAlarm3); if (_IO.ReadDiBit(ePrismaticDIAddress.FanAlarm4)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_FanAlarm4); if (_IO.ReadDiBit(ePrismaticDIAddress.FanAlarm5)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_FanAlarm5); if (_IO.ReadDiBit(ePrismaticDIAddress.FanAlarm6)) AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_FanAlarm6); return SequenceAction.Ok(); } private static bool CheckDeviceIO() { return false; if (_IO == null) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_IS_NULL); return false; } // IO 가 Simul 이면, Read Bit 를 해주지 않기 위해 if (_IO.IsSimul) { return false; } if (_IO.IsActivated == false) { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_DEACTIVATED); return false; } // 우선 주석 처리 함. 잦은 호출이 발생할 수 있어서 //if (_IO.IsConnected() == false) { // AlarmManager.Alarm(AlaramCode_PrismaticScanner.ALARM_DEVICE_IO_DISCONNECT); //} return true; } //private static SequenceActionResult LoopLastNode(SequenceContext context, string id, SequenceActionResult param) //{ // //Thread.Sleep(100); // return SequenceAction.Ok(); //} private static void OnForceError(SequenceContext arg1, string arg2) { } private static void OnStopped(SequenceContext obj) { } } }