Big changes
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
// **********************************************************************************************************
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,936 @@
|
||||
// **********************************************************************************************************
|
||||
// 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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(SolutionDir)Solution.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AssemblyName>BitGenSoftMeasurementManager</AssemblyName>
|
||||
<Product>Composable Test Software Library</Product>
|
||||
<Description>Bit GenSoft Measurement Manager</Description>
|
||||
<OutputType>Library</OutputType>
|
||||
|
||||
<!-- Static versioning (Suitable for Development) -->
|
||||
<!-- Disable the line below for dynamic versioning -->
|
||||
<Version>1.1.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user