Big changes
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user