/// <summary> /// Connect to TCP/IP Port /// </summary> /// <param name="port"></param> /// <param name="server"></param> /// <param name="monitorData"></pram> public void Connect(int port, string server, StatusMonitorData monitorData) { ModelerStepState ModelerCurrentStepState = ModelerStepState.NONE; string job = monitorData.Job; // Wait about a minute for the Modeler to start execution Thread.Sleep(StaticClass.TCP_IP_STARTUP_WAIT); StaticClass.Log(string.Format("\nStarting TCP/IP Scan for Job {0} on Port {1} at {2:HH:mm:ss.fff}", job, port, DateTime.Now)); // Log starting TCP/IP monitoring entry StaticClass.StatusDataEntry(job, JobStatus.MONITORING_TCPIP, JobType.TIME_START); try { // Create a TcpClient TcpClient client = new TcpClient(server, port); if (client == null) { StaticClass.Logger.LogError("TcpIp Connectinon client failed to instantiate"); } // Get a client stream for reading and writing NetworkStream stream = client.GetStream(); if (stream == null) { StaticClass.Logger.LogError("TcpIp Connection stream handle was not gotten from client"); StaticClass.JobShutdownFlag[job] = true; return; } // Show connection and start sending messages StaticClass.Log(string.Format("Connected to Modeler TCP/IP for Job {0} on Port {1} at {2:HH:mm:ss.fff}", job, port, DateTime.Now)); bool jobComplete = false; int numRequestSent = 0; do { // Loop shutdown/Pause check if (StaticClass.ShutDownPauseCheck("TCP/IP Connect") == true) { // Make sure to close TCP/IP socket stream.Close(); client.Close(); StaticClass.Log(string.Format("Closed TCP/IP Socket for Job {0} on Port {1} at {2:HH:mm:ss.fff}", job, port, DateTime.Now)); // Set the shutdown flag to signal the RunJob thread StaticClass.JobShutdownFlag[job] = true; return; } // Check if the stream is writable, if not, exit if (stream.CanWrite) { if (StaticClass.ShutDownPauseCheck(job) == false) { try { // Translate the passed message into ASCII and send it as a byte array byte[] sendData = Encoding.ASCII.GetBytes(StatusMessage); stream.Write(sendData, 0, sendData.Length); numRequestSent++; } catch (IOException e) { // Make sure to close TCP/IP socket stream.Close(); client.Close(); StaticClass.Log(string.Format("Closed TCP/IP Socket for Job {0} on Port {1} because of Exception {2} at {3:HH:mm:ss.fff}", job, port, e, DateTime.Now)); // Signal job complete if exception happend in Step 5 or 6 if ((ModelerCurrentStepState == ModelerStepState.STEP_5) || (ModelerCurrentStepState == ModelerStepState.STEP_6)) { // Set the TCP/IP Scan complete flag to signal the RunJob thread StaticClass.TcpIpScanComplete[job] = true; } else { // Set the Shutdown flag to signal the RunJob thread StaticClass.JobShutdownFlag[job] = true; } return; } StaticClass.Log(string.Format("\nSending {0} msg to Modeler for Job {1} on Port {2} at {3:HH:mm:ss.fff}", StatusMessage, job, port, DateTime.Now)); } } else { // Make sure to close TCP/IP socket stream.Close(); client.Close(); StaticClass.Log(string.Format("\nTCP/IP stream closed for Modeler Job {0} on Port {1} at {2:HH:mm:ss.fff}", job, port, DateTime.Now)); // Set the Shutdown flag to signal the RunJob thread StaticClass.JobShutdownFlag[job] = true; return; } // Check if TCP/IP stream is readable and data is available int adjustableSleepTime = StaticClass.STARTING_TCP_IP_WAIT; int tcpIpRetryCount = 0; bool messageReceived = false; do { if (stream.CanRead && stream.DataAvailable) { // Buffers to store the response byte[] recvData = new byte[256]; string responseData = string.Empty; int bytes = stream.Read(recvData, 0, recvData.Length); responseData = Encoding.ASCII.GetString(recvData, 0, bytes); StaticClass.Log(string.Format("Received: {0} from Job {1} on Port {2} at {3:HH:mm:ss.fff}", responseData, job, port, DateTime.Now)); // Readjust sleep time according to Step number switch (responseData) { case "Step 1 in process.": ModelerCurrentStepState = ModelerStepState.STEP_1; if (numRequestSent < StaticClass.NUM_REQUESTS_TILL_TCPIP_SLOWDOWN) { adjustableSleepTime = 15000; } else { adjustableSleepTime = 60000; } break; case "Step 2 in process.": ModelerCurrentStepState = ModelerStepState.STEP_2; adjustableSleepTime = 10000; break; case "Step 3 in process.": ModelerCurrentStepState = ModelerStepState.STEP_3; adjustableSleepTime = 7500; break; case "Step 4 in process.": ModelerCurrentStepState = ModelerStepState.STEP_4; adjustableSleepTime = 5000; break; case "Step 5 in process.": ModelerCurrentStepState = ModelerStepState.STEP_5; adjustableSleepTime = 2500; break; case "Step 6 in process.": ModelerCurrentStepState = ModelerStepState.STEP_6; adjustableSleepTime = 250; break; case "Whole process done, socket closed.": // Make sure to close TCP/IP socket stream.Close(); client.Close(); StaticClass.Log(string.Format("TCP/IP for Job {0} on Port {1} received Modeler process done at {2:HH:mm:ss.fff}", job, port, DateTime.Now)); ModelerCurrentStepState = ModelerStepState.STEP_COMPLETE; StaticClass.Log(string.Format("Closed TCP/IP Socket for Job {0} on Port {1} at {2:HH:mm:ss.fff}", job, port, DateTime.Now)); // Set the TCP/IP Scan complete flag to signal the RunJob thread StaticClass.TcpIpScanComplete[job] = true; return; default: StaticClass.Logger.LogWarning("Received Weird Response: {0} from Job {1} on Port {2} at {3:HH:mm:ss.fff}", responseData, job, port, DateTime.Now); break; } // Backup check of the process complete string, even if it is concatenated with another string if (responseData.Contains("Whole process done, socket closed.")) { // Make sure to close TCP/IP socket stream.Close(); client.Close(); StaticClass.Log(string.Format("TCP/IP for Job {0} on Port {1} received Modeler process complete at {2:HH:mm:ss.fff}", job, port, DateTime.Now)); ModelerCurrentStepState = ModelerStepState.STEP_COMPLETE; StaticClass.Log(string.Format("Closed TCP/IP Socket for Job {0} on Port {1} at {2:HH:mm:ss.fff}", job, port, DateTime.Now)); // Set the TCP/IP Scan complete flag to signal the RunJob thread StaticClass.TcpIpScanComplete[job] = true; return; } // Check for Job timeout if ((DateTime.Now - monitorData.StartTime).TotalSeconds > StaticClass.MaxJobTimeLimitSeconds) { StaticClass.Log(string.Format("Job Execution Timeout for Job {0} in state {1} at {2:HH:mm:ss.fff}", job, ModelerCurrentStepState, DateTime.Now)); // Make sure to close TCP/IP socket stream.Close(); client.Close(); StaticClass.Log(string.Format("Closed TCP/IP Socket for Job {0} on Port {1} at {2:HH:mm:ss.fff}", job, port, DateTime.Now)); // Create job Timeout status StaticClass.StatusDataEntry(job, JobStatus.JOB_TIMEOUT, JobType.TIME_START); // Set the Shutdown flag to signal the RunJob thread StaticClass.JobShutdownFlag[job] = true; return; } // Check for shutdown or pause if (StaticClass.ShutDownPauseCheck("TCP/IP Receive") == true) { // Make sure to close TCP/IP socket stream.Close(); client.Close(); // Set the Shutdown flag to signal the RunJob thread StaticClass.JobShutdownFlag[job] = true; return; } // Set the messge received flag to exit receive loop messageReceived = true; } else { // Wait 250 msec between 480 Data Available checks (2 min) CanRead is set for session Thread.Sleep(StaticClass.READ_AVAILABLE_RETRY_DELAY); tcpIpRetryCount++; } }while ((tcpIpRetryCount < StaticClass.NUM_TCP_IP_RETRIES) && (messageReceived == false)); // Wait for an adjustable time between TCP/IP status requests Thread.Sleep(adjustableSleepTime); }while (jobComplete == false); // Close everything stream.Close(); client.Close(); StaticClass.Log(string.Format("Closed TCP/IP Socket for Job {0} on Port {1} in state {2} at {3:HH:mm:ss.fff}", job, port, ModelerCurrentStepState, DateTime.Now)); } catch (SocketException e) { StaticClass.Logger.LogError(string.Format("SocketException {0} for Job {1} on Port {2} in state {3} at {4:HH:mm:ss.fff}", e, job, port, ModelerCurrentStepState, DateTime.Now)); } }
/// <summary> /// Listen for Incoming TCP/IP requests /// </summary> private static void ListenForIncommingRequests() { string testDirectory = @"C:\SSMCharacterizationHandler\test"; string testPassDirectory = testDirectory + @"\" + Job + " - Pass"; string testFailDirectory = testDirectory + @"\" + Job + " - Fail"; string testNoneDirectory = testDirectory + @"\" + Job + " - None"; string testStartDirectory = testDirectory + @"\" + Job + " - Start"; Console.WriteLine("\n780200XXC00 Simulator Starting..."); // Copy the starting data.xml file to the job Processing Buffer directory Thread.Sleep(5000); FileHandling.CopyFile(testStartDirectory + @"\" + "Data.xml", ProcessingBufferDirectory + @"\" + "Data.xml"); // TcpListener server = new TcpListener(port); TcpListener tcpListener = new TcpListener(IPAddress.Parse(Server), Port); // Start listening for client requests tcpListener.Start(); // Buffer for reading data byte[] bytes = new byte[256]; string clientMessage; // Enter the TCP/IP listening loop Console.Write("\nWaiting for a TCP/IP Connection for job {0} on Port {1}...", Job, Port); // Perform a blocking call to accept requests TcpClient client = tcpListener.AcceptTcpClient(); Console.WriteLine("Connected!"); // Get a stream object for reading and writing NetworkStream stream = client.GetStream(); // Loop to receive all the data sent by the client bool simulationComplete = false; do { try { int i = 0; ModelerStepState modelerStepState = ModelerStepState.STEP_1; while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) { // Translate data bytes to a ASCII string clientMessage = Encoding.ASCII.GetString(bytes, 0, i); Console.WriteLine("\nReceived: {0}", clientMessage); if (clientMessage == "status") { Thread.Sleep(1000); string responseMsg = string.Empty; switch (modelerStepState) { case ModelerStepState.STEP_1: modelerStepState = ModelerStepState.STEP_1; break; case ModelerStepState.STEP_2: FileHandling.CopyFile(testPassDirectory + @"\" + Job + "_step1.mat", ProcessingBufferDirectory + @"\" + Job + "_step1.mat"); modelerStepState = ModelerStepState.STEP_2; break; case ModelerStepState.STEP_3: FileHandling.CopyFile(testPassDirectory + @"\" + Job + "_step1.mat", ProcessingBufferDirectory + @"\" + Job + "_step2.mat"); modelerStepState = ModelerStepState.STEP_3; break; case ModelerStepState.STEP_4: FileHandling.CopyFile(testPassDirectory + @"\" + Job + "_step1.mat", ProcessingBufferDirectory + @"\" + Job + "_step3.mat"); modelerStepState = ModelerStepState.STEP_4; break; case ModelerStepState.STEP_5: FileHandling.CopyFile(testPassDirectory + @"\" + "EEPROM_variables_" + Job + ".mat", ProcessingBufferDirectory + @"\" + "EEPROM_variables_" + Job + ".mat"); modelerStepState = ModelerStepState.STEP_5; break; case ModelerStepState.STEP_6: FileHandling.CopyFile(testPassDirectory + @"\" + "CAP.tab", ProcessingBufferDirectory + @"\" + "CAP.tab"); FileHandling.CopyFile(testPassDirectory + @"\" + "TUNE.tab", ProcessingBufferDirectory + @"\" + "TUNE.tab"); modelerStepState = ModelerStepState.STEP_6; break; case ModelerStepState.STEP_COMPLETE: FileHandling.CopyFile(testNoneDirectory + @"\" + "Data.xml", ProcessingBufferDirectory + @"\" + "Data.xml"); modelerStepState = ModelerStepState.STEP_COMPLETE; Thread.Sleep(2000); break; } // Create the step response message if (modelerStepState != ModelerStepState.STEP_COMPLETE) { responseMsg = string.Format("Step {0} in process.", (int)modelerStepState); // Send the message to the connected TcpServer byte[] responseData = Encoding.ASCII.GetBytes(responseMsg); stream.Write(responseData, 0, responseData.Length); Console.WriteLine(string.Format("Sent: {0}", responseMsg)); // Increment Modeler step until complete modelerStepState++; } else { // Send the weird message for 1 out of 4 times Random weirdRand = new Random(DateTime.Now.Millisecond); int weirdMessage = weirdRand.Next(0, 6); if (weirdMessage != 1) { responseMsg = "Whole process done, socket closed."; } else { // Sometimes the modeler gives this combined message for the final message responseMsg = "Step 1 in process. Whole process done, socket closed."; } // Send the message to the connected TcpServer byte[] responseData = Encoding.ASCII.GetBytes(responseMsg); stream.Write(responseData, 0, responseData.Length); Console.WriteLine(string.Format("Sent: {0}", responseMsg)); if (modelerStepState == ModelerStepState.STEP_COMPLETE) { // Simulate real opertion where Modeler delays writing the data.xml file with the OverallResult field after TCP/IP is done Random sendLateOrNotRand = new Random(DateTime.Now.Millisecond); Random setRand = new Random(DateTime.Now.Millisecond); int sendMessageLateOrNot = sendLateOrNotRand.Next(0, 9); int randomWait = setRand.Next((sendMessageLateOrNot != 1) ? 2000 : 50000, (sendMessageLateOrNot != 1) ? 5000 : 60000); Console.WriteLine(string.Format("Waiting to send complete data.xml for {0} msec", randomWait)); Thread.Sleep(randomWait); // Copy over the data.xml with Pass 1 out of 4 times, or Fail for testing Random passFailRand = new Random(DateTime.Now.Millisecond); int passFail = passFailRand.Next(0, 6); if (passFail != 1) { FileHandling.CopyFile(testPassDirectory + @"\" + "Data.xml", ProcessingBufferDirectory + @"\" + "Data.xml"); } else { FileHandling.CopyFile(testFailDirectory + @"\" + "Data.xml", ProcessingBufferDirectory + @"\" + "Data.xml"); } simulationComplete = true; } } } } } catch (SocketException e) { Console.WriteLine("SocketException: {0}", e); } finally { // Stop listening for new clients tcpListener.Stop(); } }while (simulationComplete == false); // Shutdown and end connection client.Close(); ExitFlag = true; }