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