Major upgrade
This commit is contained in:
@@ -1,215 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// BITCommand.cs
|
||||
// 8/31/2023
|
||||
// NGI - Next Generation Interceptor
|
||||
//
|
||||
// Contract No. HQ0856-21-C-0003/1022000209
|
||||
//
|
||||
// DISTRIBUTION STATEMENT F: FURTHER DISSEMINATION ONLY AS DIRECTED BY
|
||||
// MISSILE DEFENSE AGENCY, MDA/GMY NEXT GENERATION INTERCEPTOR PROJECT
|
||||
// OFFICE (DATE OF DETERMINATION 14 JUNE 2021) OR HIGHER DOD AUTHORITY.
|
||||
// OTHER REQUESTS FOR THIS DOCUMENT SHALL BE REFERRED TO: MISSILE DEFENSE
|
||||
// AGENCY, CONTRACTS DIRECTORATE, ATTN: GMY‐K, BLDG. 5222 MARTIN ROAD,
|
||||
// REDSTONE ARSENAL, AL 35898.
|
||||
//
|
||||
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA WHOSE EXPORT IS
|
||||
// RESTRICTED BY THE ARMS EXPORT CONTROL ACT (TITLE 22, U.S.C.,
|
||||
// SECTION 2751, ET SEQ.) OR THE EXPORT ADMINISTRATION ACT OF 1979
|
||||
// (TITLE 50 U.S.C. APP. 2401 ET SEQ.), AS AMENDED. VIOLATIONS OF
|
||||
// THESE EXPORT LAWS ARE SUBJECT TO SEVERE CRIMINAL PENALTIES.
|
||||
// DISSEMINATE IN ACCORDANCE WITH PROVISIONS OF DOD DIRECTIVE 5230.25.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
//
|
||||
// DESTRUCTION NOTICE - FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN
|
||||
// DOD 5220.22-M, NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL,
|
||||
// FEBRUARY 2006, INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5,
|
||||
// SECTION 7, OR DODM 5200.01-VOLUME 3, DOD INFORMATION SECURITY PROGRAM:
|
||||
// PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3, SECTION 17. FOR
|
||||
// CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM
|
||||
// 5200.01-VOLUME 4, INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED
|
||||
// INFORMATION.
|
||||
//
|
||||
// CONTROLLED BY: MISSILE DEFENSE AGENCY
|
||||
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
|
||||
// CUI CATEGORY: CTI
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
// Ignore Spelling: Deserialized
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace BitGenSoftMeasurementManagerLib
|
||||
{
|
||||
|
||||
[XmlType(TypeName = "ResponseMessageType")]
|
||||
public enum ResponseMessageType
|
||||
{
|
||||
U, // Unknown or Undefined
|
||||
R, // Required
|
||||
E, // Error
|
||||
P // Parametric
|
||||
}
|
||||
|
||||
[XmlType(TypeName = "ParamType")]
|
||||
public enum ParameterType
|
||||
{
|
||||
U, // Unknown or Undefined will default to string
|
||||
N, // Numeric
|
||||
S, // String
|
||||
A, // Array
|
||||
P // p-data array
|
||||
}
|
||||
|
||||
|
||||
[XmlType(TypeName = "BITResponseMsg")]
|
||||
public class BITResponseMsg
|
||||
{
|
||||
[XmlAttribute("type")]
|
||||
public ResponseMessageType ResponseType { get; set; }
|
||||
|
||||
[XmlText]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[XmlType("Value")]
|
||||
public class BITParameter
|
||||
{
|
||||
[XmlAttribute(AttributeName = "name")]
|
||||
public string Key { get; set; }
|
||||
|
||||
[XmlAttribute(AttributeName = "type")]
|
||||
public ParameterType ParameterType { get; set; }
|
||||
|
||||
[XmlAttribute(AttributeName = "delim")]
|
||||
public string Delim { get; set; }
|
||||
|
||||
[XmlText]
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class BITCommand
|
||||
{
|
||||
[XmlElement(ElementName = "Command")]
|
||||
public string Command { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "CommandTimeout")]
|
||||
public uint CommandTimeout { get; set; }
|
||||
|
||||
[XmlArray("CommandParameters")]
|
||||
[XmlArrayItem("Value", Type = typeof(BITParameter))]
|
||||
public List<BITParameter> CommandParameters { get; set; } = new List<BITParameter>();
|
||||
|
||||
[XmlArray("CommandResponses")]
|
||||
[XmlArrayItem("BITResponseMsg", Type = typeof(BITResponseMsg))]
|
||||
public List<BITResponseMsg> CommandResponses { get; set; } = new List<BITResponseMsg>();
|
||||
|
||||
[XmlElement(ElementName = "ParametricResponse")]
|
||||
public string ParametricResponse { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "ParametricTimeout")]
|
||||
public uint ParametricTimeout { get; set; }
|
||||
|
||||
[XmlArray("ResponseParameters")]
|
||||
[XmlArrayItem("Value", Type = typeof(BITParameter))]
|
||||
public List<BITParameter> ResponseParameters { get; set; } = new List<BITParameter>();
|
||||
|
||||
/// <summary>
|
||||
/// converts one hex parameter string into parameter array
|
||||
/// </summary>
|
||||
public void UnfoldHexParameters()
|
||||
{
|
||||
if (!CommandParameters.Any(p => p.ParameterType == ParameterType.P))
|
||||
return;
|
||||
|
||||
var paramList = CommandParameters.Where(p => p.ParameterType == ParameterType.P).ToList();
|
||||
List<BITParameter> removeList = new List<BITParameter>();
|
||||
foreach (BITParameter param in paramList)
|
||||
{
|
||||
AddPDataArrayValues(param.Key, param.Value, param.Delim);
|
||||
removeList.Add(param);
|
||||
}
|
||||
CommandParameters.RemoveAll(c => removeList.Contains(c));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// takes a hex string and breaks it up into individual characters
|
||||
/// then inserts them as parameters
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="delim"></param>
|
||||
private void AddPDataArrayValues(string key, string value, string delim)
|
||||
{
|
||||
var parms = BreakByPages(value, delim);
|
||||
|
||||
int index = 0;
|
||||
foreach (var item in parms)
|
||||
{
|
||||
string itemKey = $"{key}[{index++}]";
|
||||
string itemValue = item;
|
||||
CommandParameters.Add(new BITParameter { Key = itemKey, Value = itemValue } );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// takes a large hex string and breaks it in multiple pages based on the known header
|
||||
/// adjusts the size of the page to be divisible by 4 bytes
|
||||
/// and also adds a 12 byte footer of zero values to the end of the page
|
||||
/// </summary>
|
||||
/// <param name="hexStr"></param>
|
||||
/// <param name="header"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<string> BreakByPages(string hexStr, string header)
|
||||
{
|
||||
const int footerSize = 12;
|
||||
string[] pages = hexStr.Split(new[] { header }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (string page in pages)
|
||||
{
|
||||
string completePage = header + page;
|
||||
int pageSize = (completePage.Length + 7) & ~7;
|
||||
string paddedPage = completePage.PadRight(pageSize + (footerSize * 2), '0');
|
||||
IEnumerable<string> hexChars = BreakIntoHexCharacters(paddedPage);
|
||||
foreach (string hexChar in hexChars)
|
||||
{
|
||||
yield return hexChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// takes a large string of hex characters and breaks it into individual hex values
|
||||
/// then yields these values to the calling code
|
||||
/// </summary>
|
||||
/// <param name="hexString"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<string> BreakIntoHexCharacters(string hexString)
|
||||
{
|
||||
int characterSize = 2;
|
||||
int length = hexString.Length;
|
||||
for (int i = 0; i < length; i += characterSize)
|
||||
{
|
||||
if (i + characterSize > length)
|
||||
{
|
||||
hexString = hexString.PadRight(i + characterSize, '0');
|
||||
}
|
||||
yield return "0x" + hexString.Substring(i, characterSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,936 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// BitGenSoftMeasurementManager.cs
|
||||
// 7/28/2022
|
||||
// NGI - Next Generation Interceptor
|
||||
//
|
||||
// Contract No. HQ0856-21-C-0003/1022000209
|
||||
//
|
||||
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
|
||||
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
//
|
||||
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
|
||||
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
|
||||
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
|
||||
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
|
||||
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
|
||||
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
|
||||
//
|
||||
// CONTROLLED BY: MISSILE DEFENSE AGENCY
|
||||
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
|
||||
// CUI CATEGORY: CTI
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using Raytheon.Instruments;
|
||||
using Raytheon.Instruments.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using BitGenSoftMeasurementManagerLib;
|
||||
|
||||
namespace MeasurementManagerLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Bit Gen Soft Measurement Manager class
|
||||
/// </summary>
|
||||
public class BitGenSoftMeasurementManager : IDisposable
|
||||
{
|
||||
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly Dictionary<string, IBit> _bitNodes = new Dictionary<string, IBit>();
|
||||
|
||||
private readonly IInstrumentManager _instrumentManager;
|
||||
private IConfigurationManager _configurationManager;
|
||||
private int _checkForMessageIntervalMs = 10;
|
||||
/// <summary>
|
||||
/// constructor that will create a list of BIT instruments
|
||||
/// </summary>
|
||||
/// <param name="instrumentManager"></param>
|
||||
/// <param name="instrumentNames"></param>
|
||||
public BitGenSoftMeasurementManager(IInstrumentManager instrumentManager, List<string> instrumentNames)
|
||||
: this(instrumentManager)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (string instrumentName in instrumentNames)
|
||||
{
|
||||
var bitNode = (IBit)_instrumentManager.GetGenericInstrument(instrumentName);
|
||||
if (bitNode == null)
|
||||
{
|
||||
_logger.Error("Error creating TCP BIT device, check your settings");
|
||||
}
|
||||
else
|
||||
{
|
||||
_bitNodes.Add(instrumentName, bitNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"Unable to create BIT instrument\n{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// in case instrument manager was passed from upper level
|
||||
/// </summary>
|
||||
/// <param name="instrumentManager"></param>
|
||||
private BitGenSoftMeasurementManager(IInstrumentManager instrumentManager)
|
||||
{
|
||||
_instrumentManager = instrumentManager;
|
||||
InitializeConfigurationManager();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initializes configuration manager,
|
||||
/// will use configuration path from General Instrument Manager if available
|
||||
/// otherwise will try to use the instruments path
|
||||
/// </summary>
|
||||
private void InitializeConfigurationManager()
|
||||
{
|
||||
string defaultPath;
|
||||
if (_instrumentManager is GeneralInstrumentManager generalinstrumentManager)
|
||||
{
|
||||
defaultPath = generalinstrumentManager._configLocation;
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultPath = _instrumentManager._partsLocation;
|
||||
}
|
||||
|
||||
_configurationManager = new RaytheonConfigurationManager(defaultPath);
|
||||
|
||||
var config = _configurationManager.GetConfiguration("BitGenSoftMeasurementManager");
|
||||
|
||||
_checkForMessageIntervalMs = config.GetConfigurationValue("Settings", "CheckForMessageIntervalMs", 10);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initialize COE nodes based on test type
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="testType"></param>
|
||||
public void InitNodes()
|
||||
{
|
||||
foreach (var node in _bitNodes)
|
||||
{
|
||||
try
|
||||
{
|
||||
IBit bitNode = node.Value;
|
||||
bitNode.Initialize();
|
||||
bitNode.Open();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// close all connections
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var bitNode in _bitNodes)
|
||||
{
|
||||
bitNode.Value?.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// straight pass-through the message and parameters
|
||||
/// </summary>
|
||||
/// <param name="messageId"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <param name="messageParams"></param>
|
||||
/// <returns></returns>
|
||||
public bool RunBIT(string messageId, uint timeoutInMs, IEnumerable<KeyValuePair<string, string>> messageParams = null)
|
||||
{
|
||||
if (_bitNodes.Any())
|
||||
{
|
||||
IBit bitNode = _bitNodes.First().Value;
|
||||
return bitNode.RunBIT(messageId, timeoutInMs, messageParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error($"Unable to locate BIT node. No nodes defined");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// straight pass-through the message and parameters
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="messageId"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <param name="messageParams"></param>
|
||||
/// <returns></returns>
|
||||
public bool RunBIT(string instrumentName, string messageId, uint timeoutInMs, IEnumerable<KeyValuePair<string, string>> messageParams = null)
|
||||
{
|
||||
if (_bitNodes.ContainsKey(instrumentName))
|
||||
{
|
||||
return _bitNodes[instrumentName].RunBIT(messageId, timeoutInMs, messageParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error($"Unable to locate BIT node {instrumentName}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// always runs the request on the first node,
|
||||
/// </summary>
|
||||
/// <param name="messageIdOut"></param>
|
||||
/// <param name="messageIdIn"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <param name="messageParams"></param>
|
||||
/// <returns></returns>
|
||||
public BitTestResults RunBITWaitForResults(string messageIdOut,
|
||||
string messageIdIn,
|
||||
uint timeoutInMs,
|
||||
IEnumerable<KeyValuePair<string, string>> messageParams = null)
|
||||
{
|
||||
if (_bitNodes.Any())
|
||||
{
|
||||
IBit bitNode = _bitNodes.First().Value;
|
||||
return bitNode.RunBITWaitForResults(messageIdOut, messageIdIn, timeoutInMs, messageParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error($"Unable to locate BIT node. No nodes defined");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// run BIT message and wait for result from the instrument based on the name
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="messageIdOut"></param>
|
||||
/// <param name="messageIdIn"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <param name="messageParams"></param>
|
||||
/// <returns></returns>
|
||||
public BitTestResults RunBITWaitForResults(string instrumentName,
|
||||
string messageIdOut,
|
||||
string messageIdIn,
|
||||
uint timeoutInMs,
|
||||
IEnumerable<KeyValuePair<string, string>> messageParams = null)
|
||||
{
|
||||
if (_bitNodes.ContainsKey(instrumentName))
|
||||
{
|
||||
return _bitNodes[instrumentName].RunBITWaitForResults(messageIdOut, messageIdIn, timeoutInMs, messageParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error($"Unable to locate BIT node {instrumentName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RunBITWaitForResults for the whole list of BIT Commands
|
||||
/// runs on the first node
|
||||
/// </summary>
|
||||
/// <param name="commands"></param>
|
||||
/// <returns></returns>
|
||||
public List<BitTestResults> RunBITWaitForResultsList(List<BITCommand> commands)
|
||||
{
|
||||
if (_bitNodes.Any())
|
||||
{
|
||||
return RunBITWaitForResultsList(commands, _bitNodes.First().Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error("Unable to locate BIT node. No nodes defined");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RunBITWaitForResults for the whole list of BIT Commands
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="commands"></param>
|
||||
/// <returns></returns>
|
||||
public List<BitTestResults> RunBITWaitForResultsList(string instrumentName, List<BITCommand> commands)
|
||||
{
|
||||
if (_bitNodes.ContainsKey(instrumentName))
|
||||
{
|
||||
return RunBITWaitForResultsList(commands, _bitNodes[instrumentName]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error($"Unable to locate BIT node {instrumentName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs BIT command and returns the results as a list
|
||||
/// </summary>
|
||||
/// <param name="commands"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<BitTestResults>> RunBITWaitForResultsListAsync(List<BITCommand> commands)
|
||||
{
|
||||
if (_bitNodes.Any())
|
||||
{
|
||||
return await RunBITWaitForResultsListAsync(commands, _bitNodes.First().Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error("Unable to locate BIT node. No nodes defined");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs BIT command for specific instrument and returns the results as a list
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="commands"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<BitTestResults>> RunBITWaitForResultsListAsync(string instrumentName, List<BITCommand> commands)
|
||||
{
|
||||
if (_bitNodes.ContainsKey(instrumentName))
|
||||
{
|
||||
return await RunBITWaitForResultsListAsync(commands, _bitNodes[instrumentName]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error($"Unable to locate BIT node {instrumentName}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// asynchronously runs BIT command and waits for multiple results including parametric messages
|
||||
/// </summary>
|
||||
/// <param name="instrumentName">BIT instrument to run command</param>
|
||||
/// <param name="bitCommandId">main command</param>
|
||||
/// <param name="timeout">timeout value in ms for the main response</param>
|
||||
/// <param name="commandParams">optional parameters for the main command</param>
|
||||
/// <param name="parametricResponseIds">list of additional response messages with their respective timeouts to wait for</param>
|
||||
/// <param name="timeout2">parametric timeout value in ms</param>
|
||||
/// <param name="errorMessageId">nack response id when provided will be expected as a possible response for either main response or parametric response</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<List<BitTestResults>> RunBITWaitForResultsAsync( string instrumentName,
|
||||
string bitCommandId,
|
||||
int retries,
|
||||
uint timeout,
|
||||
IEnumerable<KeyValuePair<string, string>> commandParams = null,
|
||||
List<string> parametricResponseIds = null,
|
||||
uint timeout2 = 0,
|
||||
string errorMessageId = null)
|
||||
{
|
||||
IBit bitGenSoftManager = _bitNodes[instrumentName] ?? throw new Exception("BitGenSoftManager is null. Unable to perform operation.");
|
||||
|
||||
BITCommand command = BuildBITCommand(bitCommandId, retries, timeout, commandParams, parametricResponseIds, timeout2, errorMessageId);
|
||||
|
||||
return await RunBITWaitForResultsListAsync(new List<BITCommand> { command }, bitGenSoftManager);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keep reading any of the messages from the list
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="parametricResponseIds"></param>
|
||||
/// <param name="timeOut"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task KeepReadingBitResultsListAsync(string instrumentName, List<string> parametricResponseIds, CancellationToken token)
|
||||
{
|
||||
IBit bitNode = _bitNodes[instrumentName] ?? throw new Exception("BitGenSoftManager is null. Unable to perform operation.");
|
||||
await KeepReadingBitResultsListAsync(parametricResponseIds, token, bitNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keep reading any of the messages from the list from the first node
|
||||
/// </summary>
|
||||
/// <param name="parametricResponseIds"></param>
|
||||
/// <param name="timeOut"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task KeepReadingBitResultsListAsync(List<string> parametricResponseIds, CancellationToken token)
|
||||
{
|
||||
IBit bitNode = _bitNodes.First().Value;
|
||||
await KeepReadingBitResultsListAsync(parametricResponseIds, token, bitNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// looking for a any of the messages from the list
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="parametricResponseIds"></param>
|
||||
/// <param name="timeOut"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<List<BitTestResults>> GetBitResultsListAsync(string instrumentName, List<string> parametricResponseIds, int timeOut)
|
||||
{
|
||||
IBit bitNode = _bitNodes[instrumentName] ?? throw new Exception("BitGenSoftManager is null. Unable to perform operation.");
|
||||
return await GetBitResultsListAsync(parametricResponseIds, timeOut, bitNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// looking for a any of the messages from the list on the first node
|
||||
/// </summary>
|
||||
/// <param name="parametricResponseIds"></param>
|
||||
/// <param name="timeOut"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<List<BitTestResults>> GetBitResultsListAsync(List<string> parametricResponseIds, int timeOut)
|
||||
{
|
||||
IBit bitNode = _bitNodes.First().Value;
|
||||
return await GetBitResultsListAsync(parametricResponseIds, timeOut, bitNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// look for results in the node until either result was found or canceled
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="responseId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<BitTestResults> GetBITResultsAsync(CancellationToken token, string responseId)
|
||||
{
|
||||
IBit bitNode = _bitNodes.First().Value;
|
||||
return await GetBITResultsAsync(token, responseId, bitNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// look for results in the node until either result was found or canceled
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="responseId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<BitTestResults> GetBITResultsAsync(string instrumentName, CancellationToken token, string responseId)
|
||||
{
|
||||
IBit bitNode = _bitNodes[instrumentName] ?? throw new Exception("BitGenSoftManager is null. Unable to perform operation.");
|
||||
return await GetBITResultsAsync(token, responseId, bitNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// look for results in either node
|
||||
/// </summary>
|
||||
/// <param name="messageId"></param>
|
||||
/// <returns></returns>
|
||||
public BitTestResults GetBITResults(string messageId)
|
||||
{
|
||||
_logger.Trace($"Getting BIT result for: {messageId}.");
|
||||
if (_bitNodes.Any())
|
||||
{
|
||||
IBit bitNode = _bitNodes.First().Value;
|
||||
return bitNode.GetBITResults(messageId);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// look for results in either node
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="messageId"></param>
|
||||
/// <returns></returns>
|
||||
public BitTestResults GetBITResults(string instrumentName, string messageId)
|
||||
{
|
||||
_logger.Trace($"{instrumentName} Getting BIT result for: {messageId}.");
|
||||
return _bitNodes.ContainsKey(instrumentName) ? _bitNodes[instrumentName].GetBITResults(messageId) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// opens a folder parse XML files for BITCommand definitions and returns a list
|
||||
/// </summary>
|
||||
/// <param name="dir"></param>
|
||||
/// <returns></returns>
|
||||
public Dictionary<string, List<BITCommand>> GetBITCommands(string directoryPath)
|
||||
{
|
||||
Dictionary<string, List<BITCommand>> bitCommands = new Dictionary<string, List<BITCommand>>();
|
||||
|
||||
try
|
||||
{
|
||||
string[] xmlFiles;
|
||||
if (directoryPath.EndsWith(".xml", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
xmlFiles = new string[] {directoryPath};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get all XML files recursively in the specified directory
|
||||
xmlFiles = Directory.GetFiles(directoryPath, "*.xml", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
foreach (string xmlFile in xmlFiles)
|
||||
{
|
||||
ConfigurationFile configFile = new ConfigurationFile(xmlFile);
|
||||
|
||||
List<string> sections = configFile.ReadAllSections();
|
||||
|
||||
foreach (string section in sections)
|
||||
{
|
||||
List<BITCommand> commands = configFile.ReadList<BITCommand>(section, "BIT_CMD");
|
||||
if(bitCommands.ContainsKey(section))
|
||||
{
|
||||
_logger.Warn($"Found a duplicate BIT configuration section {section}, overwriting from {xmlFile} file.");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Trace($"Adding {section} commands from {xmlFile} file");
|
||||
}
|
||||
bitCommands[section] = commands;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"Error reading BIT Command definitions in {directoryPath}");
|
||||
throw;
|
||||
}
|
||||
|
||||
return bitCommands;
|
||||
}
|
||||
|
||||
#region Private functions
|
||||
|
||||
/// <summary>
|
||||
/// will keep pumping messages from the receiving queue until canceled
|
||||
/// </summary>
|
||||
/// <param name="parametricResponseIds"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="bitNode"></param>
|
||||
/// <returns></returns>
|
||||
private async Task KeepReadingBitResultsListAsync(List<string> parametricResponseIds, CancellationToken token, IBit bitNode)
|
||||
{
|
||||
_logger.Trace($"{bitNode.Name} Start continuously reading these messages: {string.Join(", ", parametricResponseIds)}.");
|
||||
|
||||
Dictionary<uint, int> score = new Dictionary<uint, int>();
|
||||
do
|
||||
{
|
||||
foreach (var responseId in parametricResponseIds)
|
||||
{
|
||||
BitTestResults bitTestresults = await GetBITResultsAsync(token, responseId, bitNode);
|
||||
|
||||
if (bitTestresults != null && !string.IsNullOrEmpty(bitTestresults.Label))
|
||||
{
|
||||
if(uint.TryParse(bitTestresults.Label, out uint label))
|
||||
{
|
||||
if(!score.ContainsKey(label))
|
||||
{
|
||||
score.Add(label, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
score[label]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//await Task.Delay(_checkForMessageIntervalMs);
|
||||
} while (!token.IsCancellationRequested);
|
||||
|
||||
foreach (var item in score)
|
||||
{
|
||||
_logger.Trace($"{bitNode.Name} Dequeued the total of {item.Value} BIT messages for 0x{item.Key:X} label");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="parametricResponseIds"></param>
|
||||
/// <param name="timeOut"></param>
|
||||
/// <param name="node"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<List<BitTestResults>> GetBitResultsListAsync(List<string> parametricResponseIds, int timeOut, IBit node)
|
||||
{
|
||||
_logger.Trace($"{node.Name} Start continuously getting BIT results for these messages: {string.Join(", ", parametricResponseIds)}.");
|
||||
|
||||
List<BitTestResults> results = new List<BitTestResults>();
|
||||
|
||||
CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||
List<Task<BitTestResults>> responseTasks = new List<Task<BitTestResults>>();
|
||||
|
||||
foreach (var responseId in parametricResponseIds)
|
||||
{
|
||||
responseTasks.Add(GetBITResultsAsync(tokenSource.Token, responseId, node));
|
||||
}
|
||||
|
||||
Task timeoutTask = Task.Delay(timeOut);
|
||||
var completedTask = await Task.WhenAny(responseTasks.Concat(new[] { timeoutTask }));
|
||||
|
||||
tokenSource.Cancel();
|
||||
tokenSource.Dispose();
|
||||
|
||||
if (completedTask == timeoutTask)
|
||||
{
|
||||
_logger.Warn($"Timed out after {timeOut} ms while waiting on parametrized response message(s) {string.Join(", ", parametricResponseIds)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
var completedResults = responseTasks.Where(t => t.Status == TaskStatus.RanToCompletion && t.Result != null).Select(t => t.Result);
|
||||
results.AddRange(completedResults);
|
||||
}
|
||||
|
||||
_logger.Trace($"{node.Name} Completed getting BIT results for these messages: {string.Join(", ", parametricResponseIds)}, found {results?.Count} results");
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// look for results in the node until either result was found or canceled
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="responseId"></param>
|
||||
/// <param name="node"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<BitTestResults> GetBITResultsAsync(CancellationToken token, string responseId, IBit node)
|
||||
{
|
||||
//_logger.Trace($"{node.Name} Start waiting for BIT message: {responseId}.");
|
||||
|
||||
BitTestResults bitTestResults = null;
|
||||
do
|
||||
{
|
||||
await Task.Delay(_checkForMessageIntervalMs);
|
||||
try
|
||||
{
|
||||
bitTestResults = node.GetBITResults(responseId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, ex.Message);
|
||||
break;
|
||||
}
|
||||
} while (bitTestResults == null && !token.IsCancellationRequested);
|
||||
|
||||
//_logger.Trace($"{node.Name} Done waiting for BIT message: {responseId}.");
|
||||
|
||||
return bitTestResults;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// builds a command from parameters
|
||||
/// </summary>
|
||||
/// <param name="bitCommandId"></param>
|
||||
/// <param name="retries"></param>
|
||||
/// <param name="timeout"></param>
|
||||
/// <param name="commandParams"></param>
|
||||
/// <param name="parametricResponseIds"></param>
|
||||
/// <param name="timeout2"></param>
|
||||
/// <param name="errorMessageId"></param>
|
||||
/// <returns></returns>
|
||||
private static BITCommand BuildBITCommand(string bitCommandId,
|
||||
int retries,
|
||||
uint timeout,
|
||||
IEnumerable<KeyValuePair<string, string>> commandParams = null,
|
||||
List<string> parametricResponseIds = null,
|
||||
uint timeout2 = 0,
|
||||
string errorMessageId = null)
|
||||
{
|
||||
BITCommand bitCommand = new BITCommand
|
||||
{
|
||||
Command = bitCommandId,
|
||||
CommandTimeout = timeout,
|
||||
CommandParameters = new List<BITParameter>(),
|
||||
CommandResponses = new List<BITResponseMsg>(),
|
||||
ParametricResponse = retries.ToString(),
|
||||
ParametricTimeout = timeout2
|
||||
};
|
||||
|
||||
if (commandParams != null)
|
||||
{
|
||||
foreach (var commandParameter in commandParams)
|
||||
{
|
||||
bitCommand.CommandParameters.Add(new BITParameter
|
||||
{
|
||||
Key = commandParameter.Key,
|
||||
Value = commandParameter.Value,
|
||||
ParameterType = ParameterType.U
|
||||
});
|
||||
}
|
||||
}
|
||||
if(parametricResponseIds != null)
|
||||
{
|
||||
foreach (var response in parametricResponseIds)
|
||||
{
|
||||
bitCommand.CommandResponses.Add(new BITResponseMsg
|
||||
{
|
||||
Name = response,
|
||||
ResponseType = ResponseMessageType.P
|
||||
});
|
||||
}
|
||||
}
|
||||
if(!string.IsNullOrEmpty(errorMessageId))
|
||||
{
|
||||
bitCommand.CommandResponses.Add(new BITResponseMsg
|
||||
{
|
||||
Name = errorMessageId,
|
||||
ResponseType = ResponseMessageType.E
|
||||
});
|
||||
}
|
||||
|
||||
return bitCommand;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="commands"></param>
|
||||
/// <param name="node"></param>
|
||||
/// <returns></returns>
|
||||
private List<BitTestResults> RunBITWaitForResultsList(List<BITCommand> commands, IBit node)
|
||||
{
|
||||
List<BitTestResults> results = new List<BitTestResults>();
|
||||
|
||||
foreach (var command in commands)
|
||||
{
|
||||
string bitCommand = command.Command;
|
||||
string bitResponseId = ResponseGroupForFirstBITCall(command);
|
||||
uint timeout = command.CommandTimeout;
|
||||
uint timeout2 = command.ParametricTimeout;
|
||||
string strParamerticResponse = command.ParametricResponse;
|
||||
int retries = 0;
|
||||
if (int.TryParse(strParamerticResponse, out int tmpretries))
|
||||
{
|
||||
retries = tmpretries;
|
||||
}
|
||||
List<KeyValuePair<string, string>> commandParams = ConvertCommandParameters(command.CommandParameters);
|
||||
int runIndex = 0;
|
||||
do
|
||||
{
|
||||
runIndex++;
|
||||
try
|
||||
{
|
||||
var result = node.RunBITWaitForResults(bitCommand, bitResponseId, timeout, commandParams);
|
||||
results.Add(result);
|
||||
}
|
||||
catch (BitTimeoutException)
|
||||
{
|
||||
_logger.Warn($"Timeout after {timeout} ms on BIT command {bitCommand} waiting for result {bitResponseId}, retry number {runIndex}");
|
||||
if (runIndex == retries)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
} while (results == null && runIndex <= retries);
|
||||
|
||||
var responseGroup = ResponseGroupListForParameterBITCall(command);
|
||||
|
||||
if (responseGroup == null || !responseGroup.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CancellationTokenSource cts = new CancellationTokenSource();
|
||||
ParallelOptions options = new ParallelOptions
|
||||
{
|
||||
CancellationToken = cts.Token,
|
||||
MaxDegreeOfParallelism = Environment.ProcessorCount
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
Parallel.ForEach(responseGroup, options, item =>
|
||||
{
|
||||
var totalWaitTimeMs = _checkForMessageIntervalMs;
|
||||
BitTestResults parametricresults;
|
||||
do
|
||||
{
|
||||
parametricresults = node.GetBITResults(item);
|
||||
|
||||
if (parametricresults != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(_checkForMessageIntervalMs);
|
||||
totalWaitTimeMs += _checkForMessageIntervalMs;
|
||||
}
|
||||
} while (totalWaitTimeMs < timeout2 && !cts.IsCancellationRequested);
|
||||
|
||||
if (parametricresults == null && !cts.IsCancellationRequested)
|
||||
{
|
||||
_logger.Warn($"Timed out while waiting on parametrized response message(s) for {command.Command} command");
|
||||
}
|
||||
|
||||
if (parametricresults != null)
|
||||
{
|
||||
// replace earlier results (confirmation message) with parametric results
|
||||
results.Add(parametricresults);
|
||||
cts.Cancel();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_logger.Trace($"Done waiting on parametrized response message(s) for {command.Command} command");
|
||||
}
|
||||
finally
|
||||
{
|
||||
cts.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// runs bit command and then
|
||||
/// </summary>
|
||||
/// <param name="commands"></param>
|
||||
/// <param name="node"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<List<BitTestResults>> RunBITWaitForResultsListAsync(List<BITCommand> commands, IBit node)
|
||||
{
|
||||
List<BitTestResults> results = new List<BitTestResults>();
|
||||
|
||||
foreach (var command in commands)
|
||||
{
|
||||
string bitCommand = command.Command;
|
||||
string bitResponseId = ResponseGroupForFirstBITCall(command);
|
||||
uint timeout = command.CommandTimeout;
|
||||
uint timeout2 = command.ParametricTimeout;
|
||||
string strParamerticResponse = command.ParametricResponse;
|
||||
int retries = 0;
|
||||
if (int.TryParse(strParamerticResponse, out int tmpretries))
|
||||
{
|
||||
retries = tmpretries;
|
||||
}
|
||||
List<KeyValuePair<string, string>> commandParams = ConvertCommandParameters(command.CommandParameters);
|
||||
int runIndex = 0;
|
||||
do
|
||||
{
|
||||
runIndex++;
|
||||
try
|
||||
{
|
||||
var result = await Task.Run(() => node.RunBITWaitForResults(bitCommand, bitResponseId, timeout, commandParams));
|
||||
results.Add(result);
|
||||
}
|
||||
catch (BitTimeoutException)
|
||||
{
|
||||
_logger.Warn($"Timeout after {timeout} ms on BIT command {bitCommand} waiting for result {bitResponseId}, retry number {runIndex}");
|
||||
if (runIndex == retries)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
} while (results == null && runIndex <= retries);
|
||||
|
||||
var responseGroup = ResponseGroupListForParameterBITCall(command);
|
||||
|
||||
if (responseGroup == null || !responseGroup.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var paramResults = await GetBitResultsListAsync(responseGroup, (int)timeout2, node);
|
||||
if (paramResults != null)
|
||||
{
|
||||
results.AddRange(paramResults);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// for the initial BIT message expect to find R (main Response)
|
||||
/// if any responses marked as E (error) add it to the list as alternative expected response, separated by comma
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
private static string ResponseGroupForFirstBITCall(BITCommand command)
|
||||
{
|
||||
StringBuilder resp = new StringBuilder();
|
||||
var tempMainResponseGroup = command.CommandResponses.Where(m => m.ResponseType != ResponseMessageType.E).ToList();
|
||||
if (tempMainResponseGroup != null)
|
||||
{
|
||||
// check for Rs first and if no messages marked with Rs than check for Us
|
||||
var mainResponse = tempMainResponseGroup.FirstOrDefault(m => m.ResponseType == ResponseMessageType.R);
|
||||
if (mainResponse != null)
|
||||
{
|
||||
resp.Append(mainResponse.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// append all error message ids
|
||||
foreach (var item in command.CommandResponses.Where(m => m.ResponseType == ResponseMessageType.E))
|
||||
{
|
||||
resp.Append(',');
|
||||
resp.Append(item.Name);
|
||||
}
|
||||
|
||||
return resp.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// for subsequent parameter response look for either P (parameterized) or U (undefined)
|
||||
/// if any responses marked as E (error) add it to the list as alternative expected response
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
private static List<string> ResponseGroupListForParameterBITCall(BITCommand command)
|
||||
{
|
||||
List<string> resp = new List<string>();
|
||||
bool parameterizedRespExpected = false;
|
||||
var tempMainResponseGroup = command.CommandResponses.Where(m => m.ResponseType != ResponseMessageType.E).ToList();
|
||||
if (tempMainResponseGroup != null)
|
||||
{
|
||||
// check for Rs first and if no messages marked with Rs than check for Us
|
||||
var mainResponse = tempMainResponseGroup.FirstOrDefault(m => m.ResponseType == ResponseMessageType.P || m.ResponseType == ResponseMessageType.U);
|
||||
if (mainResponse != null)
|
||||
{
|
||||
resp.Add(mainResponse.Name);
|
||||
parameterizedRespExpected = true;
|
||||
}
|
||||
}
|
||||
if (parameterizedRespExpected)
|
||||
{
|
||||
// append all error message ids
|
||||
foreach (var item in command.CommandResponses.Where(m => m.ResponseType == ResponseMessageType.E))
|
||||
{
|
||||
resp.Add(item.Name);
|
||||
}
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
private static List<KeyValuePair<string, string>> ConvertCommandParameters(List<BITParameter> @in)
|
||||
{
|
||||
List<KeyValuePair<string, string>> parameters = new List<KeyValuePair<string, string>>();
|
||||
foreach (var parameter in @in)
|
||||
{
|
||||
parameters.Add(new KeyValuePair<string, string>(parameter.Key, parameter.Value));
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,9 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using Raytheon.Common;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
|
||||
namespace BitMeasurementManagerLib
|
||||
{
|
||||
@@ -34,6 +34,7 @@ namespace BitMeasurementManagerLib
|
||||
private BitMessageIDs _messageIds;
|
||||
private Dictionary<uint, List<BitConfigurableMessage>> _msgList;
|
||||
private Dictionary<uint, AutoResetEvent> _receivedMsgEvents;
|
||||
private readonly ILogger _logger;
|
||||
#endregion
|
||||
|
||||
#region PrivateFuctions
|
||||
@@ -43,6 +44,8 @@ namespace BitMeasurementManagerLib
|
||||
/// </summary>
|
||||
private BitMsgRxBuffer(BitMessageIDs messageIds)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
_messageIds = messageIds;
|
||||
|
||||
_msgList = new Dictionary<uint, List<BitConfigurableMessage>>();
|
||||
@@ -88,17 +91,17 @@ namespace BitMeasurementManagerLib
|
||||
|
||||
if (shouldWeDeleteOthers == true)
|
||||
{
|
||||
ErrorLogger.Instance().Write("BitMsgRxBuffer::AddMsg() - clearing list for " + msgId.ToString(), ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug("clearing list for " + msgId.ToString());
|
||||
ClearList(msgId);
|
||||
}
|
||||
|
||||
if (_msgList.ContainsKey(msgId) == false)
|
||||
{
|
||||
ErrorLogger.Instance().Write("BitMsgRxBuffer::AddMsg() - creating new list for " + msgId.ToString(), ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug("creating new list for " + msgId.ToString());
|
||||
_msgList[msgId] = new List<BitConfigurableMessage>();
|
||||
}
|
||||
|
||||
ErrorLogger.Instance().Write("BitMsgRxBuffer::AddMsg() - Adding " + msgId.ToString() + " to the list", ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug("Adding " + msgId.ToString() + " to the list");
|
||||
_msgList[msgId].Add(msg);
|
||||
|
||||
_receivedMsgEvents[msgId].Set();
|
||||
|
||||
@@ -15,402 +15,331 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using Raytheon.Instruments;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using Raytheon.Instruments;
|
||||
|
||||
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
|
||||
/// <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;
|
||||
private readonly ILogger _logger;
|
||||
#endregion
|
||||
|
||||
#region PrivateFunctions
|
||||
/// <summary>
|
||||
/// The finalizer. Necessary for quitting the read thread
|
||||
/// </summary>
|
||||
~BitSimCommDeviceNode()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
#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;
|
||||
/// <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();
|
||||
// close the socket and threads
|
||||
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
|
||||
}
|
||||
}
|
||||
_commDevice.Shutdown();
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// dispose of the resources
|
||||
if (initialState == State.Ready)
|
||||
{
|
||||
_socketReadWorker.Dispose();
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region PublicFuctions
|
||||
#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;
|
||||
/// <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)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
_commDevice = commDevice;
|
||||
_name = name;
|
||||
|
||||
_messageIds = messageIds;
|
||||
_commDevice = commDevice;
|
||||
|
||||
_socketReadWorker = new CommReadWorker(this, msgHandler, commReadWorkerBufferSize, readWorkerRestTimeInMs);
|
||||
_socketReadThread = new Thread(_socketReadWorker.DoWork);
|
||||
_messageIds = messageIds;
|
||||
|
||||
// start the read thread
|
||||
_socketReadThread.Start();
|
||||
_socketReadWorker = new CommReadWorker(this, msgHandler, commReadWorkerBufferSize, readWorkerRestTimeInMs);
|
||||
_socketReadThread = new Thread(_socketReadWorker.DoWork);
|
||||
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
// start the read thread
|
||||
_socketReadThread.Start();
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
|
||||
public void Open()
|
||||
{
|
||||
}
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ClearErrors()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public void Open()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DisplayEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ClearErrors()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DisplayEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a BIT Comm Sim Device Node " + _name;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a BIT Comm Sim Device Node " + _name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the device
|
||||
/// </summary>
|
||||
/*public void Close()
|
||||
{
|
||||
const int THREAD_QUIT_TIMEOUT_MS = 3000;
|
||||
public void Close()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
// tell the thread to quit
|
||||
_socketReadWorker.QuitWork();
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
// close the socket which the thread might be blocked on
|
||||
_commDevice.Close();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
if (_socketReadThread.IsAlive)
|
||||
{
|
||||
bool didThreadQuit = _socketReadThread.Join(THREAD_QUIT_TIMEOUT_MS);
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}*/
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public InstrumentMetadata Info
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
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 void Initialize()
|
||||
{
|
||||
_commDevice.Initialize();
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
return _commDevice.SelfTestResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public InstrumentMetadata Info
|
||||
{
|
||||
get
|
||||
{
|
||||
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 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
_commDevice.Initialize();
|
||||
_state = State.Ready;
|
||||
}
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
return _commDevice.SelfTestResult;
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="readTimeout"></param>
|
||||
public void SetReadTimeout(uint readTimeout)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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 SelfTestResult SelfTestResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public State Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
|
||||
Initialize();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
const int THREAD_QUIT_TIMEOUT_MS = 3000;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="readTimeout"></param>
|
||||
public void SetReadTimeout(uint readTimeout)
|
||||
{
|
||||
}
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
// tell the thread to quit
|
||||
_socketReadWorker.QuitWork();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public SelfTestResult SelfTestResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
// close the socket which the thread might be blocked on
|
||||
_commDevice.Shutdown();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public State Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
if (_socketReadThread.IsAlive)
|
||||
{
|
||||
bool didThreadQuit = _socketReadThread.Join(THREAD_QUIT_TIMEOUT_MS);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
const int THREAD_QUIT_TIMEOUT_MS = 3000;
|
||||
if (didThreadQuit == false)
|
||||
{
|
||||
_logger.Debug("Logging Thread did not quit as expected, aborting it");
|
||||
_socketReadThread.Abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Logging Thread quit successfully after join");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Logging Thread quit successfully");
|
||||
}
|
||||
}
|
||||
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
// tell the thread to quit
|
||||
_socketReadWorker.QuitWork();
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
// close the socket which the thread might be blocked on
|
||||
_commDevice.Shutdown();
|
||||
/// <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);
|
||||
|
||||
if (_socketReadThread.IsAlive)
|
||||
{
|
||||
bool didThreadQuit = _socketReadThread.Join(THREAD_QUIT_TIMEOUT_MS);
|
||||
bool isThereAResponse = _messageIds.IsThereAResponseMessage(commandId);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
// 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
|
||||
{
|
||||
}
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
return (uint)dataToSend.Length;
|
||||
}
|
||||
|
||||
/// <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
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,357 +15,316 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using Raytheon.Common;
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
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;
|
||||
/// <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;
|
||||
private uint _commReadWorkerBufferSize;
|
||||
private uint _readWorkerRestTimeInMs;
|
||||
private MsgDevice _msgHandler;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region PrivateFuctions
|
||||
/// <summary>
|
||||
/// The finalizer. Necessary for quitting the read thread
|
||||
/// </summary>
|
||||
~CommDeviceNode()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
#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;
|
||||
/// <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
|
||||
}
|
||||
}
|
||||
// close the socket and threads
|
||||
if (initialState == State.Ready)
|
||||
{
|
||||
Shutdown();
|
||||
_commDevice.Shutdown();
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// dispose of the resources
|
||||
if (initialState == State.Ready)
|
||||
{
|
||||
_socketReadWorker.Dispose();
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region PublicFuctions
|
||||
#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;
|
||||
/// <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)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_name = name;
|
||||
_commDevice = commDevice;
|
||||
|
||||
Open();
|
||||
}
|
||||
_commReadWorkerBufferSize = commReadWorkerBufferSize;
|
||||
_readWorkerRestTimeInMs = readWorkerRestTimeInMs;
|
||||
_msgHandler = msgHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Starts communication thread
|
||||
/// </summary>
|
||||
public void Open()
|
||||
{
|
||||
_socketReadWorker = new CommReadWorker(this, _msgHandler, _commReadWorkerBufferSize, _readWorkerRestTimeInMs);
|
||||
_socketReadThread = new Thread(_socketReadWorker.DoWork);
|
||||
Open();
|
||||
}
|
||||
|
||||
// start the read thread
|
||||
_socketReadThread.Start();
|
||||
/// <summary>
|
||||
/// Starts communication thread
|
||||
/// </summary>
|
||||
public void Open()
|
||||
{
|
||||
_socketReadWorker = new CommReadWorker(this, _msgHandler, _commReadWorkerBufferSize, _readWorkerRestTimeInMs);
|
||||
_socketReadThread = new Thread(_socketReadWorker.DoWork);
|
||||
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
// 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>
|
||||
/// 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 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 string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a Comm Sim Device Node " + _name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public InstrumentMetadata Info
|
||||
{
|
||||
get
|
||||
{
|
||||
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 void Initialize()
|
||||
{
|
||||
_commDevice.Initialize();
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <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>
|
||||
/// 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>
|
||||
/// Resets communications
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="readTimeout"></param>
|
||||
public void SetReadTimeout(uint readTimeout)
|
||||
{
|
||||
_commDevice.SetReadTimeout(readTimeout);
|
||||
}
|
||||
/// <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 SelfTestResult SelfTestResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public State Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public State Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close communications
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
/// <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;
|
||||
/// <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();
|
||||
// tell the thread to quit
|
||||
_socketReadWorker.QuitWork();
|
||||
|
||||
// close the socket which the thread might be blocked on
|
||||
_commDevice.Shutdown();
|
||||
// close the socket which the thread might be blocked on
|
||||
_commDevice.Shutdown();
|
||||
|
||||
if (_socketReadThread.IsAlive)
|
||||
{
|
||||
bool didThreadQuit = _socketReadThread.Join(THREAD_QUIT_TIMEOUT_MS);
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (didThreadQuit == false)
|
||||
{
|
||||
_socketReadThread.Abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Logging Thread quit successfully after join");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Logging Thread quit successfully");
|
||||
}
|
||||
}
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
_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);
|
||||
}
|
||||
/// <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
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Net.Sockets;
|
||||
using Raytheon.Instruments;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
@@ -35,6 +34,7 @@ namespace Raytheon.Instruments
|
||||
private AutoResetEvent _quitEvent;
|
||||
private byte[] _dataRead;
|
||||
private readonly uint _timeToRestBetweenReadsInMs;
|
||||
private readonly ILogger _logger;
|
||||
#endregion
|
||||
|
||||
#region PublicFuctions
|
||||
@@ -48,6 +48,7 @@ namespace Raytheon.Instruments
|
||||
/// <param name="timeToRestBetweenReadsInMs">Number of ms to rest after a read call</param>
|
||||
public CommReadWorker(ICommDevice commNode, MsgDevice msghandler, uint bufferSize, uint timeToRestBetweenReadsInMs)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_commNode = commNode;
|
||||
_threadQuitControl = false;
|
||||
_msgHandler = msghandler;
|
||||
@@ -69,23 +70,9 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
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
|
||||
}
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -110,33 +97,14 @@ namespace Raytheon.Instruments
|
||||
// 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);
|
||||
_logger.Debug("received signal to quit");
|
||||
_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);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
ErrorLogger.Instance().Write("CommReadWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -154,23 +122,9 @@ namespace Raytheon.Instruments
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
if (disposing)
|
||||
{
|
||||
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
|
||||
}
|
||||
_quitEvent.Dispose();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -15,8 +15,8 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace BitMeasurementManagerLib
|
||||
{
|
||||
@@ -71,8 +71,7 @@ namespace BitMeasurementManagerLib
|
||||
// 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");
|
||||
throw new Exception("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)
|
||||
@@ -141,8 +140,7 @@ namespace BitMeasurementManagerLib
|
||||
// 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");
|
||||
throw new Exception("Not enough data form a header. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, needed " + (headerDef.msgIdByteLocation + headerDef.msgIdDataLen).ToString() + " for a header");
|
||||
}
|
||||
|
||||
uint cmdId = 0;
|
||||
|
||||
@@ -16,9 +16,10 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using System;
|
||||
using Raytheon.Common;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace BitMeasurementManagerLib
|
||||
{
|
||||
@@ -48,6 +49,7 @@ namespace BitMeasurementManagerLib
|
||||
private readonly bool _shallWeLogIncomingAsciiData;
|
||||
private readonly uint _bitmask;
|
||||
private readonly string _crcFieldName;
|
||||
private readonly ILogger _logger;
|
||||
#endregion
|
||||
|
||||
#region PublicFuctions
|
||||
@@ -66,6 +68,7 @@ namespace BitMeasurementManagerLib
|
||||
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)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_messageIds = messageIds;
|
||||
|
||||
// hold onto the callback
|
||||
@@ -166,7 +169,7 @@ namespace BitMeasurementManagerLib
|
||||
{
|
||||
if (_messageIds.ContainsId(msgId) == false)
|
||||
{
|
||||
ErrorLogger.Instance().Write("BitMsgHandler::OnCompleteMessage() - detected unknown msg id: " + msgId.ToString());
|
||||
_logger.Warn("BitMsgHandler::OnCompleteMessage() - detected unknown msg id: " + msgId.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -184,7 +187,7 @@ namespace BitMeasurementManagerLib
|
||||
|
||||
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}");
|
||||
_logger.Warn($"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;
|
||||
}
|
||||
}
|
||||
@@ -207,14 +210,10 @@ namespace BitMeasurementManagerLib
|
||||
}
|
||||
|
||||
// some debugging
|
||||
ErrorLogger.Instance().Write("BitMsgHandler::HandleMsg() - added message " + msgId.ToString("X8") + " to buffer ", ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug("added message " + msgId.ToString("X8") + " to buffer ");
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
//@@@ need to flow error to the host
|
||||
ErrorLogger.Instance().Write("BitMsgHandler::HandleMsg() - caught an error: " + err.Message, ErrorLogger.LogLevel.ERROR);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -271,7 +270,7 @@ namespace BitMeasurementManagerLib
|
||||
{
|
||||
if (_binWriter == null && _shallWeLogIncomingBinData == true)
|
||||
{
|
||||
throw new Exception("BitMsgHandler::WriteIncomingDataToLog() - Trying to log bin data before the log file is open");
|
||||
throw new Exception("Trying to log bin data before the log file is open");
|
||||
}
|
||||
else if (_shallWeLogIncomingBinData == true)
|
||||
{
|
||||
@@ -292,7 +291,7 @@ namespace BitMeasurementManagerLib
|
||||
{
|
||||
if (_asciiWriter == null && _shallWeLogIncomingAsciiData == true)
|
||||
{
|
||||
throw new Exception("BitMsgHandler::WriteIncomingDataToLog() - Trying to log ascii data before the log file is open");
|
||||
throw new Exception("Trying to log ascii data before the log file is open");
|
||||
}
|
||||
else if (_shallWeLogIncomingAsciiData == true)
|
||||
{
|
||||
@@ -318,7 +317,7 @@ namespace BitMeasurementManagerLib
|
||||
{
|
||||
if (_binWriter == null && _shallWeLogOutgoingBinData == true)
|
||||
{
|
||||
throw new Exception("BitMsgHandler::WriteOutgoingDataToLog() - Trying to log bin data before the log file is open");
|
||||
throw new Exception("Trying to log bin data before the log file is open");
|
||||
}
|
||||
else if (_shallWeLogOutgoingBinData == true)
|
||||
{
|
||||
@@ -339,7 +338,7 @@ namespace BitMeasurementManagerLib
|
||||
{
|
||||
if (_asciiWriter == null && _shallWeLogOutgoingAsciiData == true)
|
||||
{
|
||||
throw new Exception("BitMsgHandler::WriteOutgoingDataToLog() - Trying to log ascii data before the log file is open");
|
||||
throw new Exception("Trying to log ascii data before the log file is open");
|
||||
}
|
||||
else if (_shallWeLogOutgoingAsciiData == true)
|
||||
{
|
||||
@@ -362,25 +361,18 @@ namespace BitMeasurementManagerLib
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
try
|
||||
// call the parent dispose first
|
||||
base.Dispose(disposing);
|
||||
|
||||
// now dispose of our resources
|
||||
if (_binWriter != null)
|
||||
{
|
||||
// call the parent dispose first
|
||||
base.Dispose(disposing);
|
||||
|
||||
// now dispose of our resources
|
||||
if (_binWriter != null)
|
||||
{
|
||||
_binWriter.Dispose();
|
||||
}
|
||||
|
||||
if (_asciiWriter != null)
|
||||
{
|
||||
_asciiWriter.Dispose();
|
||||
}
|
||||
_binWriter.Dispose();
|
||||
}
|
||||
catch (Exception err)
|
||||
|
||||
if (_asciiWriter != null)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
_asciiWriter.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace BitMeasurementManagerLib
|
||||
{
|
||||
@@ -34,6 +35,7 @@ namespace BitMeasurementManagerLib
|
||||
private readonly BitMessageIDs _messageIdToSizeMap;
|
||||
private BitMsgEndianControl.HeaderDef _headerDef;
|
||||
private readonly bool _shallWePerformVerboseParserLogging;
|
||||
private readonly ILogger _logger;
|
||||
#endregion
|
||||
|
||||
#region PrivateFuctions
|
||||
@@ -54,7 +56,7 @@ namespace BitMeasurementManagerLib
|
||||
|
||||
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);
|
||||
_logger.Debug("not enough data in the buffer to form a header. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, needed " + payloadHeaderSize.ToString() + " for a header");
|
||||
bytesToRemove = 0;
|
||||
return false;
|
||||
}
|
||||
@@ -67,8 +69,8 @@ namespace BitMeasurementManagerLib
|
||||
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);
|
||||
string msg = "unknown id received: " + id.ToString("X8") + " When resyncing threw away " + numBytesToRemove.ToString() + " Bytes";
|
||||
_logger.Warn(msg);
|
||||
bytesToRemove = numBytesToRemove;
|
||||
return false;
|
||||
}
|
||||
@@ -79,8 +81,8 @@ namespace BitMeasurementManagerLib
|
||||
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);
|
||||
string msg = "detected seondary ID: " + secondaryId.ToString("X8") + " was not as expected: " + _headerDef.secondaryMsgIdExpectedValue.ToString("X8") + " When resyncing threw away " + numBytesToRemove.ToString() + " Bytes";
|
||||
_logger.Warn(msg);
|
||||
bytesToRemove = numBytesToRemove;
|
||||
return false;
|
||||
}
|
||||
@@ -91,7 +93,7 @@ namespace BitMeasurementManagerLib
|
||||
// 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);
|
||||
_logger.Debug("not enough data in the buffer to form a entire message. Buffer contained " + Convert.ToString(numBytesInPdata) + " bytes, expected msg size is: " + msgSize.ToString());
|
||||
// need to wait for more data
|
||||
bytesToRemove = 0;
|
||||
return false;
|
||||
@@ -102,7 +104,7 @@ namespace BitMeasurementManagerLib
|
||||
|
||||
if (_shallWePerformVerboseParserLogging == true)
|
||||
{
|
||||
ErrorLogger.Instance().Write("BitMsgParser::HandleData() - found msg: " + id.ToString() + " which has " + msgSize.ToString() + " bytes", ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug("found msg: " + id.ToString() + " which has " + msgSize.ToString() + " bytes");
|
||||
}
|
||||
|
||||
messageId = id;
|
||||
@@ -118,7 +120,7 @@ namespace BitMeasurementManagerLib
|
||||
/// <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);
|
||||
_logger.Debug("Begin");
|
||||
|
||||
// increment pData by 1
|
||||
pData = IntPtr.Add(pData, 1);
|
||||
@@ -138,7 +140,7 @@ namespace BitMeasurementManagerLib
|
||||
|
||||
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);
|
||||
_logger.Debug("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");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -179,20 +181,20 @@ namespace BitMeasurementManagerLib
|
||||
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);
|
||||
_logger.Debug("Detected message ID: " + id.ToString("X8") + ". Detected Secondary ID: " + secondaryId.ToString("X8") + " Resync complete. Removing " + bytesToRemove.ToString() + " Bytes");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
didWeFindMsg = true;
|
||||
ErrorLogger.Instance().Write("BitMsgParser::Resync() - Detected message ID: " + id.ToString("X8") + ". Resync complete. Removing " + bytesToRemove.ToString() + " Bytes", ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug("Detected message ID: " + id.ToString("X8") + ". Resync complete. Removing " + bytesToRemove.ToString() + " Bytes");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ErrorLogger.Instance().Write("BitMsgParser::Resync() - returning " + bytesToRemove.ToString(), ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug("returning " + bytesToRemove.ToString());
|
||||
|
||||
return bytesToRemove;
|
||||
|
||||
@@ -208,6 +210,7 @@ namespace BitMeasurementManagerLib
|
||||
/// <param name="shallWePerformVerboseParserLogging"></param>
|
||||
public BitMsgParser(BitMessageIDs messageIds, bool shallWePerformVerboseParserLogging)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
// Using it to hold onto valid message ids and the size
|
||||
_messageIdToSizeMap = messageIds;
|
||||
_shallWePerformVerboseParserLogging = shallWePerformVerboseParserLogging;
|
||||
|
||||
@@ -15,12 +15,11 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using Raytheon.Instruments;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using ChillerCartMeasurementManagerLib;
|
||||
using NLog;
|
||||
using Raytheon.Instruments;
|
||||
|
||||
namespace MeasurementManagerLib
|
||||
{
|
||||
@@ -165,15 +164,6 @@ namespace MeasurementManagerLib
|
||||
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ErrorLogger.Instance().Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,10 +16,11 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Raytheon.Common;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using MeasurementManagerLib;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace ChillerCartMeasurementManagerLib
|
||||
{
|
||||
@@ -37,6 +38,7 @@ namespace ChillerCartMeasurementManagerLib
|
||||
private readonly ChillerCartMeasurementManager.ChillerDelegate _callback;
|
||||
private readonly string _logFileName;
|
||||
private readonly int _threadRestTimeMs;
|
||||
private readonly ILogger _logger;
|
||||
#endregion
|
||||
|
||||
#region PrivateFunctions
|
||||
@@ -55,25 +57,11 @@ namespace ChillerCartMeasurementManagerLib
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
if (disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_fileWriter.Dispose();
|
||||
_fileWriter.Dispose();
|
||||
|
||||
_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
|
||||
}
|
||||
_quitEvent.Dispose();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -88,6 +76,8 @@ namespace ChillerCartMeasurementManagerLib
|
||||
/// <param name="callback"></param>
|
||||
public ChillerDataLogWorker(ChillerCartMeasurementManager controller, string logFileName, int threadRestTimeMs, ChillerCartMeasurementManager.ChillerDelegate callback)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
_threadQuitControl = false;
|
||||
_quitEvent = new AutoResetEvent(false);
|
||||
|
||||
@@ -123,23 +113,9 @@ namespace ChillerCartMeasurementManagerLib
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
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
|
||||
}
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -176,7 +152,6 @@ namespace ChillerCartMeasurementManagerLib
|
||||
catch (Exception e)
|
||||
{
|
||||
string msg = e.Message;
|
||||
ErrorLogger.Instance().Write(msg + "\r\n" + e.StackTrace, ErrorLogger.LogLevel.ERROR);
|
||||
|
||||
_fileWriter.WriteLine(Util.GetTimeString() + ", " + msg);
|
||||
|
||||
@@ -184,12 +159,9 @@ namespace ChillerCartMeasurementManagerLib
|
||||
_callback?.Invoke(-1, -1, -1);
|
||||
}
|
||||
}
|
||||
ErrorLogger.Instance().Write("ChillerCartDataLogWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
|
||||
}
|
||||
catch (Exception err)
|
||||
catch (Exception)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
|
||||
//Send error code to callback if valid
|
||||
_callback?.Invoke(-1, -1, -1);
|
||||
}
|
||||
|
||||
@@ -16,10 +16,11 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Raytheon.Common;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using MeasurementManagerLib;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace ChillerCartMeasurementManagerLib
|
||||
{
|
||||
@@ -37,6 +38,7 @@ namespace ChillerCartMeasurementManagerLib
|
||||
private readonly ChillerCartMeasurementManager.FlowMeterDelegate _callback;
|
||||
private readonly string _logFileName;
|
||||
private readonly int _threadRestTimeMs;
|
||||
private readonly ILogger _logger;
|
||||
#endregion
|
||||
|
||||
#region PrivateFunctions
|
||||
@@ -56,25 +58,11 @@ namespace ChillerCartMeasurementManagerLib
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
if (disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_fileWriter.Dispose();
|
||||
_fileWriter.Dispose();
|
||||
|
||||
_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
|
||||
}
|
||||
_quitEvent.Dispose();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -89,6 +77,8 @@ namespace ChillerCartMeasurementManagerLib
|
||||
/// <param name="callback"></param>
|
||||
public FlowMeterDataLogWorker(ChillerCartMeasurementManager controller, string logFileName, int threadRestTimeMs, ChillerCartMeasurementManager.FlowMeterDelegate callback)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
_threadQuitControl = false;
|
||||
_quitEvent = new AutoResetEvent(false);
|
||||
|
||||
@@ -122,23 +112,9 @@ namespace ChillerCartMeasurementManagerLib
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
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
|
||||
}
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -175,8 +151,6 @@ namespace ChillerCartMeasurementManagerLib
|
||||
{
|
||||
string msg = e.Message;
|
||||
|
||||
ErrorLogger.Instance().Write(msg + "\r\n" + e.StackTrace, ErrorLogger.LogLevel.ERROR);
|
||||
|
||||
_fileWriter.WriteLine(Util.GetTimeString() + ", " + msg);
|
||||
|
||||
//Invoke the callback if valid
|
||||
@@ -186,12 +160,9 @@ namespace ChillerCartMeasurementManagerLib
|
||||
}
|
||||
}
|
||||
}
|
||||
ErrorLogger.Instance().Write("FlowMeterDataLogWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
|
||||
}
|
||||
catch (Exception err)
|
||||
catch (Exception)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
|
||||
//Send error code to callback if valid
|
||||
if (_callback != null && _threadQuitControl == false)
|
||||
{
|
||||
|
||||
@@ -16,10 +16,11 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Raytheon.Common;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using MeasurementManagerLib;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace ChillerCartMeasurementManagerLib
|
||||
{
|
||||
@@ -37,6 +38,7 @@ namespace ChillerCartMeasurementManagerLib
|
||||
private readonly ChillerCartMeasurementManager.TemperatureDelegate _callback;
|
||||
private readonly string _logFileName;
|
||||
private readonly int _threadRestTimeMs;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -57,25 +59,11 @@ namespace ChillerCartMeasurementManagerLib
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
if (disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_fileWriter.Dispose();
|
||||
_fileWriter.Dispose();
|
||||
|
||||
_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
|
||||
}
|
||||
_quitEvent.Dispose();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -91,6 +79,8 @@ namespace ChillerCartMeasurementManagerLib
|
||||
/// <param name="callback"></param>
|
||||
public TempDataLogWorker(ChillerCartMeasurementManager controller, string logFileName, int threadRestTimeMs, ChillerCartMeasurementManager.TemperatureDelegate callback)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
_threadQuitControl = false;
|
||||
_quitEvent = new AutoResetEvent(false);
|
||||
|
||||
@@ -125,23 +115,9 @@ namespace ChillerCartMeasurementManagerLib
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
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
|
||||
}
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -177,7 +153,6 @@ namespace ChillerCartMeasurementManagerLib
|
||||
catch (Exception e)
|
||||
{
|
||||
string msg = e.Message;
|
||||
ErrorLogger.Instance().Write(msg + "\r\n" + e.StackTrace, ErrorLogger.LogLevel.ERROR);
|
||||
|
||||
_fileWriter.WriteLine(Util.GetTimeString() + ", " + msg);
|
||||
|
||||
@@ -185,12 +160,9 @@ namespace ChillerCartMeasurementManagerLib
|
||||
_callback?.Invoke(-1, -1);
|
||||
}
|
||||
}
|
||||
ErrorLogger.Instance().Write("TempDataLogWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
|
||||
}
|
||||
catch (Exception err)
|
||||
catch (Exception)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
|
||||
//Send error code to callback if valid
|
||||
_callback(-1, -1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
// **********************************************************************************************************
|
||||
// BitGenSoftMeasurementManager.cs
|
||||
// 7/28/2022
|
||||
// NGI - Next Generation Interceptor
|
||||
//
|
||||
// Contract No. HQ0856-21-C-0003/1022000209
|
||||
//
|
||||
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
|
||||
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
//
|
||||
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
|
||||
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
|
||||
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
|
||||
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
|
||||
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
|
||||
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
|
||||
//
|
||||
// CONTROLLED BY: MISSILE DEFENSE AGENCY
|
||||
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
|
||||
// CUI CATEGORY: CTI
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.XPath;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using Raytheon.Common.Coe;
|
||||
using Raytheon.Instruments;
|
||||
|
||||
namespace MeasurementManagerLib
|
||||
{
|
||||
/// <summary>
|
||||
/// COE Measurement Manager class
|
||||
/// </summary>
|
||||
public class CoeMeasurementManager : IDisposable
|
||||
{
|
||||
private readonly ILogger _logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly Dictionary<string, CoeComm> _coeNodes = new Dictionary<string, CoeComm>();
|
||||
|
||||
private readonly IInstrumentManager _instrumentManager;
|
||||
public int CheckForMessageIntervalMs { get; private set; }
|
||||
/// <summary>
|
||||
/// constructor that will create a list of BIT instruments
|
||||
/// </summary>
|
||||
/// <param name="instrumentManager"></param>
|
||||
/// <param name="switchMeasurementManagerConfigFullPath"></param>
|
||||
public CoeMeasurementManager(IInstrumentManager instrumentManager, string coeMeasurementManagerConfigFullPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
_instrumentManager = instrumentManager;
|
||||
|
||||
ConfigurationFile configurationFile = new ConfigurationFile(coeMeasurementManagerConfigFullPath);
|
||||
|
||||
CheckForMessageIntervalMs = 10;
|
||||
|
||||
if (Int32.TryParse(configurationFile.ReadValue("GENERAL", "CheckForMessageIntervalMs"), out int val))
|
||||
{
|
||||
CheckForMessageIntervalMs = val;
|
||||
}
|
||||
|
||||
ICollection<object> coeNodeList = _instrumentManager.GetInstruments(typeof(CoeComm));
|
||||
foreach (CoeComm node in coeNodeList)
|
||||
{
|
||||
_coeNodes.Add(node.Name, node);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
~CoeMeasurementManager()
|
||||
{
|
||||
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() ...");
|
||||
foreach (var node in _coeNodes)
|
||||
{
|
||||
try
|
||||
{
|
||||
CoeComm coeNode = node.Value;
|
||||
coeNode.Shutdown();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get XML Docs
|
||||
/// </summary>
|
||||
public object GetXmlDocs(string coeDevice)
|
||||
{
|
||||
return _coeNodes[coeDevice].GetXmlDocs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a message
|
||||
/// </summary>
|
||||
public Message CreateMessage(string coeDevice, string messageName)
|
||||
{
|
||||
Message msg = null;
|
||||
|
||||
MessageXmlDocument msgXmlDocument = null;
|
||||
|
||||
Dictionary<string, MessageXmlDocument> xmlDocs = new Dictionary<string, MessageXmlDocument>();
|
||||
var xmlDocObject = GetXmlDocs(coeDevice);
|
||||
|
||||
if (xmlDocObject != null && xmlDocObject.GetType() == xmlDocs.GetType())
|
||||
{
|
||||
xmlDocs = (Dictionary<string, MessageXmlDocument>)xmlDocObject;
|
||||
|
||||
foreach (KeyValuePair<string, MessageXmlDocument> item in xmlDocs)
|
||||
{
|
||||
XPathNavigator Node = xmlDocs[item.Key].CreateNavigator();
|
||||
XPathNodeIterator Nodeset = Node.Select("interface/message/name");
|
||||
while (Nodeset.MoveNext())
|
||||
{
|
||||
if (String.Equals(Nodeset.Current.Value, messageName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
msgXmlDocument = item.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (msgXmlDocument != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (msgXmlDocument != null)
|
||||
{
|
||||
msg = new Message(messageName, msgXmlDocument, _coeNodes[coeDevice].ShallLogMessage(messageName));
|
||||
msg.Default();
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initialize COE nodes based on test type
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="testType"></param>
|
||||
public void InitNodes()
|
||||
{
|
||||
foreach (var node in _coeNodes)
|
||||
{
|
||||
try
|
||||
{
|
||||
CoeComm coeNode = node.Value;
|
||||
coeNode.Initialize();
|
||||
coeNode.Open();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// close all connections
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var coeNode in _coeNodes)
|
||||
{
|
||||
coeNode.Value?.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send message using the first available device
|
||||
/// </summary>
|
||||
/// <param name="messageId"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <param name="messageParams"></param>
|
||||
/// <returns></returns>
|
||||
public bool SendMessage(string messageId, IEnumerable<KeyValuePair<string, string>> messageParams = null)
|
||||
{
|
||||
if (_coeNodes.Any())
|
||||
{
|
||||
CoeComm coeNode = _coeNodes.First().Value;
|
||||
return coeNode.SendMessage(messageId, messageParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Unable to locate COE node. No nodes defined");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send message from a particular device
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="messageId"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <param name="messageParams"></param>
|
||||
/// <returns></returns>
|
||||
public bool SendMessage(string instrumentName, string messageId, IEnumerable<KeyValuePair<string, string>> messageParams = null)
|
||||
{
|
||||
if (_coeNodes.ContainsKey(instrumentName))
|
||||
{
|
||||
return _coeNodes[instrumentName].SendMessage(messageId, messageParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Unable to locate COE node {instrumentName}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get subscribed message from UUT using the first device
|
||||
/// </summary>
|
||||
/// <param name="messageId"></param>
|
||||
/// <returns></returns>
|
||||
public CoeResponseMsgData GetNextResponseInQueue(string messageId)
|
||||
{
|
||||
if (_coeNodes.Any())
|
||||
{
|
||||
CoeComm coeNode = _coeNodes.First().Value;
|
||||
return coeNode.GetNextResponseInQueue(messageId);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get subscribed message from UUT from a particular device
|
||||
/// </summary>
|
||||
/// <param name="instrumentName"></param>
|
||||
/// <param name="messageId"></param>
|
||||
/// <returns></returns>
|
||||
public CoeResponseMsgData GetNextResponseInQueue(string instrumentName, string messageId)
|
||||
{
|
||||
return _coeNodes.ContainsKey(instrumentName) ? _coeNodes[instrumentName].GetNextResponseInQueue(messageId) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the queue for a particular response message.
|
||||
/// This is useful if we have a large size queue and we don't want to dequeue each item to get
|
||||
/// to the newest item. So we clear the queue first, before trying to get the newest item in the queue
|
||||
/// </summary>
|
||||
public void ClearResponseMessageQueue(string instrumentName, string messageId)
|
||||
{
|
||||
if (_coeNodes.ContainsKey(instrumentName))
|
||||
{
|
||||
_coeNodes[instrumentName].ClearResponseMessageQueue(messageId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,9 @@
|
||||
<Import Project="$(SolutionDir)Solution.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AssemblyName>BitGenSoftMeasurementManager</AssemblyName>
|
||||
<AssemblyName>CoeMeasurementManager</AssemblyName>
|
||||
<Product>Composable Test Software Library</Product>
|
||||
<Description>Bit GenSoft Measurement Manager</Description>
|
||||
<Description>COE Measurement Manager</Description>
|
||||
<OutputType>Library</OutputType>
|
||||
|
||||
<!-- Static versioning (Suitable for Development) -->
|
||||
@@ -16,7 +16,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.InstrumentManager.GeneralInstrumentManager" Version="1.5.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.BIT.Contracts" Version="1.4.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.CoeComm.Contracts" Version="1.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -15,26 +15,24 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using Raytheon.Instruments;
|
||||
using Raytheon.Instruments.GeneralIO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
using Raytheon.Instruments;
|
||||
|
||||
namespace MeasurementManagerLib
|
||||
{
|
||||
/// <summary>
|
||||
/// This class manages IDIO instruments and provides an abstraction
|
||||
/// This class manages DIO instruments and provides an abstraction
|
||||
/// </summary>
|
||||
public class DioMeasurementManager : IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private SortedDictionary<string, IGeneralIO> _signalNameToObjectMap = new SortedDictionary<string, IGeneralIO>();
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private SortedDictionary<string, IGeneralIO> _signalNameToDioModuleMap = new SortedDictionary<string, IGeneralIO>();
|
||||
|
||||
public Dictionary<string, IODatatypes.DIOChannelInfo> SignalNameToChannelInfoMap { get; private set; }
|
||||
|
||||
private static NLog.ILogger _logger;
|
||||
#endregion
|
||||
@@ -49,22 +47,27 @@ namespace MeasurementManagerLib
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
SignalNameToChannelInfoMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
|
||||
|
||||
ICollection<object> dioModuleList = instrumentManager.GetInstruments(typeof(IGeneralIO));
|
||||
// populate the maps
|
||||
foreach (IGeneralIO dioModule in dioModuleList)
|
||||
{
|
||||
dioModule.Initialize();
|
||||
|
||||
List<string> signalNames = dioModule.GetSignalNames();
|
||||
Dictionary<string, IODatatypes.DIOChannelInfo> signalNameToChannelInfoMap = dioModule.GetAllSignals();
|
||||
|
||||
foreach (string signalName in signalNames)
|
||||
{
|
||||
if (_signalNameToObjectMap.ContainsKey(signalName.ToUpper()))
|
||||
// add signal map for this DIO module to master signal map
|
||||
signalNameToChannelInfoMap.ToList().ForEach(x => SignalNameToChannelInfoMap.Add(x.Key, x.Value));
|
||||
|
||||
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in signalNameToChannelInfoMap)
|
||||
{
|
||||
if (_signalNameToDioModuleMap.ContainsKey(item.Key.ToUpper()))
|
||||
{
|
||||
throw new Exception("There is more than 1 DIO card that have the same signal name: " + signalName);
|
||||
throw new Exception("There is more than 1 DIO card that have the same signal name: " + item.Key);
|
||||
}
|
||||
|
||||
_signalNameToObjectMap[signalName.ToUpper()] = dioModule;
|
||||
_signalNameToDioModuleMap[item.Key.ToUpper()] = dioModule;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +103,7 @@ namespace MeasurementManagerLib
|
||||
/// <returns>0 if the signal is low, 1 if the signal is high</returns>
|
||||
public IODatatypes.BitState GetInputSignalState(string signalName)
|
||||
{
|
||||
return _signalNameToObjectMap[signalName.ToUpper()].GetBitState(signalName);
|
||||
return _signalNameToDioModuleMap[signalName.ToUpper()].GetBitState(signalName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -111,7 +114,7 @@ namespace MeasurementManagerLib
|
||||
/// <param name="timeToSleepMs">number of ms to wait after setting signal</param>
|
||||
public void SetOutputSignalState(string signalName, IODatatypes.BitState state, uint timeToSleepMs = 100)
|
||||
{
|
||||
_signalNameToObjectMap[signalName.ToUpper()].SetBit(signalName, state);
|
||||
_signalNameToDioModuleMap[signalName.ToUpper()].SetBit(signalName, state);
|
||||
|
||||
// wait a bit
|
||||
Thread.Sleep((int)timeToSleepMs);
|
||||
@@ -125,40 +128,24 @@ namespace MeasurementManagerLib
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~DioMeasurementManager()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
foreach (KeyValuePair<string, IGeneralIO> entry in _signalNameToObjectMap)
|
||||
{
|
||||
try
|
||||
{
|
||||
entry.Value.Shutdown();
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ErrorLogger.Instance().Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
foreach (KeyValuePair<string, IGeneralIO> entry in _signalNameToDioModuleMap)
|
||||
{
|
||||
entry.Value.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,246 +0,0 @@
|
||||
// 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;
|
||||
using System.Threading;
|
||||
using Raytheon.Common;
|
||||
using System.IO;
|
||||
using Raytheon.Instruments;
|
||||
using Raytheon.Instruments.PowerSupply;
|
||||
|
||||
namespace MeasurementManagerLib
|
||||
{
|
||||
/// <summary>
|
||||
/// A worker for iterating through each supply in the system, querying its' data, logging it out, and issuing callbacks to the host
|
||||
/// </summary>
|
||||
internal class PowerSupplyDataLogWorker : IWorkerInterface
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
|
||||
private bool _threadQuitControl;
|
||||
private AutoResetEvent _quitEvent;
|
||||
private StreamWriter _fileWriter;
|
||||
private readonly string _logFilePath;
|
||||
private readonly int _threadRestTimeMs;
|
||||
private readonly PowerSupplyMeasurementManager.PowerMonitorDelegate _callback;
|
||||
private readonly PowerSupplyMeasurementManager _controller;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PrivateFunctions
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~PowerSupplyDataLogWorker()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release of resources
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_fileWriter.Dispose();
|
||||
|
||||
_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
|
||||
|
||||
#region PublicFuctions
|
||||
|
||||
/// <summary>
|
||||
/// The constructor
|
||||
/// </summary>
|
||||
/// <param name="controller">The controller for the power supplies</param>
|
||||
/// <param name="fileName">The file name to log the data to</param>
|
||||
/// <param name="threadRestTimeMs">The number os ms to rest after each iteration through the loop</param>
|
||||
/// <param name="callback">The host callback function. If null, no callback is issued</param>
|
||||
public PowerSupplyDataLogWorker(PowerSupplyMeasurementManager controller, string fileName, int threadRestTimeMs, PowerSupplyMeasurementManager.PowerMonitorDelegate callback)
|
||||
{
|
||||
_controller = controller;
|
||||
|
||||
// these gets set in SetControlParams
|
||||
_logFilePath = fileName;
|
||||
_callback = callback;
|
||||
_threadRestTimeMs = threadRestTimeMs;
|
||||
|
||||
_fileWriter = new StreamWriter(_logFilePath, true);
|
||||
|
||||
_threadQuitControl = false;
|
||||
_quitEvent = new AutoResetEvent(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>
|
||||
/// Loops thorugh each supply in the system, queries the status, logs it out and calls the host callback
|
||||
/// </summary>
|
||||
public void DoWork()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Used to handle the labels at the top of the CSV log file generated
|
||||
const string LOG_PREFIX = "DateTime,Module,Voltage,VoltageSetpoint,Current,IsOutputOn,fault status";
|
||||
|
||||
// callback error codes
|
||||
const int NO_ERROR = 0;
|
||||
const int ERROR = -1;
|
||||
|
||||
List<string> powerModules = _controller.GetPowerModuleList();
|
||||
|
||||
_fileWriter.WriteLine(LOG_PREFIX);
|
||||
|
||||
while (_threadQuitControl == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_quitEvent.WaitOne(_threadRestTimeMs))
|
||||
{
|
||||
_threadQuitControl = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//string callbackData = CALLBACK_PREFIX;
|
||||
List<PowerMonitorCallbackData> callBackDataList = new List<PowerMonitorCallbackData>();
|
||||
|
||||
//get data from each supply
|
||||
foreach (string powerModule in powerModules)
|
||||
{
|
||||
// check for quit event and exit if needed
|
||||
if (_quitEvent.WaitOne(1) == true)
|
||||
{
|
||||
_threadQuitControl = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
PowerData data = _controller.ReadPowerData(powerModule);
|
||||
|
||||
PowerMonitorCallbackData callbackData;
|
||||
callbackData.powerModule = powerModule;
|
||||
callbackData.voltage = data.Voltage;
|
||||
callbackData.voltageSetpoint = data.VoltageSetpoint;
|
||||
callbackData.current = data.Current;
|
||||
callbackData.outputStatus = data.OutputStatus;
|
||||
callbackData.ovpocpStatus = data.FaultStatus;
|
||||
callbackData.overVoltageProtectionValue = data.OverVoltageProtection;
|
||||
callbackData.overCurrentProtectionValue = data.OverCurrentProtection;
|
||||
|
||||
callBackDataList.Add(callbackData);
|
||||
|
||||
string log = Util.GetTimeString() + "," + powerModule + "," + Convert.ToString(data.Voltage) + "," + Convert.ToString(data.VoltageSetpoint) + "," + Convert.ToString(data.Current) + "," + Convert.ToString(data.OutputStatus) + "," + Convert.ToString(data.FaultStatus);
|
||||
|
||||
// log out the data
|
||||
_fileWriter.WriteLine(log);
|
||||
_fileWriter.Flush();
|
||||
|
||||
// check for quit event and exit if needed
|
||||
if (_quitEvent.WaitOne(1) == true)
|
||||
{
|
||||
_threadQuitControl = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point our return and log strings are both built, so return back the data string on the callback
|
||||
if (_callback != null && _threadQuitControl == false && callBackDataList.Count != 0)
|
||||
{
|
||||
_callback(callBackDataList, NO_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string msg = e.Message;
|
||||
|
||||
ErrorLogger.Instance().Write(msg + "\r\n" + e.StackTrace, ErrorLogger.LogLevel.ERROR);
|
||||
|
||||
_fileWriter.WriteLine(Util.GetTimeString() + ", " + msg);
|
||||
|
||||
// if callbacks are enabled, alert the host to the error
|
||||
if (_callback != null && _threadQuitControl == false)
|
||||
{
|
||||
_callback(null, ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ErrorLogger.Instance().Write("PowerSupplyDataLogWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the thread, closes the datalogger and calls move file
|
||||
/// </summary>
|
||||
public void QuitWork()
|
||||
{
|
||||
_threadQuitControl = true;
|
||||
|
||||
_quitEvent.Set();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace MeasurementManagerLib
|
||||
{
|
||||
public class SpaceChamberLSPSMeasurementManager
|
||||
public class SpaceChamberLspsMeasurementManager
|
||||
{
|
||||
private INetCdfData netCdfData_ = null;
|
||||
private readonly ILspsChamber lspsChamber_;
|
||||
@@ -25,7 +25,7 @@ namespace MeasurementManagerLib
|
||||
/// </summary>
|
||||
/// <param name="instrumentManager"></param>
|
||||
/// <param name="deviceName"></param>
|
||||
public SpaceChamberLSPSMeasurementManager(IInstrumentManager instrumentManager, string lspsChamber, string netCdfData)
|
||||
public SpaceChamberLspsMeasurementManager(IInstrumentManager instrumentManager, string lspsChamber, string netCdfData)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user