// UNCLASSIFIED /*------------------------------------------------------------------------- RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON COMPANY. THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT. UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. -------------------------------------------------------------------------*/ using Raytheon.Instruments; using Raytheon.Common; using System; using System.Runtime.InteropServices; using System.Threading; namespace BitMeasurementManagerLib { /// /// An interface to sending/receiving data over TCP sockets /// internal class BitSimCommDeviceNode : ICommDevice, IDisposable { #region PrivateClassMembers private ICommDevice _commDevice; private BitMessageIDs _messageIds; private IWorkerInterface _socketReadWorker; private Thread _socketReadThread; private readonly string _name; private SelfTestResult _selfTestResult; private State _state; #endregion #region PrivateFunctions /// /// The finalizer. Necessary for quitting the read thread /// ~BitSimCommDeviceNode() { Dispose(false); } /// /// Quit the threads associated with the node /// /// protected virtual void Dispose(bool disposing) { if (disposing) { State initialState = _state; // close the socket and threads try { if (initialState == State.Ready) { Shutdown(); _commDevice.Shutdown(); } } catch (Exception err) { try { ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace); } catch (Exception) { //Do not rethrow. Exception from error logger that has already been garbage collected } } // dispose of the resources try { if (initialState == State.Ready) { _socketReadWorker.Dispose(); _state = State.Uninitialized; } } catch (Exception err) { try { ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace); } catch (Exception) { //Do not rethrow. Exception from error logger that has already been garbage collected } } } } #endregion #region PublicFuctions /// /// /// /// The name of this instance /// /// /// /// public BitSimCommDeviceNode(string name, ICommDevice commDevice, BitMessageIDs messageIds, MsgDevice msgHandler, uint commReadWorkerBufferSize = 100000, uint readWorkerRestTimeInMs = 10) { _name = name; _commDevice = commDevice; _messageIds = messageIds; _socketReadWorker = new CommReadWorker(this, msgHandler, commReadWorkerBufferSize, readWorkerRestTimeInMs); _socketReadThread = new Thread(_socketReadWorker.DoWork); // start the read thread _socketReadThread.Start(); _selfTestResult = SelfTestResult.Unknown; _state = State.Uninitialized; } public void Open() { } /// /// /// /// public bool ClearErrors() { return true; } /// /// /// public bool DisplayEnabled { get { return false; } set { throw new NotImplementedException(); } } /// /// /// public string DetailedStatus { get { return "This is a BIT Comm Sim Device Node " + _name; } } public void Close() { Dispose(); } /// /// Close the device /// /*public void Close() { const int THREAD_QUIT_TIMEOUT_MS = 3000; // tell the thread to quit _socketReadWorker.QuitWork(); // close the socket which the thread might be blocked on _commDevice.Close(); if (_socketReadThread.IsAlive) { bool didThreadQuit = _socketReadThread.Join(THREAD_QUIT_TIMEOUT_MS); if (didThreadQuit == false) { ErrorLogger.Instance().Write("BitSimCommDeviceNode::Close() - Logging Thread did not quit as expected, aborting it"); _socketReadThread.Abort(); } else { ErrorLogger.Instance().Write("BitSimCommDeviceNode::Close() - Logging Thread quit successfully after join", ErrorLogger.LogLevel.INFO); } } else { ErrorLogger.Instance().Write("BitSimCommDeviceNode::Close() - Logging Thread quit successfully", ErrorLogger.LogLevel.INFO); } }*/ /// /// /// public void Dispose() { try { Dispose(true); GC.SuppressFinalize(this); } catch (Exception err) { try { ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace); } catch (Exception) { //Do not rethrow. Exception from error logger that has already been garbage collected } } } /// /// /// public bool FrontPanelEnabled { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } /// /// /// public InstrumentMetadata Info { get { throw new NotImplementedException(); } } /// /// /// public void Initialize() { _commDevice.Initialize(); _state = State.Ready; } /// /// /// public string Name { get { return _name; } } /// /// /// /// public SelfTestResult PerformSelfTest() { return _commDevice.SelfTestResult; } /// /// Read data from the socket /// /// The data that was read /// the number of bytes read public uint Read(ref byte[] dataRead) { return 0; } /// /// public void Reset() { Close(); Initialize(); } /// /// /// /// public void SetReadTimeout(uint readTimeout) { } /// /// /// public SelfTestResult SelfTestResult { get { return _selfTestResult; } } /// /// /// public State Status { get { return _state; } } /// /// /// public void Shutdown() { const int THREAD_QUIT_TIMEOUT_MS = 3000; if (_state == State.Ready) { // tell the thread to quit _socketReadWorker.QuitWork(); // close the socket which the thread might be blocked on _commDevice.Shutdown(); if (_socketReadThread.IsAlive) { bool didThreadQuit = _socketReadThread.Join(THREAD_QUIT_TIMEOUT_MS); if (didThreadQuit == false) { ErrorLogger.Instance().Write("BitSimCommDeviceNode::Close() - Logging Thread did not quit as expected, aborting it"); _socketReadThread.Abort(); } else { ErrorLogger.Instance().Write("BitSimCommDeviceNode::Close() - Logging Thread quit successfully after join", ErrorLogger.LogLevel.INFO); } } else { ErrorLogger.Instance().Write("BitSimCommDeviceNode::Close() - Logging Thread quit successfully", ErrorLogger.LogLevel.INFO); } } _state = State.Uninitialized; } /// /// Send data on the socket /// /// The data to send /// The number of bytes to write from the dataToSend buffer /// The number of bytes sent public uint Write(byte[] dataToSend, uint numBytesToWrite) { // determine the id and get create the rsp message IntPtr pDataPtr = Marshal.AllocHGlobal(dataToSend.Length); Marshal.Copy(dataToSend, 0, pDataPtr, dataToSend.Length); uint commandId = BitConfigurableMessageHeader.GetMessageId(pDataPtr, (uint)dataToSend.Length); Marshal.FreeHGlobal(pDataPtr); bool isThereAResponse = _messageIds.IsThereAResponseMessage(commandId); // if there is a rsp msg, create a dummy msg if (isThereAResponse == true) { uint rspId = _messageIds.GetResponseId(commandId); BitConfigurableMessage rspMessage = BitConfigurableMessageFactory.Instance().RetreiveMessage(rspId); BitMsgRxBuffer.Instance().AddMsg(rspMessage); //uint msgLen = rspMessage.GetEntireMsgLength(); //byte[] simData = new byte[msgLen]; //_msgHandler.AddData(); } else { } return (uint)dataToSend.Length; } #endregion } }