390 lines
13 KiB
C#
390 lines
13 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 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
|
|
}
|
|
}
|