2026-01-26 18:56:53 +09:00

1073 lines
44 KiB
C#

using Aurora.Api;
using Aurora.Api.Devices;
using Opc.Ua;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Timers;
using Timer = System.Timers.Timer;
namespace AuroraLaser.Coherent.Arm
{
public enum CmdType
{
Read,
Write,
Unknown
}
public class PendingCommand
{
public int TargetCmd;
public CmdType Type;
}
public class LaserArmSocketConn : SocketConn
{
// SocketConn 을 상속받았기 때문에 바로 연결함수를 쓸수는 있다.
// 그러나 기존에 감시하는 함수들을 그대로 쓰기 위해서 하위 변수로 client 를 추가해서 쓰도록하자
#region Properties
LaserArmConfig _Config;
private UdpClient udp = null; // 레이저 통신 컴.
IAsyncResult ar_ = null; // 콜백.
public bool IsConnect = false;
private bool _IsSimul;
private Timer _laserStatusTimer;
private int nodeCount = 0;
public enum eLaserStatus { STATUS_NONE = 0, STATUS_LASER_ON_STEP, STATUS_LASER_READY, STATUS_LASER_OFF_STEP, STATUS_LASER_OFF, STATUS_LASER_ERROR };
public int TestData;
public int nLaserType = 0; // TRUMPF (0), Coherent (1);
protected readonly object readNodeLock = new object();
protected readonly object writeNodeLock = new object();
private readonly ConcurrentQueue<PendingCommand> _pendingCommandQueue = new ConcurrentQueue<PendingCommand>();
private StringBuilder _messageBuffer = new StringBuilder();
private Queue<int> _refreshQueue = new Queue<int>();
private System.Timers.Timer _refreshTimer;
// Read/Write node information
public sNodeInfo[] ReadNode = new sNodeInfo[csReadCOH.MAX];
public sNodeInfo[] WriteNode = new sNodeInfo[csWriteCOH.MAX];
public List<string> ErrorMessage = new List<string>();
public List<string> WarningMessage = new List<string>();
public List<string> Humidity = new List<string>();
public string strSendMsg = ""; // 보낼 데이터.
public string strReceiveMsgTotal = ""; // 수신 완료시 받은 데이터.
public string strReceiveMsg = ""; // 완료시까지 받은 데이터.
public string CRLF = "\r\n";
public int RetryCnt = 0; // ERR_LASER_READ_ERROR retry count
public enum eSeqStep : int
{
SEQ_NONE = 0,
SEQ_LASER_ON_START,
SEQ_LASER_ON_REMOTE_ON,
SEQ_LASER_ON_REMOTE_ON_CHK,
SEQ_LASER_ON_MAINS,
SEQ_LASER_ON_MAINS_CHK,
SEQ_LASER_ON_READY_BEFORE_DELAY,
SEQ_LASER_ON_READY,
SEQ_LASER_ON_READY_CHK,
SEQ_LASER_OFF_START,
SEQ_LASER_OFF_EMISSION_OFF_CHK,
SEQ_LASER_PILOT_LASER_ON_START,
SEQ_LASER_PILOT_LASER_ON_EMISSION_OFF_CHK,
SEQ_LASER_PILOT_LASER_ON_LOCAL_MODE_ON_CHK,
SEQ_LASER_PILOT_LASER_ON_PILOT_LASER_ON_CHK,
SEQ_LASER_PILOT_LASER_OFF_START,
SEQ_LASER_PILOT_LASER_OFF_CHK,
SEQ_LASER_PILOT_LASER_OFF_REQUEST_LASER_ON_CHK,
SEQ_LASER_PILOT_LASER_OFF_REQUEST_LASER_DELAY,
SEQ_LASER_PILOT_LASER_OFF_REQUEST_LASER_OFF_CHK,
};
public eSeqStep nSequence;
public eLaserStatus nLaserStatus;
public int nTargetCommand;
public int nSettingValue;
public int nReturnType;
public int nWriteCmd = 0;
public enum eCommStatus : int { COMM_STATUS_NONE = 0, COMM_STATUS_WAIT_RECEIVE_DATA, COMM_STATUS_WAIT_RESET_START, COMM_STATUS_WAIT_RESET_FINISH, COMM_STATUS_TIME_OUT }; // 읽거나 쓸때 리턴값에 타겟이 안나온다. 결과만 오기 때문에 리턴 받은 후 다음 명령 써야 한다.
public eCommStatus nCommStatus;
#endregion
public LaserArmSocketConn(string deviceid, bool isSimul, SocketProtocol type) : base(deviceid, isSimul, type)
{
_IsSimul = isSimul;
nLaserStatus = eLaserStatus.STATUS_NONE;
nSequence = eSeqStep.SEQ_NONE;
nCommStatus = eCommStatus.COMM_STATUS_NONE;
nTargetCommand = 0;
ErrorMessage.Clear();
WarningMessage.Clear();
Humidity.Clear();
InitNodes();
InitTimer(200);
}
private void InitTimer(int intervalMs)
{
_laserStatusTimer = new System.Timers.Timer(intervalMs);
//_laserStatusTimer.Elapsed += (s, e) => RefreshAllLaserState();
_laserStatusTimer.Elapsed += (s, e) => RefreshAllLaserState_UDP();
_laserStatusTimer.AutoReset = true;
_laserStatusTimer.Start();
}
private void PauseStatusTimer()
{
_laserStatusTimer?.Stop();
}
private void ResumeStatusTimer()
{
_laserStatusTimer?.Start();
}
#region InitNodes()
private void InitNodes()
{
for (int i = 0; i < ReadNode.Length; i++) {
ReadNode[i].nExist = 0;
ReadNode[i].IsCallBack = 0;
ReadNode[i].nDigit = 1;
ReadNode[i].priority = 1;
ReadNode[i].priority = 1;
}
for (int i = 0; i < WriteNode.Length; i++) {
WriteNode[i].nExist = 0;
WriteNode[i].IsCallBack = 0;
WriteNode[i].nDigit = 1;
}
//---------- Read NODE
ReadNode[csReadCOH.INIT_COMMUNICATION].strNodeName = "?init" + CRLF;
ReadNode[csReadCOH.INIT_COMMUNICATION].strDisplayNodeName = "INIT COMMUNICATION";
ReadNode[csReadCOH.INIT_COMMUNICATION].nNodeType = csNodeType.BOOL;
ReadNode[csReadCOH.INIT_COMMUNICATION].nExist = 1;
ReadNode[csReadCOH.INIT_COMMUNICATION].strKey = csReadCOH.INIT_COMMUNICATION.ToString();
ReadNode[csReadCOH.EMS_STATUS].strNodeName = "?ems" + CRLF;
ReadNode[csReadCOH.EMS_STATUS].strDisplayNodeName = "EMISSION ON STATE";
ReadNode[csReadCOH.EMS_STATUS].nNodeType = csNodeType.BOOL;
ReadNode[csReadCOH.EMS_STATUS].nExist = 1;
ReadNode[csReadCOH.EMS_STATUS].strKey = csReadCOH.EMS_STATUS.ToString();
ReadNode[csReadCOH.MAINS_STATUS].strNodeName = "?mains" + CRLF;
ReadNode[csReadCOH.MAINS_STATUS].strDisplayNodeName = "CARD MAIN SUPPLY STATE";
ReadNode[csReadCOH.MAINS_STATUS].nNodeType = csNodeType.BOOL;
ReadNode[csReadCOH.MAINS_STATUS].nExist = 1;
ReadNode[csReadCOH.MAINS_STATUS].strKey = csReadCOH.MAINS_STATUS.ToString();
ReadNode[csReadCOH.WARNING_STATUS].strNodeName = "?alert" + CRLF;
ReadNode[csReadCOH.WARNING_STATUS].strDisplayNodeName = "WARNING STATE";
ReadNode[csReadCOH.WARNING_STATUS].nNodeType = csNodeType.BOOL;
ReadNode[csReadCOH.WARNING_STATUS].nExist = 1;
ReadNode[csReadCOH.WARNING_STATUS].strKey = csReadCOH.WARNING_STATUS.ToString();
ReadNode[csReadCOH.ERROR_STATUS].strNodeName = "?error" + CRLF;
ReadNode[csReadCOH.ERROR_STATUS].strDisplayNodeName = "ERROR STATE";
ReadNode[csReadCOH.ERROR_STATUS].nNodeType = csNodeType.BOOL;
ReadNode[csReadCOH.ERROR_STATUS].nExist = 1;
ReadNode[csReadCOH.ERROR_STATUS].strKey = csReadCOH.ERROR_STATUS.ToString();
ReadNode[csReadCOH.PILOT_LASER_STATE].strNodeName = "?abo" + CRLF;
ReadNode[csReadCOH.PILOT_LASER_STATE].strDisplayNodeName = "PILOT LASER STATE";
ReadNode[csReadCOH.PILOT_LASER_STATE].nNodeType = csNodeType.BOOL;
ReadNode[csReadCOH.PILOT_LASER_STATE].nExist = 1;
ReadNode[csReadCOH.PILOT_LASER_STATE].strKey = csReadCOH.PILOT_LASER_STATE.ToString();
ReadNode[csReadCOH.CONTROL_MODE].strNodeName = "?spm" + CRLF;
ReadNode[csReadCOH.CONTROL_MODE].strDisplayNodeName = "CONTROL MODE";
ReadNode[csReadCOH.CONTROL_MODE].nNodeType = csNodeType.STRING;
ReadNode[csReadCOH.CONTROL_MODE].nExist = 1;
ReadNode[csReadCOH.CONTROL_MODE].strKey = csReadCOH.CONTROL_MODE.ToString();
//ReadNode[csReadCOH.WATER_FLOW_MAIN].strNodeName = "?wf" + CRLF;
//ReadNode[csReadCOH.WATER_FLOW_MAIN].strDisplayNodeName = "WATER FLOW MAIN L/M";
//ReadNode[csReadCOH.WATER_FLOW_MAIN].nNodeType = csNodeType.STRING;
//ReadNode[csReadCOH.WATER_FLOW_MAIN].nExist = 1;
//ReadNode[csReadCOH.WATER_FLOW_MAIN].strKey = csReadCOH.WATER_FLOW_MAIN.ToString();
//ReadNode[csReadCOH.WATER_TEMP_MAIN].strNodeName = "?wt" + CRLF;
//ReadNode[csReadCOH.WATER_TEMP_MAIN].strDisplayNodeName = "WATER TEMP MAIN ℃"; // ℃";
//ReadNode[csReadCOH.WATER_TEMP_MAIN].nNodeType = csNodeType.STRING;
//ReadNode[csReadCOH.WATER_TEMP_MAIN].nExist = 1;
//ReadNode[csReadCOH.WATER_TEMP_MAIN].strKey = csReadCOH.WATER_TEMP_MAIN.ToString();
//ReadNode[csReadCOH.HUMIDITY_MAIN].strNodeName = "?eh" + CRLF;
//ReadNode[csReadCOH.HUMIDITY_MAIN].strDisplayNodeName = "HUMIDITY MAIN";
//ReadNode[csReadCOH.HUMIDITY_MAIN].nNodeType = csNodeType.STRING;
//ReadNode[csReadCOH.HUMIDITY_MAIN].nExist = 1;
//ReadNode[csReadCOH.HUMIDITY_MAIN].strKey = csReadCOH.HUMIDITY_MAIN.ToString();
ReadNode[csReadCOH.ERROR_MESSAGE].strNodeName = "?cerr" + CRLF;
ReadNode[csReadCOH.ERROR_MESSAGE].strDisplayNodeName = "ERROR MESSAGE";
ReadNode[csReadCOH.ERROR_MESSAGE].nNodeType = csNodeType.STRING;
ReadNode[csReadCOH.ERROR_MESSAGE].nExist = 1;
ReadNode[csReadCOH.ERROR_MESSAGE].strKey = csReadCOH.ERROR_MESSAGE.ToString();
ReadNode[csReadCOH.LASER_POWER_CENTER].strNodeName = "?powc" + CRLF;
ReadNode[csReadCOH.LASER_POWER_CENTER].strDisplayNodeName = "LASER POWER CENTER";
ReadNode[csReadCOH.LASER_POWER_CENTER].nNodeType = csNodeType.STRING;
ReadNode[csReadCOH.LASER_POWER_CENTER].nExist = 1;
ReadNode[csReadCOH.LASER_POWER_CENTER].strKey = csReadCOH.LASER_POWER_CENTER.ToString();
ReadNode[csReadCOH.LASER_POWER_RING].strNodeName = "?powr" + CRLF;
ReadNode[csReadCOH.LASER_POWER_RING].strDisplayNodeName = "LASER POWER RING";
ReadNode[csReadCOH.LASER_POWER_RING].nNodeType = csNodeType.STRING;
ReadNode[csReadCOH.LASER_POWER_RING].nExist = 1;
ReadNode[csReadCOH.LASER_POWER_RING].strKey = csReadCOH.LASER_POWER_RING.ToString();
//ReadNode[csReadCOH.SYSTEM_CONTROL_STATUS].strNodeName = "?scs" + CRLF;
//ReadNode[csReadCOH.SYSTEM_CONTROL_STATUS].strDisplayNodeName = "SYSTEM CONTROL STATUS";
//ReadNode[csReadCOH.SYSTEM_CONTROL_STATUS].nNodeType = csNodeType.STRING;
//ReadNode[csReadCOH.SYSTEM_CONTROL_STATUS].nExist = 1;
//ReadNode[csReadCOH.SYSTEM_CONTROL_STATUS].strKey = csReadCOH.SYSTEM_CONTROL_STATUS.ToString();
//ReadNode[csReadCOH.DC_VOLTAGE].strNodeName = "?slv" + CRLF;
//ReadNode[csReadCOH.DC_VOLTAGE].strDisplayNodeName = "Laser Module DC Voltage";
//ReadNode[csReadCOH.DC_VOLTAGE].nNodeType = csNodeType.STRING;
//ReadNode[csReadCOH.DC_VOLTAGE].nExist = 1;
//ReadNode[csReadCOH.DC_VOLTAGE].strKey = csReadCOH.DC_VOLTAGE.ToString();
ReadNode[csReadCOH.WARNING_MESSAGE].strNodeName = "?warn" + CRLF;
ReadNode[csReadCOH.WARNING_MESSAGE].strDisplayNodeName = "Show Warning Message";
ReadNode[csReadCOH.WARNING_MESSAGE].nNodeType = csNodeType.STRING;
ReadNode[csReadCOH.WARNING_MESSAGE].nExist = 1;
ReadNode[csReadCOH.WARNING_MESSAGE].strKey = csReadCOH.WARNING_MESSAGE.ToString();
ReadNode[csReadCOH.LASER_START].strNodeName = "?spo" + CRLF;
ReadNode[csReadCOH.LASER_START].strDisplayNodeName = "Laser Power Status";
ReadNode[csReadCOH.LASER_START].nNodeType = csNodeType.BOOL;
ReadNode[csReadCOH.LASER_START].nExist = 1;
ReadNode[csReadCOH.LASER_START].strKey = csReadCOH.LASER_START.ToString();
//ReadNode[csReadCOH.LAST_ERROR_LOG].strNodeName = "?log" + CRLF;
//ReadNode[csReadCOH.LAST_ERROR_LOG].strDisplayNodeName = "LAST ERROR LOG";
//ReadNode[csReadCOH.LAST_ERROR_LOG].nNodeType = csNodeType.STRING;
//ReadNode[csReadCOH.LAST_ERROR_LOG].nExist = 1;
//ReadNode[csReadCOH.LAST_ERROR_LOG].strKey = csReadCOH.LAST_ERROR_LOG.ToString();
//ReadNode[csReadCOH.FAN_CONTROLLER_FREQUENCY].strNodeName = "?ffc" + CRLF;
//ReadNode[csReadCOH.FAN_CONTROLLER_FREQUENCY].strDisplayNodeName = "FAN CONTROLLER FREQ";
//ReadNode[csReadCOH.FAN_CONTROLLER_FREQUENCY].nNodeType = csNodeType.STRING;
//ReadNode[csReadCOH.FAN_CONTROLLER_FREQUENCY].nExist = 1;
//ReadNode[csReadCOH.FAN_CONTROLLER_FREQUENCY].strKey = csReadCOH.FAN_CONTROLLER_FREQUENCY.ToString();
//ReadNode[csReadCOH.FAN_SPEED].strNodeName = "?ffs" + CRLF;
//ReadNode[csReadCOH.FAN_SPEED].strDisplayNodeName = "FAN SPEED";
//ReadNode[csReadCOH.FAN_SPEED].nNodeType = csNodeType.STRING;
//ReadNode[csReadCOH.FAN_SPEED].nExist = 1;
//ReadNode[csReadCOH.FAN_SPEED].strKey = csReadCOH.FAN_SPEED.ToString();
//ReadNode[csReadCOH.EMO_STATUS].strNodeName = "?estop" + CRLF;
//ReadNode[csReadCOH.EMO_STATUS].strDisplayNodeName = "EMO Status";
//ReadNode[csReadCOH.EMO_STATUS].nNodeType = csNodeType.BOOL;
//ReadNode[csReadCOH.EMO_STATUS].nExist = 1;
//ReadNode[csReadCOH.EMO_STATUS].strKey = csReadCOH.EMO_STATUS.ToString();
//ReadNode[csReadCOH.PROG_ACTIVED].strNodeName = "?progactive" + CRLF;
//ReadNode[csReadCOH.PROG_ACTIVED].strDisplayNodeName = "Program Actived";
//ReadNode[csReadCOH.PROG_ACTIVED].nNodeType = csNodeType.BOOL;
//ReadNode[csReadCOH.PROG_ACTIVED].nExist = 1;
//ReadNode[csReadCOH.PROG_ACTIVED].strKey = csReadCOH.PROG_ACTIVED.ToString();
//ReadNode[csReadCOH.PROG_INTERRUPTED].strNodeName = "?progint" + CRLF;
//ReadNode[csReadCOH.PROG_INTERRUPTED].strDisplayNodeName = "Program Interrupted";
//ReadNode[csReadCOH.PROG_INTERRUPTED].nNodeType = csNodeType.BOOL;
//ReadNode[csReadCOH.PROG_INTERRUPTED].nExist = 1;
//ReadNode[csReadCOH.PROG_INTERRUPTED].strKey = csReadCOH.PROG_INTERRUPTED.ToString();
//---------- Write NODE
WriteNode[csWriteCOH.SYSTEM_START].strNodeName = "!start" + CRLF; // 현재 상태 mains
WriteNode[csWriteCOH.SYSTEM_START].strDisplayNodeName = "START LASER";
WriteNode[csWriteCOH.SYSTEM_START].nNodeType = csNodeType.BOOL;
WriteNode[csWriteCOH.SYSTEM_START].nExist = 1;
WriteNode[csWriteCOH.SYSTEM_START].strKey = csWriteCOH.SYSTEM_START.ToString();
WriteNode[csWriteCOH.SYSTEM_START].nKey = csWriteCOH.SYSTEM_START;
WriteNode[csWriteCOH.LASER_START].strNodeName = "!spo ";
WriteNode[csWriteCOH.LASER_START].strDisplayNodeName = "EMISSION ENABLE";
WriteNode[csWriteCOH.LASER_START].nNodeType = csNodeType.BOOL;
WriteNode[csWriteCOH.LASER_START].nExist = 1;
WriteNode[csWriteCOH.LASER_START].strKey = csWriteCOH.LASER_START.ToString();
WriteNode[csWriteCOH.LASER_START].nKey = csWriteCOH.LASER_START;
WriteNode[csWriteCOH.PILOT_LASER].strNodeName = "!abo ";
WriteNode[csWriteCOH.PILOT_LASER].strDisplayNodeName = "PILOT LASER ON";
WriteNode[csWriteCOH.PILOT_LASER].nNodeType = csNodeType.BOOL;
WriteNode[csWriteCOH.PILOT_LASER].nExist = 1;
WriteNode[csWriteCOH.PILOT_LASER].strKey = csWriteCOH.PILOT_LASER.ToString();
WriteNode[csWriteCOH.PILOT_LASER].nKey = csWriteCOH.PILOT_LASER;
WriteNode[csWriteCOH.LASER_RESET].strNodeName = "!reset" + CRLF; // max 30sec disconnect comm.
WriteNode[csWriteCOH.LASER_RESET].strDisplayNodeName = "RESET";
WriteNode[csWriteCOH.LASER_RESET].nNodeType = csNodeType.BOOL;
WriteNode[csWriteCOH.LASER_RESET].nExist = 1;
WriteNode[csWriteCOH.LASER_RESET].strKey = csWriteCOH.LASER_RESET.ToString();
WriteNode[csWriteCOH.LASER_RESET].nKey = csWriteCOH.LASER_RESET;
WriteNode[csWriteCOH.CONTROL_MODE].strNodeName = "!spm "; // Control mode Local(1) Remote(2)
WriteNode[csWriteCOH.CONTROL_MODE].strDisplayNodeName = "CONTROL MODE";
WriteNode[csWriteCOH.CONTROL_MODE].nNodeType = csNodeType.BOOL;
WriteNode[csWriteCOH.CONTROL_MODE].nExist = 1;
WriteNode[csWriteCOH.CONTROL_MODE].strKey = csWriteCOH.CONTROL_MODE.ToString();
WriteNode[csWriteCOH.CONTROL_MODE].nKey = csWriteCOH.CONTROL_MODE;
WriteNode[csWriteCOH.CLEAR_FAULT].strNodeName = "!fcerr" + CRLF;
WriteNode[csWriteCOH.CLEAR_FAULT].strDisplayNodeName = "CLEAR FAULT";
WriteNode[csWriteCOH.CLEAR_FAULT].nNodeType = csNodeType.BOOL;
WriteNode[csWriteCOH.CLEAR_FAULT].nExist = 1;
WriteNode[csWriteCOH.CLEAR_FAULT].strKey = csWriteCOH.CLEAR_FAULT.ToString();
WriteNode[csWriteCOH.CLEAR_FAULT].nKey = csWriteCOH.CLEAR_FAULT;
WriteNode[csWriteCOH.POWER_LEVEL].strNodeName = "!pow ";
WriteNode[csWriteCOH.POWER_LEVEL].strDisplayNodeName = "SET POWER MAIN";
WriteNode[csWriteCOH.POWER_LEVEL].nNodeType = csNodeType.STRING;
WriteNode[csWriteCOH.POWER_LEVEL].nExist = 1;
WriteNode[csWriteCOH.POWER_LEVEL].strKey = csWriteCOH.POWER_LEVEL.ToString();
WriteNode[csWriteCOH.POWER_LEVEL].nKey = csWriteCOH.POWER_LEVEL;
WriteNode[csWriteCOH.POWER_CENTER].strNodeName = "!powc ";
WriteNode[csWriteCOH.POWER_CENTER].strDisplayNodeName = "SET POWER CENTER";
WriteNode[csWriteCOH.POWER_CENTER].nNodeType = csNodeType.STRING;
WriteNode[csWriteCOH.POWER_CENTER].nExist = 1;
WriteNode[csWriteCOH.POWER_CENTER].strKey = csWriteCOH.POWER_CENTER.ToString();
WriteNode[csWriteCOH.POWER_CENTER].nKey = csWriteCOH.POWER_CENTER;
WriteNode[csWriteCOH.POWER_RING].strNodeName = "!powr ";
WriteNode[csWriteCOH.POWER_RING].strDisplayNodeName = "SET POWER RING";
WriteNode[csWriteCOH.POWER_RING].nNodeType = csNodeType.STRING;
WriteNode[csWriteCOH.POWER_RING].nExist = 1;
WriteNode[csWriteCOH.POWER_RING].strKey = csWriteCOH.POWER_RING.ToString();
WriteNode[csWriteCOH.POWER_RING].nKey = csWriteCOH.POWER_RING;
}
#endregion
private void StartListening()
{
try {
ar_ = udp.BeginReceive(ReceiveCallback, new object());
} catch {
}
}
private void StopListening()
{
PauseStatusTimer();
}
private void ReceiveCallback(IAsyncResult ar)
{
try {
lock (readNodeLock) {
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 0);
byte[] bytes = udp.EndReceive(ar, ref ip);
string message = Encoding.Default.GetString(bytes);
_messageBuffer.Append(message);
string bufferStr = _messageBuffer.ToString();
var lines = bufferStr.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
int count = lines.Length;
bool endsWithNewline = bufferStr.EndsWith("\n") || bufferStr.EndsWith("\r\n");
int lastCompleteLine = endsWithNewline ? count : count - 1;
for (int i = 0; i < lastCompleteLine; i++)
{
string msg = lines[i].Trim();
if (string.IsNullOrEmpty(msg))
{
continue;
}
if (msg.StartsWith("MDM>"))
{
if (_pendingCommandQueue.TryDequeue(out PendingCommand pcRead) && pcRead.Type == CmdType.Read)
{
int targetCmd = pcRead.TargetCmd;
string data = ParsePayload(msg);
if (ReadNode[targetCmd].nNodeType == csNodeType.BOOL)
{
ReadNode[targetCmd].nRet = data.Contains("1") ? 1 : 0;
Logger.I(String.Format("Coherent Receive {0}-{1}", ReadNode[targetCmd].strNodeName, data));
}
else
{
if (nTargetCommand == csReadCOH.ERROR_MESSAGE)
{
ReadNode[targetCmd].strRet = ParseErrorMessage(data);
Logger.I(String.Format("Coherent Receive {0}-{1}", ReadNode[targetCmd].strNodeName, ReadNode[targetCmd].strRet));
}
else
{
ReadNode[targetCmd].strRet = data;
Logger.I(String.Format("Coherent Receive {0}-{1}", ReadNode[targetCmd].strNodeName, data));
}
}
}
}
else if (msg.StartsWith("CMD>"))
{
string data = ParsePayload(msg);
if (_pendingCommandQueue.TryDequeue(out PendingCommand pcWrite) && pcWrite.Type == CmdType.Write)
{
int targetCmd = pcWrite.TargetCmd;
if (WriteNode[targetCmd].nNodeType == csNodeType.BOOL)
{
WriteNode[targetCmd].nRet = data.Contains("1") ? 1 : 0;
Logger.I(String.Format("Coherent Receive {0}-{1}", WriteNode[targetCmd].strNodeName, data));
}
else
{
WriteNode[targetCmd].strRet = data;
Logger.I(String.Format("Coherent Receive {0}-{1}", WriteNode[targetCmd].strNodeName, data));
}
}
else
{
//
}
}
else if (msg.StartsWith("ALARM>") || msg.StartsWith("BOOT>") || msg.StartsWith("MDM_HDR>"))
{
//
}
else
{
if (_pendingCommandQueue.TryDequeue(out PendingCommand pcRead) && pcRead.Type == CmdType.Read)
{
int targetCmd = pcRead.TargetCmd;
string nodename = ReadNode[targetCmd].strNodeName.TrimEnd('\r', '\n');
string Message = message.TrimEnd('\r', '\n');
//Logger.I(String.Format("Coherent Receive {0} - {1}", nodename, Message));
ReadNode[targetCmd].strRet = Message.Substring(2);
if (ReadNode[targetCmd].nNodeType == csNodeType.BOOL)
{
ReadNode[targetCmd].nRet = ReadNode[targetCmd].strRet.Contains("1") ? 1 : 0;
}
else if (nTargetCommand == csReadCOH.ERROR_MESSAGE)
{
ErrorMessage = ParseBracketMessages(ReadNode[targetCmd].strRet);
}
else if (nTargetCommand == csReadCOH.WARNING_MESSAGE)
{
WarningMessage = ParseBracketMessages(ReadNode[targetCmd].strRet);
}
//else if(nTargetCommand == csReadCOH.HUMIDITY_MAIN)
//{
// Humidity = ParseBracketMessages(ReadNode[targetCmd].strRet);
//}
}
}
}
_messageBuffer.Clear();
if (!endsWithNewline && count > 0)
_messageBuffer.Append(lines[count - 1]);
}
} catch { } finally {
StartListening();
}
}
public List<string> ParseBracketMessages(string raw)
{
var result = new List<string>();
var lines = raw.Split(new[] { "\r\n", "\n" }, System.StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
// [0] OK, [1] OK 등에서 대괄호 이후 값만 추출
var match = Regex.Match(line, @"\[\d+\]\s*(.*)");
if (match.Success)
{
result.Add(match.Groups[1].Value.Trim());
}
}
return result;
}
private string ParseErrorMessage(string raw)
{
if (string.IsNullOrWhiteSpace(raw)) {
return "";
}
var match = Regex.Match(raw, @"(E\\d{3}):\\s*(.+?)\\r?\\n?");
if (match.Success) {
return $"[{match.Groups[1].Value}] {match.Groups[2].Value}";
} else {
return raw.Trim();
}
}
private string ParsePayload(string msg)
{
// 예시: CMD>25-06-25T04:00:02>!abo 1
// 예시: MDM>25-06-25T04:00:02>561;273;1
int idx = msg.IndexOf('>');
if (idx < 0) return msg;
idx = msg.IndexOf('>', idx + 1); // 두 번째 > 위치
if (idx < 0) return msg;
return msg.Substring(idx + 1).Trim();
}
public string GetErrorMessage()
{
string Temp = ErrorMessage[0];
return ReadNode[csReadCOH.ERROR_MESSAGE].strRet;
}
public List<string> GetErrorMessages()
{
return ErrorMessage;
}
public string GetWarningMessage()
{
string Temp = WarningMessage[0];
return ReadNode[csReadCOH.WARNING_MESSAGE].strRet;
}
public List<string> GetWarningMessages()
{
return WarningMessage;
}
public void RefreshAllLaserState()
{
//TimeSpan spanTime;
//DateTime startTime = DateTime.Now;
//int timeOut = 1;
for (int i = 0; i < ReadNode.Length; i++) {
if (ReadNode[i].nExist == 1 && !string.IsNullOrEmpty(ReadNode[i].strNodeName)) {
Logger.I(String.Format("Coherent send {0}", ReadNode[i].strNodeName));
Send(ReadNode[i].strNodeName, i, CmdType.Read);
//while (true) {
// spanTime = DateTime.Now.Subtract(startTime);
// if (spanTime.TotalMilliseconds > (timeOut * 1000)) {
// break;
// }
//}
//startTime = DateTime.Now;
//Logger.I(String.Format("Timeover"));
Thread.Sleep(500);
}
}
}
public void RefreshAllLaserState_UDP()
{
if (_refreshTimer != null && _refreshTimer.Enabled)
return;
_refreshQueue.Clear();
for (int i = 0; i < ReadNode.Length; i++)
{
if (ReadNode[i].nExist == 1 && !string.IsNullOrEmpty(ReadNode[i].strNodeName))
{
_refreshQueue.Enqueue(i);
}
}
_refreshTimer = new System.Timers.Timer(100);
_refreshTimer.Elapsed += (s, e) => RefreshSendNext();
_refreshTimer.AutoReset = true;
_refreshTimer.Start();
RefreshSendNext();
}
private void RefreshSendNext()
{
lock (_refreshQueue)
{
if (_refreshQueue.Count == 0)
{
_refreshTimer?.Stop();
_refreshTimer?.Dispose();
_refreshTimer = null;
return;
}
int idx = _refreshQueue.Dequeue();
//Logger.I($"{DateTime.Now:HH:mm:ss.fff} Coherent send {ReadNode[idx].strNodeName}");
Send(ReadNode[idx].strNodeName, idx, CmdType.Read);
}
}
public int Send(string message, int nTargetCmd, CmdType cmdType)
{
lock(writeNodeLock) {
try
{
var connConfig = _Config.ConnConfig as SocketConnConfig;
IPEndPoint ip = new IPEndPoint(IPAddress.Parse(connConfig.Address.IpAddress), connConfig.Address.PortNumber);
byte[] bytes = Encoding.Default.GetBytes(message);
_pendingCommandQueue.Enqueue(new PendingCommand { TargetCmd = nTargetCmd, Type = cmdType });
//_pendingCommandQueue.Enqueue(nTargetCmd);
// udp.Send(bytes, bytes.Length, ip);
nTargetCommand = nTargetCmd;
return udp.Send(bytes, bytes.Length, ip);
}
catch {
return 0;
}
}
}
public int Initialize(LaserArmConfig Config)
{
_Config = Config;
var connConfig = Config.ConnConfig as SocketConnConfig;
udp = new UdpClient(connConfig.Address.PortNumber);
return 0;
}
public int Open(LaserArmConfig Config)
{
if (udp == null) {
Initialize(Config);
}
StartListening();
SetControlModeToRemote();
SetLaserStart(true);
return 0;
}
public new void DisConnect()
{
TimeSpan spanTime;
DateTime startTime = DateTime.Now;
bool bRet = true;
int timeOut = 7;
try {
LaserOff();
SetLaserStart(false);
StopListening();
while (bRet) {
spanTime = DateTime.Now.Subtract(startTime);
if (spanTime.TotalMilliseconds > (timeOut * 1000) ||
nCommStatus == eCommStatus.COMM_STATUS_NONE) {
bRet = false;
}
Thread.Sleep(10);
}
udp.Close();
} catch {
}
IsConnect = false;
}
public bool GetConnected()
{
return GetInitCommunication();
//return IsConnect;
}
public int SetControlModeToRemote()
{
WriteNode[csWriteCOH.CONTROL_MODE].nSettingValue = 2;
string cmd = WriteNode[csWriteCOH.CONTROL_MODE].strNodeName + ("2") + CRLF;
return Send(cmd, csWriteCOH.CONTROL_MODE, CmdType.Write);
}
public int LaserOn()
{
WriteNode[csWriteCOH.LASER_START].nSettingValue = 1;
string cmd = WriteNode[csWriteCOH.LASER_START].strNodeName + ("1") + CRLF;
return Send(cmd, csWriteCOH.LASER_START, CmdType.Write);
}
public int LaserOff()
{
WriteNode[csWriteCOH.LASER_START].nSettingValue = 0;
string cmd = WriteNode[csWriteCOH.LASER_START].strNodeName + ("0") + CRLF;
return Send(cmd, csWriteCOH.LASER_START, CmdType.Write);
}
public int PilotLaserOn()
{
WriteNode[csWriteCOH.PILOT_LASER].nSettingValue = 1;
string cmd = WriteNode[csWriteCOH.PILOT_LASER].strNodeName + ("1") + CRLF;
return Send(cmd, csWriteCOH.PILOT_LASER, CmdType.Write);
}
public int PilotLaserOff()
{
WriteNode[csWriteCOH.PILOT_LASER].nSettingValue = 0;
string cmd = WriteNode[csWriteCOH.PILOT_LASER].strNodeName + ("0") + CRLF;
return Send(cmd, csWriteCOH.PILOT_LASER, CmdType.Write);
}
public eLaserStatus GetLaserStatus()
{
// 추상함수를 추가할지 검토하자. 다른 레이저에도 이런 함수는 있을거같은데
// Thread 로 계속 업데이트를 하고 변수만 꺼내오는듯하다.
return nLaserStatus;
}
public void GetLaserPower(out List<double> lsPower)
{
// ArmLaser 는 Power 종류가 2가지임.
lsPower = new List<double>();
lsPower.Add(ReadNode[csReadCOH.LASER_POWER_CENTER].dRet);
lsPower.Add(ReadNode[csReadCOH.LASER_POWER_RING].dRet);
return;
}
public bool ResetFault()
{
// 원래 class의 return 은 void type 이므로 true 로 return 고정함.
nLaserStatus = eLaserStatus.STATUS_NONE;
return true;
}
public int SetData(int nTarget, int value)
{
if (WriteNode[nTarget].nExist != 1) return 2;
if (nWriteCmd != 0) return 3;
try {
nWriteCmd = WriteNode[nTarget].nKey;
WriteNode[nTarget].nSettingValue = value;
} catch (Exception ex) {
//To Do : AlarmLog 수정할 것
Logger.E("Coherent Laser", string.Format("[Laser] Coherent Laser Communication SetData Fail;{0}", ex.Message));
//UtilUnit.logUnit.SetLog(LogUnit.eLogType.ALARM, "Coherent Laser", string.Format("[Laser] Coherent Laser Communication SetData Fail;{0}", ex.Message), LogUnit.eLogLevel.HIGH);
}
return 1;
}
public string GetData(int nTarget)
{
string strRet = "Not Exist";
int nArrayNo;
try {
if (nTarget >= 0 && nTarget < 100) {
nArrayNo = nTarget;
if (ReadNode[nArrayNo].nExist != 1) return strRet;
switch (ReadNode[nArrayNo].nNodeType) {
case csNodeType.BOOL:
strRet = (ReadNode[nArrayNo].nRet == 1 ? "1" : "0");
break;
case csNodeType.STRING:
strRet = ReadNode[nArrayNo].strRet;
break;
default:
strRet = ReadNode[nArrayNo].strRet;
break;
}
} else {
nArrayNo = nTarget - 100;
if (WriteNode[nArrayNo].nExist != 1) return strRet;
if (nArrayNo == csWriteCOH.SYSTEM_START) strRet = (ReadNode[csReadCOH.MAINS_STATUS].nRet == 1 ? "1" : "0");
else if (nArrayNo == csWriteCOH.LASER_START) strRet = (ReadNode[csReadCOH.EMS_STATUS].nRet == 1 ? "1" : "0");
else if (nArrayNo == csWriteCOH.PILOT_LASER) strRet = (ReadNode[csReadCOH.PILOT_LASER_STATE].nRet == 1 ? "1" : "0");
//else if (nArrayNo == csWriteCOH.CONTROL_MODE) strRet = (ReadNode[csReadCOH.CONTROL_MODE].strRet == "REMOTE" ? "1" : "0");
else strRet = "0";
}
} catch (Exception) {
}
return strRet;
}
public void ResetLaserStatus()
{
nLaserStatus = eLaserStatus.STATUS_NONE;
}
public void GetLaserPower(out double power1, out double power2)
{
power1 = ReadNode[csReadCOH.LASER_POWER_CENTER].dRet;
power2 = ReadNode[csReadCOH.LASER_POWER_RING].dRet;
return;
}
public void GetLaserCoolingStatus(
out double PressureDiff,
out double ReturnPressure,
out double CCB_PressureOut_Ext,
out double CCB_PressureIn_Ext,
out double CCB_TempWaterIn_Ext,
out double CCB_PWM_X30_MV,
out double CCB_TempTank_Set_Tracking,
out double CCB_TempCoolingWater,
out double CCB_PressurePump,
out double CCB_FC_MaxFrequency,
out double CCB_FC_FrequencyPump,
out double TEMP_X80,
out double PRES_X90,
out UInt16 SPEED_PAN)
{
PressureDiff = ReturnPressure = CCB_PressureOut_Ext = CCB_PressureIn_Ext = CCB_TempWaterIn_Ext = CCB_PWM_X30_MV = CCB_TempTank_Set_Tracking = CCB_TempCoolingWater = 0;
CCB_PressurePump = CCB_FC_MaxFrequency = CCB_FC_FrequencyPump = TEMP_X80 = PRES_X90 = 0;
SPEED_PAN = 0;
return;
}
// CoherentReceive 에서 강제로 처리해주는듯. BOOL type 도 string 을 받아서 nRet 에 넣어준다.
// write 는 CoherentReceive 에서 처리 안해주는듯
// nRet==1 이면 true 다.
public bool GetLaserError()
{
return ReadNode[csReadCOH.ERROR_STATUS].nRet == 1 ? true : false;
}
#region Read/Write Node 호출 함수
public bool GetExternalActivation()
{
lock (readNodeLock) {
return false;
}
}
public bool GetLaserIsOn()
{
// Laser On Set bit on인지
lock (readNodeLock) {
return WriteNode[csWriteCOH.LASER_START].nRet == 1 ? true : false;
}
}
public bool GetLaserAssigned()
{
lock (readNodeLock) {
return false;
}
}
public bool GetLaserReady()
{
// Laser On 후 Ready 인지
lock (readNodeLock) {
//return ReadNode[csReadCOH.MAINS_STATUS].nRet == 1 ? true : false;
return ReadNode[csReadCOH.EMS_STATUS].nRet == 1 ? true : false;
}
}
public bool GetProgramActive()
{
return ReadNode[csReadCOH.PILOT_LASER_STATE].nRet == 1 ? true : false;
}
public bool GetProgramCompleted()
{
lock (readNodeLock) {
return GetProgramActived();
}
}
public bool GetProgramCancelled()
{
lock (readNodeLock) {
return false;
}
}
public int GetProgramNo()
{
lock (readNodeLock) {
return -1;
}
}
public int GetProgramLineNo()
{
lock (readNodeLock) {
return -1;
}
}
public int SetExternalActivation(bool bOn)
{
return 0;
}
public int SetLaserReset(bool bOn)
{
if (bOn == true) {
return ResetLaser();
}
return 0;
}
public int SetLaserOn(bool bOn)
{
WriteNode[csWriteCOH.LASER_START].nSettingValue = bOn ? 1 : 0;
string cmd = WriteNode[csWriteCOH.LASER_START].strNodeName + (bOn ? "1" : "0") + CRLF;
return Send(cmd, csWriteCOH.LASER_START, CmdType.Write);
}
public int SetLaserStart(bool bOn)
{
WriteNode[csWriteCOH.SYSTEM_START].nSettingValue = bOn ? 1 : 0;
string cmd = WriteNode[csWriteCOH.SYSTEM_START].strNodeName + (bOn ? "1" : "0") + CRLF;
return Send(cmd, csWriteCOH.SYSTEM_START, CmdType.Write);
}
public int SetRequestLaser(bool bOn)
{
return 0;
}
public int SetProgramStartDynamic(bool bOn)
{
return 0;
}
public int SetProgramStop(bool bOn)
{
return 0;
}
public int SetProgramNo(int no)
{
return 0;
}
// 여기서부터 새로 추가
public bool GetInitCommunication()
{
return ReadNode[csReadCOH.INIT_COMMUNICATION].nRet == 1 ? true : false;
}
public bool GetEmissionStatus()
{
return ReadNode[csReadCOH.EMS_STATUS].nRet == 1 ? true : false;
}
public bool GetWarningStatus()
{
return ReadNode[csReadCOH.WARNING_STATUS].nRet == 1 ? true : false;
}
public bool GetMainsStatus()
{
return ReadNode[csReadCOH.MAINS_STATUS].nRet == 1 ? true : false;
}
// MAINS_STATUS, ERROR_STATUS 는 위에 있음
public bool GetPilotLaserStatus()
{
return ReadNode[csReadCOH.PILOT_LASER_STATE].nRet == 1 ? true : false;
}
public string GetControlMode()
{
return "";// ReadNode[csReadCOH.CONTROL_MODE].strRet;
}
public string GetPowerCenter()
{
return ReadNode[csReadCOH.LASER_POWER_CENTER].strRet;
}
public string GetPowerRing()
{
return ReadNode[csReadCOH.LASER_POWER_RING].strRet;
}
public int SetPowerLevel(double dPowerLevel)
{
int nPowerLevel = (int)(dPowerLevel * 10.0);
return Send(WriteNode[csWriteCOH.POWER_LEVEL].strNodeName + nPowerLevel.ToString(), csWriteCOH.POWER_LEVEL, CmdType.Write);
}
public int SetPowerCenter(int nCenterPower)
{
return Send(WriteNode[csWriteCOH.POWER_CENTER].strNodeName + nCenterPower.ToString(), csWriteCOH.POWER_CENTER, CmdType.Write);
}
public int SetPowerRing(int nRingPower)
{
return Send(WriteNode[csWriteCOH.POWER_RING].strNodeName + nRingPower.ToString(), csWriteCOH.POWER_RING, CmdType.Write);
}
public int ResetLaser()
{
return Send(WriteNode[csWriteCOH.LASER_RESET].strNodeName, csWriteCOH.LASER_RESET, CmdType.Write);
}
public int ClearFault()
{
return Send(WriteNode[csWriteCOH.CLEAR_FAULT].strNodeName, csWriteCOH.CLEAR_FAULT, CmdType.Write);
}
public bool GetProgramInterrupted()
{
//return ReadNode[csReadCOH.PROG_INTERRUPTED].nRet == 1 ? true : false;
return false;
}
public bool GetProgramActived()
{
//return ReadNode[csReadCOH.PROG_ACTIVED].nRet == 1 ? true : false;
return false;
}
public bool GetEStop()
{
//return ReadNode[csReadCOH.EMO_STATUS].nRet == 1 ? true : false;
return false;
}
#region Set 명령 나간 bit 를 모니터링
public bool GetStartLaserSetBitStatus()
{
// Laser Start 명령
return false;// ReadNode[csReadCOH.CONTROL_MODE].bRet ? true: false;
//return WriteNode[csWriteCOH.SYSTEM_START].nSettingValue == 1 ? true : false;
}
public bool GetLaserStartSetBitStatus()
{
// Laser On 명령. Laser Emission Ready 를 위한 bit
return WriteNode[csWriteCOH.LASER_START].nSettingValue == 1 ? true : false;
}
public bool GetPilotLaserSetBitStatus()
{
// Pilot Laser On 명령.
return ReadNode[csReadCOH.PILOT_LASER_STATE].nRet == 1 ? true : false;
}
public bool GetLaserResetSetBitStatus()
{
// Laser Reset 명령.
return WriteNode[csWriteCOH.LASER_RESET].nSettingValue == 1 ? true : false;
}
public bool GetControlModeSetStatus()
{
// Control mode Local(false) Remote(true)
return WriteNode[csWriteCOH.CONTROL_MODE].nSettingValue == 1 ? true : false;
}
#endregion
#endregion
}
}