2026-06-05 13:44:39 +09:00

333 lines
14 KiB
C#

using Aurora.Api;
using HarfBuzzSharp;
using Hermes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using WeldingCommon.Devices;
using WeldingCommon.Settings;
namespace WeldingCommon.Sequences.Main
{
public class SeqCheckWeldingComplete
{
static readonly Logger Log = new Logger("SeqExecutePlcBitInterface");
const string SEQ_ENTER = "[SeqCheckWeldingComplete] SEQ_ENTER"; // inputParam 으로 받자.
const string SEQ_CHECK_INIT_CONDITION = "[SeqCheckWeldingComplete] Check Init Condition"; // Check Init Condition
const string SEQ_SET_PC_WELD_COMPLETE_ON = "[SeqCheckWeldingComplete] Set PC Weld Complete On"; // PC 용접 완료 설정
const string SEQ_CHECK_PLC_WELDING_COMPLETE = "[SeqCheckWeldingComplete] Check Rewelding Request"; // 재용접 요청 확인
const string SEQ_SET_PC_WELD_COMPLETE_OFF_WITH_END = "[SeqCheckWeldingComplete] Set PC Weld Complete Off With End"; // 종료와 함께 PC 용접 완료 설정
const string SEQ_GET_PLC_WELD_COMPLETE_ACK_OFF = "[SeqCheckWeldingComplete] Set PLC Weld Complete Ack Off"; // PLC 용접 완료 확인 종료
const string SEQ_SET_PC_WELD_COMPLETE_OFF_WITH_RETRY = "[SeqCheckWeldingComplete] Set PC Weld Complete Off With Retry"; // 재시도와 함께 PC 용접 완료 설정
const string SEQ_SET_PC_PAGE_CHANGE_COMPLETE_ON = "[SeqCheckWeldingComplete] Set PC Page Change Complete On"; // PC 페이지 변경 완료 설정
const string SEQ_GET_PLC_PAGE_REQ_OFF = "[SeqCheckWeldingComplete] Get PLC Page Request Off"; // PLC 페이지 요청 종료
const string SEQ_SET_PC_PAGE_CHANGE_COMPLETE_OFF = "[SeqCheckWeldingComplete] Set PC Page Change Complete Off"; // PC 페이지 변경 완료 종료
const string SEQ_COMPLETE = "[SeqCheckWeldingComplete] SEQ_COMPLETE"; // 완료
static class ContextKey
{
public const string KEY_SEQUENCE_IS_COMPLETE = "KEY_SEQUENCE_IS_COMPLETE_SeqCheckWeldingComplete";
public const string KEY_SEQUENCE_PAGE_NO = "KEY_SEQUENCE_PAGE_NO_SeqCheckWeldingComplete";
}
private PLCController _PLC;
private SeqCheckWeldingComplete_InitParam _InitParam;
private SeqCheckWeldingComplete_OutParam _OutParam;
private SystemParameter _SystemParameter;
const int timeoutSeconds = 10;
private bool _IsComplete = false;
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); //분기
sb.AddAction(SEQ_SET_PC_WELD_COMPLETE_ON, SetPcWeldCompletOn);
sb.AddDecision(SEQ_CHECK_PLC_WELDING_COMPLETE, CheckPlcWeldingComplete); // 분기
sb.AddAction(SEQ_SET_PC_WELD_COMPLETE_OFF_WITH_END, SetPcWeldCompleteOffWithEnd);
sb.AddAction(SEQ_GET_PLC_WELD_COMPLETE_ACK_OFF, GetPlcWeldCompleteAckOff);
sb.AddAction(SEQ_SET_PC_WELD_COMPLETE_OFF_WITH_RETRY, SetPcWeldCompleteOffWithRetry);
sb.AddAction(SEQ_SET_PC_PAGE_CHANGE_COMPLETE_ON, SetPcPageChangeCompleteOn);
sb.AddAction(SEQ_GET_PLC_PAGE_REQ_OFF, GetPlcPageRequestOff);
sb.AddAction(SEQ_SET_PC_PAGE_CHANGE_COMPLETE_OFF, SetPcPageChangeCompleteOff);
sb.AddAction(SEQ_COMPLETE, Complete);
sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION]
> sb[SEQ_SET_PC_WELD_COMPLETE_ON] > sb[SEQ_CHECK_PLC_WELDING_COMPLETE]
> sb[SEQ_SET_PC_WELD_COMPLETE_OFF_WITH_END] > sb[SEQ_GET_PLC_WELD_COMPLETE_ACK_OFF]
> sb[SEQ_COMPLETE]);
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final);
sb.Flows(sb[SEQ_CHECK_PLC_WELDING_COMPLETE] > sb[SEQ_SET_PC_WELD_COMPLETE_OFF_WITH_RETRY]
> sb[SEQ_SET_PC_PAGE_CHANGE_COMPLETE_ON] > sb[SEQ_GET_PLC_PAGE_REQ_OFF]
> sb[SEQ_SET_PC_PAGE_CHANGE_COMPLETE_OFF] > sb[SEQ_COMPLETE]);
sb.OnForceError(OnForceError);
sb.OnStopped(OnStopped);
//sb.Draw("SeqCheckWeldingComplete.pdf");
return sb;
}
private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param)
{
Log.I("SeqCheckWeldingComplete Start");
_InitParam = param.Param as SeqCheckWeldingComplete_InitParam;
_SystemParameter = context.GetSetting<SystemParameter>(CommonSettingIds.SystemParameter);
InitDev(context);
if (!CheckDeviceReady(context)) {
Log.E("The devices are not active.");
return null;
}
if (InitSequenceVariable(context) == false) {
return null;
}
return SequenceAction.Ok();
}
private string CheckInitCondition(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
{
if (!CheckCondition(context)) {
Log.E("Condition is not in state to start sequence.");
context.PutValue(ContextKey.KEY_SEQUENCE_IS_COMPLETE, false);
return SEQ_COMPLETE;
}
context.PutValue(ContextKey.KEY_SEQUENCE_PAGE_NO, (short)0);
return SEQ_SET_PC_WELD_COMPLETE_ON;
}
private SequenceActionResult SetPcWeldCompletOn(SequenceContext context, string id, SequenceActionResult param)
{
int setAddress = _InitParam.WeldingCompleteAddress;
_PLC.WriteBit(setAddress, true);
Log.I(string.Format("Set PC Welding Complete On"));
return SequenceAction.Ok();
}
private string CheckPlcWeldingComplete(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
{
int completeAckAddress = _InitParam.WeldingCompleteAckAddress;
int pageChangeRequestAddress = _InitParam.PageChangeRequestAddress;
// Retry에 대해서 어떤 부분이 좋을지 고민됨.. while(!context.Stopped) or RetryUntilSuccess
Func<bool> plcResponse = () => _PLC.ReadBit(completeAckAddress).data
|| _PLC.ReadBit(pageChangeRequestAddress).data;
var res = context.RetryUntilSuccess(plcResponse, timeoutSeconds * 1000);
if (res == E2.TIMEOUT) {
Log.FuncE("Get PLC Welding Complete or Page Change Request Timeout !");
return null;
} else {
if (_PLC.ReadBit(completeAckAddress).data) {
Log.I(string.Format("Get PLC Weld Complete Ack On"));
return SEQ_SET_PC_WELD_COMPLETE_OFF_WITH_END;
} else if (_PLC.ReadBit(pageChangeRequestAddress).data) {
Log.I(string.Format("Get PLC Page Change Request On"));
return SEQ_SET_PC_WELD_COMPLETE_OFF_WITH_RETRY;
} else {
Log.I(string.Format("Unexpected Situation."));
return null;
}
}
}
private SequenceActionResult SetPcWeldCompleteOffWithEnd(SequenceContext context, string id, SequenceActionResult param)
{
int setAddress = _InitParam.WeldingCompleteAddress;
_PLC.WriteBit(setAddress, false);
Log.I(string.Format("Set PC Weld Complete Off For End"));
context.PutValue(ContextKey.KEY_SEQUENCE_IS_COMPLETE, true);
// 완료하였음.
_IsComplete = true;
return SequenceAction.Ok();
}
private SequenceActionResult GetPlcWeldCompleteAckOff(SequenceContext context, string id, SequenceActionResult param)
{
int getAddress = _InitParam.WeldingCompleteAckAddress;
// Retry에 대해서 어떤 부분이 좋을지 고민됨.. while(!context.Stopped) or RetryUntilSuccess
Func<bool> plcResponse = () => !_PLC.ReadBit(getAddress).data;
var res = context.RetryUntilSuccess(plcResponse, timeoutSeconds * 1000);
if (res == E2.TIMEOUT) {
Log.FuncE("Get PLC Welding Complete ACK Off Timeout !");
return null;
} else {
Log.I(string.Format("Get PLC Weld Complete Ack Off"));
}
return SequenceAction.Ok();
}
private SequenceActionResult SetPcWeldCompleteOffWithRetry(SequenceContext context, string id, SequenceActionResult param)
{
int setAddress = _InitParam.WeldingCompleteAddress;
_PLC.WriteBit(setAddress, false);
Log.I(string.Format("Set PC Weld Complete Off For End"));
context.PutValue(ContextKey.KEY_SEQUENCE_IS_COMPLETE, false);
// Retry 해야함.
_IsComplete = false;
return SequenceAction.Ok();
}
private SequenceActionResult SetPcPageChangeCompleteOn(SequenceContext context, string id, SequenceActionResult param)
{
int wordNo = _InitParam.PageNoAddress;
short pageNo = _PLC.ReadWord(wordNo).data;
context.PutValue(ContextKey.KEY_SEQUENCE_PAGE_NO, (short)pageNo);
Log.I(string.Format("Write Page No & _IsComplete !"));
int setAddress = _InitParam.PageChangeCompleteAddress;
_PLC.WriteBit(setAddress, true);
Log.I(string.Format("Set PC Page Change Complete On"));
return SequenceAction.Ok();
}
private SequenceActionResult GetPlcPageRequestOff(SequenceContext context, string id, SequenceActionResult param)
{
int getAddress = _InitParam.PageChangeRequestAddress;
// Retry에 대해서 어떤 부분이 좋을지 고민됨.. while(!context.Stopped) or RetryUntilSuccess
Func<bool> plcResponse = () => !_PLC.ReadBit(getAddress).data;
var res = context.RetryUntilSuccess(plcResponse, timeoutSeconds * 1000);
if (res == E2.TIMEOUT) {
Log.FuncE("Get PLC Page Change Request Off Timeout !");
return null;
} else {
Log.I(string.Format("Get PLC Page Change Request Off"));
}
return SequenceAction.Ok();
}
private SequenceActionResult SetPcPageChangeCompleteOff(SequenceContext context, string id, SequenceActionResult param)
{
int setAddress = _InitParam.PageChangeCompleteAddress;
_PLC.WriteBit(setAddress, false);
Log.I(string.Format("Set PC Page Change Complete Off"));
return SequenceAction.Ok();
}
private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param)
{
context.TryGetValue(ContextKey.KEY_SEQUENCE_IS_COMPLETE, out bool isComplete);
context.TryGetValue(ContextKey.KEY_SEQUENCE_PAGE_NO, out short pageNo);
SeqCheckWeldingComplete_OutParam result = new SeqCheckWeldingComplete_OutParam()
{ Success = true, IsComplete = _IsComplete, PageNo = pageNo };
Log.D("CheckWeldingComplete Sequence Complete");
return SequenceAction.Ok(result);
}
private void OnStopped(SequenceContext context)
{
Log.I("SequenceAction Ok : OnStopped");
}
private void OnForceError(SequenceContext context, string arg2)
{
Log.I("SequenceAction Ok : OnForceError");
}
#region Device 및 상태 확인 함수 (시퀸스 공용)
private bool InitSequenceVariable(SequenceContext context)
{
// TODO: [장비구현필요] Initialize Variable 추가
_IsComplete = false;
return true;
}
private void InitDev(SequenceContext context)
{
//Device Init
_PLC = context.GetPLC();
}
private bool CheckDeviceReady(SequenceContext context)
{
List<string> deviceListToCheck = new List<string>() { CommonDeviceIds.PLCDevice };
bool isAllDeviceActivated = true;
foreach (string item in deviceListToCheck) {
if (!context.Devices[item].IsActivated) {
isAllDeviceActivated = isAllDeviceActivated && false;
}
}
return isAllDeviceActivated;
}
private bool CheckCondition(SequenceContext context)
{
if (CheckCondition_Interlock()) {
if (InitializeDeviceStatus(context)) {
return true;
}
}
return false;
}
private bool InitializeDeviceStatus(SequenceContext context)
{
// format 유지, ReceiveCellInfo 없음
return true;
}
private bool CheckCondition_Interlock()
{
// PLC, Data, IO 등 Interlock checking
return true;
}
#endregion
}
public class SeqCheckWeldingComplete_InitParam : InitParam
{
public int WeldingCompleteAddress { get; set; }
public int WeldingCompleteAckAddress { get; set; }
public int PageChangeRequestAddress { get; set; }
public int PageChangeCompleteAddress { get; set; }
public int PageNoAddress { get; set; }
}
public class SeqCheckWeldingComplete_OutParam : OutParam
{
public bool IsComplete { get; set; }
public short PageNo { get; set; }
}
}