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(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 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 branches, SequenceActionResult param) { int completeAckAddress = _InitParam.WeldingCompleteAckAddress; int pageChangeRequestAddress = _InitParam.PageChangeRequestAddress; // Retry에 대해서 어떤 부분이 좋을지 고민됨.. while(!context.Stopped) or RetryUntilSuccess Func 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 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 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 deviceListToCheck = new List() { 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; } } }