319 lines
13 KiB
C#
319 lines
13 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// PLC의 Request 신호와 PC의 Ack 신호를 인터페이스하기 위한 시퀸스임.
|
|
/// 자동 운전, 수동 운전 전환 / 용접 요청 등의 신호를 확인하기 위해서 제작
|
|
/// </summary>
|
|
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<string> 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<SystemParameter>(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<string> 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<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
|
|
|
|
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; } }
|
|
}
|
|
}
|