using Aurora.Api; using Hermes; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using WeldingCommon.Devices; using WeldingCommon.Settings; using static WeldingCommon.Devices.PLCController; using static WeldingCommon.Sequences.Main.SeqExecutePlcBitInterface_InitParam; namespace WeldingCommon.Sequences.Main { /// /// PLC의 Request 신호와 PC의 Ack 신호를 인터페이스하기 위한 시퀸스임. /// 자동 운전, 수동 운전 전환 / 용접 요청 등의 신호를 확인하기 위해서 제작 /// public class SeqExecutePlcBitInterface { static readonly Logger Log = new Logger("SeqExecutePlcBitInterface"); const string SEQ_ENTER = "[SeqExecutePlcBitInterface] SEQ_ENTER"; // inputParam 으로 받자. const string SEQ_CHECK_INIT_CONDITION = "[SeqExecutePlcBitInterface] Check Init Condition"; // Check Init Condition const string SEQ_CHECK_BIT_SET_MODE = "[SeqExecutePlcBitInterface] Check Bit Set Mode"; const string SEQ_GET_PLC_READY_REQ_ON = "[SeqExecutePlcBitInterface] Get PLC Ready Request On"; // PLC 용접 준비 요청 수신 const string SEQ_SET_PC_READY_ACK_ON = "[SeqExecutePlcBitInterface] Set PC Ready Ack On"; // PC 용접 준비 확인 const string SEQ_GET_PLC_READY_REQ_OFF = "[SeqExecutePlcBitInterface] Get PLC Ready Request Off"; // PLC 용접 준비 요청 종료 const string SEQ_SET_PC_READY_ACK_OFF = "[SeqExecutePlcBitInterface] Set PC Ready Ack Off"; // PC 용접 준비 확인 종료 const string SEQ_SET_PC_COMPLETE_ON = "[SeqExecutePlcBitInterface] Set PC Complete On"; // PLC 용접 준비 요청 수신 const string SEQ_SET_PLC_COMPLETE_ACK_ON = "[SeqExecutePlcBitInterface] Get PLC Complete Ack On"; // PLC 용접 준비 확인 const string SEQ_SET_PC_COMPLETE_OFF = "[SeqExecutePlcBitInterface] Set PC Complete Off"; // PLC 용접 준비 요청 종료 const string SEQ_SET_PLC_COMPLETE_ACK_OFF = "[SeqExecutePlcBitInterface] Get PLC Complete Ack Off"; // PLC 용접 준비 확인 종료 const string SEQ_COMPLETE = "[SeqExecutePlcBitInterface] SEQ_COMPLETE"; // 완료 static class ContextKey { public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqExecutePlcBitInterface"; public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqExecutePlcBitInterface"; } private PLCController _PLC; private SeqExecutePlcBitInterface_InitParam _InitParam; private SeqExecutePlcBitInterface_OutParam _OutParam; private SystemParameter _SystemParameter; private static short plcPageNo; private int timeoutSeconds = 10; public SequenceBuilder Builder() { var sb = new SequenceBuilder(1000, true); sb.AddAction(SEQ_ENTER, Sequence_Enter); sb.AddDecision(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); //분기 sb.AddDecision(SEQ_CHECK_BIT_SET_MODE, CheckBitSetMode); sb.AddAction(SEQ_GET_PLC_READY_REQ_ON, GetPlcReadyReqOn); sb.AddAction(SEQ_SET_PC_READY_ACK_ON, SetPcReadyAckOn); sb.AddAction(SEQ_GET_PLC_READY_REQ_OFF, GetPlcReadyReqOff); sb.AddAction(SEQ_SET_PC_READY_ACK_OFF, SetPcReadyAckOff); sb.AddAction(SEQ_SET_PC_COMPLETE_ON, SetPcCompleteOn); sb.AddAction(SEQ_SET_PLC_COMPLETE_ACK_ON, GetPlcCompleteAckOn); sb.AddAction(SEQ_SET_PC_COMPLETE_OFF, SetPcCompleteOff); sb.AddAction(SEQ_SET_PLC_COMPLETE_ACK_OFF, GetPlcCompleteAckOff); sb.AddAction(SEQ_COMPLETE, Complete); sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_CHECK_BIT_SET_MODE] > sb[SEQ_GET_PLC_READY_REQ_ON] > sb[SEQ_SET_PC_READY_ACK_ON] > sb[SEQ_GET_PLC_READY_REQ_OFF] > sb[SEQ_SET_PC_READY_ACK_OFF] > sb[SEQ_COMPLETE]); sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final); sb.Flows(sb[SEQ_CHECK_BIT_SET_MODE] > sb[SEQ_SET_PC_COMPLETE_ON] > sb[SEQ_SET_PLC_COMPLETE_ACK_ON] > sb[SEQ_SET_PC_COMPLETE_OFF] > sb[SEQ_SET_PLC_COMPLETE_ACK_OFF] > sb[SEQ_COMPLETE]); sb.OnStopped(OnStopped); sb.OnForceError(OnForceError); //sb.Draw("SeqExecutePlcBitInterface.pdf"); return sb; } private SequenceActionResult GetPlcCompleteAckOff(SequenceContext context, string id, SequenceActionResult param) { var getAddress = _InitParam.GetAddress; var res = context.RetryUntilSuccess(() => !_PLC.ReadBit(getAddress).data, _InitParam.TimeoutSec * 1000, interval: 10); if (res == E2.TIMEOUT) { Log.FuncE(string.Format("Get PLC Complete Ack OFF Timeout ! : {0}", getAddress)); return null; } else Log.W(string.Format("Get PLC Complete Ack OFF Complete : {0}", getAddress)); return SequenceAction.Ok(); } private SequenceActionResult SetPcCompleteOff(SequenceContext context, string id, SequenceActionResult param) { var setAddress = _InitParam.SetAddress; _PLC.WriteBit(setAddress, false); Log.W(string.Format("Set PC Complete Off : {0}", setAddress)); return SequenceAction.Ok(); } private SequenceActionResult GetPlcCompleteAckOn(SequenceContext context, string id, SequenceActionResult param) { var getAddress = _InitParam.GetAddress; var res = context.RetryUntilSuccess(() => _PLC.ReadBit(getAddress).data, _InitParam.TimeoutSec * 1000, interval: 10); if (res == E2.TIMEOUT) { Log.FuncE(string.Format("Get PLC Complete Ack On Timeout ! : {0}", getAddress)); return null; } else Log.W(string.Format("Get PLC Complete Ack On Complete : {0}", getAddress)); return SequenceAction.Ok(); } private SequenceActionResult SetPcCompleteOn(SequenceContext context, string id, SequenceActionResult param) { var setAddress = _InitParam.SetAddress; _PLC.WriteBit(setAddress, true); Log.W(string.Format("Set PC Complete On : {0}", setAddress)); return SequenceAction.Ok(); } private string CheckBitSetMode(SequenceContext context, string id, ICollection branches, SequenceActionResult param) { if (_InitParam.IsSetMode) return SEQ_SET_PC_COMPLETE_ON; else return SEQ_GET_PLC_READY_REQ_ON; } private void OnStopped(SequenceContext context) { Log.I("SequenceAction Ok : OnStopped"); } private void OnForceError(SequenceContext context, string arg2) { Log.I("SequenceAction Ok : OnForceError"); } private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param) { Log.W("SeqExecutePlcBitInterface Start"); _InitParam = param.Param as SeqExecutePlcBitInterface_InitParam; _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); plcPageNo = 1; 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_RESULT, false); return SEQ_COMPLETE; } var startTime = DateTime.Now; context.PutValue(ContextKey.KEY_SEQUENCE_START_TIME, startTime); return SEQ_CHECK_BIT_SET_MODE; } #region Device 및 상태 확인 함수 (시퀸스 공용) private bool InitSequenceVariable(SequenceContext context) { // TODO: [장비구현필요] Initialize Variable 추가 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 private SequenceActionResult GetPlcReadyReqOn(SequenceContext context, string id, SequenceActionResult param) { var getAddress = _InitParam.GetAddress; var res = context.RetryUntilSuccess(() => _PLC.ReadBit(getAddress).data, _InitParam.FirstTimeoutSec * 1000, interval: 10); if (res == E2.TIMEOUT) { Log.FuncE(string.Format("Get PLC Ready Request On Timeout ! : {0}", getAddress)); return null; } else Log.W(string.Format("Get PLC Ready Request On Complete : {0}", getAddress)); if (_InitParam.NeedPageNo) { plcPageNo = _PLC.ReadWord(_InitParam.GetPageNo).data; _PLC.WriteWord(_InitParam.SetPageNo, (short) plcPageNo); Log.W($"read Page No : {plcPageNo}"); } return SequenceAction.Ok(); } private SequenceActionResult SetPcReadyAckOn(SequenceContext context, string id, SequenceActionResult param) { var setAddress = _InitParam.SetAddress; _PLC.WriteBit(setAddress, true); Log.W(string.Format("Set PC Ready Ack On : {0}", setAddress)); return SequenceAction.Ok(); } private SequenceActionResult GetPlcReadyReqOff(SequenceContext context, string id, SequenceActionResult param) { var getAddress = _InitParam.GetAddress; var res = context.RetryUntilSuccess(() => !_PLC.ReadBit(getAddress).data, _InitParam.TimeoutSec * 1000, interval:10); if (res == E2.TIMEOUT) { Log.FuncE(string.Format("Get PLC Ready Request OFF Timeout ! : {0}", getAddress)); return null; } else Log.W(string.Format("Get PLC Ready Request OFF Complete : {0}", getAddress)); return SequenceAction.Ok(); } private SequenceActionResult SetPcReadyAckOff(SequenceContext context, string id, SequenceActionResult param) { var setAddress = _InitParam.SetAddress; _PLC.WriteBit(_InitParam.SetAddress, false); Log.W(string.Format("Set PC Ready Ack Off : {0}", setAddress)); context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true); return SequenceAction.Ok(); } private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param) { RestoreDeviceStatus(); Log.D("ExecutePlcBitInterface Complete"); // 여기서 왜 문제이지 ..? context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult); SeqExecutePlcBitInterface_OutParam result = new SeqExecutePlcBitInterface_OutParam() { Success = true, PLCPageNo = plcPageNo }; return SequenceAction.Ok(result); } private bool RestoreDeviceStatus() { return true; } } public class SeqExecutePlcBitInterface_InitParam : InitParam { public eCommonBitInput GetAddress { get; set; } public eCommonBitOutput SetAddress { get; set; } public int FirstTimeoutSec { get; set; } public int TimeoutSec { get; set; } public bool IsSetMode { get; set; } public bool NeedPageNo { get; set; } = false; public int GetPageNo { get; set; } public int SetPageNo { get; set; } public class SeqExecutePlcBitInterface_OutParam : OutParam { public short PLCPageNo { get; set; } } } }