/RunScanner Calib은 비전이 개발환경pc에 없어서 확인 불가 -> MoveStageToOrigin -> StageX ->0 이동 완료 -> EncoderReset [스킵] -MOTF비활성화 상태라 스킵 -> UploadWeldingList - 라인 업로드 확인 -> 전체 시퀸스 -> 토스트메시지 성공 표시되는 것까지 확인 = UseMarkingOnTheFly = false 이면 EncoderRest은 스킵된다. [변경사항] -SeqComponentTeachingRun.cs - SeqTeachingRun.cs
649 lines
27 KiB
C#
649 lines
27 KiB
C#
using Aurora.Api;
|
|
using Aurora.Api.Devices;
|
|
using Aurora.Api.Services;
|
|
// 26.04.08 NDY 추가 - 비전 있는 오토 티칭 버튼은 MIL없어서 리스트만으로 테스트 시퀸스 확인하고자 추가 예정
|
|
using AuroraACS;
|
|
using AuroraIO;
|
|
using AuroraLaserScanner;
|
|
using AuroraLBAD;
|
|
using AuroraLBAD.Services;
|
|
using AuroraMotionBoard.Ajin;
|
|
using AuroraOCT;
|
|
using CoreUnit.Control.UserControl.Canvas;
|
|
using CoreUnit.Scanner.UserControl.ScannerCanvas;
|
|
using DB;
|
|
using Hermes;
|
|
using Matrox.MatroxImagingLibrary;
|
|
using OpenCvSharp.Dnn;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Configuration;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using VisionCommon;
|
|
using WeldingCommon.Alarm;
|
|
using WeldingCommon.Data;
|
|
using WeldingCommon.Settings;
|
|
using WeldingCommon.Utils;
|
|
using static AuroraIO.AJINEXTEK.AjinIO.IOModuleInfo;
|
|
using static AuroraIO.Vendor.PAIX.PAIXIO;
|
|
|
|
namespace WeldingCommon.Sequences
|
|
{
|
|
public class SeqTeachingRun
|
|
{
|
|
static readonly Logger Log = new Logger("SeqTeachingRun");
|
|
|
|
const string SEQ_ENTER = "[SeqTeachingRun] SEQ_ENTER"; // inputParam 으로 받자.
|
|
const string SEQ_CHECK_INIT_CONDITION = "[SeqTeachingRun] Check Init Condition"; // Check Init Condition
|
|
|
|
const string SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ = "[SeqTeachingRun] Set Sequence Param (UploadWeldingList Seq)";
|
|
const string SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ = "[SeqTeachingRun] Process (UploadWeldingList Seq)";
|
|
const string SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ = "[SeqTeachingRun] Get Sequence Result (UploadWeldingList Seq)";
|
|
|
|
const string SEQ_SET_BLOW_ON = "[SeqTeachingRun] Set Blow On";
|
|
const string SEQ_STREAM_LBAD_BEFORE_WELDLINES = "[SeqTeachingRun] StreamLBAD Before Weldlines";
|
|
const string SEQ_EXECUTE_WELDLINES = "[SeqTeachingRun] Execute WeldLines";
|
|
const string SEQ_SET_BLOW_OFF = "[SeqTeachingRun] Set Blow Off";
|
|
const string SEQ_STREAM_LBAD_AFTER_WELDLINES = "[SeqTeachingRun] StreamLBAD After Weldlines";
|
|
|
|
const string SEQ_SAVE_RESULT_DATA = "[SeqTeachingRun] Save Result Data";
|
|
|
|
const string SEQ_WRITE_COMPLETION_PLC_BIT = "[SeqTeachingRun] Write Completion PLC Bit";
|
|
const string SEQ_COMPLETE = "[SeqTeachingRun] SEQ_COMPLETE"; // 완료
|
|
|
|
#region 26.04.08 NDY 상수 추가
|
|
const string SEQ_MOVE_STAGE_ORIGIN = "[SeqTeachingRun] Move Stage To Origin";
|
|
const string SEQ_ENCODER_RESET = "[SeqTeachingRun] Encoder Reset";
|
|
|
|
#endregion
|
|
|
|
static class ContextKey
|
|
{
|
|
public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqTeachingRun";
|
|
public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqTeachingRun";
|
|
}
|
|
|
|
private SeqTeachingRun_InitParam _InitParam;
|
|
|
|
private Scanner _Scanner;
|
|
private OCT _OCT;
|
|
private IODevice _IO;
|
|
private StreamLBADClient _StreamLBADClient;
|
|
private ACSMotor _AxisX; // ← 26.04.08 NDY 필드 추가
|
|
|
|
private SystemParameter _SystemParameter;
|
|
private ScannerCanvasUserCtrl _ScannerCanvasUserCtrl; //스캐너 동작관련 객체 선언
|
|
|
|
private eListNo _WeldingScannerListNo;
|
|
private List<IDrawObject> _SelectedObjectList;
|
|
|
|
private static TimeSpan _WeldingSpanTime; //TeacingRun 시퀀스에서 용접 소요시간
|
|
|
|
|
|
|
|
|
|
public SequenceBuilder Builder()
|
|
{
|
|
var sb = new SequenceBuilder(1000, true);
|
|
////var sb = new SequenceBuilder(1000, false); // With log
|
|
|
|
sb.AddAction(SEQ_ENTER, Sequence_Enter);
|
|
sb.AddDecision(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); //분기
|
|
|
|
#region 26.04.08 NDY 노드 추가
|
|
sb.AddAction(SEQ_MOVE_STAGE_ORIGIN, MoveStageToOrigin);
|
|
sb.AddAction(SEQ_ENCODER_RESET, EncoderReset);
|
|
#endregion
|
|
|
|
|
|
sb.AddAction(SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ, SetUploadWeldingList_SeqParams);
|
|
sb.AddSubsequence(SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ, CommonSequenceManager.GetSeqBuilder_SeqUploadWeldingList());
|
|
sb.AddAction(SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ, GetUploadWeldingList_SeqResult);
|
|
|
|
sb.AddAction(SEQ_SET_BLOW_ON, SetBlowOn);
|
|
sb.AddAction(SEQ_STREAM_LBAD_BEFORE_WELDLINES, StreamLBADBeforeWeldlines);
|
|
sb.AddAction(SEQ_EXECUTE_WELDLINES, ExecuteWeldLines);
|
|
sb.AddAction(SEQ_SET_BLOW_OFF, SetBlowOff);
|
|
sb.AddAction(SEQ_STREAM_LBAD_AFTER_WELDLINES, StreamLBADAfterWeldlines);
|
|
|
|
sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함.
|
|
sb.AddAction(SEQ_WRITE_COMPLETION_PLC_BIT, WriteCompletionPLCBit); // 정상적으로 종료 되면, complete bit write
|
|
sb.AddAction(SEQ_COMPLETE, Complete);
|
|
|
|
#region 기존 흐름 26.04.08 주석처리
|
|
//sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION]
|
|
// > sb[SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ]
|
|
// > sb[SEQ_SET_BLOW_ON] > sb[SEQ_STREAM_LBAD_BEFORE_WELDLINES] > sb[SEQ_EXECUTE_WELDLINES]
|
|
// > sb[SEQ_SET_BLOW_OFF] > sb[SEQ_STREAM_LBAD_AFTER_WELDLINES]
|
|
// > sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_WRITE_COMPLETION_PLC_BIT] > sb[SEQ_COMPLETE]);
|
|
#endregion
|
|
|
|
#region 2개 노드 추가 흐름 26.04.08 - Test 중
|
|
sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION]
|
|
> sb[SEQ_MOVE_STAGE_ORIGIN] // ← 추가
|
|
> sb[SEQ_ENCODER_RESET] // ← 추가
|
|
> sb[SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ]
|
|
> sb[SEQ_SET_BLOW_ON] > sb[SEQ_STREAM_LBAD_BEFORE_WELDLINES] > sb[SEQ_EXECUTE_WELDLINES]
|
|
> sb[SEQ_SET_BLOW_OFF] > sb[SEQ_STREAM_LBAD_AFTER_WELDLINES]
|
|
> sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_WRITE_COMPLETION_PLC_BIT] > sb[SEQ_COMPLETE]);
|
|
#endregion
|
|
|
|
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final);
|
|
|
|
sb.OnStopped(OnStopped);
|
|
sb.OnForceError(OnForceError);
|
|
|
|
|
|
//sb.Draw("SeqTeachingRun.pdf");
|
|
|
|
return sb;
|
|
}
|
|
#region 26.04.08 NDY 메서드 추가
|
|
private SequenceActionResult EncoderReset(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (_AxisX == null)
|
|
{
|
|
Log.W("[EncoderReset] AxisX2 null - 스킵");
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
if (!_Scanner.Config.UseMarkingOnTheFly)
|
|
{
|
|
Log.W("[EncoderReset] MOTF 비활성화 - 스킵");
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
Log.I("[EncoderReset] 시작");
|
|
|
|
_Scanner.SetFlyX(_Scanner.Config.MarkingOnTheFlyEncoderResolutionX);
|
|
Log.I($"[EncoderReset] SetFlyX: {_Scanner.Config.MarkingOnTheFlyEncoderResolutionX}");
|
|
|
|
_Scanner.WaitForEncoderX(_Scanner.Config.MarkingStartEncoderPositionX);
|
|
Log.I($"[EncoderReset] WaitForEncoderX: {_Scanner.Config.MarkingStartEncoderPositionX}");
|
|
|
|
_Scanner.StoreEncoder(0);
|
|
_Scanner.SaveAndRestartTimer();
|
|
|
|
Log.I("[EncoderReset] 완료 - Stage(0) = Scanner(0) 동기화");
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult MoveStageToOrigin(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (_AxisX == null)
|
|
{
|
|
Log.W("[MoveStageToOrigin] AxisX2 null - 스킵");
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
Log.I("[MoveStageToOrigin] Stage X → 0 이동 시작");
|
|
|
|
_AxisX.SetTargetPos(0, TargetPosType.ABS);
|
|
_AxisX.SetMoveVelocityImm(AuroraACS.Speed.M);
|
|
_AxisX.AccelerationImm(AuroraACS.Speed.M);
|
|
_AxisX.DecelerationImm(AuroraACS.Speed.M);
|
|
_AxisX.JerkImm(AuroraACS.Speed.M);
|
|
_AxisX.Move();
|
|
|
|
var res = context.RetryUntilSuccess(
|
|
() => _AxisX.IsReachedTargetPosition(0),
|
|
30 * 1000, 20, true);
|
|
|
|
if (res == E2.TIMEOUT) { Log.E("[MoveStageToOrigin] TIMEOUT"); return null; }
|
|
if (res == E2.CANCELLED) { Log.E("[MoveStageToOrigin] CANCELLED"); return null; }
|
|
|
|
Log.I("[MoveStageToOrigin] Stage X = 0 도달 완료");
|
|
return SequenceAction.Ok();
|
|
}
|
|
#endregion
|
|
|
|
private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.I("SeqTeachingRun Start");
|
|
|
|
_InitParam = param.Param as SeqTeachingRun_InitParam;
|
|
_SystemParameter = context.GetSetting<SystemParameter>(CommonSettingIds.SystemParameter);
|
|
|
|
InitDev(context);
|
|
if (!CheckDeviceReady(context)) { //Check Device
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_DeviceNotReady);
|
|
Log.E("The devices are not active.");
|
|
return null;
|
|
}
|
|
|
|
if (InitSequenceVariable(context) == false) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_InitVariableError);
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private bool InitSequenceVariable(SequenceContext context)
|
|
{
|
|
var mainPage = CommonHelper.GetMainPage();
|
|
_ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching;
|
|
|
|
_WeldingScannerListNo = eListNo.LIST1;
|
|
|
|
if (_InitParam.IsObjectSelectAll) {
|
|
_SelectedObjectList = _ScannerCanvasUserCtrl.Model.ActiveLayer.Objects;
|
|
} else {
|
|
_SelectedObjectList = _ScannerCanvasUserCtrl.Canvas.Model.SelectedObjects;
|
|
}
|
|
|
|
//Status.GetProcessingWeldingData().WeldingScannerListNo = _WeldingScannerListNo;
|
|
//Status.GetProcessingWeldingData().SelectedDrawObjectList = _SelectedObjectList;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
private void InitDev(SequenceContext context)
|
|
{
|
|
//Device Init
|
|
_Scanner = context.GetLaserScanner();
|
|
_OCT = context.GetOCT();
|
|
_IO = context.GetIOUnit();
|
|
|
|
if (_InitParam.UseStream) {
|
|
_StreamLBADClient = context.GetLBADClient();
|
|
}
|
|
|
|
// @geprecated 각형배터리에서 문제 생겨서 추가한 코드임
|
|
// Scanner를 다시 초기화해주면 시간이 오래걸린다.. 굳이 수동용접시 마다 해줄 필요가 없음
|
|
//if (E1.OK != _scanner._scannerObj.Open())
|
|
//{
|
|
// Log.E("Scanner open Error");
|
|
// return SequenceAction.Error();
|
|
//}
|
|
|
|
//if (E1.OK != _scanner._scannerObj.Initialize(_scanner.Config))
|
|
//{
|
|
// Log.E("Scanner Initialize Error");
|
|
// return SequenceAction.Error();
|
|
//}
|
|
|
|
|
|
#region 26.04.08 NDY 수정 예외처리를 위해서
|
|
|
|
// ↓ 추가
|
|
try { _AxisX = context.Devices[CommonDeviceIds.AxisX2] as ACSMotor; }
|
|
catch { _AxisX = null; Log.W("[SeqTeachingRun] AxisX2 취득 실패"); }
|
|
#endregion
|
|
|
|
}
|
|
|
|
private bool CheckDeviceReady(SequenceContext context)
|
|
{
|
|
List<string> deviceListToCheck = new List<string>() { CommonDeviceIds.Scanner, /*CommonDeviceIds.OCT, */CommonDeviceIds.IODevice };
|
|
if (_InitParam.UseStream) {
|
|
deviceListToCheck.Add(CommonServiceIds.StreamLBADClient);
|
|
}
|
|
|
|
bool isAllDeviceActivated = true;
|
|
foreach (string item in deviceListToCheck) {
|
|
if (!context.Devices[item].IsActivated) {
|
|
isAllDeviceActivated = isAllDeviceActivated && false;
|
|
}
|
|
}
|
|
|
|
return isAllDeviceActivated;
|
|
}
|
|
|
|
private bool CheckCondition()
|
|
{
|
|
if (CheckCondition_Interlock()) {
|
|
if (InitializeDeviceStatus()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool CheckCondition_Interlock()
|
|
{
|
|
// PLC, Data, IO 등 Interlock checking
|
|
return true;
|
|
}
|
|
|
|
private bool InitializeDeviceStatus()
|
|
{
|
|
//Vision Correction File 선택
|
|
//_scanner._scannerObj.SelectCorrectionTable(1);
|
|
_Scanner.SelectCorrectionTable(2);
|
|
|
|
if (_InitParam.UseStream) {
|
|
if (InitializeStream() == false) {
|
|
Log.E("Fail Initialize Stream");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private string CheckInitCondition(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
if (!CheckCondition()) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_CheckInitCondition);
|
|
Log.E("Condition is not in state to start sequence.");
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, false);
|
|
return SEQ_COMPLETE;
|
|
}
|
|
|
|
var startTime = DateTime.Now;
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_START_TIME, startTime);
|
|
|
|
Log.D("TeachingRun Sequence CheckInitCondition");
|
|
return SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ;
|
|
}
|
|
|
|
private bool InitializeStream()
|
|
{
|
|
// TODO: 이거는 원래 source 에 없었는데, 언제 반영 되었는지 확인 필요. 그리고 맞는 방법으로 되었는지 확인 필요함.
|
|
// TODO: 우선은 주석 처리 해 둠. 2025.03.05
|
|
// TODO: StreamLBADClient 의 생성자에 해당 Message 가 있음. 이걸 좀 바꿔야 함. 생성할때 보내는 것이 맞는지 명시적으로 보내는것이 맞는지.
|
|
|
|
//// CELL ID와 LOT ID는 CellTacker로부터 받은 정보를 LBAD측으로 용접 전 줘야함, Reply는 로그만 남기자
|
|
//_StreamLBADClient.AddParser(StreamMessageNames.MESSAGE_PC_LBAD_CELL_ID, new StreamStringParser(), new StreamNumberParser<int>());
|
|
//_StreamLBADClient.AddParser(StreamMessageNames.MESSAGE_PC_LBAD_LOT_ID, new StreamStringParser(), new StreamNumberParser<int>());
|
|
|
|
////LBAD측이랑 통신하기 전 항상 ReadyStauts에 대한 Request하고 LBAD에서는 Ready가 되있으면 Reply를 한다..
|
|
//_StreamLBADClient.AddParser(StreamMessageNames.MESSAGE_PC_LBAD_READY_STATUS, new StreamNumberParser<int>(), new StreamNumberParser<int>());
|
|
//_StreamLBADClient.AddParser(StreamMessageNames.MESSAGE_PC_LBAD_WELDING_TRIGGER, new StreamNumberParser<int>(), new StreamNumberParser<int>());
|
|
//_StreamLBADClient.AddParser(StreamMessageNames.MESSAGE_PC_LBAD_WELDING_STOP, new StreamNumberParser<int>(), new StreamNumberParser<int>());
|
|
////용접 완료 후 LBAD측에 JudgeComplete를 요청한뒤 JudgeFlag를 회신 받는다
|
|
//_StreamLBADClient.AddParser(StreamMessageNames.MESSAGE_PC_LBAD_JUDGEMENT_COMPLETE, new StreamNumberParser<int>(), new StreamNumberParser<int>());
|
|
//_StreamLBADClient.AddParser(StreamMessageNames.MESSAGE_PC_LBAD_CELL_ID, new StreamStringParser(), new StreamNumberParser<int>());
|
|
//_StreamLBADClient.AddParser(StreamMessageNames.MESSAGE_PC_LBAD_LOT_ID, new StreamStringParser(), new StreamNumberParser<int>());
|
|
|
|
return true;
|
|
}
|
|
|
|
private SequenceActionResult SetUploadWeldingList_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// TeachingRun 에서는 CellMeasureCenterOffset 사용하지 않음. 0 으로 넘기자
|
|
SeqUploadWeldingList_InitParam seqParams = new SeqUploadWeldingList_InitParam() {
|
|
NeedSetLaserTiming = _InitParam.NeedSetLaserTiming,
|
|
IncludeListStartEnd = true,
|
|
CellMeasureCenterOffsetX = 0.0,
|
|
CellMeasureCenterOffsetY = 0.0,
|
|
SelectedDrawObjectList = _SelectedObjectList,
|
|
WeldingScannerListNo = _WeldingScannerListNo,
|
|
};
|
|
|
|
return SequenceAction.Ok(seqParams);
|
|
}
|
|
|
|
private SequenceActionResult GetUploadWeldingList_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
var resultOutParam = param.Param as SeqUploadWeldingList_OutParam;
|
|
if (resultOutParam.Success == false) {
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult SetBlowOn(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (_InitParam.UseBlow == false) {
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
int intervalTime = _InitParam.IntervalTimeBlowOn;
|
|
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePDOAddress.SeamWeldingN2BlowSol), true);
|
|
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePDOAddress.SeamWeldingOpticAirKnifeSol), true);
|
|
Thread.Sleep(intervalTime);
|
|
|
|
Log.D(string.Format($"[TeachingRun] Blow ON Complete"));
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult StreamLBADBeforeWeldlines(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (_InitParam.UseStream == false) {
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
if (!_StreamLBADClient.CheckReadyStatus()) {
|
|
return null;
|
|
}
|
|
|
|
if (!_StreamLBADClient.SendCellID(1)) {
|
|
return null;
|
|
}
|
|
|
|
if (!_StreamLBADClient.SendLotID(2)) {
|
|
return null;
|
|
}
|
|
|
|
if (!_StreamLBADClient.SetWeldTriggerOn()) {
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult StreamLBADAfterWeldlines(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (_InitParam.UseStream == false) {
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
//Welding Stop On
|
|
if (!_StreamLBADClient.SendWeldingStop()) {
|
|
return null;
|
|
}
|
|
|
|
//JudgeFlag에 따라서 시퀀스 결정
|
|
var judgeFlag = _StreamLBADClient.CheckJudgeComplete();
|
|
if (judgeFlag == StreamLBADClient.eJudgeFlag.NO_RESPONSE) {
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult ExecuteWeldLines(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.D(string.Format($"[TeachingRun] Welding Start"));
|
|
DateTime weldingTime = DateTime.Now;
|
|
_Scanner.ExecuteList(_WeldingScannerListNo);
|
|
_Scanner.WaitForListTaskCompleted(_SystemParameter.WeldLinesTaskTimeOut);
|
|
_WeldingSpanTime = DateTime.Now.Subtract(weldingTime);
|
|
Log.D(string.Format($"[TeachingRun] Welding Complete Time : {_WeldingSpanTime.TotalMilliseconds}"));
|
|
|
|
double dExecuteListTime = _Scanner.GetTime();
|
|
Log.I(string.Format($"[TeachingRun] ExecuteList Time : {dExecuteListTime * 1000} msec"));
|
|
//Welding Stop On
|
|
if (_InitParam.UseStream) {
|
|
if (!_StreamLBADClient.SendWeldingStop()) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// OCT File Fomrat Record Test
|
|
//SaveOCTFileFormat();
|
|
|
|
// File Format Record Test
|
|
weldingTime = DateTime.Now;
|
|
//SaveScannerRecordFileForamt();
|
|
_WeldingSpanTime = DateTime.Now.Subtract(weldingTime);
|
|
Log.D(string.Format($"[TeachingRun] SaveScannerRecordFileForamt Time : {_WeldingSpanTime.TotalMilliseconds}"));
|
|
|
|
weldingTime = DateTime.Now;
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
|
|
//용접 완료 후 CorrectionFile Vision으로 원복
|
|
_Scanner.SelectCorrectionTable(1);
|
|
|
|
_WeldingSpanTime = DateTime.Now.Subtract(weldingTime);
|
|
Log.D(string.Format($"[TeachingRun] Change SelectCorrectionTable Time : {_WeldingSpanTime.TotalMilliseconds}"));
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private void SaveScannerRecordFileForamt()
|
|
{
|
|
_Scanner.SaveRecord("Normal");
|
|
}
|
|
|
|
private void SaveOCTFileFormat()
|
|
{
|
|
// TODO: ian0513.kim, DataPath 옮겨야 함.
|
|
var DefaultPath = ConfigurationManager.AppSettings.Get("DATA_PATH");
|
|
string fullPath = Path.Combine(DefaultPath, "_device", "_scanner", "Record");
|
|
string coordinateFolderpath = fullPath + string.Format("\\Coordinate");
|
|
string metaDataFolderpath = fullPath + string.Format("\\Metadata");
|
|
|
|
if (Directory.Exists(coordinateFolderpath) == false) {
|
|
Directory.CreateDirectory(coordinateFolderpath);
|
|
}
|
|
|
|
if (Directory.Exists(metaDataFolderpath) == false) {
|
|
Directory.CreateDirectory(metaDataFolderpath);
|
|
}
|
|
|
|
List<string> MetaDataWeldName = new List<string>(_SelectedObjectList.Count);
|
|
List<string> MetaDataWeldType = new List<string>(_SelectedObjectList.Count);
|
|
List<int> MetaDataWeldCoordinateID = new List<int>(_SelectedObjectList.Count);
|
|
|
|
int iCoordinateID = 0;
|
|
for (int i = 0; i < _SelectedObjectList.Count; i++) {
|
|
if (_SelectedObjectList.ElementAt(i).Type == "Dot") {
|
|
MetaDataWeldCoordinateID.Add(0);
|
|
} else {
|
|
MetaDataWeldCoordinateID.Add(++iCoordinateID);
|
|
}
|
|
|
|
MetaDataWeldName.Add(_SelectedObjectList.ElementAt(i).Type + (i + 1));
|
|
MetaDataWeldType.Add(_SelectedObjectList.ElementAt(i).Type);
|
|
//MetaDataWeldCoordinateID.Add(m_selectedObjects.ElementAt(i).No + 1)
|
|
}
|
|
|
|
_Scanner.SaveRecord("CoordinateFile", true, MetaDataWeldCoordinateID, iCoordinateID);
|
|
_OCT.SaveMetaData(MetaDataWeldName, MetaDataWeldType, MetaDataWeldCoordinateID);
|
|
|
|
string coordinateFilepath = _Scanner.GetLatestFile(coordinateFolderpath);
|
|
string metaDataFilepath = _Scanner.GetLatestFile(metaDataFolderpath);
|
|
|
|
_Scanner.SaveRecordZip(coordinateFilepath, metaDataFilepath);
|
|
|
|
MetaDataWeldName.Clear();
|
|
MetaDataWeldType.Clear();
|
|
MetaDataWeldCoordinateID.Clear();
|
|
}
|
|
|
|
private SequenceActionResult SetBlowOff(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (_InitParam.UseBlow == false) {
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
int intervalTime = _InitParam.IntervalTimeBlowOff;
|
|
Thread.Sleep(intervalTime);
|
|
|
|
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePDOAddress.SeamWeldingN2BlowSol), false);
|
|
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePDOAddress.SeamWeldingOpticAirKnifeSol), false);
|
|
|
|
Log.D(string.Format($"[TeachingRun] Blow OFF Complete"));
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// 결과 Data 를 업데이트 함.
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true);
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult WriteCompletionPLCBit(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// 완료 비트 write 하는 Node 추가 필요. format 유지, SeqScoutNormal 없음
|
|
|
|
Log.D("TeachingRun Sequence WriteCompletionPLCBit");
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
RestoreDeviceStatus();
|
|
Log.I("TeachingRun Complete");
|
|
|
|
context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult);
|
|
SeqTeachingRun_OutParam result = new SeqTeachingRun_OutParam() { Success = seqResult };
|
|
|
|
if (seqResult == false) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_ResultFailed);
|
|
}
|
|
|
|
Log.D("TeachingRun Sequence Complete");
|
|
return SequenceAction.Ok(result);
|
|
}
|
|
|
|
private bool RestoreDeviceStatus()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
private void OnForceError(SequenceContext arg1, string arg2)
|
|
{
|
|
//List 실행 종료
|
|
_Scanner.StopExecution();
|
|
|
|
//Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND);
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA2, 0, eFunctionType.COMMAND);
|
|
|
|
//Scanner 원점 복귀
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
|
|
Log.I("SequenceAction Ok : OnForceError");
|
|
}
|
|
|
|
private void OnStopped(SequenceContext obj)
|
|
{
|
|
//List 실행 종료
|
|
_Scanner.StopExecution();
|
|
|
|
//Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND);
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA2, 0, eFunctionType.COMMAND);
|
|
|
|
//Scanner 원점 복귀
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
|
|
Log.I("SequenceAction Ok : OnStopped");
|
|
}
|
|
|
|
}
|
|
|
|
// TODO: UseStream 으로 TeachingRun 을 할 필요가 있을까?? 확인 필요
|
|
public class SeqTeachingRun_InitParam : InitParam
|
|
{
|
|
public bool IsUseExternalObjects { get; set; }
|
|
public List<CoreUnit.Control.UserControl.Canvas.IDrawObject> ExternalObjects { get; set; }
|
|
public bool IsObjectSelectAll { get; set; } // All == true, Selected Object == false
|
|
public bool UseStream { get; set; }
|
|
public bool UseBlow { get; set; }
|
|
public int IntervalTimeBlowOn { get; set; }
|
|
public int IntervalTimeBlowOff { get; set; }
|
|
public bool NeedSetLaserTiming { get; set; } // For SubSequence, SeqUploadWeldingList
|
|
public double CellCenterOffsetX { get; set; } = 0;
|
|
public double CellCenterOffsetY { get; set; } = 0;
|
|
}
|
|
|
|
public class SeqTeachingRun_OutParam : OutParam
|
|
{
|
|
|
|
}
|
|
} |