421 lines
17 KiB
C#
421 lines
17 KiB
C#
using Aurora;
|
|
using Aurora.Api;
|
|
using AuroraChiller;
|
|
using AuroraIO;
|
|
using AuroraLaser;
|
|
using AuroraLaserScanner;
|
|
using AuroraLBAD;
|
|
using AuroraOCT;
|
|
using CoreUnit.Scanner.UserControl.ScannerCanvas;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using WeldingCommon.Alarm;
|
|
using WeldingCommon.Devices;
|
|
using WeldingCommon.Settings;
|
|
//using static AuroraIO.AJINEXTEK.AjinIO.IOModuleInfo;
|
|
|
|
namespace WeldingCommon.Sequences
|
|
{
|
|
public class AlarmMonitoring
|
|
{
|
|
static readonly Logger Log = new Logger("AlarmMonitoring");
|
|
|
|
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_CHECK_DEVICE_WITH_IO = "Check Device_With_IO";
|
|
|
|
private static SequenceSetting _SequenceSetting;
|
|
|
|
private static PLCController _Plc;
|
|
private static Scanner _Scanner;
|
|
private static LaserDevice _Laser;
|
|
private static IODevice _IO;
|
|
private static SmcChiller _Chiller;
|
|
private static OCT _OCT;
|
|
private static LBAD _LBAD;
|
|
|
|
public delegate void ExternalDeviceActivatedCheckWithIO(SequenceContext context);
|
|
public static ExternalDeviceActivatedCheckWithIO _ExternalDeviceActivatedCheckWithIO;
|
|
public static void SetExternalDeviceActivatedCheckWithIO(ExternalDeviceActivatedCheckWithIO externalDeviceActivatedCheckWithIO)
|
|
{
|
|
_ExternalDeviceActivatedCheckWithIO = externalDeviceActivatedCheckWithIO;
|
|
}
|
|
|
|
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_CHECK_DEVICE_WITH_IO, CheckDeviceWithIO);
|
|
|
|
//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_CHECK_DEVICE_WITH_IO]
|
|
//> 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 SequenceActionResult StartNode(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
_SequenceSetting = context.GetSetting<SequenceSetting>(CommonSettingIds.Sequence);
|
|
InitDev(context);
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private void InitDev(SequenceContext context)
|
|
{
|
|
if (_SequenceSetting.PlcActivated) {
|
|
_Plc = context.GetPLC();
|
|
}
|
|
if (_SequenceSetting.ScannerActivated) {
|
|
_Scanner = context.GetLaserScanner();
|
|
}
|
|
if (_SequenceSetting.LaserActivated) {
|
|
_Laser = context.GetLaser();
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
|
|
private string LoopFirstNode(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
while (!context.Stopped) {
|
|
_SequenceSetting = context.GetSetting<SequenceSetting>(CommonSettingIds.Sequence);
|
|
return SEQ_WAIT_TIME;
|
|
}
|
|
|
|
return SeqNodeIds.FINAL;
|
|
}
|
|
|
|
private SequenceActionResult WaitTime(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Thread.Sleep(100); // Delay 가 얼마가 적당 한가
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private 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(AlarmCode.ALARM_DEVICE_PLC_DEACTIVATED);
|
|
} else {
|
|
if (_SequenceSetting.PlcActivatedLive) {
|
|
//PLC Live Check 시간은 확인 필요
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
while (!context.Stopped) {
|
|
if (_Plc.ReadBit(_Plc.PLC_LIVE_STATUSAddr).data == true) {
|
|
break;
|
|
}
|
|
if (sw.ElapsedMilliseconds > TIMEOUT_PLC_LIVE_CHECK) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_PLC_DISCONNECT);
|
|
break;
|
|
}
|
|
Thread.Sleep(10);
|
|
}
|
|
}
|
|
|
|
// EMO check 는 항상 해야 함.
|
|
if (_Plc.ReadBit(_Plc.PLC_EMO_STATUSAddr).data == false) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_PLC_EMO);
|
|
}
|
|
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private 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.ALARM_DEVICE_SCANNER_DEACTIVATED);
|
|
} else {
|
|
var lastErrorcode = _Scanner.GetLastError();
|
|
//Scanner의 activate 상태를 체크하면.. 수동상태에서 디바이스를 deactivaed시키면 알람 발생하므로 조건문 변경 필요
|
|
if (lastErrorcode != 0) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_SCANNER_ERROR);
|
|
Log.E($"Scanner Error Code : {lastErrorcode}");
|
|
}
|
|
|
|
// TODO: Scanner 는 Alarm 과 연결되어 있지 않음. 알람 추가되었을 시에 어떤 IO 를 check 하지??
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private 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.ALARM_DEVICE_LASER_DEACTIVATED);
|
|
} else {
|
|
if (!_Laser.GetConnected()) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_LASER_DISCONNECT);
|
|
}
|
|
|
|
// Won : IPG Ethernet Type 대비하여 Interface 함수로 확인 추가
|
|
if (_SequenceSetting.LaserActivated) {
|
|
//Laser Disconnect Check 조건문 변경 필요
|
|
//if (!_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LaserAssigned))) {
|
|
|
|
//TODO: 아래 부분은 Laser 에 따로 추가 필요. Interface 에 추가 해야 할까?? 구현상 모든 Laser 에 있지는 않던데
|
|
// Won : GetLaserAssinged는 Pilot 설비에서만 사용함, 내용 추가 필요하면 구현 후 주석해제
|
|
|
|
//if (!_Laser.GetLaserAssigned()) {
|
|
// AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_LASER_DISCONNECT);
|
|
//}
|
|
|
|
if (_Laser.GetLaserError()) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_LASER_ERROR);
|
|
}
|
|
if (_Laser.GetWarningStatus()) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_LASER_WARNING);
|
|
}
|
|
// Won : 2170 EMO 배선 현재 없음
|
|
//if (_Laser.GetEStop()) {
|
|
// AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_LASER_EMO);
|
|
//}
|
|
}
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private 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.ALARM_DEVICE_LBAD_DEACTIVATED);
|
|
} else {
|
|
// TODO: ReadyByAuto 는 Auto 돌렸을 때, Sequence 안뜨도록 하는 로직 이라고 함. 이 부분 수정이 필요 할 듯.
|
|
// 이게 Sequence 안에서 Try 하면서 계속 붙이는 부분과 관련이 있는 듯함.
|
|
if (_LBAD.GetReadybyAuto()) {
|
|
if (!_LBAD.GetConnected()) {
|
|
AlarmManager.Alarm(AlarmCode.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.ALARM_DEVICE_IO_LBAD_ERROR);
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private 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.ALARM_DEVICE_OCT_DEACTIVATED);
|
|
} else {
|
|
if (!_OCT.GetConnected()) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_OCT_DISCONNECT);
|
|
}
|
|
|
|
if (_SequenceSetting.OctActivatedWithIO && CheckDeviceIO()) {
|
|
//if (!_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LDDError))) {
|
|
// AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_OCT_ERROR);
|
|
//}
|
|
}
|
|
if (_OCT.OCT_QA_Error == true) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_OCT_QA_ERROR);
|
|
_OCT.OCT_QA_Error = false;
|
|
}
|
|
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private 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.ALARM_DEVICE_CHILLER_DEACTIVATED);
|
|
} else {
|
|
if (!_Chiller.GetConnected()) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_CHILLER_DISCONNECT);
|
|
}
|
|
if (_Chiller.GetChillerRunningFlag()) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_CHILLER_ERROR);
|
|
}
|
|
|
|
if (_SequenceSetting.ChillerActivatedWithIO && CheckDeviceIO()) {
|
|
// TODO: IO 로 Chiller check 하는 것이 있으면 추가
|
|
|
|
}
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private 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.ALARM_DEVICE_IO_LEAK_SENSOR_DETECT_SCANNER);
|
|
//}
|
|
//if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LeakSensorChiller))) {
|
|
// AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_LEAK_SENSOR_DETECT_CHILLER);
|
|
//}
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult CheckDeviceWithIO(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (CheckDeviceIO()) {
|
|
if (_ExternalDeviceActivatedCheckWithIO != null) {
|
|
_ExternalDeviceActivatedCheckWithIO(context);
|
|
}
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private bool CheckDeviceIO()
|
|
{
|
|
// WithIO 중 1개라도 True가 되어있지 않으면 _IO 객체 생성을 하지못하기때문에 Null 체크를 먼저 하자
|
|
if (_IO == null) {
|
|
//_IO가 Simul이라서 Null이면 Alarm이 지속발생해서 우선 주석해둔다
|
|
//AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_IS_NULL);
|
|
return false;
|
|
}
|
|
// IO 가 Simul 이면, Read Bit 를 해주지 않기 위해
|
|
if (_IO.IsSimul) {
|
|
return false;
|
|
}
|
|
if (_IO.IsActivated == false) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_DEACTIVATED);
|
|
return false;
|
|
}
|
|
|
|
// 우선 주석 처리 함. 잦은 호출이 발생할 수 있어서
|
|
//if (_IO.IsConnected() == false) {
|
|
// AlarmManager.Alarm(AlarmCode.ALARM_DEVICE_IO_DISCONNECT);
|
|
//}
|
|
|
|
return true;
|
|
}
|
|
|
|
//private static SequenceActionResult LoopLastNode(SequenceContext context, string id, SequenceActionResult param)
|
|
//{
|
|
// //Thread.Sleep(100);
|
|
// return SequenceAction.Ok();
|
|
//}
|
|
|
|
private void OnForceError(SequenceContext arg1, string arg2)
|
|
{
|
|
|
|
}
|
|
|
|
private void OnStopped(SequenceContext obj)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|