// 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
{
///
/// This class interfaces to a host application for the purpose of sending and receiving messages to/from a UUT
///
public class BitMeasurementManager : IDisposable
{
#region PublicClassMembers
///
/// A delegate for host applications to get notified once a particular message arrives
///
/// The message id that was received
/// The number of bytes in the message
/// An error code
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
///
/// Dispose of this object.
///
/// True = currently disposing, False = not disposing.
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);
}
}
}
///
/// Write bytes onto an interface
///
/// the bytes to send
/// the number of bytes to send
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());
}
}
}
///
/// Send out a message and wait for a response
///
/// The message to send
/// Timeout in ms
///
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 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(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(comNodeName);
_commNode?.Initialize();
}
catch (Exception)
{
Dispose(true);
throw;
}
}
///
/// The Finalizer
///
~BitMeasurementManager()
{
Dispose(false);
}
///
///
///
///
public void AddDataTestFunction(byte[] dataToAdd)
{
_msgHandler.AddData(dataToAdd, (uint)dataToAdd.Length);
}
///
/// Closes the data files
///
public void CloseDataFiles()
{
lock (_syncObj)
{
_msgHandler.CloseDataFiles();
}
}
///
/// Instantiate a message object. The host configure its parameters prior to sending it
///
/// The message id for the message to create
/// The message object
public BitConfigurableMessage CreateMessage(uint messageId)
{
lock (_syncObj)
{
BitConfigurableMessage message = BitConfigurableMessageFactory.Instance().RetreiveMessage(messageId);
return message;
}
}
///
/// Release the resources
///
public void Dispose()
{
Dispose(true);
}
///
///
///
///
///
///
public TType GetDataItemByName(BitConfigurableMessage message, string name)
{
lock (_syncObj)
{
return message.GetDataItemByName(name);
}
}
///
///
///
///
///
///
public uint GetDataItemByNameUint(BitConfigurableMessage message, string dataItemName)
{
lock (_syncObj)
{
uint dataValue = GetDataItemByName(message, dataItemName);
return dataValue;
}
}
///
/// Return a list of message IDs that are supported
///
/// A list of message Ids
public List GetSupportedMessages()
{
lock (_syncObj)
{
List mesages = _messageIds.GetAllIds();
return mesages;
}
}
///
/// Retrieve the newest message in the buffer
///
/// The message ID to Retrieve
/// True to delete all of the other messages of this ID
/// The retrieved message
public BitConfigurableMessage GetNewestMessage(uint rspMessageId, bool shallWeDeleteOthers = true)
{
lock (_syncObj)
{
BitConfigurableMessage messageToReturn = BitMsgRxBuffer.Instance().GetNewestMessage(rspMessageId, shallWeDeleteOthers);
return messageToReturn;
}
}
///
/// Retrieve the oldest message in the buffer
///
/// The message ID to Retrieve
/// The retrieved message
public BitConfigurableMessage GetOldestMessage(uint rspMessageId)
{
lock (_syncObj)
{
BitConfigurableMessage messageToReturn = BitMsgRxBuffer.Instance().GetOldestMessage(rspMessageId);
return messageToReturn;
}
}
///
/// Open the communication device, if it is already open, it closes it and then reopens it
///
public void OpenCommDevice()
{
lock (_syncObj)
{
// shut it down and reinitialize
_commNode.Shutdown();
_commNode.Initialize();
}
}
///
/// Runs a BIT test, return the test results
///
///
/// The number of ms to wait for a response
///
/// The test result register
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(_bitResultsFieldName.ToUpper());
return testResult;
}
}
///
///
///
///
///
///
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);
}
}
///
/// Send out a message and wait for a response
///
/// The message ID to send
///
/// The response message for the command that was sent
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;
}
}
///
/// Send out a message on the comm interface
///
/// The message to send
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);
}
}
///
/// Enable or Disable the Callback for a specific message
///
///
///
public void SetCallbackControl(uint msgId, bool shallWeEnableCallback)
{
lock (_syncObj)
{
_msgHandler.SetCallbackControl(msgId, shallWeEnableCallback);
}
}
#endregion
}
}