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

418 lines
19 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Aurora.Api;
using Hermes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace WeldingCommon.Devices
{
public class PLCMonitor
{
private static readonly Logger Log = new Logger("PLCMonitor");
//private static readonly Logger EventLog = new Logger(eMsg_TYPE.PLC.ToString(), "Event");
private const int SLEEP_TIME_MS = 50;
private const int SLEEP_TIME_FOR_CLOSE_MS = 200;
private const int SLEEP_TIME_FOR_RECONNECT_MS = 10000;
private const string SEQ_INIT = "Init";
private const string CHECK_ACTIVE = "Check PLC Activation";
private const string MONITOR_NETWORK = "Monitor PLC Network status";
private const string MONITOR_ALARM = "Monitor Alarm change";
private const string MONITOR_SETTING = "Monitor Setting change";
private const string RECONNECT_NETWORK = "Reconnect to PLC";
private const string GO_CHECK_ACTIVE = "Go to check active";
// ¸ð¾ÆÁÖ´Â ³ëµå
private const string GO_MONITOR_NETWORK = "Go to monitor network";
private const string PLC_IS_DEACTIVATING = "PLC is deactivating";
private const string GO_RECONNECT_NETWORK = "Reconnect PLC Phase";
private static PLCController _plc;
const int TIME_OUT = 2000; // 2 [s]
/*
public enum eMainSeqStep
{
INIT,
WORK,
WAIT_MANUAL_SELECT,
WAIT_MANUAL_SHOT_SELECT,
VISION_WAIT,
ACK_WAIT,
FAIL,
MAVIN_SEND_WAIT,
MAVIN_SEND,
MAVIN_RESULT_WAIT,
}
static eMainSeqStep Step_ALARM = new eMainSeqStep();
static eMainSeqStep Step_SETTING = new eMainSeqStep();
static Stopwatch swAlarm = new Stopwatch();
static Stopwatch swSetting = new Stopwatch();
*/
//static ulong _latchForWriteBitUpdate;
public static SequenceBuilder Builder()
{
SequenceBuilder sb = new SequenceBuilder(1000, true); // ¹«ÇÑ, ½ÃÄö½º Stop½Ã ÃÖ´ë ´ë±â½Ã°£.
sb.AddAction(SEQ_INIT, Init);
sb.AddDecision(CHECK_ACTIVE, CheckActive);
sb.AddDecision(MONITOR_NETWORK, MonitorNetworkStatus);
//-------------------- Setting/Alarm ·Î±ë ºÎºÐ
sb.AddDecision(MONITOR_ALARM, MonitorPLCAlarmStatus);
sb.AddDecision(MONITOR_SETTING, MonitorPLCSettingStatus);
//==================================================
sb.AddDecision(RECONNECT_NETWORK, ReconnectPLCNetwork);
sb.AddDecision(GO_CHECK_ACTIVE, GoToCheckActive);
// °æÀ¯¿ë ³ëµå (Ç÷οì Â÷Æ®¸¦ ÀÌ»Ú°Ô ¸¸µé±â À§ÇÑ ¸ñÀû)
sb.AddAction(GO_MONITOR_NETWORK, GoToMonitorNetwork);
sb.AddAction(PLC_IS_DEACTIVATING, PlcIsDeactivating);
sb.AddAction(GO_RECONNECT_NETWORK, GoToReconnectNetwork);
//===================================================
//----------------------------------------------------
//------ ½ºÄö½º Ç÷οì Â÷Æ®
sb.Flows(sb.Init > sb[SEQ_INIT] > sb[CHECK_ACTIVE]);
sb.Flows(sb[CHECK_ACTIVE] > sb[MONITOR_NETWORK]);
sb.Flows(sb[CHECK_ACTIVE] > sb.Final); // Á¾·á
//------------------- ÁÖ¿ä ·ÎÁ÷
// ·çÇÁ
sb.Flows(sb[MONITOR_NETWORK] > sb[MONITOR_ALARM] > sb[MONITOR_SETTING] > sb[GO_MONITOR_NETWORK] > sb[MONITOR_NETWORK]);
//------ Åë½Å À翬°á ·çÆ®
sb.Flows(sb[MONITOR_NETWORK] > sb[GO_RECONNECT_NETWORK]);
sb.Flows(sb[MONITOR_ALARM] > sb[GO_RECONNECT_NETWORK]);
sb.Flows(sb[MONITOR_SETTING] > sb[GO_RECONNECT_NETWORK]);
// ·çÇÁ
sb.Flows(sb[GO_RECONNECT_NETWORK] > sb[RECONNECT_NETWORK] > sb[GO_RECONNECT_NETWORK]);
sb.Flows(sb[RECONNECT_NETWORK] > sb[GO_CHECK_ACTIVE]);
//------ PLC ºñȰ¼ºÈ­ ·çÆ®
sb.Flows(sb[MONITOR_NETWORK] > sb[PLC_IS_DEACTIVATING]);
sb.Flows(sb[MONITOR_ALARM] > sb[PLC_IS_DEACTIVATING]);
sb.Flows(sb[MONITOR_SETTING] > sb[PLC_IS_DEACTIVATING]);
sb.Flows(sb[PLC_IS_DEACTIVATING] > sb[GO_CHECK_ACTIVE] > sb[CHECK_ACTIVE]);
//===================================================
sb.OnStopped(OnStopped);
sb.OnForceError(OnForceError);
//sb.Draw("PLCMonitoring.pdf");
return sb;
}
private static void OnForceError(SequenceContext arg1, string arg2)
{
Log.E("Enter Forced Error phase");
}
private static void OnStopped(SequenceContext obj)
{
Log.I("Enter Stopped phase");
}
private static string GoToCheckActive(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
{
//Log.I("GO_CHECK_ACTIVE: --> CHECK_ACTIVE");
#if DEBUG
//Debug.WriteLine($"GO_CHECK_ACTIVE: --> CHECK_ACTIVE");
#endif
return CHECK_ACTIVE;
}
private static string ReconnectPLCNetwork(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
{
if (_plc.IsActivated) {
//EventLog.W($"PLC Reconnection Phase due to connection error");
// ¿©±â´Â µ¶¸³ ½º·¹µåÀ̰í, PLC Åë½Å ¿¬°áÀÌ ½ÇÆÐÇϸé, ´Ù¸¥ ÀÛ¾÷ÀÌ ¹«ÀǹÌÇϹǷÎ, µô·¹ÀÌ·Î Sleep À» »ç¿ëÇÔ
if (_plc.ReconnectNetwork() != E1.OK) {
Log.E("PLC reconnection is failed. Retry after 10 [s]");
Thread.Sleep(SLEEP_TIME_FOR_RECONNECT_MS); // 10 ÃÊ
return GO_RECONNECT_NETWORK;
}
//_plc.WriteOffsetData(Data.UnitType.Max, null);
//EventLog.I($"PLC is reconnected");
return GO_CHECK_ACTIVE;
}
return GO_CHECK_ACTIVE;
}
private static SequenceActionResult GoToReconnectNetwork(SequenceContext context, string id, SequenceActionResult param)
{
return SequenceAction.Ok();
}
private static SequenceActionResult PlcIsDeactivating(SequenceContext context, string id, SequenceActionResult param)
{
// PLC ºñȰ¼ºÈ­ »óÅÂ
// IsActivated °¡ false °¡ µÉ¶§±îÁö ´ë±â½ÃŰÀÚ...
// Å×½ºÆ®: ¾à 1ÃÊ ½Ã°£ÀÇ Å¸ÀӾƿôÀ¸·Î üũ
var timeOutMS = 1000;
if (_plc.WaitUntilDeactivated(timeOutMS, out int elapsedMS)) {
Log.I($"PLC is deactivated: {elapsedMS} [ms] elapsed");
} else {
Log.W($"PLC is deactivating: {elapsedMS} [ms] elapsed");
Thread.Sleep(SLEEP_TIME_MS);
}
return SequenceAction.Ok();
}
private static SequenceActionResult GoToMonitorNetwork(SequenceContext context, string id, SequenceActionResult param)
{
#if DEBUG
//Debug.WriteLine($"GO_MONITOR_NETWORK: --> MONITOR_NETWORK");
#endif
Thread.Sleep(50);
return SequenceAction.Ok();
}
private static string MonitorPLCSettingStatus(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
{
/*
switch (Step_SETTING) {
case eMainSeqStep.INIT: {
Step_SETTING = eMainSeqStep.WORK;
_latchForWriteBitUpdate = _plc.LatchForWriteBitUpdate;
_plc.WriteBit((int)eBitOutput.EQP_SETTING_DATA_CHANGE_COMPLETE, false); //ST1_SETTING_COMPLETE
// ´ë±âÇÔ¼ö Ãß°¡..
if (_plc.WaitWriteBitUpdate(_latchForWriteBitUpdate, out _) == false) {
// ÇÔ¼ö¸íÀº ±âÁ¸ ·Î°Å¿¡¼­ Áö¿øÇÏ´Ï, ¶óÀιøÈ£¸¸ ÂïÀÚ..
Log.W(_plc.WriteLogTag("WriteBit timed out"));
}
break;
}
case eMainSeqStep.WORK: {
var res2 = _plc.ReadBit((int)eBitInput.EQP_SETTING_DATA_CHANGE_REQ); //ST1_SETTING_REQ
// ºñȰ¼ºÈ­¿Í ºñ¿¬°á ¿¹¿Ü¸¦ ±¸ºÐÇØ¾ß ÇÒ °Í °°Àºµ¥...»ý°¢ Á» ÇØº¸ÀÚ...
if (res2.err != E1.OK) {
Step_SETTING = eMainSeqStep.INIT;
swSetting.Stop();
Log.I($"Step_SETTING.eMainSeqStep.WORK 1: PLC is deactivating: {res2.err}");
return PLC_IS_DEACTIVATING;
} else {
if (res2.data) {
// ZR ÀåÄ¡ Àбâ
var res = _plc.ReadPLCSettingData();
if (res != E1.OK) {
// ºñȰ¼ºÈ­¿¡ ÀÇÇÑ ½ÇÆÐÀÎÁö, Åë½Å ¿À·ù¿¡ ÀÇÇÑ ½ÇÆÐÀÎÁö ±¸ºÐ
if (_plc._dataUpdateTimer.IsRunning) {
Log.E("ReadPLCSettingData() is failed: --> reconnect");
// ¿øº»°ú ´Ù¸¥ ºÎºÐ, Åë½Å ½ÇÆÐ·Î À翬°áÀ» ½ÃµµÇÏ´Ï, óÀ½ºÎÅÍ ´Ù½ÃÇØ¾ß ÇÏÁö ¾ÊÀ»±î??
Step_SETTING = eMainSeqStep.INIT;
swSetting.Stop();
return GO_RECONNECT_NETWORK;
} else {
Log.E("ReadPLCSettingData() is failed: PLC is deactivating");
Step_SETTING = eMainSeqStep.INIT;
swSetting.Stop();
return PLC_IS_DEACTIVATING;
}
}
_plc.Check_SettingData();
_latchForWriteBitUpdate = _plc.LatchForWriteBitUpdate;
_plc.WriteBit((int)eBitOutput.EQP_SETTING_DATA_CHANGE_COMPLETE, true); //ST1_SETTING_COMPLETE
// ´ë±âÇÔ¼ö Ãß°¡..
if (_plc.WaitWriteBitUpdate(_latchForWriteBitUpdate, out _) == false) {
// ÇÔ¼ö¸íÀº ±âÁ¸ ·Î°Å¿¡¼­ Áö¿øÇÏ´Ï, ¶óÀιøÈ£¸¸ ÂïÀÚ..
Log.W(_plc.WriteLogTag("WriteBit timed out"));
}
Step_SETTING = eMainSeqStep.ACK_WAIT;
swSetting.Restart();
}
}
break;
}
case eMainSeqStep.ACK_WAIT: {
var res2 = _plc.ReadBit((int)PLCController.eBitInput.EQP_SETTING_DATA_CHANGE_REQ); //ST1_SETTING_REQ
if (res2.err != E1.OK) {
Step_SETTING = eMainSeqStep.INIT;
swSetting.Stop();
Log.I("Step_SETTING.eMainSeqStep.ACK: PLC is deactivating");
return PLC_IS_DEACTIVATING;
} else {
if (!res2.data) {
Step_SETTING = eMainSeqStep.INIT;
swSetting.Stop();
} else if (swSetting.ElapsedMilliseconds > TIME_OUT) {
Step_SETTING = eMainSeqStep.INIT;
EventLog.W($"PLC Setting Change Bit Clear TimeOver");
swSetting.Stop();
}
}
}
break;
}
*/
#if DEBUG
//Debug.WriteLine($"MONITOR_SETTING: --> GO_MONITOR_NETWORK");
#endif
return GO_MONITOR_NETWORK;
}
private static string MonitorPLCAlarmStatus(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
{
/*
switch (Step_ALARM) {
case eMainSeqStep.INIT: {
Step_ALARM = eMainSeqStep.WORK;
_latchForWriteBitUpdate = _plc.LatchForWriteBitUpdate;
_plc.WriteBit((int)eBitOutput.EQP_ALARM_STATUS_CHANGE_COMPLETE, false);
// ´ë±âÇÔ¼ö Ãß°¡..
if (_plc.WaitWriteBitUpdate(_latchForWriteBitUpdate, out _) == false) {
// ÇÔ¼ö¸íÀº ±âÁ¸ ·Î°Å¿¡¼­ Áö¿øÇÏ´Ï, ¶óÀιøÈ£¸¸ ÂïÀÚ..
Log.W(_plc.WriteLogTag("WriteBit timed out"));
}
break;
}
case eMainSeqStep.WORK: {
var res2 = _plc.ReadBit((int)eBitInput.EQP_ALARM_STATUS_CHANGE_REQ);
if (res2.err != E1.OK) {
Step_ALARM = eMainSeqStep.INIT;
swAlarm.Stop();
Log.I("Step_ALARM.eMainSeqStep.WORK: PLC is deactivating");
return PLC_IS_DEACTIVATING;
} else {
if (res2.data) { // ¾Ë¶÷ ¿äû
// LUKAS: ²Ï ¸¹Àº M ÀåÄ¡¸¦ Àаí ÀÖÀ½
var res = _plc.ReadPLCAlarm();
if (res != E1.OK) {
// ºñȰ¼ºÈ­¿¡ ÀÇÇÑ ½ÇÆÐÀÎÁö, Åë½Å ¿À·ù¿¡ ÀÇÇÑ ½ÇÆÐÀÎÁö ±¸ºÐ
if (_plc._dataUpdateTimer.IsRunning) {
Log.E("ReadPLCAlarm() is failed: --> reconnect");
// ¿øº»°ú ´Ù¸¥ ºÎºÐ, Åë½Å ½ÇÆÐ·Î À翬°áÀ» ½ÃµµÇÏ´Ï, óÀ½ºÎÅÍ ´Ù½ÃÇØ¾ß ÇÏÁö ¾ÊÀ»±î??
Step_ALARM = eMainSeqStep.INIT;
swAlarm.Stop();
return GO_RECONNECT_NETWORK;
} else {
Log.E("ReadPLCAlarm() is failed: PLC is deactivating");
Step_ALARM = eMainSeqStep.INIT;
swAlarm.Stop();
return PLC_IS_DEACTIVATING;
}
}
//Thread.Sleep(50);
// LUKAS: ¼øÈ¸¸¦ Çϸ鼭 ·Î±×¸¦ ³²±â´Âµ¥...Èì...
_plc.CheckPLCAlarm();
_latchForWriteBitUpdate = _plc.LatchForWriteBitUpdate;
_plc.WriteBit((int)eBitOutput.EQP_ALARM_STATUS_CHANGE_COMPLETE, true);
// ´ë±âÇÔ¼ö Ãß°¡..
if (_plc.WaitWriteBitUpdate(_latchForWriteBitUpdate, out _) == false) {
// ÇÔ¼ö¸íÀº ±âÁ¸ ·Î°Å¿¡¼­ Áö¿øÇÏ´Ï, ¶óÀιøÈ£¸¸ ÂïÀÚ..
Log.W(_plc.WriteLogTag("WriteBit timed out"));
}
Step_ALARM = eMainSeqStep.ACK_WAIT;
swAlarm.Restart();
}
}
break;
}
case eMainSeqStep.ACK_WAIT: {
// LUKAS: ¾Ë¶÷ ¿äûÀÌ ¾øÀ¸¸é, Init (óÀ½)À¸·Î À̵¿
var res2 = _plc.ReadBit((int)PLCController.eBitInput.EQP_ALARM_STATUS_CHANGE_REQ);
if (res2.err != E1.OK) {
Step_ALARM = eMainSeqStep.INIT;
swAlarm.Stop();
Log.I("Step_ALARM.eMainSeqStep.ACK: PLC is deactivating");
return PLC_IS_DEACTIVATING;
} else {
if (!res2.data) {
Step_ALARM = eMainSeqStep.INIT;
swAlarm.Stop();
} else if (swAlarm.ElapsedMilliseconds > TIME_OUT) { // LUKAS: PLC ¾Ë¶÷ ¸®¼Â ŸÀÔ¿À¹ö ??
Step_ALARM = eMainSeqStep.INIT;
EventLog.W($"PLC ALARM Change Bit Clear TimeOver");
swAlarm.Stop();
}
}
break;
}
}
*/
#if DEBUG
//Debug.WriteLine($"MONITOR_ALARM: --> MONITOR_SETTING");
#endif
return MONITOR_SETTING;
}
private static string MonitorNetworkStatus(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
{
// Åë½Å ¿¬°á »óŸ¦ °Ë»çÇÑ´Ù.
// Åë½ÅÀÌ ²÷°åÀ» °æ¿ì´Â 1. PLC¸¦ ºñȰ¼ºÈ­ÇßÀ» ¶§, 2. Åë½Å¿¡·¯·Î Á¾·áµÇ¾úÀ» °æ¿ì,
// => Check Active ·Î À̵¿ÇÑ´Ù...
// 1. => PLC ºñȰ¼ºÈ­
// ==> Check Active ¿¡¼­ 󸮵Ê...
// 2. => Åë½Å À翬°á ·ÎÁ÷ ¼öÇà
// ==> ¿©±â¼­ 󸮵Ê...
if (_plc.IsConnected) {
#if DEBUG
/* // TEST CODE For TEST
_plc.ReadBit(1);
_plc.WriteBit(1, true);
_plc.ReadWord(1);
_plc.WriteWord(1, 1);
*/
//Debug.WriteLine($"MONITOR_NETWORK: --> CHECK_RUN_STATUS");
#endif
return MONITOR_ALARM;
} else { // Åë½ÅÀÌ Á¾·áµÇ¾ú´Ù...
if (_plc._dataUpdateTimer.IsRunning == false) { // ºñȰ¼ºÈ­ Æ®¸®°Å¸µ
Log.I("MonitorNetworkStatus(): PLC is deactivating");
return PLC_IS_DEACTIVATING;
}
// Åë½Å ÀÌ»ó...!!!
Log.I("Try to reconnect to PLC");
return GO_RECONNECT_NETWORK;
}
}
private static string CheckActive(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
{
while (!context.Stopped) {
if (_plc.IsActivated) {
// data ¾÷µ¥ÀÌÆ® ½º·¹µå´Â ºñµ¿±â·Î µ¿ÀÛÁßÀÌ´Ù..
Log.I("PLC is activated: --> Monitor PLC Network state");
return MONITOR_NETWORK;
}
// ÁÖ±âÀû µô·¹ÀÌ
Thread.Sleep(SLEEP_TIME_MS);
}
Log.W("Fatal error or Seq. Stop is occurred: --> Final");
return SeqNodeIds.FINAL;
}
private static SequenceActionResult Init(SequenceContext context, string id, SequenceActionResult param)
{
_plc = context.Devices[CommonDeviceIds.PLCDevice] as PLCController;
//Log.I("PLC Mon. Sequence starts");
return SequenceAction.Ok();
}
}
}