Big changes

This commit is contained in:
Duc
2025-03-13 12:04:22 -07:00
parent c689fcb7f9
commit ffa9905494
748 changed files with 199255 additions and 3743 deletions

View File

@@ -0,0 +1,39 @@
// 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.
-------------------------------------------------------------------------*/
namespace BitMeasurementManagerLib
{
/// <summary>
/// A spot to hold application constants
/// </summary>
internal static class BitInterfaceManagerConstants
{
// data types
internal static readonly string FLOAT_DATA_TYPE = "FLOAT";
internal static readonly string UINT_DATA_TYPE = "UINT";
internal static readonly string UINT_HEX_DATA_TYPE = "UINT_HEX";
internal static readonly string USHORT_HEX_DATA_TYPE = "USHORT_HEX";
internal static readonly string USHORT_DATA_TYPE = "USHORT";
internal static readonly string BYTE_HEX_DATA_TYPE = "BYTE_HEX";
internal static readonly string BYTE_ARRAY_HEX_DATA_TYPE = "BYTE_ARRAY_HEX";
internal static readonly string DOUBLE_DATA_TYPE = "DOUBLE";
internal static readonly string ULONG_DATA_TYPE = "ULONG";
internal static readonly string ULONG_HEX_DATA_TYPE = "ULONG_HEX";
internal static readonly string BITS_DATA_TYPE = "BITS";
}
}

View File

@@ -0,0 +1,97 @@
// 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.Common;
using System;
namespace BitMeasurementManagerLib
{
/// <summary>
/// Singleton for holding onto message objects
/// </summary>
internal class BitMsgEndianControl
{
#region PublicMembers
public struct HeaderDef
{
public int msgIdByteLocation;
public int msgIdDataLen;
public int secondaryMsgIdByteLocation;
public int secondaryMsgIdDataLen;
public uint secondaryMsgIdExpectedValue;
};
#endregion
#region PrivateClassMembers
// class variables
private static BitMsgEndianControl _msgEndianControlInstance;
private bool _shallWeSwap;
private HeaderDef _headerDef;
#endregion
#region PrivateFuctions
/// <summary>
/// The constructor
/// </summary>
private BitMsgEndianControl(bool shallWeSwap, IniFile defFile)
{
_shallWeSwap = shallWeSwap;
_headerDef.msgIdByteLocation = Convert.ToInt32(defFile.ReadValue("MSG_HEADER_DEF", "MSG_ID_LOCATION"));
_headerDef.msgIdDataLen = Convert.ToInt32(defFile.ReadValue("MSG_HEADER_DEF", "MSG_ID_DATA_LEN"));
_headerDef.secondaryMsgIdByteLocation = Convert.ToInt32(defFile.ReadValue("MSG_HEADER_DEF", "SECONDARY_MSG_ID_LOCATION"));
_headerDef.secondaryMsgIdDataLen = Convert.ToInt32(defFile.ReadValue("MSG_HEADER_DEF", "SECONDARY_MSG_ID_DATA_LEN"));
_headerDef.secondaryMsgIdExpectedValue = Convert.ToUInt32(defFile.ReadValue("MSG_HEADER_DEF", "SECONDARY_MSG_ID_EXPECTED_VALUE"), 16);
}
#endregion
#region PublicFuctions
/// <summary>
/// The way to get access to this singleton
/// <param name="shallWeSwap"></param>
/// <returns>the instance to this class</returns>
internal static BitMsgEndianControl Instance(bool shallWeSwap = true, IniFile defFile = null)
{
if (_msgEndianControlInstance == null)
{
_msgEndianControlInstance = new BitMsgEndianControl(shallWeSwap, defFile);
}
return _msgEndianControlInstance;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
internal HeaderDef GetHeaderDef()
{
return _headerDef;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
internal bool ShallWeSwap()
{
return _shallWeSwap;
}
#endregion
}
}

View File

@@ -0,0 +1,248 @@
// 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 System;
using System.Threading;
using System.Collections.Generic;
using Raytheon.Common;
namespace BitMeasurementManagerLib
{
/// <summary>
/// Singleton for holding onto message objects
/// </summary>
internal class BitMsgRxBuffer
{
#region PrivateClassMembers
// class variables
private static BitMsgRxBuffer _msgBufferInstance;
private static object _syncObj = new Object();
private BitMessageIDs _messageIds;
private Dictionary<uint, List<BitConfigurableMessage>> _msgList;
private Dictionary<uint, AutoResetEvent> _receivedMsgEvents;
#endregion
#region PrivateFuctions
/// <summary>
/// The constructor
/// </summary>
private BitMsgRxBuffer(BitMessageIDs messageIds)
{
_messageIds = messageIds;
_msgList = new Dictionary<uint, List<BitConfigurableMessage>>();
// create an event for each msg.
_receivedMsgEvents = new Dictionary<uint, AutoResetEvent>();
List<uint> msgIds = _messageIds.GetAllIds();
foreach (uint id in msgIds)
{
_receivedMsgEvents[id] = new AutoResetEvent(false);
}
}
#endregion
#region PublicFuctions
/// <summary>
/// The way to get access to this singleton
/// </summary>
/// <returns>the instance to this class</returns>
internal static BitMsgRxBuffer Instance(BitMessageIDs messageIds = null)
{
if (_msgBufferInstance == null)
{
_msgBufferInstance = new BitMsgRxBuffer(messageIds);
}
return _msgBufferInstance;
}
/// <summary>
/// Add a message to this buffer
/// </summary>
/// <param name="msg">The message to add</param>
/// <param name="shouldWeDeleteOthers">flag for if the other messages of this type should be deleted from the buffer</param>
internal void AddMsg(BitConfigurableMessage msg, bool shouldWeDeleteOthers = true)
{
lock (_syncObj)
{
uint msgId = msg.GetMessageId();
if (shouldWeDeleteOthers == true)
{
ErrorLogger.Instance().Write("BitMsgRxBuffer::AddMsg() - clearing list for " + msgId.ToString(), ErrorLogger.LogLevel.INFO);
ClearList(msgId);
}
if (_msgList.ContainsKey(msgId) == false)
{
ErrorLogger.Instance().Write("BitMsgRxBuffer::AddMsg() - creating new list for " + msgId.ToString(), ErrorLogger.LogLevel.INFO);
_msgList[msgId] = new List<BitConfigurableMessage>();
}
ErrorLogger.Instance().Write("BitMsgRxBuffer::AddMsg() - Adding " + msgId.ToString() + " to the list", ErrorLogger.LogLevel.INFO);
_msgList[msgId].Add(msg);
_receivedMsgEvents[msgId].Set();
}
}
/// <summary>
/// Remove all messages from the buffer
/// </summary>
internal void ClearAllMsgs()
{
lock (_syncObj)
{
foreach (uint id in _msgList.Keys)
{
ClearList(id);
}
}
}
/// <summary>
/// Remove all messages of the command type from the buffer
/// </summary>
/// <param name="id">The message id to remove</param>
internal void ClearList(uint id)
{
lock (_syncObj)
{
if (_msgList.ContainsKey(id) == true)
{
_msgList[id].Clear();
_msgList.Remove(id);
_receivedMsgEvents[id].Reset();
}
}
}
/// <summary>
/// Gets the oldest message in the buffer
/// </summary>
/// <param name="id">The id of the message to get</param>
/// <returns>The oldest message in the buffer</returns>
internal BitConfigurableMessage GetOldestMessage(uint id)
{
lock (_syncObj)
{
if (_msgList.ContainsKey(id))
{
List<BitConfigurableMessage> list = _msgList[id];
if (list.Count == 0)
{
throw new Exception("BitMsgRxBuffer::GetOldestMessage() - there are no messges in the queue for id: " + id.ToString());
}
BitConfigurableMessage oldestMsg = list[0];
list.RemoveAt(0);
return oldestMsg;
}
else
{
throw new Exception("BitMsgRxBuffer::GetOldestMessage() - no message exists with id: " + id.ToString());
}
}
}
/// <summary>
/// Gets the most recent message from the buffer
/// </summary>
/// <param name="id">The id of the message to get</param>
/// <param name="shouldWeDeleteOthers">flag controlling if the other messages of this type should be deleted</param>
/// <returns>The message</returns>
internal BitConfigurableMessage GetNewestMessage(uint id, bool shouldWeDeleteOthers = true)
{
lock (_syncObj)
{
if (_msgList.ContainsKey(id))
{
List<BitConfigurableMessage> list = _msgList[id];
BitConfigurableMessage newestMsg = list[list.Count - 1];
list.RemoveAt(list.Count - 1);
if (shouldWeDeleteOthers == true)
{
ClearList(id);
}
return newestMsg;
}
else
{
throw new Exception("BitMsgRxBuffer::GetNewestMessage() - no message exists with id: " + id.ToString("X"));
}
}
}
/// <summary>
/// Get the number of messages of this type in the buffer
/// </summary>
/// <param name="id">The id of the message to get</param>
/// <returns>the number of messages of this type in the buffer</returns>
internal int GetNumMsgsInQueue(uint id)
{
lock (_syncObj)
{
if (_msgList.ContainsKey(id) == true)
{
return _msgList[id].Count;
}
else
{
return 0;
}
}
}
/// <summary>
///
/// </summary>
internal void ResetReceiveEvent(uint id)
{
lock (_syncObj)
{
_receivedMsgEvents[id].Reset();
}
}
/// <summary>
/// Wait for a message to get added to the buffer
/// </summary>
/// <param name="id">The message id to wait for</param>
/// <param name="timeoutMs">The amount of time in ms to wait</param>
/// <returns>true if the message arrived, false if it did not</returns>
internal bool WaitForRspMsg(uint id, uint timeoutMs)
{
return _receivedMsgEvents[id].WaitOne((int)timeoutMs);
}
#endregion
}
}

View File

@@ -0,0 +1,416 @@
// 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
{
/// <summary>
/// An interface to sending/receiving data over TCP sockets
/// </summary>
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
/// <summary>
/// The finalizer. Necessary for quitting the read thread
/// </summary>
~BitSimCommDeviceNode()
{
Dispose(false);
}
/// <summary>
/// Quit the threads associated with the node
/// </summary>
/// <param name="disposing"></param>
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
/// <summary>
///
/// </summary>
/// <param name="name">The name of this instance</param>
/// <param name="messageIds"></param>
/// <param name="msgHandler"></param>
/// <param name="commReadWorkerBufferSize"></param>
/// <param name="readWorkerRestTimeInMs"></param>
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()
{
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
return true;
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
return false;
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a BIT Comm Sim Device Node " + _name;
}
}
public void Close()
{
Dispose();
}
/// <summary>
/// Close the device
/// </summary>
/*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);
}
}*/
/// <summary>
///
/// </summary>
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
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Initialize()
{
_commDevice.Initialize();
_state = State.Ready;
}
/// <summary>
///
/// </summary>
public string Name
{
get
{
return _name;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
return _commDevice.SelfTestResult;
}
/// <summary>
/// Read data from the socket
/// </summary>
/// <param name="dataRead">The data that was read</param>
/// <returns>the number of bytes read</returns>
public uint Read(ref byte[] dataRead)
{
return 0;
}
/// <summary>
/// </summary>
public void Reset()
{
Close();
Initialize();
}
/// <summary>
///
/// </summary>
/// <param name="readTimeout"></param>
public void SetReadTimeout(uint readTimeout)
{
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
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;
}
/// <summary>
/// Send data on the socket
/// </summary>
/// <param name="dataToSend">The data to send</param>
/// <param name="numBytesToWrite">The number of bytes to write from the dataToSend buffer</param>
/// <returns>The number of bytes sent</returns>
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
}
}

View File

@@ -0,0 +1,371 @@
// 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.Common;
using System;
using System.Threading;
namespace Raytheon.Instruments
{
/// <summary>
/// An interface to sending/receiving data over comm devices
/// </summary>
internal class CommDeviceNode : ICommDevice, IDisposable
{
#region PrivateClassMembers
private ICommDevice _commDevice;
private IWorkerInterface _socketReadWorker;
private Thread _socketReadThread;
private readonly string _name;
private SelfTestResult _selfTestResult;
private State _state;
private uint _commReadWorkerBufferSize;
private uint _readWorkerRestTimeInMs;
private MsgDevice _msgHandler;
#endregion
#region PrivateFuctions
/// <summary>
/// The finalizer. Necessary for quitting the read thread
/// </summary>
~CommDeviceNode()
{
Dispose(false);
}
/// <summary>
/// Quit the threads associated with the node
/// </summary>
/// <param name="disposing"></param>
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
/// <summary>
/// The constructor
/// </summary>
/// <param name="name">The name of this instance</param>
/// <param name="commDevice">The communication device</param>
/// <param name="msgHandler">The message handler for this interface</param>
/// <param name="commReadWorkerBufferSize">The number of bytes for the buffer internal to this class. Each individual read will read upto this buffer size (or until the timeout happens)</param>
/// <param name="readWorkerRestTimeInMs">Number of ms to reset between read calls on the comm interface</param>
public CommDeviceNode(string name, ICommDevice commDevice, MsgDevice msgHandler, uint commReadWorkerBufferSize = 100000, uint readWorkerRestTimeInMs = 10)
{
_name = name;
_commDevice = commDevice;
_commReadWorkerBufferSize = commReadWorkerBufferSize;
_readWorkerRestTimeInMs = readWorkerRestTimeInMs;
_msgHandler = msgHandler;
Open();
}
/// <summary>
/// Starts communication thread
/// </summary>
public void Open()
{
_socketReadWorker = new CommReadWorker(this, _msgHandler, _commReadWorkerBufferSize, _readWorkerRestTimeInMs);
_socketReadThread = new Thread(_socketReadWorker.DoWork);
// start the read thread
_socketReadThread.Start();
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
}
/// <summary>
/// there is no error msg repository
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
return false;
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
return false;
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a Comm Sim Device Node " + _name;
}
}
/// <summary>
///
/// </summary>
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
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
return false;
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Initialize()
{
_commDevice.Initialize();
_state = State.Ready;
}
/// <summary>
///
/// </summary>
public string Name
{
get
{
return _name;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
throw new NotImplementedException();
}
/// <summary>
/// Read data from the socket
/// </summary>
/// <param name="dataRead">The data that was read</param>
/// <returns>the number of bytes read</returns>
public uint Read(ref byte[] dataRead)
{
return _commDevice.Read(ref dataRead);
}
/// <summary>
/// Resets communications
/// </summary>
public void Reset()
{
Close();
Open();
}
/// <summary>
///
/// </summary>
/// <param name="readTimeout"></param>
public void SetReadTimeout(uint readTimeout)
{
_commDevice.SetReadTimeout(readTimeout);
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
/// Close communications
/// </summary>
public void Close()
{
Shutdown();
}
/// <summary>
/// Close communications
/// </summary>
public void Shutdown()
{
if (_state == State.Ready)
{
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.Shutdown();
if (_socketReadThread.IsAlive)
{
bool didThreadQuit = _socketReadThread.Join(THREAD_QUIT_TIMEOUT_MS);
if (didThreadQuit == false)
{
ErrorLogger.Instance().Write("CommDeviceNode::Close() - Logging Thread did not quit as expected, aborting it");
_socketReadThread.Abort();
}
else
{
ErrorLogger.Instance().Write("CommDeviceNode::Close() - Logging Thread quit successfully after join", ErrorLogger.LogLevel.INFO);
}
}
else
{
ErrorLogger.Instance().Write("CommDeviceNode::Close() - Logging Thread quit successfully", ErrorLogger.LogLevel.INFO);
}
}
_state = State.Uninitialized;
}
/// <summary>
/// Send data on the socket
/// </summary>
/// <param name="dataToSend">The data to send</param>
/// <param name="numBytesToWrite">The number of bytes to write from the dataToSend buffer</param>
/// <returns>The number of bytes sent</returns>
public uint Write(byte[] dataToSend, uint numBytesToWrite)
{
return _commDevice.Write(dataToSend, numBytesToWrite);
}
#endregion
}
}

View File

@@ -0,0 +1,178 @@
// 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 System;
using System.Threading;
using System.Net.Sockets;
using Raytheon.Instruments;
using Raytheon.Common;
namespace Raytheon.Instruments
{
/// <summary>
/// Takes raw data from an ICommDevice and throws it in a buffer
/// </summary>
internal class CommReadWorker : IWorkerInterface
{
#region PrivateClassMembers
private ICommDevice _commNode;
private MsgDevice _msgHandler;
private bool _threadQuitControl;
private AutoResetEvent _quitEvent;
private byte[] _dataRead;
private readonly uint _timeToRestBetweenReadsInMs;
#endregion
#region PublicFuctions
/// <summary>
/// Constructor
/// </summary>
/// <param name="commNode">The communication interface</param>
/// <param name="msghandler">The message handler for received data</param>
/// <param name="bufferSize">The number of bytes for the buffer internal to this class. Each individual read will read upto this buffer size (or until the timeout happens)</param>
/// <param name="timeToRestBetweenReadsInMs">Number of ms to rest after a read call</param>
public CommReadWorker(ICommDevice commNode, MsgDevice msghandler, uint bufferSize, uint timeToRestBetweenReadsInMs)
{
_commNode = commNode;
_threadQuitControl = false;
_msgHandler = msghandler;
_quitEvent = new AutoResetEvent(false);
_dataRead = new byte[bufferSize];
_timeToRestBetweenReadsInMs = timeToRestBetweenReadsInMs;
}
/// <summary>
/// Finalizer
/// </summary>
~CommReadWorker()
{
Dispose(false);
}
/// <summary>
/// Dispose of this object. Needed for releasing thread/comm resources
/// </summary>
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
}
}
}
/// <summary>
/// Reads the socket and puts data into a buffer
/// </summary>
public void DoWork()
{
try
{
while (_threadQuitControl == false)
{
try
{
uint numBytesRead = _commNode.Read(ref _dataRead);
// add into buffer
if (numBytesRead > 0)
{
_msgHandler.AddData(_dataRead, numBytesRead);
}
// not using timeToRestBetweenReadsInMs. Just going to wait 1 ms and get back to the read
if (_quitEvent.WaitOne(1))
{
ErrorLogger.Instance().Write("CommReadWorker::DoWork() - received signal to quit", ErrorLogger.LogLevel.INFO);
_threadQuitControl = true;
}
}
catch (SocketException e)
{
if (e.SocketErrorCode == SocketError.TimedOut)
{
//expected
}
else
{
ErrorLogger.Instance().Write("CommReadWorker::DoWork() - " + e.Message, ErrorLogger.LogLevel.ERROR);
}
}
catch (Exception e)
{
ErrorLogger.Instance().Write("CommReadWorker::DoWork() - " + e.Message, ErrorLogger.LogLevel.ERROR);
}
}
ErrorLogger.Instance().Write("CommReadWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
}
catch (Exception err)
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
}
/// <summary>
/// Commands the worker to stop
/// </summary>
public void QuitWork()
{
_quitEvent.Set();
_threadQuitControl = true;
}
/// <summary>
/// Dispose of this object
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
_quitEvent.Dispose();
}
}
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
}
}