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,491 @@
// 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 BitMeasurementManagerLib;
using Raytheon.Instruments;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using static BitMeasurementManagerLib.BitConfigurableMessageFactory;
using NLog;
namespace MeasurementManagerLib
{
/// <summary>
/// This class interfaces to a host application for the purpose of sending and receiving messages to/from a UUT
/// </summary>
public class BitMeasurementManager : IDisposable
{
#region PublicClassMembers
/// <summary>
/// A delegate for host applications to get notified once a particular message arrives
/// </summary>
/// <param name="messageId">The message id that was received</param>
/// <param name="messageDataLength">The number of bytes in the message</param>
/// <param name="errorCode">An error code</param>
public delegate void MessageReceivedDelegate(uint messageId, uint messageDataLength, int errorCode);
#endregion
#region PrivateClassMembers
private ICommDevice _commNode;
private ICommDevice _commDevice;
private BitMsgHandler _msgHandler;
private BitMessageIDs _messageIds;
private uint _readWorkerBufferSize;
private uint _readWorkerRestTimeMs;
private string _bitResultsFieldName;
private static object _syncObj = new Object();
private static NLog.ILogger _logger;
#endregion
#region PrivateFuctions
/// <summary>
/// Dispose of this object.
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
try
{
if (_commNode != null)
{
_commNode.Shutdown();
}
}
catch (Exception err)
{
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
}
try
{
if (_msgHandler != null)
{
_msgHandler.Dispose();
}
}
catch (Exception err)
{
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
}
}
}
/// <summary>
/// Write bytes onto an interface
/// </summary>
/// <param name="message">the bytes to send</param>
/// <param name="numBytesToSend">the number of bytes to send</param>
private void SendMessage(byte[] message, uint numBytesToSend)
{
lock (_syncObj)
{
uint numBytesSent = 0;
_msgHandler.WriteOutgoingDataToLog(message, (int)numBytesToSend);
numBytesSent = _commNode.Write(message, numBytesToSend);
if (numBytesSent != numBytesToSend)
{
throw new Exception("Sent " + numBytesSent.ToString() + " bytes, expected to send " + numBytesToSend.ToString());
}
}
}
/// <summary>
/// Send out a message and wait for a response
/// </summary>
/// <param name="messageToSend">The message to send</param>
/// <param name="timeoutInMs">Timeout in ms</param>
/// <returns></returns>
private BitConfigurableMessage SendMessageGetRsp(BitConfigurableMessage messageToSend, uint timeoutInMs)
{
lock (_syncObj)
{
uint cmdMessageId = messageToSend.GetMessageId();
uint rspMessageId = _messageIds.GetResponseId(cmdMessageId);
// reset the rsp event
BitMsgRxBuffer.Instance().ResetReceiveEvent(rspMessageId);
// send out the message
SendMessage(messageToSend);
// wait for the response
bool didWeGetTheMsg = BitMsgRxBuffer.Instance().WaitForRspMsg(rspMessageId, timeoutInMs);
if (didWeGetTheMsg == false)
{
throw new Exception("Did not receive msg: " + rspMessageId.ToString());
}
return GetNewestMessage(rspMessageId);
}
}
#endregion
#region PublicFuctions
public BitMeasurementManager(IInstrumentManager instrumentManager,
string measurementDefFile,
string comDeviceName,
string comNodeName,
string binDataLogFilename,
string asciiDataLogFileName,
MessageReceivedDelegate callback)
{
const string CONFIGURATION_INI_SECTION_NAME = "CONFIGURATION";
try
{
_logger = LogManager.GetCurrentClassLogger();
IniFile ini = new IniFile(measurementDefFile);
// hold onto the UUT byte order and header def
bool shallWeByteSwap = Convert.ToBoolean(ini.ReadValue(CONFIGURATION_INI_SECTION_NAME, "SHALL_WE_BYTE_SWAP"));
BitMsgEndianControl.Instance(shallWeByteSwap, ini);
_bitResultsFieldName = ini.ReadValue(CONFIGURATION_INI_SECTION_NAME, "BIT_RESULTS_FIELD_NAME");
string messageDefFile = ini.ReadValue(CONFIGURATION_INI_SECTION_NAME, "MESSAGE_DEF_FILE");
string messageInpuStr = ini.ReadValue(CONFIGURATION_INI_SECTION_NAME, "MESSAGE_INPUT_TYPE");
FactoryType bitMsgFactoryType = (FactoryType)Enum.Parse(typeof(FactoryType), messageInpuStr, true);
// initialize the BitMessageFactory
BitConfigurableMessageFactory.Instance(messageDefFile, bitMsgFactoryType);
// initialize the Message ID List, set each message size and set the rsp IDs
_messageIds = new BitMessageIDs();
Dictionary<uint, BitConfigurableMessage> allMessages = BitConfigurableMessageFactory.Instance().RetreiveAllMessages();
foreach (var msg in allMessages.Values)
{
uint messageId = msg.GetMessageId();
uint msgRspId = msg.GetMessageRspId();
_messageIds.AddId(messageId);
if (msgRspId != 0xffffffff)
{
_messageIds.SetRspId(messageId, msgRspId);
}
_messageIds.SetMsgSize(msg.GetMessageId(), msg.GetEntireMsgLength());
}
BitMsgRxBuffer.Instance(_messageIds);
//_isThereHardware = isThereHardware;
uint parseBufferSize = Convert.ToUInt32(ini.ReadValue(CONFIGURATION_INI_SECTION_NAME, "PARSE_BUFFER_SIZE"));
bool shallWeLogOutgoingBinData = Convert.ToBoolean(ini.ReadValue("LOGGING", "SHALL_WE_LOG_OUTGOING_BIN"));
bool shallWeLogOutgoingAsciiData = Convert.ToBoolean(ini.ReadValue("LOGGING", "SHALL_WE_LOG_OUTGOING_ASCII"));
bool shallWeLogIncomingBinData = Convert.ToBoolean(ini.ReadValue("LOGGING", "SHALL_WE_LOG_INCOMING_BIN"));
bool shallWeLogIncomingAsciiData = Convert.ToBoolean(ini.ReadValue("LOGGING", "SHALL_WE_LOG_INCOMING__ASCII"));
bool shallWeLogParserVerboseInfo = Convert.ToBoolean(ini.ReadValue("LOGGING", "SHALL_WE_LOG_VERBOSE_PARSER_INFO"));
// get the CRC check info
uint crcMask = Convert.ToUInt32(ini.ReadValue("CRC_STATUS", "BITMASK"), 16);
string crcFieldName = ini.ReadValue("CRC_STATUS", "CRC_FIELD_LOGICAL_NAME");
// create the message handler
_msgHandler = new BitMsgHandler(_messageIds, callback, parseBufferSize, binDataLogFilename, asciiDataLogFileName, shallWeLogOutgoingBinData, shallWeLogOutgoingAsciiData, shallWeLogIncomingBinData, shallWeLogIncomingAsciiData, crcMask, crcFieldName, shallWeLogParserVerboseInfo);
// create the communication device
_commDevice = instrumentManager.GetInstrument<ICommDevice>(comDeviceName);
_commDevice?.Initialize();
// get the read thread buffer size and thread rate
_readWorkerBufferSize = Convert.ToUInt32(ini.ReadValue(CONFIGURATION_INI_SECTION_NAME, "READ_WORKER_BUFFER_SIZE"));
_readWorkerRestTimeMs = Convert.ToUInt32(ini.ReadValue(CONFIGURATION_INI_SECTION_NAME, "READ_WORKER_REST_TIME_MS"));
// create the communication node
_commNode = instrumentManager.GetInstrument<ICommDevice>(comNodeName);
_commNode?.Initialize();
}
catch (Exception)
{
Dispose(true);
throw;
}
}
/// <summary>
/// The Finalizer
/// </summary>
~BitMeasurementManager()
{
Dispose(false);
}
/// <summary>
///
/// </summary>
/// <param name="dataToAdd"></param>
public void AddDataTestFunction(byte[] dataToAdd)
{
_msgHandler.AddData(dataToAdd, (uint)dataToAdd.Length);
}
/// <summary>
/// Closes the data files
/// </summary>
public void CloseDataFiles()
{
lock (_syncObj)
{
_msgHandler.CloseDataFiles();
}
}
/// <summary>
/// Instantiate a message object. The host configure its parameters prior to sending it
/// </summary>
/// <param name="messageId">The message id for the message to create</param>
/// <returns>The message object</returns>
public BitConfigurableMessage CreateMessage(uint messageId)
{
lock (_syncObj)
{
BitConfigurableMessage message = BitConfigurableMessageFactory.Instance().RetreiveMessage(messageId);
return message;
}
}
/// <summary>
/// Release the resources
/// </summary>
public void Dispose()
{
Dispose(true);
}
/// <summary>
///
/// </summary>
/// <param name="message"></param>
/// <param name="name"></param>
/// <returns></returns>
public TType GetDataItemByName<TType>(BitConfigurableMessage message, string name)
{
lock (_syncObj)
{
return message.GetDataItemByName<TType>(name);
}
}
/// <summary>
///
/// </summary>
/// <param name="message"></param>
/// <param name="dataItemName"></param>
/// <returns></returns>
public uint GetDataItemByNameUint(BitConfigurableMessage message, string dataItemName)
{
lock (_syncObj)
{
uint dataValue = GetDataItemByName<uint>(message, dataItemName);
return dataValue;
}
}
/// <summary>
/// Return a list of message IDs that are supported
/// </summary>
/// <returns>A list of message Ids</returns>
public List<uint> GetSupportedMessages()
{
lock (_syncObj)
{
List<uint> mesages = _messageIds.GetAllIds();
return mesages;
}
}
/// <summary>
/// Retrieve the newest message in the buffer
/// </summary>
/// <param name="rspMessageId">The message ID to Retrieve</param>
/// <param name="shallWeDeleteOthers">True to delete all of the other messages of this ID</param>
/// <returns>The retrieved message</returns>
public BitConfigurableMessage GetNewestMessage(uint rspMessageId, bool shallWeDeleteOthers = true)
{
lock (_syncObj)
{
BitConfigurableMessage messageToReturn = BitMsgRxBuffer.Instance().GetNewestMessage(rspMessageId, shallWeDeleteOthers);
return messageToReturn;
}
}
/// <summary>
/// Retrieve the oldest message in the buffer
/// </summary>
/// <param name="rspMessageId">The message ID to Retrieve</param>
/// <returns>The retrieved message</returns>
public BitConfigurableMessage GetOldestMessage(uint rspMessageId)
{
lock (_syncObj)
{
BitConfigurableMessage messageToReturn = BitMsgRxBuffer.Instance().GetOldestMessage(rspMessageId);
return messageToReturn;
}
}
/// <summary>
/// Open the communication device, if it is already open, it closes it and then reopens it
/// </summary>
public void OpenCommDevice()
{
lock (_syncObj)
{
// shut it down and reinitialize
_commNode.Shutdown();
_commNode.Initialize();
}
}
/// <summary>
/// Runs a BIT test, return the test results
/// </summary>
/// <param name="messageId"></param>
/// <param name="timeoutInMs">The number of ms to wait for a response</param>
/// <param name="messageParams"></param>
/// <returns>The test result register</returns>
public uint RunBitTest(uint messageId, uint timeoutInMs, params object[] messageParams)
{
lock (_syncObj)
{
BitConfigurableMessage cmdMessage = BitConfigurableMessageFactory.Instance().RetreiveMessage(messageId);
if (messageParams.Length > 0)
{
cmdMessage.SetParams(messageParams);
}
BitConfigurableMessage rspMessage = SendMessageGetRsp(cmdMessage, timeoutInMs);
uint testResult = rspMessage.GetDataItemByName<uint>(_bitResultsFieldName.ToUpper());
return testResult;
}
}
/// <summary>
///
/// </summary>
/// <param name="messageId"></param>
/// <param name="messageParams"></param>
/// <returns></returns>
public void SendMessage(uint messageId, params object[] messageParams)
{
lock (_syncObj)
{
BitConfigurableMessage cmdMessage = BitConfigurableMessageFactory.Instance().RetreiveMessage(messageId);
if (messageParams.Length > 0)
{
cmdMessage.SetParams(messageParams);
}
SendMessage(cmdMessage);
}
}
/// <summary>
/// Send out a message and wait for a response
/// </summary>
/// <param name="messageId">The message ID to send</param>
/// <param name="messageParams"></param>
/// <returns>The response message for the command that was sent</returns>
public BitConfigurableMessage SendMessageGetRsp(uint messageId, uint timeoutInMs, params object[] messageParams)
{
lock (_syncObj)
{
BitConfigurableMessage cmdMessage = BitConfigurableMessageFactory.Instance().RetreiveMessage(messageId);
if (messageParams.Length > 0)
{
cmdMessage.SetParams(messageParams);
}
BitConfigurableMessage rspMessage = SendMessageGetRsp(cmdMessage, timeoutInMs);
return rspMessage;
}
}
/// <summary>
/// Send out a message on the comm interface
/// </summary>
/// <param name="message">The message to send</param>
public void SendMessage(BitConfigurableMessage message)
{
lock (_syncObj)
{
// get the ascii msg for logging just before sending
string asciiMessage = message.ToString();
// get the formatted gu message
uint messageNumBytes = message.GetEntireMsgLength();
// allocate an array to hold onto the data that we will send
byte[] messageDataToSend = new byte[messageNumBytes];
// get a pointer to the data
GCHandle messagePinnedArray = GCHandle.Alloc(messageDataToSend, GCHandleType.Pinned);
IntPtr pMessageData = messagePinnedArray.AddrOfPinnedObject();
// get the encoded data to send
message.Format(pMessageData);
// free the ptr
messagePinnedArray.Free();
// log the data
_msgHandler.WriteOutgoingDataToLog(asciiMessage);
// send the data
SendMessage(messageDataToSend, messageNumBytes);
}
}
/// <summary>
/// Enable or Disable the Callback for a specific message
/// </summary>
/// <param name="msgId"></param>
/// <param name="shallWeEnableCallback"></param>
public void SetCallbackControl(uint msgId, bool shallWeEnableCallback)
{
lock (_syncObj)
{
_msgHandler.SetCallbackControl(msgId, shallWeEnableCallback);
}
}
#endregion
}
}

View File

@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>BitMeasurementManager</AssemblyName>
<Product>Composable Test Software Library</Product>
<Description>Bit Measurement Manager</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.1.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.CommDevice.Contracts" Version="1.2.0" />
<PackageReference Include="Raytheon.Instruments.InstrumentManager.Contracts" Version="1.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\SupportProjects\ExcelZip\ExcelZip.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,50 @@
// 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;
namespace BitMeasurementManagerLib
{
public interface IConfigurableDataItem
{
Type DataType { get;}
object Data { get; set; }
string GetDataItemName();
BitConfigurableMessage.DataItemType GetDataItemType();
int GetNumDataItems();
string GetDefaultValueStr();
}
public interface IConfigurableDataItem<TData> : IConfigurableDataItem
{
new TData Data { get; set;}
new string GetDataItemName();
new BitConfigurableMessage.DataItemType GetDataItemType();
new int GetNumDataItems();
new string GetDefaultValueStr();
}
}

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
}
}

View File

@@ -0,0 +1,961 @@
// 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.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace BitMeasurementManagerLib
{
/// <summary>
/// This class implements a message that can be put on a communication interface
/// </summary>
public class BitConfigurableMessage
{
#region PublicClassMembers
public enum DataItemType
{
FLOAT,
UINT,
UINT_HEX,
USHORT_HEX,
USHORT,
BYTE_HEX,
BYTE_ARRAY_HEX,
DOUBLE,
ULONG,
ULONG_HEX,
BITS
}
#endregion
#region PrivateClassMembers
public List<IConfigurableDataItem> _dataItems;
public Dictionary<string, int> _byteArrayCount;
public Dictionary<string, int> _bitCount;
private string _messageName;
private uint _entireMsgLen;
private uint _messageId;
private uint _rspMessageId;
#endregion
#region PublicFuctions
/// <summary>
/// Copy constructor
/// </summary>
/// <param name="rhs">The object to copy</param>
public BitConfigurableMessage(BitConfigurableMessage rhs)
{
// copy over the basic types
_messageId = rhs._messageId;
_rspMessageId = rhs._rspMessageId;
_messageName = String.Copy(rhs._messageName);
// _entireMsgLen will get set when we add the data items
_entireMsgLen = 0;
// initialize the objects
_dataItems = new List<IConfigurableDataItem>();
_byteArrayCount = new Dictionary<string, int>();
_bitCount = new Dictionary<string, int>();
// copy the data items over
foreach (IConfigurableDataItem dataItem in rhs._dataItems)
{
AddDataItem(dataItem.GetDataItemName(), dataItem.GetDataItemType(), dataItem.GetNumDataItems(), dataItem.GetDefaultValueStr());
}
}
/// <summary>
///
/// </summary>
/// <param name="messageId"></param>
/// <param name="rspMessageId"></param>
/// <param name="messageName"></param>
public BitConfigurableMessage(uint messageId, uint rspMessageId, string messageName)
{
_messageId = messageId;
_rspMessageId = rspMessageId;
_messageName = messageName;
_entireMsgLen = 0;
_dataItems = new List<IConfigurableDataItem>();
_byteArrayCount = new Dictionary<string, int>();
_bitCount = new Dictionary<string, int>();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public uint GetMessageId()
{
return _messageId;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public uint GetMessageRspId()
{
return _rspMessageId;
}
/// <summary>
///
/// </summary>
/// <param name="dataItemName"></param>
/// <param name="dataItemType"></param>
/// <param name="numItems"></param>
/// <param name="defaultValue"></param>
public void AddDataItem(string dataItemName, DataItemType dataItemType, int numItems, string defaultValue)
{
if (numItems < 1)
{
throw new Exception("BitConfigurableMessage::AddDataItem() - numItems is not valid: " + numItems + ", data item name is: " + dataItemName);
}
if (numItems > 1 && (dataItemType != DataItemType.BYTE_ARRAY_HEX && dataItemType != DataItemType.BITS))
{
throw new Exception("BitConfigurableMessage::AddDataItem() - numItems greater than one only allowed for hex byte arrays and BITs: " + numItems + ", data item name is: " + dataItemName);
}
if (dataItemType == DataItemType.UINT)
{
uint value = Convert.ToUInt32(defaultValue);
BitConfigurableMessageDataItem<uint> dataItem = new BitConfigurableMessageDataItem<uint>(dataItemName, dataItemType, value, defaultValue, numItems);
_entireMsgLen += (uint)(4 * numItems);
_dataItems.Add(dataItem);
}
else if (dataItemType == DataItemType.UINT_HEX)
{
uint value = Convert.ToUInt32(defaultValue, 16);
BitConfigurableMessageDataItem<uint> dataItem = new BitConfigurableMessageDataItem<uint>(dataItemName, dataItemType, value, defaultValue, numItems);
_entireMsgLen += (uint)(4 * numItems);
_dataItems.Add(dataItem);
}
else if (dataItemType == DataItemType.FLOAT)
{
float value = (float)Convert.ToDouble(defaultValue);
BitConfigurableMessageDataItem<float> dataItem = new BitConfigurableMessageDataItem<float>(dataItemName, dataItemType, value, defaultValue, numItems);
_entireMsgLen += (uint)(4 * numItems);
_dataItems.Add(dataItem);
}
else if (dataItemType == DataItemType.USHORT)
{
ushort value = Convert.ToUInt16(defaultValue);
BitConfigurableMessageDataItem<ushort> dataItem = new BitConfigurableMessageDataItem<ushort>(dataItemName, dataItemType, value, defaultValue, numItems);
_entireMsgLen += (uint)(2 * numItems);
_dataItems.Add(dataItem);
}
else if (dataItemType == DataItemType.USHORT_HEX)
{
ushort value = Convert.ToUInt16(defaultValue, 16);
BitConfigurableMessageDataItem<ushort> dataItem = new BitConfigurableMessageDataItem<ushort>(dataItemName, dataItemType, value, defaultValue, numItems);
_entireMsgLen += (uint)(2 * numItems);
_dataItems.Add(dataItem);
}
else if (dataItemType == DataItemType.DOUBLE)
{
double value = Convert.ToDouble(defaultValue);
BitConfigurableMessageDataItem<double> dataItem = new BitConfigurableMessageDataItem<double>(dataItemName, dataItemType, value, defaultValue, numItems);
_entireMsgLen += (uint)(8 * numItems);
_dataItems.Add(dataItem);
}
else if (dataItemType == DataItemType.ULONG)
{
ulong value = Convert.ToUInt64(defaultValue);
BitConfigurableMessageDataItem<ulong> dataItem = new BitConfigurableMessageDataItem<ulong>(dataItemName, dataItemType, value, defaultValue, numItems);
_entireMsgLen += (uint)(8 * numItems);
_dataItems.Add(dataItem);
}
else if (dataItemType == DataItemType.ULONG_HEX)
{
ulong value = Convert.ToUInt64(defaultValue, 16);
BitConfigurableMessageDataItem<ulong> dataItem = new BitConfigurableMessageDataItem<ulong>(dataItemName, dataItemType, value, defaultValue, numItems);
_entireMsgLen += (uint)(8 * numItems);
_dataItems.Add(dataItem);
}
else if (dataItemType == DataItemType.BYTE_HEX)
{
byte value = Convert.ToByte(defaultValue, 16);
BitConfigurableMessageDataItem<byte> dataItem = new BitConfigurableMessageDataItem<byte>(dataItemName, dataItemType, value, defaultValue, numItems);
_entireMsgLen += (uint)(1 * numItems);
_dataItems.Add(dataItem);
}
else if (dataItemType == DataItemType.BITS)
{
if (numItems > 8)
{
throw new Exception("BitConfigurableMessage::AddDataItem() - trying to add bit field: " + dataItemName + " that has more than 8 bits, bit fields are required to be less than 8 bits at this time");
}
// query how many bit fields have been added
// use this later when updating the number of bytes in the message
int totalBitPrevCount = 0;
foreach (KeyValuePair<string, int> entry in _bitCount)
{
totalBitPrevCount += entry.Value;
}
//intention integer division
uint numBytesPrevAdded = (uint)(totalBitPrevCount / 8);
int totalBitPrevCountRemander = totalBitPrevCount % 8;
// if remander is not 0, bump up the byte count by 1
if (totalBitPrevCountRemander != 0)
{
numBytesPrevAdded++;
}
// convert value to a byte and create the data item
defaultValue = defaultValue.Replace("0b", "");
defaultValue = defaultValue.Replace("0B", "");
byte value = Convert.ToByte(defaultValue, 2);
BitConfigurableMessageDataItem<byte> dataItem = new BitConfigurableMessageDataItem<byte>(dataItemName, dataItemType, value, defaultValue, numItems);
_dataItems.Add(dataItem);
// store the number of bits for this items
_bitCount[dataItemName.ToUpper()] = numItems;
// now that we updated the bit fields, query how many bit fields there are
int totalBitCount = 0;
foreach (KeyValuePair<string, int> entry in _bitCount)
{
totalBitCount += entry.Value;
}
// intentional integer division
uint numBytesToAdd = (uint)(totalBitCount / 8);
int totalBitCountRemander = totalBitCount % 8;
// if remander is not 0, bump up the byte count by 1
if (totalBitCountRemander != 0)
{
numBytesToAdd++;
}
// increment the message length we crossed a byte boundary with the total number of bits
_entireMsgLen += numBytesToAdd - numBytesPrevAdded;
}
else if (dataItemType == DataItemType.BYTE_ARRAY_HEX)
{
byte value = Convert.ToByte(defaultValue, 16);
byte[] data = new byte[numItems];
for (int i = 0; i < numItems; i++)
{
data[i] = value;
}
BitConfigurableMessageDataItem<Array> dataItem = new BitConfigurableMessageDataItem<Array>(dataItemName, dataItemType, data, defaultValue, numItems);
_dataItems.Add(dataItem);
_entireMsgLen += (uint)(1 * numItems);
_byteArrayCount[dataItemName.ToUpper()] = numItems;
}
else
{
throw new Exception("BitConfigurableMessage::AddDataItem() - Unsupported data item type: " + dataItemType.ToString());
}
}
/// <summary>
///
/// </summary>
/// <param name="pData"></param>
public void Format(IntPtr pData)
{
IntPtr pDataLocation = pData;
// should we byte swap
bool shallWeSwap = BitMsgEndianControl.Instance().ShallWeSwap();
// format the data
List<IConfigurableDataItem> formattedData = _dataItems;
for (int i = 0; i < formattedData.Count; i++)
{
IConfigurableDataItem dataItem = _dataItems[i];
DataItemType itemType = dataItem.GetDataItemType();
string itemName = dataItem.GetDataItemName();
object itemValue = dataItem.Data;
int dataItemSize = 0;
if (itemValue is float)// if (itemType == DataItemType.FLOAT)
{
float data = (float)itemValue;
if (shallWeSwap == true)
{
itemValue = Util.Swap(data);
}
else
{
itemValue = data;
}
dataItemSize = 4;
//copy data from our data items, info the buffer
Marshal.StructureToPtr(itemValue, pDataLocation, true);
}
else if (itemValue is uint)
{
uint data = (uint)itemValue;
if (shallWeSwap == true)
{
itemValue = Util.Swap(data);
}
else
{
itemValue = data;
}
dataItemSize = 4;
//copy data from our data items, info the buffer
Marshal.StructureToPtr(itemValue, pDataLocation, true);
}
else if (itemValue is ushort)
{
ushort data = (ushort)itemValue;
if (shallWeSwap == true)
{
itemValue = Util.Swap(data);
}
else
{
itemValue = data;
}
dataItemSize = 2;
//copy data from our data items, info the buffer
Marshal.StructureToPtr(itemValue, pDataLocation, true);
}
else if (itemValue is byte)
{
// handle the case where we stored an array of BITS as a byte
if (itemType == DataItemType.BITS)
{
// grab the value of the first bit item
byte totalBitItemValue = (byte)itemValue;
// queue up the rest of the BITs to the next byte boundary
int totalBitsProcessed = dataItem.GetNumDataItems();
for (int j = i + 1; totalBitsProcessed < 8; j++)
{
// grab the next data items
IConfigurableDataItem bitDataItem = _dataItems[j];
DataItemType bitItemType = bitDataItem.GetDataItemType();
// the next item should be BITS
if (bitItemType != DataItemType.BITS)
{
throw new Exception("BitConfigurableMessage::Format() - Bit fields not consecutive out to byte boundary for msg ID: " + _messageId.ToString("X8"));
}
int bitItemNumBites = bitDataItem.GetNumDataItems();
byte bitItemValue = (byte)bitDataItem.Data;
uint mask = (uint)((1 << bitItemNumBites) - 1) << totalBitsProcessed;
// mask in the next bit value
byte valueToMaskIn = (byte)((bitItemValue << totalBitsProcessed) & mask);
totalBitItemValue = (byte)(totalBitItemValue | valueToMaskIn);
// increment the bit counter
totalBitsProcessed += bitItemNumBites;
// increment the outer loop counter since we just processed it
i++;
}
// double check that we are on a byte boundary
//int byteBoundaryRemainder = totalBitsProcessed % 8;
if (totalBitsProcessed != 8)
{
throw new Exception("BitConfigurableMessage::Format() - Bit fields not equal to 8 for msg ID: " + _messageId.ToString("X8"));
}
dataItemSize = 1;
// hold onto the total bit item value
itemValue = (byte)totalBitItemValue;
//copy data from our data items, info the buffer
Marshal.StructureToPtr(itemValue, pDataLocation, true);
}
else
{
itemValue = (byte)itemValue;
dataItemSize = 1;
//copy data from our data items, info the buffer
Marshal.StructureToPtr(itemValue, pDataLocation, true);
}
}
else if (itemValue is double)
{
itemValue = (double)itemValue;
dataItemSize = 8;
//copy data from our data items, info the buffer
Marshal.StructureToPtr(itemValue, pDataLocation, true);
}
else if (itemValue is ulong)
{
itemValue = (ulong)itemValue;
dataItemSize = 8;
//copy data from our data items, info the buffer
Marshal.StructureToPtr(itemValue, pDataLocation, true);
}
else if (itemValue is Array)
{
IEnumerable en = (IEnumerable)itemValue;
byte[] arrayTemp = en.OfType<byte>().ToArray();
dataItemSize = arrayTemp.Length;
Marshal.Copy(arrayTemp, 0, pDataLocation, dataItemSize);
}
else
{
throw new Exception("BitConfigurableMessage::Format() - Unsupported data item type: " + itemType.ToString());
}
// increment the pointer
pDataLocation = IntPtr.Add(pDataLocation, dataItemSize);
}
}
/// <summary>
///
/// </summary>
/// <param name="dataItemName"></param>
/// <returns></returns>
public byte[] GetDataItemByName_ByteArray(string dataItemName)
{
for (int i = 0; i < _dataItems.Count; i++)
{
if (_dataItems[i].GetDataItemName().ToUpper() == dataItemName.ToUpper())
{
if (_dataItems[i].GetDataItemType() != DataItemType.BYTE_ARRAY_HEX)
{
throw new Exception("BitConfigurableMessage::GetDataItemByName_ByteArray() - item was not a byte array: " + dataItemName);
}
IEnumerable en = (IEnumerable)_dataItems[i].Data;
byte[] dataToReturn = en.OfType<byte>().ToArray();
return dataToReturn;
}
}
throw new Exception("BitConfigurableMessage::GetDataItemByName_ByteArray() - Could not find data item: " + dataItemName);
}
/// <summary>
///
/// </summary>
/// <param name="dataItemName"></param>
/// <returns></returns>
public T GetDataItemByName<T>(string dataItemName)
{
for (int i = 0; i < _dataItems.Count; i++)
{
if (_dataItems[i].GetDataItemName().ToUpper() == dataItemName.ToUpper())
{
T value = (T)Convert.ChangeType(_dataItems[i].Data, typeof(T));
return value;
}
}
throw new Exception("BitConfigurableMessage::GetDataItemByName() - Could not find data item: " + dataItemName);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public uint GetEntireMsgLength()
{
return _entireMsgLen;
}
/// <summary>
///
/// </summary>
/// <param name="pData"></param>
public void Parse(IntPtr pData)
{
// should we byte swap
bool shallWeSwap = BitMsgEndianControl.Instance().ShallWeSwap();
IntPtr pMsgDataPtr = pData;
for (int i = 0; i < _dataItems.Count; i++)
{
IConfigurableDataItem item = _dataItems[i];
object itemData = item.Data;
if (itemData is float)
{
float itemValue = 0;
unsafe
{
float* pFloatItem = (float*)pMsgDataPtr;
itemValue = *pFloatItem;
}
if (shallWeSwap == true)
{
itemValue = Util.Swap(itemValue);
}
item.Data = itemValue;
_dataItems[i] = item;
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 4);
}
else if (itemData is uint)
{
uint itemValue = 0;
unsafe
{
uint* pUInt32Item = (uint*)pMsgDataPtr;
itemValue = *pUInt32Item;
}
if (shallWeSwap == true)
{
itemValue = Util.Swap(itemValue);
}
item.Data = itemValue;
_dataItems[i] = item;
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 4);
}
else if (itemData is ushort)
{
ushort itemValue = 0;
unsafe
{
ushort* pUInt16Item = (ushort*)pMsgDataPtr;
itemValue = *pUInt16Item;
}
if (shallWeSwap == true)
{
itemValue = Util.Swap(itemValue);
}
item.Data = itemValue;
_dataItems[i] = item;
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 2);
}
else if (itemData is double)
{
double itemValue = 0;
unsafe
{
double* pDoubleItem = (double*)pMsgDataPtr;
itemValue = *pDoubleItem;
}
if (shallWeSwap == true)
{
itemValue = Util.Swap(itemValue);
}
item.Data = itemValue;
_dataItems[i] = item;
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 8);
}
else if (itemData is ulong)
{
ulong itemValue = 0;
unsafe
{
ulong* pUlongItem = (ulong*)pMsgDataPtr;
itemValue = *pUlongItem;
}
if (shallWeSwap == true)
{
itemValue = Util.Swap(itemValue);
}
item.Data = itemValue;
_dataItems[i] = item;
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 8);
}
else if (itemData is byte)
{
// handle the case where we are storing bit arrays as a byte
if (item.GetDataItemType() == DataItemType.BITS)
{
// grab the value of the first bit item
byte rawDataValue = 0;
// Grab the byte from the msg pointer
unsafe
{
byte* pUInt8Item = (byte*)pMsgDataPtr;
rawDataValue = *pUInt8Item;
}
// set the first data item
uint mask = (uint)((1 << item.GetNumDataItems()) - 1);
item.Data = (byte)(rawDataValue & mask);
_dataItems[i] = item;
int totalBitsProcessed = item.GetNumDataItems();
// set the rest of the data items
for (int j = i + 1; totalBitsProcessed < 8; j++)
{
IConfigurableDataItem bitDataItem = _dataItems[j];
DataItemType bitItemType = bitDataItem.GetDataItemType();
// the next item should be BITS
if (bitItemType != DataItemType.BITS)
{
throw new Exception("BitConfigurableMessage::Parse() - Bit fields not consecutive out to byte boundary for msg ID: " + _messageId.ToString("X8"));
}
// shift the data into the beggining of the byte and mask out the other bits
mask = (uint)((1 << bitDataItem.GetNumDataItems()) - 1);
bitDataItem.Data = (byte)((rawDataValue >> totalBitsProcessed) & mask);
_dataItems[j] = bitDataItem;
// increment the bit counter
totalBitsProcessed += bitDataItem.GetNumDataItems();
// increment the outer loop counter since we just processed it
i++;
}
// double check that we are on a byte boundary
//int byteBoundaryRemainder = totalBitsProcessed % 8;
if (totalBitsProcessed != 8)
{
throw new Exception("BitConfigurableMessage::Parse() - Bit fields not on byte boundary forequal to 8 msg ID: " + _messageId.ToString("X8"));
}
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 1);
}
else
{
byte itemValue = 0;
unsafe
{
byte* pUInt8Item = (byte*)pMsgDataPtr;
itemValue = *pUInt8Item;
}
item.Data = itemValue;
_dataItems[i] = item;
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 1);
}
}
else if (itemData is Array)
{
int numBytes = _byteArrayCount[item.GetDataItemName().ToUpper()];
byte[] data = new byte[numBytes];
unsafe
{
for (int byteCounter = 0; byteCounter < numBytes; byteCounter++)
{
byte* pUInt8Item = (byte*)pMsgDataPtr;
data[byteCounter] = *pUInt8Item;
pMsgDataPtr = IntPtr.Add(pMsgDataPtr, 1);
}
}
item.Data = data;
_dataItems[i] = item;
}
else
{
throw new Exception("BitConfigurableMessage::Parse() - Unsupported data item type: " + item.GetDataItemType().ToString());
}
}
}
/// <summary>
/// Set the params of the message.
/// This function will iterate over the list of params passed in and sequentially set the data items in the message starting at the data item at index 0
/// </summary>
/// <param name="messageParams">an array of params</param>
public void SetParams(params object[] messageParams)
{
if (messageParams.Length > _dataItems.Count)
{
throw new Exception("BitConfigurableMessage::SetParams() - number of supplied parameters: " + messageParams.Length.ToString() + ", is larger than the number of parameters in the definition file: " + _dataItems.Count.ToString());
}
for (int i = 0; i < messageParams.Length; i++)
{
IConfigurableDataItem item = _dataItems[i];
object itemData = item.Data;
if (itemData is uint)
{
item.Data = Convert.ToUInt32(messageParams[i]);
_dataItems[i] = item;
}
else if (itemData is float)
{
item.Data = Convert.ToDouble(messageParams[i]);
_dataItems[i] = item;
}
else if (itemData is ushort)
{
item.Data = Convert.ToUInt16(messageParams[i]);
_dataItems[i] = item;
}
else if (itemData is double)
{
item.Data = Convert.ToDouble(messageParams[i]);
_dataItems[i] = item;
}
else if (itemData is ulong)
{
item.Data = Convert.ToUInt64(messageParams[i]);
_dataItems[i] = item;
}
else if (itemData is byte)
{
item.Data = Convert.ToByte(messageParams[i]);
_dataItems[i] = item;
// doesnt matter if it is of types BITs or not, the configurable data item already knows
/*if (item.GetDataItemType() == DataItemType.BITS)
{
item.Data = Convert.ToByte(messageParams[i]);
_dataItems[i] = item;
}
else
{
item.Data = Convert.ToByte(messageParams[i]);
_dataItems[i] = item;
}*/
}
else if (itemData is Array)
{
// convert object to byte array
IEnumerable en = (IEnumerable)messageParams[i];
byte[] data = en.OfType<byte>().ToArray();
item.Data = data;
_dataItems[i] = item;
}
else
{
throw new Exception("BitConfigurableMessage::SetParams() - unknown type");
}
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString()
{
string dataToReturn = "Description: " + _messageName + "\r\n";
dataToReturn += "Payload Data:\r\n";
for (int i = 0; i < _dataItems.Count; i++)
{
IConfigurableDataItem dataItem = _dataItems[i];
DataItemType itemType = dataItem.GetDataItemType();
string itemName = dataItem.GetDataItemName();
object itemValue = dataItem.Data;
if (itemValue is uint)
{
if (itemValue == null)
{
dataToReturn += " " + itemName + ":Not Set\r\n";
}
else
{
uint data = (uint)itemValue;
dataToReturn += " " + itemName + ":" + "0x" + data.ToString("X8") + "\r\n";
}
}
else if (itemValue is ushort)
{
if (itemValue == null)
{
dataToReturn += " " + itemName + ":Not Set\r\n";
}
else
{
ushort data = (ushort)itemValue;
dataToReturn += " " + itemName + ":" + "0x" + data.ToString("X4") + "\r\n";
}
}
else if (itemValue is double)
{
if (itemValue == null)
{
dataToReturn += " " + itemName + ":Not Set\r\n";
}
else
{
double data = (double)itemValue;
dataToReturn += " " + itemName + ":" + data + "\r\n";
}
}
else if (itemValue is ulong)
{
if (itemValue == null)
{
dataToReturn += " " + itemName + ":Not Set\r\n";
}
else
{
ulong data = (ulong)itemValue;
dataToReturn += " " + itemName + ":" + data + "\r\n";
}
}
else if (itemValue is byte)
{
if (itemValue == null)
{
dataToReturn += " " + itemName + ":Not Set\r\n";
}
else
{
if (itemType == DataItemType.BITS)
{
byte data = (byte)itemValue;
string binString = Convert.ToString(data, 2).PadLeft(dataItem.GetNumDataItems(), '0');
dataToReturn += " " + itemName + ":" + "0b" + binString + "\r\n";
}
else
{
byte data = (byte)itemValue;
dataToReturn += " " + itemName + ":" + "0x" + data.ToString("X2") + "\r\n";
}
}
}
else if (itemValue is Array)
{
string arrayDataStr = "";
if (itemValue == null)
{
arrayDataStr += " " + itemName + ":Not Set" + "\r\n";
}
else
{
IEnumerable en = (IEnumerable)itemValue;
byte[] arrayTemp = en.OfType<byte>().ToArray();
StringBuilder hex = new StringBuilder(arrayTemp.Length * 2);
foreach (byte b in arrayTemp)
hex.AppendFormat("{0:x2}", b);
arrayDataStr += " " + itemName + ":" + hex.ToString() + "\r\n";
}
dataToReturn += arrayDataStr;
}
else if (itemValue is float)
{
if (itemValue == null)
{
dataToReturn += " " + itemName + ":Not Set\r\n";
}
else
{
float data = (float)itemValue;
dataToReturn += " " + itemName + ":" + data + "\r\n";
}
}
else
{
dataToReturn += " " + itemName + ":" + "UNKNOWN TYPE:" + itemType + "\r\n";
}
}
return dataToReturn + "\r\n";
}
#endregion
}
}

View File

@@ -0,0 +1,114 @@
// 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;
namespace BitMeasurementManagerLib
{
/// <summary>
///
/// </summary>
/// <typeparam name="TData"></typeparam>
public class BitConfigurableMessageDataItem<TData> : IConfigurableDataItem<TData>
{
#region PublicClassMembers
#endregion
#region PrivateClassMembers
private string _dataItemName;
private int _numItems;
private string _defaultValueStr;
private BitConfigurableMessage.DataItemType _dataItemType;
#endregion
#region PublicFunctions
/// <summary>
///
/// </summary>
/// <param name="dataItemName"></param>
/// <param name="type"></param>
/// <param name="dataValue"></param>
public BitConfigurableMessageDataItem(string dataItemName, BitConfigurableMessage.DataItemType type, TData dataValue, string defaultValueStr, int numItems)
{
_dataItemName = dataItemName;
_dataItemType = type;
_defaultValueStr = defaultValueStr;
_numItems = numItems;
Data = dataValue;
}
/// <summary>
///
/// </summary>
public Type DataType
{
get { return typeof(TData); }
}
/// <summary>
///
/// </summary>
object IConfigurableDataItem.Data
{
get { return Data; }
set { Data = (TData)value; }
}
/// <summary>
///
/// </summary>
public TData Data { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public string GetDataItemName()
{
return _dataItemName;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public string GetDefaultValueStr()
{
return _defaultValueStr;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public BitConfigurableMessage.DataItemType GetDataItemType()
{
return _dataItemType;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public int GetNumDataItems()
{
return _numItems;
}
#endregion
}
}

View File

@@ -0,0 +1,213 @@
// 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.Collections.Generic;
namespace BitMeasurementManagerLib
{
/// <summary>
/// This class creates BitConfigurableMessage objects
/// </summary>
internal class BitConfigurableMessageExcelFactory : BitConfigurableMessageFactory
{
#region PrivateClassMembers
private Dictionary<uint, BitConfigurableMessage> _messageDictionary;
#endregion
#region PrivateFuctions
/// <summary>
///
/// </summary>
/// <param name="filename"></param>
public BitConfigurableMessageExcelFactory(string filename)
{
const int MIN_ROWS = 3;
const int MIN_COLS = 4;
ExcelReader reader = null;
try
{
_messageDictionary = new Dictionary<uint, BitConfigurableMessage>();
reader = new ExcelReader(filename);
List<string> sheetNamesList = reader.ReadAllSheetNames();
foreach (string sheet in sheetNamesList)
{
// read the whole sheet and split on the lines
string entireSheet = reader.ReadAllRows(sheet, 1, 1);
string[] allRows = entireSheet.Split('\n');
// check that there is the min number of rows
if (allRows.Length < MIN_ROWS)
{
throw new Exception("BitConfigurableMessageExcelFactory::BitConfigurableMessageExcelFactory() - Sheet ID: " + sheet + " does not have the min amount of rows: " + MIN_ROWS.ToString());
}
// grab the first line where the command ID should be
string messageIdLine = allRows[1];
string[] messageIdLineTokens = messageIdLine.Split(',');
// check for the min number of columns
if (messageIdLineTokens.Length < MIN_COLS)
{
throw new Exception("BitConfigurableMessageExcelFactory::BitConfigurableMessageExcelFactory() - Sheet ID: " + sheet + " line 1 does not have the min amount of Cols: " + MIN_COLS.ToString());
}
// grab the message ID
uint msgId = Convert.ToUInt32(messageIdLineTokens[3], 16);
// grab the line with the response msg ID
string rspMessageIdLine = allRows[2];
string[] rspMessageIdLineTokens = rspMessageIdLine.Split(',');
// check the number of cols
if (rspMessageIdLineTokens.Length < MIN_COLS)
{
throw new Exception("BitConfigurableMessageExcelFactory::BitConfigurableMessageExcelFactory() - Sheet ID: " + sheet + " line 2 does not have the min amount of Cols: " + MIN_COLS.ToString());
}
// grab the rsp msg ID
uint rspMsgId = Convert.ToUInt32(rspMessageIdLineTokens[3], 16);
// create the message
BitConfigurableMessage msg = new BitConfigurableMessage(msgId, rspMsgId, sheet);
// process the sheet to create the message object
// we already processed the first two lines, start at 3
for (int i = 3; i < allRows.Length; i++)
{
var line = allRows[i];
var values = line.Split(',');
if (values.Length < MIN_COLS)
{
throw new Exception("BitConfigurableMessageExcelFactory::BitConfigurableMessageExcelFactory() - Sheet ID: " + msgId.ToString("X8") + " does not have all of the fields populated");
}
string dataItemName = values[0].Trim().ToUpper();
string fieldType = values[1].Trim().ToUpper();
string numberOfItemsTemp = values[2].Trim().ToUpper();
numberOfItemsTemp = numberOfItemsTemp.Replace(",", "");
int numberOfItems = Convert.ToInt32(numberOfItemsTemp);
string defaultValue = values[3].Trim().ToUpper();
BitConfigurableMessage.DataItemType dataType = BitConfigurableMessage.DataItemType.FLOAT;
if (fieldType == BitInterfaceManagerConstants.FLOAT_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.FLOAT;
}
else if (fieldType == BitInterfaceManagerConstants.UINT_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.UINT;
}
else if (fieldType == BitInterfaceManagerConstants.UINT_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.UINT_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.USHORT_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.USHORT_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.USHORT_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.USHORT;
}
else if (fieldType == BitInterfaceManagerConstants.BYTE_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.BYTE_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.BYTE_ARRAY_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.BYTE_ARRAY_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.DOUBLE_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.DOUBLE;
}
else if (fieldType == BitInterfaceManagerConstants.ULONG_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.ULONG;
}
else if (fieldType == BitInterfaceManagerConstants.ULONG_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.ULONG_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.BITS_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.BITS;
}
else
{
throw new Exception("BitConfigurableMessageExcelFactory::BitConfigurableMessageExcelFactory() - Unknown type: " + values[1]);
}
msg.AddDataItem(dataItemName, dataType, numberOfItems, defaultValue);
}
_messageDictionary[msgId] = msg;
}
}
catch (Exception)
{
throw;
}
finally
{
if (reader != null)
{
reader.Dispose();
}
}
}
#endregion
#region PublicFuctions
/// <summary>
///
/// </summary>
/// <param name="messageId"></param>
/// <returns></returns>
protected override BitConfigurableMessage CreateMessage(uint messageId)
{
if (_messageDictionary.ContainsKey(messageId) == false)
{
throw new Exception("BitConfigurableMessageExcelFactory:CreateMessage() - unknown ID: " + messageId.ToString("X8") + ", make sure this ID is defined in the definition ini file");
}
return new BitConfigurableMessage(_messageDictionary[messageId]);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
protected override Dictionary<uint, BitConfigurableMessage> GetAllMessages()
{
return _messageDictionary;
}
#endregion
}
}

View File

@@ -0,0 +1,204 @@
// 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 ExcelZipLib;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace BitMeasurementManagerLib
{
/// <summary>
/// This class creates BitConfigurableMessage objects
/// </summary>
internal class BitConfigurableMessageExcelZipFactory : BitConfigurableMessageFactory
{
#region PrivateClassMembers
private Dictionary<uint, BitConfigurableMessage> _messageDictionary;
#endregion
#region PrivateFuctions
/// <summary>
///
/// </summary>
/// <param name="filename"></param>
/// <param name="msgIds"></param>
public BitConfigurableMessageExcelZipFactory(string filename)
{
const int MIN_ROWS = 3;
const int MIN_COLS = 4;
try
{
_messageDictionary = new Dictionary<uint, BitConfigurableMessage>();
List<worksheet> allWorkSheets = Workbook.Worksheets(filename);
foreach (worksheet sheet in allWorkSheets)
{
string test = sheet.ToString();
// check that there is the min number of rows
if (sheet.Rows.Count < MIN_ROWS)
{
throw new Exception("BitConfigurableMessageExcelZipFactory::BitConfigurableMessageExcelZipFactory() - Sheet ID: " + sheet + " does not have the min amount of rows: " + MIN_ROWS.ToString());
}
// grab the command ID Row
Row cmdIdRow = sheet.Rows[1];
if (cmdIdRow.Cells.Length < MIN_COLS)
{
throw new Exception("BitConfigurableMessageExcelZipFactory::BitConfigurableMessageExcelZipFactory() - Sheet ID: " + sheet + " line 1 does not have the min amount of Cols: " + MIN_COLS.ToString());
}
string msgIdStr = cmdIdRow.Cells[3].Text.Trim().ToUpper();
uint msgId = Convert.ToUInt32(msgIdStr, 16);
// grab the rsp ID Row
Row rspIdRow = sheet.Rows[2];
if (rspIdRow.Cells.Length < MIN_COLS)
{
throw new Exception("BitConfigurableMessageExcelZipFactory::BitConfigurableMessageExcelZipFactory() - Sheet ID: " + sheet + " line 1 does not have the min amount of Cols: " + MIN_COLS.ToString());
}
string rspMsgIdStr = rspIdRow.Cells[3].Text.Trim().ToUpper();
// grab the rsp msg ID
uint rspMsgId = Convert.ToUInt32(rspMsgIdStr, 16);
// create the message
BitConfigurableMessage msg = new BitConfigurableMessage(msgId, rspMsgId, msgId.ToString("X8"));
//remove header, cmd ID and rsp ID rows from worksheet
sheet.Rows.Remove(sheet.Rows[0]);
sheet.Rows.Remove(sheet.Rows[0]);
sheet.Rows.Remove(sheet.Rows[0]);
// process the sheet to create the message object
// start at 1 to skip the file header
foreach (Row row in sheet.Rows)
{
if (row.Cells.Length < MIN_COLS)
{
throw new Exception("BitConfigurableMessageExcelZipFactory::BitConfigurableMessageFactory() - Sheet ID: " + msgId.ToString("X8") + " does not have all of the fields populated");
}
string dataItemName = row.Cells[0].Text.Trim().ToUpper();
string fieldType = row.Cells[1].Text.Trim().ToUpper();
string numberOfItemsTemp = row.Cells[2].Text.Trim().ToUpper();
numberOfItemsTemp = numberOfItemsTemp.Replace(",", "");
int numberOfItems = Convert.ToInt32(numberOfItemsTemp);
string defaultValue = row.Cells[3].Text.Trim().ToUpper();
BitConfigurableMessage.DataItemType dataType = BitConfigurableMessage.DataItemType.FLOAT;
if (fieldType == BitInterfaceManagerConstants.FLOAT_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.FLOAT;
}
else if (fieldType == BitInterfaceManagerConstants.UINT_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.UINT;
}
else if (fieldType == BitInterfaceManagerConstants.UINT_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.UINT_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.USHORT_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.USHORT_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.USHORT_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.USHORT;
}
else if (fieldType == BitInterfaceManagerConstants.BYTE_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.BYTE_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.BYTE_ARRAY_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.BYTE_ARRAY_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.DOUBLE_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.DOUBLE;
}
else if (fieldType == BitInterfaceManagerConstants.ULONG_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.ULONG;
}
else if (fieldType == BitInterfaceManagerConstants.ULONG_HEX_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.ULONG_HEX;
}
else if (fieldType == BitInterfaceManagerConstants.BITS_DATA_TYPE.ToUpper())
{
dataType = BitConfigurableMessage.DataItemType.BITS;
}
else
{
throw new Exception("BitConfigurableMessageExcelZipFactory::BitConfigurableMessageExcelZipFactory() - Unknown type: " + row.FilledCells[0].ToString());
}
msg.AddDataItem(dataItemName, dataType, numberOfItems, defaultValue);
}
// hold onto the message object
_messageDictionary[msgId] = msg;
}
}
catch (Exception)
{
throw;
}
}
#endregion
#region PublicFuctions
/// <summary>
///
/// </summary>
/// <param name="messageId"></param>
/// <returns></returns>
protected override BitConfigurableMessage CreateMessage(uint messageId)
{
if (_messageDictionary.ContainsKey(messageId) == false)
{
throw new Exception("BitConfigurableMessageExcelZipFactory:CreateMessage() - unknown ID: " + messageId.ToString("X8") + ", make sure this ID is defined in the definition ini file");
}
return new BitConfigurableMessage(_messageDictionary[messageId]);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
protected override Dictionary<uint, BitConfigurableMessage> GetAllMessages()
{
return _messageDictionary;
}
#endregion
}
}

View File

@@ -0,0 +1,77 @@
// 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.Collections.Generic;
namespace BitMeasurementManagerLib
{
/// <summary>
/// This class creates BitConfigurableMessage objects
/// </summary>
internal abstract class BitConfigurableMessageFactory
{
internal enum FactoryType
{
EXCEL,
EXCEL_ZIP
};
private static BitConfigurableMessageFactory _bitFactoryInstance;
#region PublicFuctions
public static BitConfigurableMessageFactory Instance(string inputFileName = "", FactoryType type = FactoryType.EXCEL_ZIP)
{
if (_bitFactoryInstance == null)
{
if (type == FactoryType.EXCEL)
{
_bitFactoryInstance = new BitConfigurableMessageExcelFactory(inputFileName);
}
else if (type == FactoryType.EXCEL_ZIP)
{
_bitFactoryInstance = new BitConfigurableMessageExcelZipFactory(inputFileName);
}
else
{
throw new Exception("BitConfigurableMessageFactory::Instance() - unsupport input type: " + type.ToString());
}
}
return _bitFactoryInstance;
}
protected abstract Dictionary<uint, BitConfigurableMessage> GetAllMessages();
protected abstract BitConfigurableMessage CreateMessage(uint messageId);
public Dictionary<uint, BitConfigurableMessage> RetreiveAllMessages()
{
return _bitFactoryInstance.GetAllMessages();
}
public BitConfigurableMessage RetreiveMessage(uint messageId)
{
return _bitFactoryInstance.CreateMessage(messageId);
}
#endregion
}
}

View File

@@ -0,0 +1,205 @@
// 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>
/// This class implements a message header that is used by the BitConfigurableMessage
/// </summary>
public static class BitConfigurableMessageHeader
{
#region PrivateClassMembers
#endregion
#region PublicFuctions
/// <summary>
///
/// </summary>
/// <param name="pData"></param>
/// <returns></returns>
public static uint GetMessageId(IntPtr pData, uint numBytesInPdata)
{
return GetCmdMessageId(pData, numBytesInPdata);
}
/// <summary>
///
/// </summary>
/// <param name="pData"></param>
/// <param name="isSecondaryIdUsed"></param>
/// <returns></returns>
public static uint GetSecondaryMessageId(IntPtr pData, uint numBytesInPdata, out bool isSecondaryIdUsed)
{
return GetSecondaryCmdMessageId(pData, numBytesInPdata, out isSecondaryIdUsed);
}
/// <summary>
///
/// </summary>
/// <param name="pData"></param>
/// <param name="isSecondaryIdUsed"></param>
/// <returns></returns>
private static uint GetSecondaryCmdMessageId(IntPtr pData, uint numBytesInPdata, out bool isSecondaryIdUsed)
{
unsafe
{
isSecondaryIdUsed = false;
bool shallWeSwap = BitMsgEndianControl.Instance().ShallWeSwap();
BitMsgEndianControl.HeaderDef headerDef = BitMsgEndianControl.Instance().GetHeaderDef();
// is there enough data?
if (numBytesInPdata <= headerDef.secondaryMsgIdByteLocation + headerDef.secondaryMsgIdDataLen)
{
ErrorLogger.Instance().Write("BitConfigurableMessageHeader::GetSecondaryCmdMessageId() - not enough data form a header. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, needed " + (headerDef.secondaryMsgIdByteLocation + headerDef.secondaryMsgIdDataLen).ToString() + " for a header", ErrorLogger.LogLevel.INFO);
throw new Exception("BitConfigurableMessageHeader::GetSecondaryCmdMessageId() - not enough data form a header. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, needed " + (headerDef.secondaryMsgIdByteLocation + headerDef.secondaryMsgIdDataLen).ToString() + " for a header");
}
if (headerDef.secondaryMsgIdByteLocation == 0)
{
isSecondaryIdUsed = false;
return 0;
}
else
{
isSecondaryIdUsed = true;
uint cmdId = 0;
if (headerDef.secondaryMsgIdDataLen == 1)
{
byte* pCmdIdBytePtr = (byte*)pData.ToPointer() + headerDef.secondaryMsgIdByteLocation;
cmdId = pCmdIdBytePtr[0];
}
else if (headerDef.secondaryMsgIdDataLen == 2)
{
ushort* pCmdIdUshortPtr = (ushort*)pData.ToPointer() + headerDef.secondaryMsgIdByteLocation;
ushort cmdIdTemp = (ushort)pCmdIdUshortPtr[0];
if (shallWeSwap == true)
{
cmdIdTemp = Util.Swap(cmdIdTemp);
}
cmdId = cmdIdTemp;
}
else if (headerDef.secondaryMsgIdDataLen == 4)
{
uint* pCmdIdUInttPtr = (uint*)pData.ToPointer() + headerDef.secondaryMsgIdByteLocation;
cmdId = (uint)pCmdIdUInttPtr[0];
if (shallWeSwap == true)
{
cmdId = Util.Swap(cmdId);
}
}
else
{
throw new Exception("BitConfigurableMessageHeader::GetSecondaryCmdMessageId() - unhandled Cmd ID data length: " + headerDef.msgIdDataLen);
}
return cmdId;
}
}
}
/// <summary>
/// getter for the message id
/// </summary>
/// <returns>The id</returns>
private static uint GetCmdMessageId(IntPtr pData, uint numBytesInPdata)
{
unsafe
{
bool shallWeSwap = BitMsgEndianControl.Instance().ShallWeSwap();
BitMsgEndianControl.HeaderDef headerDef = BitMsgEndianControl.Instance().GetHeaderDef();
// is there enough data?
if (numBytesInPdata <= headerDef.msgIdByteLocation + headerDef.msgIdDataLen)
{
ErrorLogger.Instance().Write("BitConfigurableMessageHeader::GetCmdMessageId() - not enough data form a header. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, needed " + (headerDef.msgIdByteLocation + headerDef.msgIdDataLen).ToString() + " for a header", ErrorLogger.LogLevel.INFO);
throw new Exception("BitConfigurableMessageHeader::GetCmdMessageId() - not enough data form a header. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, needed " + (headerDef.msgIdByteLocation + headerDef.msgIdDataLen).ToString() + " for a header");
}
uint cmdId = 0;
if (headerDef.msgIdDataLen == 1)
{
byte* pCmdIdBytePtr = (byte*)pData.ToPointer() + headerDef.msgIdByteLocation;
cmdId = pCmdIdBytePtr[0];
}
else if (headerDef.msgIdDataLen == 2)
{
ushort* pCmdIdUshortPtr = (ushort*)pData.ToPointer() + headerDef.msgIdByteLocation;
ushort cmdIdTemp = (ushort)pCmdIdUshortPtr[0];
if (shallWeSwap == true)
{
cmdIdTemp = Util.Swap(cmdIdTemp);
}
cmdId = cmdIdTemp;
}
else if (headerDef.msgIdDataLen == 4)
{
uint* pCmdIdUInttPtr = (uint*)pData.ToPointer() + headerDef.msgIdByteLocation;
cmdId = (uint)pCmdIdUInttPtr[0];
if (shallWeSwap == true)
{
cmdId = Util.Swap(cmdId);
}
}
else
{
throw new Exception("BitConfigurableMessageHeader::GetCmdMessageId() - unhandled Cmd ID data length: " + headerDef.msgIdDataLen);
}
return cmdId;
}
}
/// <summary>
/// Getter for the header length
/// The Header is considered to be all of the data up to the message ID
/// </summary>
/// <returns>The header length in bytes. The head Length is the number of bytes from the beginning of the message through the message ID</returns>
public static uint GetHeaderSize()
{
BitMsgEndianControl.HeaderDef headerDef = BitMsgEndianControl.Instance().GetHeaderDef();
int idSize = headerDef.msgIdByteLocation + headerDef.msgIdDataLen;
return (uint)idSize;
}
#endregion
}
}

View File

@@ -0,0 +1,144 @@
// 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.Collections.Generic;
namespace BitMeasurementManagerLib
{
/// <summary>
///
/// </summary>
internal class BitMessageIDs
{
#region PrivateClassMembers
private Dictionary<uint, uint> _idToSizeMap;
private Dictionary<uint, uint> _cmdIdToRspIdMap;
private List<uint> _msgIds;
#endregion
#region PublicFuctions
/// <summary>
///
/// </summary>
internal BitMessageIDs()
{
_idToSizeMap = new Dictionary<uint, uint>();
_cmdIdToRspIdMap = new Dictionary<uint, uint>();
_msgIds = new List<uint>();
}
/// <summary>
///
/// </summary>
/// <param name="messageId"></param>
internal void AddId(uint messageId)
{
_idToSizeMap.Add(messageId, 0);
_msgIds.Add(messageId);
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
internal bool ContainsId(uint id)
{
return _idToSizeMap.ContainsKey(id);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
internal List<uint> GetAllIds()
{
return _msgIds;
}
/// <summary>
///
/// </summary>
/// <param name="cmdId"></param>
/// <returns></returns>
internal uint GetResponseId(uint cmdId)
{
if (_cmdIdToRspIdMap.ContainsKey(cmdId) == false)
{
throw new Exception("BitMessageIDs::GetResponseId() - cmdIdToRspIdMap does not contains messageId: " + cmdId.ToString("X8"));
}
return _cmdIdToRspIdMap[cmdId];
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
internal uint GetSize(uint id)
{
if (_idToSizeMap.ContainsKey(id) == false)
{
throw new Exception("BitMessageIDs::GetSize() - _idToSizeMap does not contais messageId: " + id.ToString("X8"));
}
return _idToSizeMap[id];
}
/// <summary>
///
/// </summary>
/// <param name="cmdId"></param>
/// <returns></returns>
internal bool IsThereAResponseMessage(uint cmdId)
{
if (_cmdIdToRspIdMap.ContainsKey(cmdId) == false)
{
return false;
}
else
{
return true;
}
}
/// <summary>
///
/// </summary>
/// <param name="msgId"></param>
/// <param name="numBytes"></param>
internal void SetMsgSize(uint msgId, uint numBytes)
{
_idToSizeMap[msgId] = numBytes;
}
/// <summary>
///
/// </summary>
/// <param name="cmdId"></param>
/// <param name="rspId"></param>
internal void SetRspId(uint cmdId, uint rspId)
{
_cmdIdToRspIdMap[cmdId] = rspId;
}
#endregion
}
}

View File

@@ -0,0 +1,389 @@
// 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 Raytheon.Common;
using System.IO;
using System.Collections.Generic;
namespace BitMeasurementManagerLib
{
/// <summary>
/// Handles received messages from the UUT
/// </summary>
internal class BitMsgHandler : MsgDevice
{
#region PublicClassMembers
public enum ErrorCodes
{
NO_ERROR = 0,
UNKNOWN_MSG_ID = 1
};
#endregion
#region PrivateClassMembers
private static object _syncObj = new Object();
private BinaryWriter _binWriter;
private StreamWriter _asciiWriter;
private MeasurementManagerLib.BitMeasurementManager.MessageReceivedDelegate _callback;
private SortedDictionary<uint, bool> _callbackControl;
private readonly BitMessageIDs _messageIds;
private readonly bool _shallWeLogOutgoingBinData;
private readonly bool _shallWeLogOutgoingAsciiData;
private readonly bool _shallWeLogIncomingBinData;
private readonly bool _shallWeLogIncomingAsciiData;
private readonly uint _bitmask;
private readonly string _crcFieldName;
#endregion
#region PublicFuctions
/// <summary>
/// The constructor
/// </summary>
/// <param name="callback">Host callback for received messages</param>
/// <param name="bufferSize">The size of the internal parsing buffer</param>
/// <param name="binLogFileName">THe binary file log name</param>
/// <param name="asciiLogFileName">The ascii file log name</param>
/// <param name="shallWeLogOutgoingBinData"></param>
/// <param name="shallWeLogOutgoingAsciiData"></param>
/// <param name="shallWeLogIncomingBinData"></param>
/// <param name="shallWeLogIncomingAsciiData"></param>
unsafe public BitMsgHandler(BitMessageIDs messageIds, MeasurementManagerLib.BitMeasurementManager.MessageReceivedDelegate callback, uint bufferSize, string binLogFileName, string asciiLogFileName, bool shallWeLogOutgoingBinData, bool shallWeLogOutgoingAsciiData, bool shallWeLogIncomingBinData, bool shallWeLogIncomingAsciiData, uint crcBitmask, string crcFieldName, bool shallWePerformVerboseParserLogging)
: base(new BitMsgParser(messageIds, shallWePerformVerboseParserLogging), bufferSize)
{
_messageIds = messageIds;
// hold onto the callback
_callback = callback;
_shallWeLogOutgoingBinData = shallWeLogOutgoingBinData;
_shallWeLogOutgoingAsciiData = shallWeLogOutgoingAsciiData;
_shallWeLogIncomingBinData = shallWeLogIncomingBinData;
_shallWeLogIncomingAsciiData = shallWeLogIncomingAsciiData;
_bitmask = crcBitmask;
_crcFieldName = crcFieldName;
// set all messages to not issue a callback. Host can change it as necessary
_callbackControl = new SortedDictionary<uint, bool>();
List<uint> msgIds = messageIds.GetAllIds();
foreach (uint id in msgIds)
{
_callbackControl[id] = false;
}
_binWriter = null;
_asciiWriter = null;
SetLogFileNames(binLogFileName, asciiLogFileName);
// set the callback
base.SetCompleteMessageCallback(this.OnCompleteMessage);
}
/// <summary>
/// The finalizer
/// </summary>
~BitMsgHandler()
{
Dispose(false);
}
/// <summary>
/// Add data to the buffer. For this Handler, we are just going to log out the data
/// </summary>
/// <param name="data">The data to add</param>
/// <param name="numBytes">The number of bytes in the data buffer</param>
public override void AddData(byte[] data, uint numBytes)
{
// log out raw data and add to buffer for processing
lock (_syncObj)
{
WriteIncomingDataToLog(data, (int)numBytes);
AddToBuffer(data, numBytes);
}
}
/// <summary>
/// Clear all data from the buffer. We are just logging out data, no buffer to clear
/// </summary>
public void ClearData()
{
ClearBuffer();
}
/// <summary>
///
/// </summary>
public void CloseDataFiles()
{
lock (_syncObj)
{
if (_binWriter != null)
{
_binWriter.Close();
_binWriter.Dispose();
_binWriter = null;
}
if (_asciiWriter != null)
{
_asciiWriter.Close();
_asciiWriter.Dispose();
_asciiWriter = null;
}
}
}
/// <summary>
/// The callback function for when a complete message is received. We are just logging out data, no messages to handle.
/// </summary>
/// <param name="msgId">The id of the message received</param>
/// <param name="pData">The data for the message received</param>
/// <param name="numBytes">the number of bytes in pData</param>
/// <param name="errorCode">The parser error code</param>
unsafe public void OnCompleteMessage(uint msgId, IntPtr pData, uint numBytes, uint errorCode)
{
try
{
if (_messageIds.ContainsId(msgId) == false)
{
ErrorLogger.Instance().Write("BitMsgHandler::OnCompleteMessage() - detected unknown msg id: " + msgId.ToString());
}
else
{
// create the msg and parse it
BitConfigurableMessage msg = BitConfigurableMessageFactory.Instance().RetreiveMessage(msgId);
msg.Parse(pData);
int callbackValue = 0;
// check for crc errors
if (_bitmask != 0x00000000)
{
uint rawStatus = msg.GetDataItemByName<uint>(_crcFieldName);
var maskedStatus = rawStatus & _bitmask;
if (maskedStatus != 0)
{
ErrorLogger.Instance().Write($"Message Status register indicates that a CRC error may have occurred. Raw status read: 0x{rawStatus:X8}. Masked status value: 0x{maskedStatus:X8}");
callbackValue = -1;
}
}
// get the ascii msg
string asciiMessage = msg.ToString();
// log it
WriteIncomingDataToLog(asciiMessage);
// add the message to the buffer in case the host wants it
BitMsgRxBuffer.Instance().AddMsg(msg, false);
// issue callback if requested
uint id = msg.GetMessageId();
if (_callbackControl[id] == true)
{
_callback(id, msg.GetEntireMsgLength(), callbackValue);
}
// some debugging
ErrorLogger.Instance().Write("BitMsgHandler::HandleMsg() - added message " + msgId.ToString("X8") + " to buffer ", ErrorLogger.LogLevel.INFO);
}
}
catch (Exception err)
{
//@@@ need to flow error to the host
ErrorLogger.Instance().Write("BitMsgHandler::HandleMsg() - caught an error: " + err.Message, ErrorLogger.LogLevel.ERROR);
}
}
/// <summary>
/// Subscribe a callback to a specific msg
/// </summary>
/// <param name="msgId">The msg to subscribe to</param>
/// <param name="shallWeIssueCallback">true to get the callbacks, false to not get them</param>
public void SetCallbackControl(uint msgId, bool shallWeIssueCallback)
{
_callbackControl[msgId] = shallWeIssueCallback;
}
/// <summary>
/// Set the data file log names. Closes the previous file and opens a new one
/// </summary>
/// <param name="binLogFileName">The binary file log name</param>
/// <param name="asciiLogFileName">The ascii file log name</param>
public void SetLogFileNames(string binFileName, string asciiFileName)
{
lock (_syncObj)
{
if (_binWriter != null)
{
_binWriter.Close();
}
_binWriter = new BinaryWriter(File.Open(binFileName, FileMode.Create));
if (_asciiWriter != null)
{
_asciiWriter.Close();
}
_asciiWriter = new StreamWriter(File.Open(asciiFileName, FileMode.Create));
}
}
/// <summary>
/// Stops the message handler
/// </summary>
public void QuitHandler()
{
base.QuitThread();
}
/// <summary>
/// Write bin data to a file
/// </summary>
/// <param name="data">The data to write</param>
/// <param name="numBytes">The number of bytes to write</param>
public void WriteIncomingDataToLog(byte[] data, int numBytes)
{
lock (_syncObj)
{
if (_binWriter == null && _shallWeLogIncomingBinData == true)
{
throw new Exception("BitMsgHandler::WriteIncomingDataToLog() - Trying to log bin data before the log file is open");
}
else if (_shallWeLogIncomingBinData == true)
{
// write the data out and flush it for immediate viewing
_binWriter.Write(data, 0, (int)numBytes);
_binWriter.Flush();
}
}
}
/// <summary>
/// Write ascii data to a log file. Prepends a timestamp to the data
/// </summary>
/// <param name="data">The data to write</param>
public void WriteIncomingDataToLog(string data)
{
lock (_syncObj)
{
if (_asciiWriter == null && _shallWeLogIncomingAsciiData == true)
{
throw new Exception("BitMsgHandler::WriteIncomingDataToLog() - Trying to log ascii data before the log file is open");
}
else if (_shallWeLogIncomingAsciiData == true)
{
string timestamp = "Time: " + Util.GetTimeString();
string dataToLog = timestamp + "\r\n" + data;
_asciiWriter.WriteLine(dataToLog);
_asciiWriter.Flush();
}
}
}
/// <summary>
/// Write bin data to a file
/// </summary>
/// <param name="data">The data to write</param>
/// <param name="numBytes">The number of bytes to write</param>
public void WriteOutgoingDataToLog(byte[] data, int numBytes)
{
lock (_syncObj)
{
if (_binWriter == null && _shallWeLogOutgoingBinData == true)
{
throw new Exception("BitMsgHandler::WriteOutgoingDataToLog() - Trying to log bin data before the log file is open");
}
else if (_shallWeLogOutgoingBinData == true)
{
_binWriter.Write(data, 0, numBytes);
_binWriter.Flush();
}
}
}
/// <summary>
/// Write ascii data to a log file. Prepends a timestamp to the data
/// </summary>
/// <param name="data">The data to write</param>
public void WriteOutgoingDataToLog(string data)
{
lock (_syncObj)
{
if (_asciiWriter == null && _shallWeLogOutgoingAsciiData == true)
{
throw new Exception("BitMsgHandler::WriteOutgoingDataToLog() - Trying to log ascii data before the log file is open");
}
else if (_shallWeLogOutgoingAsciiData == true)
{
string timestamp = "Time: " + Util.GetTimeString();
string dataToLog = timestamp + "\r\n" + data;
_asciiWriter.WriteLine(dataToLog);
_asciiWriter.Flush();
}
}
}
/// <summary>
///
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
try
{
// call the parent dispose first
base.Dispose(disposing);
// now dispose of our resources
if (_binWriter != null)
{
_binWriter.Dispose();
}
if (_asciiWriter != null)
{
_asciiWriter.Dispose();
}
}
catch (Exception err)
{
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,234 @@
// 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>
/// Parses out messages that go between the VRSUI and the Test Controller
/// This class is meant to be used by both the test controller and the VRSUI, so it parses out messages that target either of those systems
/// </summary>
internal class BitMsgParser : IMsgParser
{
#region PublicClassMembers
#endregion
#region PrivateClassMembers
private readonly BitMessageIDs _messageIdToSizeMap;
private BitMsgEndianControl.HeaderDef _headerDef;
private readonly bool _shallWePerformVerboseParserLogging;
#endregion
#region PrivateFuctions
/// <summary>
///
/// </summary>
/// <param name="pData"></param>
/// <param name="numBytesInPdata"></param>
/// <param name="bytesToRemove"></param>
/// <param name="messageId"></param>
/// <param name="errorCode"></param>
/// <returns></returns>
private bool HandleData(IntPtr pData, uint numBytesInPdata, ref uint bytesToRemove, ref uint messageId, ref uint errorCode)
{
// check to see if we have enough data for at least a standard header
uint payloadHeaderSize = BitConfigurableMessageHeader.GetHeaderSize();
if (numBytesInPdata < payloadHeaderSize)
{
ErrorLogger.Instance().Write("BitMsgParser::HandleData() - not enough data in the buffer to form a header. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, needed " + payloadHeaderSize.ToString() + " for a header", ErrorLogger.LogLevel.INFO);
bytesToRemove = 0;
return false;
}
uint id = BitConfigurableMessageHeader.GetMessageId(pData, numBytesInPdata);
bool isSecondaryIdUsed = false;
uint secondaryId = BitConfigurableMessageHeader.GetSecondaryMessageId(pData, numBytesInPdata, out isSecondaryIdUsed);
// check that this is an expected message
if (_messageIdToSizeMap.ContainsId(id) == false)
{
uint numBytesToRemove = Resync(pData, numBytesInPdata);
string msg = "BitMsgParser::HandleData() - unknown id received: " + id.ToString("X8") + " When resyncing threw away " + numBytesToRemove.ToString() + " Bytes";
ErrorLogger.Instance().Write(msg, ErrorLogger.LogLevel.ERROR);
bytesToRemove = numBytesToRemove;
return false;
}
// look at secondary ID if applicable
if (isSecondaryIdUsed == true)
{
if (secondaryId != _headerDef.secondaryMsgIdExpectedValue)
{
uint numBytesToRemove = Resync(pData, numBytesInPdata);
string msg = "BitMsgParser::HandleData() - detected seondary ID: " + secondaryId.ToString("X8") + " was not as expected: " + _headerDef.secondaryMsgIdExpectedValue.ToString("X8") + " When resyncing threw away " + numBytesToRemove.ToString() + " Bytes";
ErrorLogger.Instance().Write(msg, ErrorLogger.LogLevel.ERROR);
bytesToRemove = numBytesToRemove;
return false;
}
}
uint msgSize = _messageIdToSizeMap.GetSize(id);
// do we have enough data to make the complete message
if (numBytesInPdata < msgSize)
{
ErrorLogger.Instance().Write("BitMsgParser::HandleData() - not enough data in the buffer to form a entire message. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, expected msg size is: " + msgSize.ToString(), ErrorLogger.LogLevel.INFO);
// need to wait for more data
bytesToRemove = 0;
return false;
}
// everything has checked out, set the return params
bytesToRemove = msgSize;
if (_shallWePerformVerboseParserLogging == true)
{
ErrorLogger.Instance().Write("BitMsgParser::HandleData() - found msg: " + id.ToString() + " which has " + msgSize.ToString() + " bytes", ErrorLogger.LogLevel.INFO);
}
messageId = id;
return true;
}
/// <summary>
///
/// </summary>
/// <param name="pData"></param>
/// <param name="numBytesInPdata"></param>
/// <returns>The number of bytes to remove from the buffer</returns>
private uint Resync(IntPtr pData, uint numBytesInPdata)
{
ErrorLogger.Instance().Write("BitMsgParser::Resync() - Begin", ErrorLogger.LogLevel.INFO);
// increment pData by 1
pData = IntPtr.Add(pData, 1);
// keep track of how many bytes to remove
uint bytesToRemove = 1;
// update bytes remaining
numBytesInPdata = numBytesInPdata - 1;
bool didWeFindMsg = false;
while (didWeFindMsg == false)
{
// check to see if we have enough data for at least a standard header
uint payloadHeaderSize = BitConfigurableMessageHeader.GetHeaderSize();
if (numBytesInPdata < payloadHeaderSize)
{
ErrorLogger.Instance().Write("BitMsgParser::Resync() - not enough data in the buffer to form a header. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, needed " + payloadHeaderSize.ToString() + " for a header. Removing " + bytesToRemove.ToString() + " bytes", ErrorLogger.LogLevel.INFO);
break;
}
uint id = BitConfigurableMessageHeader.GetMessageId(pData, numBytesInPdata);
bool isSecondaryIdUsed = false;
uint secondaryId = BitConfigurableMessageHeader.GetSecondaryMessageId(pData, numBytesInPdata, out isSecondaryIdUsed);
// check that this is an expected message
if (_messageIdToSizeMap.ContainsId(id) == false)
{
// need to keep looking
// increment pData by 1
pData = IntPtr.Add(pData, 1);
// keep track of how many bytes to remove
bytesToRemove++;
// update bytes remaining
numBytesInPdata--;
}
else
{
// look at secondary ID if applicable
if (isSecondaryIdUsed == true)
{
if (secondaryId != _headerDef.secondaryMsgIdExpectedValue)
{
// need to keep looking
// increment pData by 1
pData = IntPtr.Add(pData, 1);
// keep track of how many bytes to remove
bytesToRemove++;
// update bytes remaining
numBytesInPdata--;
}
else
{
didWeFindMsg = true;
ErrorLogger.Instance().Write("BitMsgParser::Resync() - Detected message ID: " + id.ToString("X8") + ". Detected Secondary ID: " + secondaryId.ToString("X8") + " Resync complete. Removing " + bytesToRemove.ToString() + " Bytes", ErrorLogger.LogLevel.INFO);
break;
}
}
else
{
didWeFindMsg = true;
ErrorLogger.Instance().Write("BitMsgParser::Resync() - Detected message ID: " + id.ToString("X8") + ". Resync complete. Removing " + bytesToRemove.ToString() + " Bytes", ErrorLogger.LogLevel.INFO);
break;
}
}
}
ErrorLogger.Instance().Write("BitMsgParser::Resync() - returning " + bytesToRemove.ToString(), ErrorLogger.LogLevel.INFO);
return bytesToRemove;
}
#endregion
#region PublicFuctions
/// <summary>
///
/// </summary>
/// <param name="messageIds"></param>
/// <param name="shallWePerformVerboseParserLogging"></param>
public BitMsgParser(BitMessageIDs messageIds, bool shallWePerformVerboseParserLogging)
{
// Using it to hold onto valid message ids and the size
_messageIdToSizeMap = messageIds;
_shallWePerformVerboseParserLogging = shallWePerformVerboseParserLogging;
_headerDef = BitMsgEndianControl.Instance().GetHeaderDef();
}
/// <summary>
/// Search the data buffer for the next valid message
/// </summary>
/// <param name="pData">The data buffer to search</param>
/// <param name="numBytesInPdata">The number of bytes in pData</param>
/// <param name="bytesToRemove">The number of bytes to remove from the buffer</param>
/// <param name="messageId">The message id of the message that was found</param>
/// <returns>true if a message was found, false otherwise</returns>
public bool Run(IntPtr pData, uint numBytesInPdata, ref uint bytesToRemove, ref uint messageId, ref uint errorCode)
{
// default error code to 0;
errorCode = 0;
return HandleData(pData, numBytesInPdata, ref bytesToRemove, ref messageId, ref errorCode);
}
#endregion
}
}