492 lines
17 KiB
C#
492 lines
17 KiB
C#
// 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
|
|
}
|
|
}
|