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 _pendingCommandQueue = new ConcurrentQueue(); private StringBuilder _messageBuffer = new StringBuilder(); private Queue _refreshQueue = new Queue(); 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 ErrorMessage = new List(); public List WarningMessage = new List(); public List Humidity = new List(); 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 ParseBracketMessages(string raw) { var result = new List(); 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 GetErrorMessages() { return ErrorMessage; } public string GetWarningMessage() { string Temp = WarningMessage[0]; return ReadNode[csReadCOH.WARNING_MESSAGE].strRet; } public List 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 lsPower) { // ArmLaser 는 Power 종류가 2가지임. lsPower = new List(); 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 } }