Major upgrade
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
coeWindows-shared.dll must be built from the "coeWindows-shared" project in the NGSRI_TE_Common_SRNSTE72374 repo https://tfs.rms.ray.com/TE/NGSRI_TE/_git/NGSRI_TE_Common_SRNSTE72374
|
||||
Branch: Dev
|
||||
Commit: 748d125cceab2fb7988876b425313b48f83fe04f
|
||||
COE version: v04.09.00.56
|
||||
|
||||
Had to fix a bug in "coeWindows-shared" code where it doesn't process the flag TCP_SELECT_VALUE which determine whether COE messaging goes through TCP or UDP in TCP mode. So it always uses UDP mode for COE messaging no matter what we set for TCP_SELECT_VALUE.
|
||||
Need Windows SDK Version 10.0.22621.0 in order to build
|
||||
|
||||
This DLL must be built in release mode. If need to debug, rebuild the project in debug mode and replace this DLL with it.
|
||||
Only use debug DLL for debugging only. Otherwise, need to use the release DLL in order to process COE messages as fast as possible.
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
// **********************************************************************************************************
|
||||
using System;
|
||||
|
||||
namespace Raytheon.Instruments.MessagingUtilities
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
// This is a generic class used to apply a bitfield to
|
||||
// a value to get the desired value
|
||||
@@ -0,0 +1,525 @@
|
||||
// **********************************************************************************************************
|
||||
// BytePackingXml.cs
|
||||
// 5/18/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.Expressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
// Takes an XML ICD and adds in nodes to represent the byte packing
|
||||
// The padding added will be displayed in the tool as arrays of characters
|
||||
internal class BytePackingXml : XmlDocument
|
||||
{
|
||||
private readonly int m_Packing = 0;
|
||||
private readonly Dictionary<string, double> m_ConstMap;
|
||||
private readonly Dictionary<string, int> m_SizeMap;
|
||||
private readonly Dictionary<string, int> m_PadMap;
|
||||
|
||||
public BytePackingXml(string icdStr) : base()
|
||||
{
|
||||
// Create the dictionaries
|
||||
m_ConstMap = new Dictionary<string, double>();
|
||||
m_PadMap = new Dictionary<string, int>();
|
||||
m_SizeMap = new Dictionary<string, int>();
|
||||
|
||||
// Create an XML document from the string
|
||||
LoadXml(icdStr);
|
||||
|
||||
XPathNavigator node = CreateNavigator();
|
||||
//Get the type of packing
|
||||
XPathNodeIterator nodeset = node.Select("/interface/packing");
|
||||
if (nodeset.MoveNext() == true)
|
||||
{
|
||||
if (!Parse.Try(nodeset.Current.Value.Trim(), out m_Packing))
|
||||
{
|
||||
switch (nodeset.Current.Value.Trim())
|
||||
{
|
||||
case "char":
|
||||
case "1":
|
||||
m_Packing = 1;
|
||||
break;
|
||||
case "short":
|
||||
case "2":
|
||||
m_Packing = 2;
|
||||
break;
|
||||
case "long":
|
||||
case "4":
|
||||
m_Packing = 4;
|
||||
break;
|
||||
case "double":
|
||||
case "8":
|
||||
default:
|
||||
m_Packing = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle all of the constants
|
||||
nodeset = node.Select("/interface/constant|/interface/namespace/constant");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
ProcessConstantNode(nodeset.Current);
|
||||
}
|
||||
|
||||
nodeset = node.Select("/interface/typedef|/interface/namespace/typedef");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
ProcessTypedefNode(nodeset.Current);
|
||||
}
|
||||
|
||||
nodeset = node.Select("/interface/enum|/interface/namespace/enum");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
ProcessEnumerationNode(nodeset.Current);
|
||||
}
|
||||
|
||||
nodeset = node.Select("/interface/structure|/interface/message|/interface/namespace/structure|/interface/namespace/message");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
ProcessStructureNode(nodeset.Current);
|
||||
}
|
||||
|
||||
NormalizeIcdLabels();
|
||||
}
|
||||
|
||||
// This function takes all of the messages in the ICD
|
||||
// and converts the labels into decimal, so when we do
|
||||
// a string lookup, they will all be in the same known format
|
||||
private void NormalizeIcdLabels()
|
||||
{
|
||||
XPathNavigator navigator = CreateNavigator();
|
||||
XPathNodeIterator nodeset;
|
||||
|
||||
nodeset = navigator.Select("/interface/message/label|/interface/namespace/message/label");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
double dLabel = GetConstFromString(nodeset.Current.Value);
|
||||
nodeset.Current.SetValue(((int)dLabel).ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("Message Label, " + nodeset.Current.Value + ", can not be converted to an integer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessConstantNode(XPathNavigator node)
|
||||
{
|
||||
string name = "";
|
||||
string constStr = "";
|
||||
double constNum = 0;
|
||||
|
||||
if (node.MoveToChild("name", ""))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
node.MoveToParent();
|
||||
}
|
||||
if (node.MoveToChild("value", ""))
|
||||
{
|
||||
constStr = node.Value.Trim();
|
||||
if ((constStr.Length != 0) && (constStr[0] != '\"'))
|
||||
{
|
||||
constNum = GetConstFromString(constStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
constNum = 0;
|
||||
}
|
||||
node.MoveToParent();
|
||||
}
|
||||
|
||||
// Verify the correctnes of the <constant> tag
|
||||
if ((name != "") && (constStr != ""))
|
||||
{
|
||||
AddItemToMap(m_ConstMap, name, constNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(
|
||||
"ERROR: Constant Definition Incorrect - <name>:" + name +
|
||||
" <value>:" + constStr);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessTypedefNode(XPathNavigator node)
|
||||
{
|
||||
string name = "";
|
||||
string type = "";
|
||||
int typeSize = 0; // Size of the item
|
||||
int typePad = 0; //Size of the largest item to pad to
|
||||
|
||||
if (node.MoveToChild("name", ""))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
node.MoveToParent();
|
||||
}
|
||||
if (node.MoveToChild("value", ""))
|
||||
{
|
||||
type = node.Value.Trim();
|
||||
GetSizeFromType(type, out typeSize, out typePad);
|
||||
node.MoveToParent();
|
||||
}
|
||||
|
||||
// Verify the correctnes of the <typedef> tag
|
||||
if ((name != "") && (type != ""))
|
||||
{
|
||||
AddItemToMap(m_PadMap, name, typePad);
|
||||
AddItemToMap(m_SizeMap, name, typeSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(
|
||||
"ERROR: Typedef Definition Incorrect - <name>:" + name +
|
||||
" <value>:" + type);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessEnumerationNode(XPathNavigator node)
|
||||
{
|
||||
string name;
|
||||
double constNum = 0;
|
||||
var constStr = string.Empty;
|
||||
|
||||
if (node.MoveToChild("name", ""))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
AddItemToMap(m_PadMap, name, 4);
|
||||
AddItemToMap(m_SizeMap, name, 4);
|
||||
node.MoveToParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("ERROR: Enumeration Definition Incorrect. No <name> tag present.");
|
||||
}
|
||||
|
||||
XPathNodeIterator nodeSet = node.Select("item|enum_item");
|
||||
while (nodeSet.MoveNext())
|
||||
{
|
||||
name = string.Empty;
|
||||
|
||||
if ((nodeSet.Current.MoveToChild("name", "")) ||
|
||||
(nodeSet.Current.MoveToChild("item_name", "")))
|
||||
{
|
||||
name = nodeSet.Current.Value.Trim();
|
||||
nodeSet.Current.MoveToParent();
|
||||
}
|
||||
if (nodeSet.Current.MoveToChild("value", ""))
|
||||
{
|
||||
constStr = nodeSet.Current.Value.Trim();
|
||||
constNum = GetConstFromString(constStr);
|
||||
nodeSet.Current.MoveToParent();
|
||||
}
|
||||
|
||||
// Verify the correctnes of the <enum><item> tag
|
||||
if ((name != "") && (constStr != ""))
|
||||
{
|
||||
AddItemToMap(m_ConstMap, name, constNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"ERROR: Enumeration Item Definition Incorrect - <name>: {name} <value>: {constStr}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessStructureNode(XPathNavigator node)
|
||||
{
|
||||
string name;
|
||||
|
||||
if (node.MoveToChild("name", ""))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
node.MoveToParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("ERROR: Stucture/Message Definition Incorrect. No <name> tag present.");
|
||||
}
|
||||
|
||||
int maxSize = 0;
|
||||
int padCount = 0;
|
||||
uint bitCount = 0; // Used to see how many bits have been processed.
|
||||
int lastItemSize = 0;
|
||||
|
||||
var nodeSet = node.Select("item|struct_item|msg_item");
|
||||
while (nodeSet.MoveNext())
|
||||
{
|
||||
GetItemSize(nodeSet.Current, out int padSize, out int itemSize, out int reps, out uint bits);
|
||||
if ((lastItemSize != itemSize) || ((bitCount + bits) > (uint)(itemSize * 8)))
|
||||
{
|
||||
bitCount = 0; // Size changed or bit rollover
|
||||
}
|
||||
|
||||
if (bitCount == 0)
|
||||
{
|
||||
padCount += AddPadding(node, nodeSet.Current, padSize, padCount);
|
||||
|
||||
// Set maxSize
|
||||
if (padSize > maxSize)
|
||||
{
|
||||
maxSize = padSize;
|
||||
}
|
||||
|
||||
// Keep up with the pad count
|
||||
padCount += (itemSize * reps);
|
||||
}
|
||||
|
||||
lastItemSize = itemSize;
|
||||
bitCount += bits;
|
||||
}
|
||||
|
||||
if (maxSize != 0)
|
||||
{
|
||||
// Add final padding
|
||||
padCount += AddPadding(node, null, maxSize, padCount);
|
||||
}
|
||||
|
||||
AddItemToMap(m_PadMap, name, maxSize);
|
||||
AddItemToMap(m_SizeMap, name, padCount);
|
||||
}
|
||||
|
||||
private void GetItemSize(XPathNavigator node, out int padSize, out int itemSize, out int reps, out uint bits)
|
||||
{
|
||||
string name = "";
|
||||
|
||||
if ((node.MoveToChild("name", "")) ||
|
||||
(node.MoveToChild("item_name", "")))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
node.MoveToParent();
|
||||
}
|
||||
|
||||
itemSize = -1;
|
||||
padSize = -1;
|
||||
reps = 1;
|
||||
bits = 0;
|
||||
|
||||
var nodeSet = node.Select("type");
|
||||
while (nodeSet.MoveNext())
|
||||
{
|
||||
GetSizeFromType(nodeSet.Current.Value.Trim(), out padSize, out itemSize);
|
||||
}
|
||||
|
||||
nodeSet = node.Select("bits");
|
||||
if (nodeSet.MoveNext())
|
||||
{
|
||||
bits = (uint)GetConstFromString(nodeSet.Current.Value.Trim());
|
||||
}
|
||||
|
||||
nodeSet = node.Select("arrayLength|imageWidth|imageHeight");
|
||||
while (nodeSet.MoveNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
reps *= (int)GetConstFromString(nodeSet.Current.Value.Trim());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception
|
||||
(e.Message + " item name = \"" + name + "\", tag = <" +
|
||||
nodeSet.Current.Name + ">.");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ((itemSize == -1) || (padSize == -1))
|
||||
{
|
||||
throw new Exception
|
||||
("ERROR: Item named " + name + "does not contain a <type> tag.");
|
||||
}
|
||||
|
||||
if (bits == 0)
|
||||
bits = (uint)padSize * 8;
|
||||
}
|
||||
|
||||
private double GetConstFromString(string constStr)
|
||||
{
|
||||
// remove namespace
|
||||
constStr = Regex.Replace(constStr, @"[^:]+::([^:]+)", "$1");
|
||||
if ((constStr.Length > 0) && (constStr[0] == '\''))
|
||||
{
|
||||
byte charData = (byte)constStr[1];
|
||||
constStr = charData.ToString();
|
||||
}
|
||||
|
||||
if (Parse.Try(constStr, out double data) == false)
|
||||
{
|
||||
if (Parse.Try(constStr, out int iData) == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
data = m_ConstMap[constStr];
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("ERROR: ConstantValue - \"" + constStr + "\" does not resolve to a number.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = (double)iData;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private void AddItemToMap(Dictionary<string, int> map, string name, int value)
|
||||
{
|
||||
if (map.ContainsKey(name))
|
||||
{
|
||||
throw new Exception("ERROR: Element " + name + " is defined multiple times.");
|
||||
}
|
||||
else
|
||||
{
|
||||
map.Add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddItemToMap(Dictionary<string, double> map, string name, double value)
|
||||
{
|
||||
if (map.ContainsKey(name))
|
||||
{
|
||||
throw new Exception("ERROR: Element " + name + " is defined multiple times.");
|
||||
}
|
||||
else
|
||||
{
|
||||
map.Add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetSizeFromType(string type, out int typePad, out int typeSize)
|
||||
{
|
||||
// Remove all whitespace
|
||||
type = type.Replace(" ", "");
|
||||
// remove namespace
|
||||
type = Regex.Replace(type, @"[^:]+::([^:]+)", "$1");
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case "uint8_t":
|
||||
type = "char";
|
||||
break;
|
||||
case "uint16_t":
|
||||
case "int16_t":
|
||||
type = "short";
|
||||
break;
|
||||
case "uint32_t":
|
||||
case "int32_t":
|
||||
type = "int";
|
||||
break;
|
||||
case "uint64_t":
|
||||
case "int64_t":
|
||||
type = "double";
|
||||
break;
|
||||
}
|
||||
|
||||
if ((type == "char"))
|
||||
{
|
||||
typePad = 1;
|
||||
typeSize = 1;
|
||||
}
|
||||
else if ((type == "short"))
|
||||
{
|
||||
typePad = 2;
|
||||
typeSize = 2;
|
||||
}
|
||||
else if ((Regex.IsMatch(type, @"unsigned", RegexOptions.IgnoreCase)) || (type == "int") || (type == "float") ||
|
||||
(type == "boolean") || (type == "address"))
|
||||
{
|
||||
typePad = 4;
|
||||
typeSize = 4;
|
||||
}
|
||||
else if ((type == "double"))
|
||||
{
|
||||
typePad = 8;
|
||||
typeSize = 8;
|
||||
}
|
||||
else // The type is complex and has already been defined
|
||||
{
|
||||
try
|
||||
{
|
||||
typePad = m_PadMap[type];
|
||||
typeSize = m_SizeMap[type];
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("ERROR: <type> - " + type + " used without being defined.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int AddPadding(XPathNavigator ParentElement, XPathNavigator CurrentElement, int padSize, int padCount)
|
||||
{
|
||||
int padAdd = 0;
|
||||
int padTo = padSize;
|
||||
|
||||
if (m_Packing < padSize)
|
||||
{
|
||||
padTo = m_Packing;
|
||||
}
|
||||
|
||||
if (m_Packing > 0 && padTo != 0 && (padCount % padTo != 0))
|
||||
{
|
||||
padAdd = padTo - (padCount % padTo);
|
||||
InsertPaddingNode(ParentElement, CurrentElement, padAdd);
|
||||
}
|
||||
|
||||
return padAdd;
|
||||
}
|
||||
|
||||
private void InsertPaddingNode(XPathNavigator ParentElement, XPathNavigator CurrentElement, int padAdd)
|
||||
{
|
||||
string pad = "<item>" +
|
||||
"<name>" + Message.PADDING_ITEM_NAME + "</name>" +
|
||||
"<type>char</type>" +
|
||||
"<arrayLength>" + padAdd + "</arrayLength>" +
|
||||
"<instruType>S</instruType>" +
|
||||
"</item>";
|
||||
if (CurrentElement != null)
|
||||
{
|
||||
CurrentElement.InsertBefore(pad);
|
||||
}
|
||||
else // End padding
|
||||
{
|
||||
ParentElement.AppendChild(pad);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,604 @@
|
||||
// **********************************************************************************************************
|
||||
// MessageData.cs
|
||||
// 5/18/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.IO;
|
||||
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
public class MessageData : ICloneable
|
||||
{
|
||||
public string FieldName;
|
||||
public string FieldType;
|
||||
public string FieldValue;
|
||||
public string FieldArrayValue;
|
||||
public string FieldDefaultValue;
|
||||
public string FieldMaxValue;
|
||||
public string FieldMinValue;
|
||||
public string FieldBitValue;
|
||||
public string FieldInstruType;
|
||||
public string Variable;
|
||||
public string MaxOffset;
|
||||
public string MinOffset;
|
||||
public string VerifyType;
|
||||
public bool isSelected;
|
||||
public bool isArray;
|
||||
public bool isStructure;
|
||||
public bool isArrayOfStructures;
|
||||
public bool isEnum;
|
||||
public bool usesRegister;
|
||||
public bool isValid;
|
||||
public bool useRange;
|
||||
public int arrayLength;
|
||||
public uint imageWidth;
|
||||
public uint imageHeight;
|
||||
public uint imagePixelSize;
|
||||
public ulong bitMask;
|
||||
public bool expanded;
|
||||
public int depth;
|
||||
public byte[] imageBuffer;
|
||||
public uint imageBufferSize;
|
||||
public MessageData[] MessageArray;
|
||||
|
||||
public delegate coe.Status ReadImageDelegate
|
||||
(
|
||||
string filename,
|
||||
uint columns,
|
||||
uint rows,
|
||||
uint pixel_size,
|
||||
byte[] buffer
|
||||
);
|
||||
|
||||
private MessageXmlDocument m_Icd;
|
||||
|
||||
internal int m_BitCounter = 0; // used to calculate the bit mask
|
||||
|
||||
internal static Dictionary<string, ReadImageDelegate> m_ReadFunctions = null;
|
||||
|
||||
public bool LogData { get; set; }
|
||||
|
||||
private MessageData() { }
|
||||
private MessageData(MessageXmlDocument Icd)
|
||||
{
|
||||
FieldName = null;
|
||||
FieldType = null;
|
||||
FieldValue = null;
|
||||
FieldArrayValue = null;
|
||||
FieldDefaultValue = null;
|
||||
FieldMaxValue = null;
|
||||
FieldMinValue = null;
|
||||
FieldBitValue = null;
|
||||
Variable = null;
|
||||
MaxOffset = null;
|
||||
MinOffset = null;
|
||||
VerifyType = null;
|
||||
isSelected = false;
|
||||
isArray = false;
|
||||
isStructure = false;
|
||||
isArrayOfStructures = false;
|
||||
usesRegister = false;
|
||||
useRange = false;
|
||||
arrayLength = 0;
|
||||
imageWidth = 0;
|
||||
imageHeight = 0;
|
||||
imagePixelSize = 0;
|
||||
bitMask = 0;
|
||||
expanded = false;
|
||||
depth = 0;
|
||||
imageBufferSize = 0;
|
||||
imageBuffer = null;
|
||||
|
||||
m_Icd = Icd;
|
||||
}
|
||||
|
||||
public MessageData(string fieldname,
|
||||
string fieldtype,
|
||||
string fieldvalue,
|
||||
string fielddefaultvalue,
|
||||
MessageXmlDocument Icd,
|
||||
bool logData = true) :
|
||||
this(Icd)
|
||||
{
|
||||
FieldName = fieldname;
|
||||
FieldType = fieldtype;
|
||||
FieldValue = fieldvalue;
|
||||
|
||||
LogData = logData;
|
||||
|
||||
SetInstruType(null);
|
||||
SetDefaultValue(fielddefaultvalue);
|
||||
|
||||
}
|
||||
|
||||
public MessageData(string fieldname,
|
||||
string fieldtype,
|
||||
string fieldvalue,
|
||||
string fielddefaultvalue,
|
||||
string fieldmaxvalue,
|
||||
string fieldminvalue,
|
||||
MessageXmlDocument Icd) :
|
||||
this(fieldname, fieldtype, fieldvalue, fielddefaultvalue, Icd)
|
||||
{
|
||||
SetMaxValue(fieldmaxvalue);
|
||||
SetMinValue(fieldminvalue);
|
||||
}
|
||||
|
||||
public string FormattedValue
|
||||
{
|
||||
get { return FormatValue(FieldValue); }
|
||||
}
|
||||
public string FormattedMinValue
|
||||
{
|
||||
get { return FormatValue(FieldMinValue); }
|
||||
}
|
||||
public string FormattedMaxValue
|
||||
{
|
||||
get { return FormatValue(FieldMaxValue); }
|
||||
}
|
||||
|
||||
public static string ImageFileReadTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
string fileTypes = "";
|
||||
if (m_ReadFunctions == null) return null;
|
||||
foreach (string type in m_ReadFunctions.Keys)
|
||||
{
|
||||
if (fileTypes != "")
|
||||
fileTypes += "|";
|
||||
|
||||
fileTypes += type.ToUpper() + " files (*." + type.ToLower() + ")|*." + type.ToLower();
|
||||
}
|
||||
|
||||
return fileTypes;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddReadExtension(string extension, ReadImageDelegate readFunc)
|
||||
{
|
||||
if (m_ReadFunctions == null)
|
||||
m_ReadFunctions = new Dictionary<string, ReadImageDelegate>();
|
||||
|
||||
if (m_ReadFunctions.ContainsKey(extension))
|
||||
m_ReadFunctions[extension] = readFunc;
|
||||
else
|
||||
m_ReadFunctions.Add(extension, readFunc);
|
||||
}
|
||||
|
||||
public void UpdateImage()
|
||||
{
|
||||
if (FieldInstruType == "P")
|
||||
{
|
||||
if (File.Exists(FieldValue))
|
||||
{
|
||||
string extension = FieldValue.Substring(FieldValue.LastIndexOf(".") + 1);
|
||||
m_ReadFunctions[extension](FieldValue,
|
||||
imageWidth,
|
||||
imageHeight,
|
||||
imagePixelSize,
|
||||
imageBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO add error message
|
||||
//MessageBox.Show("Unable to open file " + FieldValue +
|
||||
// " to populate " + FieldName,
|
||||
// "File Read Error",
|
||||
// MessageBoxButtons.OK,
|
||||
// MessageBoxIcon.Error);
|
||||
FieldValue = "";
|
||||
for (int i = 0; i < imageBuffer.Length; i++)
|
||||
{
|
||||
imageBuffer[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetDefaultValue(string fieldDefaultValue)
|
||||
{
|
||||
// Initialize uninitialized value
|
||||
if (fieldDefaultValue == null)
|
||||
{
|
||||
fieldDefaultValue = "";
|
||||
}
|
||||
|
||||
if ((FieldType == "char") && (fieldDefaultValue.Contains("\"")))
|
||||
{
|
||||
FieldInstruType = "S";
|
||||
}
|
||||
|
||||
FieldDefaultValue = RemoveCharFromString(fieldDefaultValue, '\"');
|
||||
}
|
||||
|
||||
public void SetMaxValue(string fieldmaxvalue)
|
||||
{
|
||||
if (fieldmaxvalue == null) return; /* Bad argument */
|
||||
|
||||
if ((FieldType == "char") && (fieldmaxvalue.Contains("\"")))
|
||||
{
|
||||
FieldInstruType = "S";
|
||||
}
|
||||
|
||||
FieldMaxValue = RemoveCharFromString(fieldmaxvalue, '\"');
|
||||
}
|
||||
|
||||
public void SetMinValue(string fieldminvalue)
|
||||
{
|
||||
if (fieldminvalue == null) return; /* Bad argument */
|
||||
|
||||
if ((FieldType == "char") && (fieldminvalue.Contains("\"")))
|
||||
{
|
||||
FieldInstruType = "S";
|
||||
}
|
||||
|
||||
FieldMinValue = RemoveCharFromString(fieldminvalue, '\"');
|
||||
}
|
||||
|
||||
public void SetBitValue(int bits)
|
||||
{
|
||||
int size = (int)Message.GetTypeSize(FieldType, isEnum, LogData);
|
||||
|
||||
// Determine the bitMask
|
||||
if (bits == 0)
|
||||
{
|
||||
m_BitCounter = 0;
|
||||
FieldBitValue = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
FieldBitValue = bits.ToString();
|
||||
|
||||
// If bits overflow across the type boundary, then
|
||||
// they start at the next boundary.
|
||||
//
|
||||
// MSDN :
|
||||
// "Note that nYear is 8 bits long and would overflow
|
||||
// the word boundary of the declared type, unsigned short.
|
||||
// Therefore, it is begun at the beginning of a
|
||||
// new unsigned short."
|
||||
if (m_BitCounter + bits > size * 8)
|
||||
{
|
||||
m_BitCounter = 0;
|
||||
}
|
||||
|
||||
// 2^bits-1 will give a bit mask with bit# of 1's
|
||||
// ex: bits = 5, bitMask = 11111
|
||||
bitMask = (ulong)Math.Pow(2, (double)bits) - 1;
|
||||
|
||||
// We must slide the bitMask left to put it in place
|
||||
bitMask <<= m_BitCounter;
|
||||
m_BitCounter += bits;
|
||||
|
||||
// If we have used all the bits in the type that was defined, then
|
||||
// restart the counter
|
||||
if (m_BitCounter == size * 8)
|
||||
m_BitCounter = 0;
|
||||
}
|
||||
|
||||
if (bitMask == 0xffffff)
|
||||
{
|
||||
bitMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetArraySize(int size)
|
||||
{
|
||||
char result;
|
||||
|
||||
arrayLength = size; // Save the size
|
||||
|
||||
if (!isArray && !isStructure)
|
||||
{
|
||||
// Don't handle strings as arrays
|
||||
if ((FieldInstruType != "S") && (FieldInstruType != "P"))
|
||||
{
|
||||
isArray = true;
|
||||
|
||||
MessageArray = new MessageData[size];
|
||||
// If the field type is char or unsigned char and the default value
|
||||
// exists and is a string then write one char of the string to
|
||||
// each element of the array
|
||||
if ((FieldType == "char" || FieldType == "unsigned char") &&
|
||||
FieldDefaultValue != null &&
|
||||
!Parse.Try(FieldDefaultValue, out result))
|
||||
{
|
||||
for (uint index = 0; index < size; index++)
|
||||
{
|
||||
//Only the elements that are required to spell out the string should
|
||||
//receive default values.
|
||||
if (index < FieldDefaultValue.Length)
|
||||
{
|
||||
MessageArray[index] = new MessageData(FieldName + "[" + index + "]",
|
||||
FieldType, FieldValue, FieldDefaultValue[(int)index].ToString(),
|
||||
FieldMaxValue, FieldMinValue, m_Icd);
|
||||
MessageArray[index].FieldInstruType = FieldInstruType;
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageArray[index] = new MessageData(FieldName + "[" + index + "]",
|
||||
FieldType, FieldValue, "0",
|
||||
FieldMaxValue, FieldMinValue, m_Icd);
|
||||
MessageArray[index].FieldInstruType = FieldInstruType;
|
||||
}
|
||||
MessageArray[index].depth = depth + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint index = 0; index < size; index++)
|
||||
{
|
||||
MessageArray[index] = new MessageData(FieldName + "[" + index + "]",
|
||||
FieldType, FieldValue, FieldDefaultValue, FieldMaxValue,
|
||||
FieldMinValue, m_Icd);
|
||||
MessageArray[index].FieldInstruType = FieldInstruType;
|
||||
MessageArray[index].depth = depth + 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStructureSize(int size)
|
||||
{
|
||||
if (!isArray && !isStructure)
|
||||
{
|
||||
isStructure = true;
|
||||
MessageArray = new MessageData[size];
|
||||
for (uint index = 0; index < size; index++)
|
||||
{
|
||||
MessageArray[index] = new MessageData(FieldName + ".", null, null, null, m_Icd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetInstruType(string Type)
|
||||
{
|
||||
if (Type != null)
|
||||
{
|
||||
FieldInstruType = Type;
|
||||
|
||||
// Ensure 'S' is used properly
|
||||
if ((Type == "S") && (FieldType != "char"))
|
||||
{
|
||||
return; /* << EXIT >> */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((FieldType != null) &&
|
||||
((FieldType.Trim() == "float") || (FieldType.Trim() == "double")))
|
||||
{
|
||||
FieldInstruType = "F";
|
||||
}
|
||||
else
|
||||
{
|
||||
FieldInstruType = "I";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetPixelSize()
|
||||
{
|
||||
// Only do this if the user did not define a size
|
||||
if (imagePixelSize == 0)
|
||||
{
|
||||
switch (FieldType)
|
||||
{
|
||||
case "char":
|
||||
case "unsigned char":
|
||||
case "unsignedchar":
|
||||
imagePixelSize = 1;
|
||||
break;
|
||||
|
||||
case "short":
|
||||
case "unsigned short":
|
||||
case "unsignedshort":
|
||||
imagePixelSize = 2;
|
||||
break;
|
||||
|
||||
case "int":
|
||||
case "unsigned int":
|
||||
case "unsignedint":
|
||||
case "unsigned":
|
||||
case "boolean":
|
||||
case "address":
|
||||
case "float":
|
||||
imagePixelSize = 4;
|
||||
break;
|
||||
|
||||
case "double":
|
||||
case "long long":
|
||||
case "longlong":
|
||||
case "unsigned long long":
|
||||
case "unsignedlonglong":
|
||||
imagePixelSize = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isEnum)
|
||||
{
|
||||
imagePixelSize = 4;
|
||||
}
|
||||
else // Error case
|
||||
{
|
||||
imagePixelSize = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string FormatValue(string Value)
|
||||
{
|
||||
if ((Value == null) || (Value == ""))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
else // Value exists
|
||||
{
|
||||
if (isEnum == false)
|
||||
{
|
||||
if (FieldInstruType == "I")
|
||||
{
|
||||
// This is being represented as a decimal
|
||||
if (Parse.Try(Value, out long dec) == true)
|
||||
{
|
||||
return dec.ToString();
|
||||
}
|
||||
}
|
||||
else if (FieldInstruType == "F")
|
||||
{
|
||||
// This is being represented as floating point
|
||||
if (Parse.Try(Value, out double flt) == true)
|
||||
{
|
||||
return flt.ToString();
|
||||
}
|
||||
}
|
||||
else if ((FieldInstruType == "X") ||
|
||||
(FieldInstruType == "B") ||
|
||||
(FieldInstruType == "T"))
|
||||
{
|
||||
// This is being represented as a hexadecimal value
|
||||
if (Parse.Try(Value, out long hex) == true)
|
||||
{
|
||||
return "0x" + hex.ToString("X");
|
||||
}
|
||||
}
|
||||
else if (FieldInstruType == "N")
|
||||
{
|
||||
// This is being represented as a binary number
|
||||
if (Parse.Try(Value, out long bin) == true)
|
||||
{
|
||||
return Convert.ToString(bin, 2) + "b";
|
||||
}
|
||||
}
|
||||
// else InstruType == 'S' or 'P' or anything else return the value
|
||||
}
|
||||
else // This value is an enumeration
|
||||
{
|
||||
Dictionary<string, string> enums = m_Icd.GetEnumerations(FieldType);
|
||||
if (enums.ContainsValue(Value) == true)
|
||||
{
|
||||
foreach (KeyValuePair<string, string> pair in enums)
|
||||
{
|
||||
if (pair.Value.Trim() == Value.Trim())
|
||||
{
|
||||
return pair.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Value; // If nothing above applies, simply return the value string
|
||||
}
|
||||
|
||||
private String RemoveCharFromString(String str, char c)
|
||||
{
|
||||
if (str == null) return null; // Handle null case
|
||||
|
||||
int index = str.IndexOf(c);
|
||||
while (index != -1)
|
||||
{
|
||||
str = str.Remove(index, 1);
|
||||
index = str.IndexOf(c);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#region ICloneable Members
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
MessageData clone = new MessageData();
|
||||
|
||||
clone.FieldName = FieldName;
|
||||
clone.FieldType = FieldType;
|
||||
clone.FieldValue = FieldValue;
|
||||
clone.FieldArrayValue = FieldArrayValue;
|
||||
clone.FieldDefaultValue = FieldDefaultValue;
|
||||
clone.FieldMaxValue = FieldMaxValue;
|
||||
clone.FieldMinValue = FieldMinValue;
|
||||
clone.FieldBitValue = FieldBitValue;
|
||||
clone.FieldInstruType = FieldInstruType;
|
||||
clone.Variable = Variable;
|
||||
clone.MaxOffset = MaxOffset;
|
||||
clone.MinOffset = MinOffset;
|
||||
clone.VerifyType = VerifyType;
|
||||
clone.isSelected = isSelected;
|
||||
clone.isArray = isArray;
|
||||
clone.isStructure = isStructure;
|
||||
clone.isArrayOfStructures = isArrayOfStructures;
|
||||
clone.isEnum = isEnum;
|
||||
clone.usesRegister = usesRegister;
|
||||
clone.isValid = isValid;
|
||||
clone.useRange = useRange;
|
||||
clone.arrayLength = arrayLength;
|
||||
clone.bitMask = bitMask;
|
||||
clone.expanded = expanded;
|
||||
clone.depth = depth;
|
||||
clone.m_Icd = m_Icd;
|
||||
clone.imageWidth = imageWidth;
|
||||
clone.imageHeight = imageHeight;
|
||||
clone.imagePixelSize = imagePixelSize;
|
||||
clone.imageBufferSize = imageBufferSize;
|
||||
if (imageBufferSize > 0)
|
||||
{
|
||||
clone.imageBuffer = new byte[imageBufferSize];
|
||||
imageBuffer.CopyTo(clone.imageBuffer, 0);
|
||||
}
|
||||
|
||||
if (MessageArray == null)
|
||||
{
|
||||
clone.MessageArray = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
clone.MessageArray = new MessageData[MessageArray.Length];
|
||||
for (int i = 0; i < MessageArray.Length; i++)
|
||||
{
|
||||
clone.MessageArray[i] = (MessageData)MessageArray[i].Clone();
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
// **********************************************************************************************************
|
||||
// MessageXmlDocument.cs
|
||||
// 5/18/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.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using NLog;
|
||||
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
public class MessageXmlDocument : XmlDocument
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly string _XmlFileName;
|
||||
private string BuiltXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><?xml-stylesheet type=\"text/xsl\" ?><interface>";
|
||||
|
||||
private uint m_MaxMsgSize = 0;
|
||||
private readonly List<string> m_IncludeList;
|
||||
|
||||
public bool LogData { get; set; }
|
||||
|
||||
private MessageXmlDocument() : base()
|
||||
{
|
||||
LogData = true;
|
||||
}
|
||||
|
||||
public MessageXmlDocument(string Pathname, bool logData = true) :
|
||||
base()
|
||||
{
|
||||
LogData = logData;
|
||||
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_XmlFileName = Pathname;
|
||||
|
||||
m_IncludeList = new List<string>();
|
||||
RecurseProcessing(Pathname);
|
||||
|
||||
BuiltXML = string.Concat(BuiltXML, "</interface>");
|
||||
BytePackingXml addPacking = new BytePackingXml(BuiltXML);
|
||||
LoadXml(addPacking.OuterXml);
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetEnumerations(string Type)
|
||||
{
|
||||
Dictionary<string, string> enumList = new Dictionary<string, string>();
|
||||
|
||||
// Get XML nodes to parse the XML ICD document
|
||||
XPathNavigator Node = CreateNavigator();
|
||||
XPathNodeIterator Nodeset = Node.Select("interface/enum/name");
|
||||
|
||||
while (Nodeset.MoveNext())
|
||||
{
|
||||
// Find the enumeration with the name of the type
|
||||
if (Nodeset.Current.Value.Trim().Equals(Type.Trim()))
|
||||
{
|
||||
// Find all the enumeration items
|
||||
XPathNavigator enumNode = Nodeset.Current.Clone();
|
||||
while (enumNode.MoveToNext())
|
||||
{
|
||||
if (enumNode.Name.Trim().Equals("item") ||
|
||||
enumNode.Name.Trim().Equals("enum_item"))
|
||||
{
|
||||
string name = null;
|
||||
string value = null;
|
||||
|
||||
// Find all name nodes
|
||||
XPathNavigator childNode = enumNode.Clone();
|
||||
childNode.MoveToFirstChild();
|
||||
do
|
||||
{
|
||||
if (childNode.Name.Trim().Equals("name"))
|
||||
{
|
||||
name = childNode.Value.Trim();
|
||||
}
|
||||
else if (childNode.Name.Trim().Equals("item_name"))
|
||||
{
|
||||
name = childNode.Value.Trim();
|
||||
}
|
||||
|
||||
if (childNode.Name.Trim().Equals("value"))
|
||||
{
|
||||
value = childNode.Value.Trim();
|
||||
}
|
||||
|
||||
// Once we find the name & value, add it to the list
|
||||
if ((name != null) && (value != null))
|
||||
{
|
||||
enumList.Add(name, value);
|
||||
break;
|
||||
}
|
||||
} while (childNode.MoveToNext());
|
||||
}
|
||||
}
|
||||
|
||||
break; // We found the enumeration we wanted
|
||||
}
|
||||
}
|
||||
|
||||
return enumList;
|
||||
}
|
||||
|
||||
private void RecurseProcessing(string pathName)
|
||||
{
|
||||
string directory;
|
||||
string IncludePathname;
|
||||
XPathNodeIterator nodeset;
|
||||
|
||||
// Only process each file once
|
||||
pathName = pathName.Replace('/', '\\');
|
||||
if (m_IncludeList.Contains(pathName))
|
||||
{
|
||||
return; // This file has already been processed
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IncludeList.Add(pathName);
|
||||
}
|
||||
|
||||
if (LogData)
|
||||
_logger.Info($"Loading File: {pathName}");
|
||||
XPathDocument document = new XPathDocument(pathName);
|
||||
XPathNavigator navigator = document.CreateNavigator();
|
||||
|
||||
// Verify this is a COE XML ICD
|
||||
nodeset = navigator.Select("/interface");
|
||||
if (nodeset.Count == 0)
|
||||
{
|
||||
// This is not an XML ICD
|
||||
throw new Exception($"Invalid COE XML Format. Unable to process {pathName}" +
|
||||
"\nEnsure this is a properly formatted ICD.");
|
||||
}
|
||||
|
||||
nodeset = navigator.Select("/interface/include/file");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
directory = DirectoryOf(pathName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
directory = ".\\";
|
||||
}
|
||||
|
||||
IncludePathname = nodeset.Current.Value.Trim();
|
||||
if ((!IncludePathname.StartsWith("\\")) && (!IncludePathname.Contains(":")))
|
||||
{
|
||||
while (IncludePathname.StartsWith("."))
|
||||
{
|
||||
if ((IncludePathname.StartsWith("..\\")) || (IncludePathname.StartsWith("../")))
|
||||
{
|
||||
directory = DirectoryOf(directory);
|
||||
IncludePathname = IncludePathname.Remove(0, 3);
|
||||
}
|
||||
else if ((IncludePathname.StartsWith(".\\")) || (IncludePathname.StartsWith("./")))
|
||||
{
|
||||
IncludePathname = IncludePathname.Remove(0, 2);
|
||||
}
|
||||
}
|
||||
IncludePathname = string.Concat(directory, "\\", IncludePathname);
|
||||
}
|
||||
|
||||
if (Regex.IsMatch(IncludePathname, @"\.xml", RegexOptions.IgnoreCase))
|
||||
RecurseProcessing(IncludePathname);
|
||||
}
|
||||
|
||||
nodeset = navigator.Select("/interface/packing|/interface/typedef|/interface/namespace/typedef|" +
|
||||
"/interface/constant|/interface/namespace/constant|interface/enum|interface/namespace/enum|" +
|
||||
"/interface/structure|/interface/namespace/structure|/interface/message|/interface/namespace/message");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
string item = nodeset.Current.OuterXml;
|
||||
int index;
|
||||
while ((index = item.IndexOf("<description>")) != -1)
|
||||
{
|
||||
item = item.Remove(index, item.IndexOf("</description>") + 14 - index);
|
||||
}
|
||||
while ((index = item.IndexOf("<!--")) != -1)
|
||||
{
|
||||
item = item.Remove(index, item.IndexOf("-->") + 3 - index);
|
||||
}
|
||||
while (item.IndexOf("> ") != -1)
|
||||
{
|
||||
item = item.Replace("> ", ">");
|
||||
}
|
||||
while (item.IndexOf(" <") != -1)
|
||||
{
|
||||
item = item.Replace(" <", "<");
|
||||
}
|
||||
//_logger.Log(LogLevel.Trace, $"Loading Node :\n{item}");
|
||||
Thread.Sleep(1);
|
||||
BuiltXML = string.Concat(BuiltXML, item);
|
||||
}
|
||||
}
|
||||
|
||||
private string DirectoryOf(string Pathname)
|
||||
{
|
||||
return Pathname.Remove(Pathname.LastIndexOf("\\"));
|
||||
}
|
||||
|
||||
//
|
||||
// From the XML document, the definition of a single message can be identified
|
||||
// from the Message Name and returned as an XML string.
|
||||
//
|
||||
public string XmlFileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _XmlFileName;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetMessage(string messageName)
|
||||
{
|
||||
string message;
|
||||
|
||||
messageName = messageName.Trim();
|
||||
|
||||
if (LogData)
|
||||
_logger.Info($"Searching for message : {messageName}");
|
||||
try
|
||||
{
|
||||
message = SelectSingleNode($"/interface/message[name='{messageName}']").OuterXml;
|
||||
message = TranslateValue(message);
|
||||
|
||||
string labelStr = Regex.Replace(message, @".+<label>([\d]+)[^\d]+", "$1", RegexOptions.IgnoreCase);
|
||||
|
||||
int label = 0;
|
||||
|
||||
Parse.Try(labelStr, out label);
|
||||
|
||||
if (LogData)
|
||||
_logger.Trace($"Found by name: {Regex.Replace(message, @"<label>[\d]+", $"<label>0x{label.ToString("X8")}")}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
message = null;
|
||||
throw new Exception("Message not found");
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
//
|
||||
// From the XML document, the definition of a single message can be identified
|
||||
// from the Message Label and returned as an XML string.
|
||||
//
|
||||
public string GetMessageFromLabel(string messageLabel)
|
||||
{
|
||||
string message;
|
||||
|
||||
int label = 0;
|
||||
|
||||
if (Parse.Try(messageLabel, out label) == true)
|
||||
{
|
||||
if (LogData)
|
||||
_logger.Debug($"Searching for message: 0x{label.ToString("X8")}");
|
||||
|
||||
// Search by message label
|
||||
message = SelectSingleNode($"/interface/message[label='{label.ToString()}']").OuterXml;
|
||||
message = TranslateValue(message);
|
||||
|
||||
if (LogData)
|
||||
_logger.Debug($"Found by label: {Regex.Replace(message, @"<label>[\d]+", $"<label>0x{label.ToString("X8")}")}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LogData)
|
||||
_logger.Debug($"Searching for message: {messageLabel}");
|
||||
|
||||
// Search by instruLabel
|
||||
message = SelectSingleNode($"/interface/message[instruLabel='{messageLabel}']").OuterXml;
|
||||
message = TranslateValue(message);
|
||||
|
||||
string labelStr = Regex.Replace(message, @".+<label>([\d]+)[^\d]+", "$1", RegexOptions.IgnoreCase);
|
||||
|
||||
Parse.Try(labelStr, out label);
|
||||
|
||||
if (LogData)
|
||||
_logger.Debug($"Found by name: {Regex.Replace(message, @"<label>[\d]+", $"<label>0x{label.ToString("X8")}")}");
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
//
|
||||
// From the XML document, the definition of a single message can be identified
|
||||
// from the Message InstruLabel and returned as an XML string.
|
||||
//
|
||||
public string GetMessageFromInstruLabel(string messageInstruLabel)
|
||||
{
|
||||
string message;
|
||||
|
||||
messageInstruLabel = messageInstruLabel.Trim();
|
||||
if (LogData)
|
||||
_logger.Debug($"Searching for message: {messageInstruLabel}");
|
||||
try
|
||||
{
|
||||
message = SelectSingleNode($"/interface/message[instruLabel='{messageInstruLabel}']").OuterXml;
|
||||
message = TranslateValue(message);
|
||||
|
||||
if (LogData)
|
||||
_logger.Debug($"Found by instrument label: {message}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
message = null;
|
||||
throw new Exception("Message not found");
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public uint GetLargestMessageSize()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// return the max message size if we have already calculated it
|
||||
if (m_MaxMsgSize != 0)
|
||||
{
|
||||
return m_MaxMsgSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
DateTime t1 = DateTime.Now;
|
||||
|
||||
XPathNavigator navigator = CreateNavigator();
|
||||
XPathNodeIterator nodeset = navigator.Select("/interface/message/name");
|
||||
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
Message msg = new Message(nodeset.Current.Value.Trim(), this);
|
||||
uint msgSize = msg.GetMessageSize();
|
||||
if (msgSize > m_MaxMsgSize)
|
||||
{
|
||||
m_MaxMsgSize = msgSize;
|
||||
}
|
||||
}
|
||||
|
||||
DateTime t2 = DateTime.Now;
|
||||
TimeSpan duration = t2 - t1;
|
||||
Debug.WriteLine("Max Msg Size Algorithm Time = " + duration);
|
||||
}
|
||||
}
|
||||
|
||||
return m_MaxMsgSize;
|
||||
}
|
||||
|
||||
public uint GetMessageSize(string MsgName)
|
||||
{
|
||||
uint msg_size = 0;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
XPathNavigator navigator = CreateNavigator();
|
||||
XPathNodeIterator nodeset = navigator.Select("/interface/message/name");
|
||||
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
if (MsgName == nodeset.Current.Value.Trim())
|
||||
{
|
||||
Message msg = new Message(nodeset.Current.Value.Trim(), this);
|
||||
msg_size = msg.GetMessageSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return msg_size;
|
||||
}
|
||||
|
||||
//
|
||||
// Since the XML message definitions contain the definitions of all the enumerations and constants,
|
||||
// this object is the only one containing the knowledge to interpret strings using enumerations and/or
|
||||
// constants. This method will substitute enumerations and constants with their respective base values
|
||||
// in a specified string.
|
||||
//
|
||||
public string TranslateValue(string Value)
|
||||
{
|
||||
XPathNavigator navigator = CreateNavigator();
|
||||
XPathNavigator position;
|
||||
string NewValue = Value;
|
||||
|
||||
//
|
||||
// Substitute enumeration
|
||||
//
|
||||
try
|
||||
{
|
||||
position = navigator.SelectSingleNode("/interface/enum/item[name='" + NewValue + "']");
|
||||
if (position == null)
|
||||
{
|
||||
position = navigator.SelectSingleNode("/interface/enum/item[item_name='" + NewValue + "']");
|
||||
}
|
||||
if (position != null)
|
||||
{
|
||||
position.MoveToChild("value", "");
|
||||
NewValue = position.Value;
|
||||
}
|
||||
|
||||
//
|
||||
// Substitute constants
|
||||
//
|
||||
position = navigator.SelectSingleNode("/interface/constant[name='" + NewValue + "']");
|
||||
if (position != null)
|
||||
{
|
||||
NewValue = position.Value;
|
||||
_logger.Debug("Translating field value : " + Value + " -> " + NewValue);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e.Message);
|
||||
}
|
||||
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,9 @@
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
|
||||
using Raytheon.Instruments.coeCSharp;
|
||||
using System;
|
||||
|
||||
namespace Raytheon.Instruments.MessagingUtilities
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
public class OeMessage : coeMessage
|
||||
{
|
||||
@@ -32,7 +32,7 @@
|
||||
// **********************************************************************************************************
|
||||
using System;
|
||||
|
||||
namespace Raytheon.Instruments.MessagingUtilities
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
public class Parse
|
||||
{
|
||||
@@ -38,7 +38,7 @@ using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
namespace Raytheon.Instruments.XmlUtilities
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
public class XmlMbitParser
|
||||
{
|
||||
@@ -35,7 +35,7 @@ using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
namespace Raytheon.Instruments.XmlUtilities
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
public class XmlParser
|
||||
{
|
||||
@@ -32,7 +32,7 @@
|
||||
// **********************************************************************************************************
|
||||
using System;
|
||||
|
||||
namespace Raytheon.Instruments.XmlUtilities
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
class XmlParsingException : SystemException
|
||||
{
|
||||
@@ -65,7 +65,7 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
/// <summary>
|
||||
/// Message: compatability option; This class provides a message object option that is compatible
|
||||
1361
Source/TSRealLib/Common/Raytheon.Common/COE/coeCSharp/coe.cs
Normal file
1361
Source/TSRealLib/Common/Raytheon.Common/COE/coeCSharp/coe.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -64,7 +64,7 @@
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
@@ -66,7 +66,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
//
|
||||
//
|
||||
@@ -0,0 +1,308 @@
|
||||
// **********************************************************************************************************
|
||||
// coeEndpoint.cs
|
||||
// 6/1/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)
|
||||
// **********************************************************************************************************
|
||||
|
||||
//\\<Unclassified>
|
||||
//----------------------------------------------------------------------------//
|
||||
// UNCLASSIFIED //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\Unclassified>
|
||||
|
||||
//\\<UnlimitedRights>
|
||||
//----------------------------------------------------------------------------//
|
||||
// Copyright %(copyright)s Raytheon Company. //
|
||||
// This software was developed pursuant to Contract Number %(contractNumber)s //
|
||||
// with the U.S. government. The U.S. government's rights in and to this //
|
||||
// copyrighted software are as specified in DFARS 252.227-7014 which was made //
|
||||
// part of the above contract. //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\UnlimitedRights>
|
||||
|
||||
//\\<EximUndetermined>
|
||||
//----------------------------------------------------------------------------//
|
||||
// WARNING - This document contains technical data and / or technology whose //
|
||||
// export or disclosure to Non-U.S. Persons, wherever located, is restricted //
|
||||
// by the International Traffic in Arms Regulations (ITAR) (22 C.F.R. //
|
||||
// Section 120-130) or the Export Administration Regulations (EAR) (15 C.F.R. //
|
||||
// Section 730-774). This document CANNOT be exported (e.g., provided to a //
|
||||
// supplier outside of the United States) or disclosed to a Non-U.S. Person, //
|
||||
// wherever located, until a final jurisdiction and classification //
|
||||
// determination has been completed and approved by Raytheon, and any //
|
||||
// required U.S. Government approvals have been obtained. Violations are //
|
||||
// subject to severe criminal penalties. //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\EximUndetermined>
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
//
|
||||
//
|
||||
//
|
||||
// Endpoint
|
||||
//
|
||||
//
|
||||
//
|
||||
public class coeEndpoint : IDisposable
|
||||
{
|
||||
#region DLLImports
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Create_Dynamic_With_Domain")]
|
||||
private static extern IntPtr OE_Endpoint_Create_Dynamic_With_Domain(IntPtr Name,
|
||||
coe.ScopeType Scope,
|
||||
IntPtr Router,
|
||||
uint Domain,
|
||||
uint MaximumTransmitMessages,
|
||||
uint MaximumReceiveMessages,
|
||||
uint MaximumTransmitMessageSize,
|
||||
uint MaximumReceiveMessageSize,
|
||||
// Not used in old version and removed in new version.
|
||||
//IntPtr ApplicationContext,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Delete")]
|
||||
private static extern coe.Status OE_Endpoint_Delete(IntPtr _obj);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Associate")]
|
||||
private static extern coe.Status OE_Endpoint_Associate(IntPtr _obj,
|
||||
IntPtr Event,
|
||||
TriggerType Trigger);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Send_Labeled")]
|
||||
private static extern coe.Status OE_Endpoint_Send_Labeled(IntPtr _obj,
|
||||
IntPtr Message,
|
||||
uint Options,
|
||||
uint Handling_Policy);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Peek")]
|
||||
private static extern coe.Status OE_Endpoint_Peek(IntPtr _obj,
|
||||
out uint Message_Label,
|
||||
out uint Message_Size,
|
||||
out int Message_Priority);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Wait")]
|
||||
private static extern coe.Status OE_Endpoint_Wait(IntPtr _obj,
|
||||
int Timeout);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Receive")]
|
||||
private static extern coe.Status OE_Endpoint_Receive(IntPtr _obj,
|
||||
ref IntPtr Message,
|
||||
uint Handling_Policy,
|
||||
int Timeout,
|
||||
IntPtr Source);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Register_Ex2")]
|
||||
private static extern coe.Status OE_Endpoint_Register_Ex2(IntPtr _obj,
|
||||
uint Label,
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
coe.CallBackDelegate callbackD);
|
||||
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Deregister")]
|
||||
private static extern coe.Status OE_Endpoint_Deregister(IntPtr _obj,
|
||||
uint Label);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Empty")]
|
||||
private static extern coe.Status OE_Endpoint_Empty(IntPtr _obj);
|
||||
|
||||
#endregion
|
||||
|
||||
public enum TriggerType : int
|
||||
{
|
||||
DATA_RECEIVED = 0,
|
||||
BUFFER_EMPTY = 1,
|
||||
DATA_DISCARDED = 2
|
||||
};
|
||||
|
||||
private bool _disposed;
|
||||
private IntPtr _handle;
|
||||
private readonly coeEvent[] _events;
|
||||
private const int MaximumNumberOfEvents = 4;
|
||||
private int _numberOfEvents;
|
||||
|
||||
// Constant to be used for a non-queued endpoint
|
||||
public const uint NON_QUEUED_SIZE = 0;
|
||||
|
||||
public coeEndpoint(uint maxMessageSize, IntPtr router = default) : this(0, maxMessageSize, 0, router) { }
|
||||
public coeEndpoint(uint maxMessageSize, uint maxBufferMessages, IntPtr router = default)
|
||||
: this(0, maxMessageSize, maxBufferMessages, router) { }
|
||||
public coeEndpoint(uint domain, uint maxMessageSize, uint maxBufferMessages, IntPtr router = default)
|
||||
{
|
||||
// Second to last argument not used in old version and removed in new version.
|
||||
//_handle = OE_Endpoint_Create_Dynamic_With_Domain(IntPtr.Zero, coe.ScopeType.OE_Local, router, domain,
|
||||
// maxBufferMessages, maxBufferMessages, maxMessageSize, maxMessageSize, IntPtr.Zero, out coe.Status oe_status);
|
||||
_handle = OE_Endpoint_Create_Dynamic_With_Domain(IntPtr.Zero, coe.ScopeType.OE_Local, router, domain,
|
||||
maxBufferMessages, maxBufferMessages, maxMessageSize, maxMessageSize, out coe.Status oe_status);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
_handle = IntPtr.Zero;
|
||||
throw new Exception("Unable to create OE_Endpoint. Error = " + oe_status);
|
||||
}
|
||||
else
|
||||
{
|
||||
_numberOfEvents = 0;
|
||||
_events = new coeEvent[MaximumNumberOfEvents];
|
||||
}
|
||||
}
|
||||
|
||||
~coeEndpoint()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
if (_handle != IntPtr.Zero)
|
||||
{
|
||||
for (int index = 0; index < _numberOfEvents; index++)
|
||||
{
|
||||
_events[index].Disable();
|
||||
}
|
||||
OE_Endpoint_Delete(_handle);
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public IntPtr Handle
|
||||
{
|
||||
get { return _handle; }
|
||||
}
|
||||
|
||||
public coe.Status Register(uint label)
|
||||
{
|
||||
coe.Status status = OE_Endpoint_Register_Ex2(_handle, label, null);
|
||||
return status;
|
||||
}
|
||||
|
||||
public coe.Status Register(uint label, coeDataInterchange.FormatPacketType packet)
|
||||
{
|
||||
|
||||
coe._dataInterchangePackets.Add(label, packet);
|
||||
coe.Status status = OE_Endpoint_Register_Ex2(_handle, label, coe._dataInterchangePackets._delegate);
|
||||
return status;
|
||||
}
|
||||
|
||||
public coe.Status Deregister(uint label)
|
||||
{
|
||||
coe.Status status = OE_Endpoint_Deregister(_handle, label);
|
||||
return status;
|
||||
}
|
||||
|
||||
public coe.Status Send(coeMessage message)
|
||||
{
|
||||
message.Serialize();
|
||||
return OE_Endpoint_Send_Labeled(_handle, message.Handle, 0, 0);
|
||||
}
|
||||
|
||||
public coe.Status Peek(out uint message_Label,
|
||||
out uint message_Size,
|
||||
out int message_Priority)
|
||||
{
|
||||
coe.Status status;
|
||||
status = OE_Endpoint_Peek(_handle, out uint messageLabel, out uint messageSize, out int messagePriority);
|
||||
message_Label = messageLabel;
|
||||
message_Size = messageSize;
|
||||
message_Priority = messagePriority;
|
||||
return status;
|
||||
}
|
||||
|
||||
public coe.Status Wait(int timeout)
|
||||
{
|
||||
return OE_Endpoint_Wait(_handle, timeout);
|
||||
}
|
||||
|
||||
public coe.Status Clear()
|
||||
{
|
||||
return OE_Endpoint_Empty(_handle);
|
||||
}
|
||||
|
||||
public coe.Status Receive(coeMessage message, int timeout)
|
||||
{
|
||||
coe.Status Status;
|
||||
IntPtr coeMessageHandle = message != null ? message.Handle : IntPtr.Zero;
|
||||
Status = OE_Endpoint_Receive(_handle, ref coeMessageHandle, 0, timeout, IntPtr.Zero);
|
||||
if (Status == coe.Status.SUCCESS)
|
||||
{
|
||||
message.Deserialize();
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
public coe.Status Receive(coeMessage message)
|
||||
{
|
||||
return Receive(message, coe.OE_Wait_Forever);
|
||||
}
|
||||
|
||||
public coe.Status Associate(coeEventFlag eventFlag, uint mask, TriggerType trigger)
|
||||
{
|
||||
coe.Status status;
|
||||
|
||||
if (_numberOfEvents >= MaximumNumberOfEvents)
|
||||
{
|
||||
status = coe.Status.FAILED_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
_events[_numberOfEvents] = new coeEvent();
|
||||
_events[_numberOfEvents].SetNotification(eventFlag, mask);
|
||||
status = OE_Endpoint_Associate(_handle, _events[_numberOfEvents].Handle, trigger);
|
||||
if (status == coe.Status.SUCCESS)
|
||||
{
|
||||
status = _events[_numberOfEvents].Enable();
|
||||
_numberOfEvents++;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//\\<Unclassified>
|
||||
//----------------------------------------------------------------------------//
|
||||
// UNCLASSIFIED //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\Unclassified>
|
||||
|
||||
@@ -65,108 +65,111 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
//
|
||||
//
|
||||
//
|
||||
// Event
|
||||
//
|
||||
//
|
||||
//
|
||||
public class coeEvent : IDisposable
|
||||
{
|
||||
//
|
||||
//
|
||||
//
|
||||
// Event
|
||||
//
|
||||
//
|
||||
//
|
||||
public class coeEvent : IDisposable
|
||||
{
|
||||
|
||||
#region DLLImports
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Create_Dynamic")]
|
||||
private static extern IntPtr OE_Event_Create_Dynamic(IntPtr Name,
|
||||
PersistenceType Persistence,
|
||||
int Priority,
|
||||
IntPtr ApplicationContext,
|
||||
out coe.Status Status);
|
||||
#region DLLImports
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Create_Dynamic")]
|
||||
private static extern IntPtr OE_Event_Create_Dynamic(// IntPtr Name, // Not used in new DLL
|
||||
PersistenceType Persistence,
|
||||
int Priority,
|
||||
// Not used in the new DLL.
|
||||
//IntPtr ApplicationContext,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Delete")]
|
||||
public static extern coe.Status OE_Event_Delete(IntPtr _obj);
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Delete")]
|
||||
public static extern coe.Status OE_Event_Delete(IntPtr _obj);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Enable")]
|
||||
private static extern coe.Status OE_Event_Enable(IntPtr _obj);
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Enable")]
|
||||
private static extern coe.Status OE_Event_Enable(IntPtr _obj);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Disable")]
|
||||
private static extern coe.Status OE_Event_Disable(IntPtr _obj);
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Disable")]
|
||||
private static extern coe.Status OE_Event_Disable(IntPtr _obj);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Set_Event_Flag_Notification")]
|
||||
private static extern coe.Status OE_Event_Set_Event_Flag_Notification(IntPtr _obj,
|
||||
IntPtr EventFlag,
|
||||
uint Mask);
|
||||
#endregion
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Set_Event_Flag_Notification")]
|
||||
private static extern coe.Status OE_Event_Set_Event_Flag_Notification(IntPtr _obj,
|
||||
IntPtr EventFlag,
|
||||
uint Mask);
|
||||
#endregion
|
||||
|
||||
public enum PersistenceType : int
|
||||
{
|
||||
ONE_SHOT = 0,
|
||||
ENDURING = 1
|
||||
}
|
||||
private bool _disposed = false;
|
||||
private IntPtr _handle = IntPtr.Zero;
|
||||
public enum PersistenceType : int
|
||||
{
|
||||
ONE_SHOT = 0,
|
||||
ENDURING = 1
|
||||
}
|
||||
private bool _disposed = false;
|
||||
private IntPtr _handle = IntPtr.Zero;
|
||||
|
||||
public coeEvent() : this(PersistenceType.ENDURING, 0) { }
|
||||
public coeEvent(PersistenceType persistence) : this(persistence, 0) { }
|
||||
public coeEvent(int priority) : this(PersistenceType.ENDURING, priority) { }
|
||||
public coeEvent(PersistenceType persistence, int priority)
|
||||
{
|
||||
_handle = OE_Event_Create_Dynamic(IntPtr.Zero, persistence, priority, IntPtr.Zero, out coe.Status oe_status);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
_handle = IntPtr.Zero;
|
||||
throw new Exception("Unable to create OE_Event. Error = " + oe_status);
|
||||
}
|
||||
}
|
||||
public coeEvent() : this(PersistenceType.ENDURING, 0) { }
|
||||
public coeEvent(PersistenceType persistence) : this(persistence, 0) { }
|
||||
public coeEvent(int priority) : this(PersistenceType.ENDURING, priority) { }
|
||||
public coeEvent(PersistenceType persistence, int priority)
|
||||
{
|
||||
// Two fewer arguments in in new DLL.
|
||||
//_handle = OE_Event_Create_Dynamic(IntPtr.Zero, persistence, priority, IntPtr.Zero, out coe.Status oe_status);
|
||||
_handle = OE_Event_Create_Dynamic(persistence, priority, out coe.Status oe_status);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
_handle = IntPtr.Zero;
|
||||
throw new Exception("Unable to create OE_Event. Error = " + oe_status);
|
||||
}
|
||||
}
|
||||
|
||||
~coeEvent()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
~coeEvent()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed) return;
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed) return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
if (_handle != IntPtr.Zero)
|
||||
{
|
||||
OE_Event_Delete(_handle);
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
if (_handle != IntPtr.Zero)
|
||||
{
|
||||
OE_Event_Delete(_handle);
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
internal IntPtr Handle
|
||||
{
|
||||
get { return _handle; }
|
||||
}
|
||||
internal IntPtr Handle
|
||||
{
|
||||
get { return _handle; }
|
||||
}
|
||||
|
||||
public coe.Status Enable()
|
||||
{
|
||||
return OE_Event_Enable(_handle);
|
||||
}
|
||||
public coe.Status Enable()
|
||||
{
|
||||
return OE_Event_Enable(_handle);
|
||||
}
|
||||
|
||||
public coe.Status Disable()
|
||||
{
|
||||
return OE_Event_Disable(_handle);
|
||||
}
|
||||
public coe.Status Disable()
|
||||
{
|
||||
return OE_Event_Disable(_handle);
|
||||
}
|
||||
|
||||
public coe.Status SetNotification(coeEventFlag eventFlag, uint mask)
|
||||
{
|
||||
return OE_Event_Set_Event_Flag_Notification(_handle, eventFlag.Handle, mask);
|
||||
}
|
||||
}
|
||||
public coe.Status SetNotification(coeEventFlag eventFlag, uint mask)
|
||||
{
|
||||
return OE_Event_Set_Event_Flag_Notification(_handle, eventFlag.Handle, mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//\\<Unclassified>
|
||||
@@ -65,132 +65,135 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
//
|
||||
//
|
||||
//
|
||||
// Event Flag
|
||||
//
|
||||
//
|
||||
//
|
||||
public class coeEventFlag : IDisposable
|
||||
{
|
||||
//
|
||||
//
|
||||
//
|
||||
// Event Flag
|
||||
//
|
||||
//
|
||||
//
|
||||
public class coeEventFlag : IDisposable
|
||||
{
|
||||
|
||||
#region DLLImports
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Create_Dynamic")]
|
||||
private static extern IntPtr OE_Event_Flag_Create_Dynamic(IntPtr Name,
|
||||
coe.ScopeType Scope,
|
||||
uint InitialMask,
|
||||
IntPtr ApplicationContext,
|
||||
out coe.Status Status);
|
||||
#region DLLImports
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Create_Dynamic")]
|
||||
private static extern IntPtr OE_Event_Flag_Create_Dynamic(IntPtr Name,
|
||||
coe.ScopeType Scope,
|
||||
uint InitialMask,
|
||||
// Not used in new verion of dll.
|
||||
//IntPtr ApplicationContext,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Delete")]
|
||||
private static extern coe.Status OE_Event_Flag_Delete(IntPtr _obj);
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Delete")]
|
||||
private static extern coe.Status OE_Event_Flag_Delete(IntPtr _obj);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Set")]
|
||||
private static extern coe.Status OE_Event_Flag_Set(IntPtr _obj,
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Set")]
|
||||
private static extern coe.Status OE_Event_Flag_Set(IntPtr _obj,
|
||||
uint Mask);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Clear")]
|
||||
private static extern coe.Status OE_Event_Flag_Clear(IntPtr _obj,
|
||||
uint Mask);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Clear")]
|
||||
private static extern coe.Status OE_Event_Flag_Clear(IntPtr _obj,
|
||||
uint Mask);
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Peek_Mask")]
|
||||
private static extern coe.Status OE_Event_Flag_Peek_Mask(IntPtr _obj,
|
||||
out uint Mask);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Peek_Mask")]
|
||||
private static extern coe.Status OE_Event_Flag_Peek_Mask(IntPtr _obj,
|
||||
out uint Mask);
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Wait")]
|
||||
private static extern coe.Status OE_Event_Flag_Wait(IntPtr _obj,
|
||||
uint Mask,
|
||||
uint ResetMask,
|
||||
WaitPolicyType PolicyType,
|
||||
int TimeInterval,
|
||||
out uint CurrentMask);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Event_Flag_Wait")]
|
||||
private static extern coe.Status OE_Event_Flag_Wait(IntPtr _obj,
|
||||
uint Mask,
|
||||
uint ResetMask,
|
||||
WaitPolicyType PolicyType,
|
||||
int TimeInterval,
|
||||
out uint CurrentMask);
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
private bool _disposed = false;
|
||||
private IntPtr _handle = IntPtr.Zero;
|
||||
|
||||
private bool _disposed = false;
|
||||
private IntPtr _handle = IntPtr.Zero;
|
||||
|
||||
public enum WaitPolicyType : int
|
||||
{
|
||||
WAIT_FOR_ALL = 0,
|
||||
WAIT_FOR_ANY = 1
|
||||
}
|
||||
public enum WaitPolicyType : int
|
||||
{
|
||||
WAIT_FOR_ALL = 0,
|
||||
WAIT_FOR_ANY = 1
|
||||
}
|
||||
|
||||
public coeEventFlag()
|
||||
{
|
||||
_handle = OE_Event_Flag_Create_Dynamic(IntPtr.Zero, coe.ScopeType.OE_Local, 0, IntPtr.Zero, out coe.Status oe_status);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
_handle = IntPtr.Zero;
|
||||
throw new Exception("Unable to create OE_Event_Flag. Error = " + oe_status);
|
||||
}
|
||||
}
|
||||
public coeEventFlag()
|
||||
{
|
||||
// Not used in new verion of dll does not use app context argument.
|
||||
//_handle = OE_Event_Flag_Create_Dynamic(IntPtr.Zero, coe.ScopeType.OE_Local, 0, IntPtr.Zero, out coe.Status oe_status);
|
||||
_handle = OE_Event_Flag_Create_Dynamic(IntPtr.Zero, coe.ScopeType.OE_Local, 0, out coe.Status oe_status);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
_handle = IntPtr.Zero;
|
||||
throw new Exception("Unable to create OE_Event_Flag. Error = " + oe_status);
|
||||
}
|
||||
}
|
||||
|
||||
~coeEventFlag()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
~coeEventFlag()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
if (_handle != IntPtr.Zero)
|
||||
{
|
||||
OE_Event_Flag_Delete(_handle);
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
if (_handle != IntPtr.Zero)
|
||||
{
|
||||
OE_Event_Flag_Delete(_handle);
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
internal IntPtr Handle
|
||||
{
|
||||
get { return _handle; }
|
||||
}
|
||||
internal IntPtr Handle
|
||||
{
|
||||
get { return _handle; }
|
||||
}
|
||||
|
||||
public coe.Status Set(uint mask)
|
||||
{
|
||||
return OE_Event_Flag_Set(_handle, mask);
|
||||
}
|
||||
public coe.Status Set(uint mask)
|
||||
{
|
||||
return OE_Event_Flag_Set(_handle, mask);
|
||||
}
|
||||
|
||||
public coe.Status Clear(uint mask)
|
||||
{
|
||||
return OE_Event_Flag_Clear(_handle, mask);
|
||||
}
|
||||
public coe.Status Clear(uint mask)
|
||||
{
|
||||
return OE_Event_Flag_Clear(_handle, mask);
|
||||
}
|
||||
|
||||
public coe.Status Peek(out uint mask)
|
||||
{
|
||||
coe.Status status;
|
||||
status = OE_Event_Flag_Peek_Mask(_handle, out uint currentMask);
|
||||
mask = currentMask;
|
||||
return status;
|
||||
}
|
||||
public coe.Status Peek(out uint mask)
|
||||
{
|
||||
coe.Status status;
|
||||
status = OE_Event_Flag_Peek_Mask(_handle, out uint currentMask);
|
||||
mask = currentMask;
|
||||
return status;
|
||||
}
|
||||
|
||||
public coe.Status Wait(uint mask,
|
||||
uint resetMask,
|
||||
WaitPolicyType waitPolicy,
|
||||
int timeout,
|
||||
out uint currentMask)
|
||||
{
|
||||
coe.Status status;
|
||||
status = OE_Event_Flag_Wait(_handle, mask, resetMask, waitPolicy, timeout, out uint returnedMask);
|
||||
currentMask = returnedMask;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
public coe.Status Wait(uint mask,
|
||||
uint resetMask,
|
||||
WaitPolicyType waitPolicy,
|
||||
int timeout,
|
||||
out uint currentMask)
|
||||
{
|
||||
coe.Status status;
|
||||
status = OE_Event_Flag_Wait(_handle, mask, resetMask, waitPolicy, timeout, out uint returnedMask);
|
||||
currentMask = returnedMask;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//\\<Unclassified>
|
||||
@@ -0,0 +1,397 @@
|
||||
// **********************************************************************************************************
|
||||
// coeMessage.cs
|
||||
// 6/1/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)
|
||||
// **********************************************************************************************************
|
||||
|
||||
//\\<Unclassified>
|
||||
//----------------------------------------------------------------------------//
|
||||
// UNCLASSIFIED //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\Unclassified>
|
||||
|
||||
//\\<UnlimitedRights>
|
||||
//----------------------------------------------------------------------------//
|
||||
// Copyright %(copyright)s Raytheon Company. //
|
||||
// This software was developed pursuant to Contract Number %(contractNumber)s //
|
||||
// with the U.S. government. The U.S. government's rights in and to this //
|
||||
// copyrighted software are as specified in DFARS 252.227-7014 which was made //
|
||||
// part of the above contract. //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\UnlimitedRights>
|
||||
|
||||
//\\<EximUndetermined>
|
||||
//----------------------------------------------------------------------------//
|
||||
// WARNING - This document contains technical data and / or technology whose //
|
||||
// export or disclosure to Non-U.S. Persons, wherever located, is restricted //
|
||||
// by the International Traffic in Arms Regulations (ITAR) (22 C.F.R. //
|
||||
// Section 120-130) or the Export Administration Regulations (EAR) (15 C.F.R. //
|
||||
// Section 730-774). This document CANNOT be exported (e.g., provided to a //
|
||||
// supplier outside of the United States) or disclosed to a Non-U.S. Person, //
|
||||
// wherever located, until a final jurisdiction and classification //
|
||||
// determination has been completed and approved by Raytheon, and any //
|
||||
// required U.S. Government approvals have been obtained. Violations are //
|
||||
// subject to severe criminal penalties. //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\EximUndetermined>
|
||||
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
/// <summary>
|
||||
/// Message Attributes
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class MessageOffset : Attribute
|
||||
{
|
||||
readonly uint _bufferOffset;
|
||||
public MessageOffset(uint bufferOffset)
|
||||
{
|
||||
_bufferOffset = bufferOffset;
|
||||
}
|
||||
public uint Offset
|
||||
{
|
||||
get { return _bufferOffset; }
|
||||
}
|
||||
}
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class MessageSize : Attribute
|
||||
{
|
||||
readonly int _bufferSize;
|
||||
public MessageSize(int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
}
|
||||
public int Size
|
||||
{
|
||||
get { return _bufferSize; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Message: base class
|
||||
/// </summary>
|
||||
public abstract class coeMessage : IDisposable
|
||||
{
|
||||
#region DLLImports
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_Create")]
|
||||
private static extern IntPtr OE_Message_Create(IntPtr Buffer_Address,
|
||||
uint Size,
|
||||
// Not used in new verion of dll.
|
||||
//int Create_Shared,
|
||||
//IntPtr ApplicationContext,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_Delete")]
|
||||
private static extern coe.Status OE_Message_Delete(IntPtr Handle);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_set_Priority")]
|
||||
private static extern coe.Status OE_Message_set_Priority(IntPtr Handle,
|
||||
int Priority);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Priority")]
|
||||
private static extern int OE_Message_get_Priority(IntPtr Handle,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_set_Domain")]
|
||||
private static extern coe.Status OE_Message_set_Domain(IntPtr Handle,
|
||||
uint Domain);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Domain")]
|
||||
private static extern uint OE_Message_get_Domain(IntPtr Handle,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_set_Label")]
|
||||
private static extern coe.Status OE_Message_set_Label(IntPtr Handle,
|
||||
uint Label);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Label")]
|
||||
private static extern uint OE_Message_get_Label(IntPtr Handle,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_set_Data_Size")]
|
||||
private static extern coe.Status OE_Message_set_Data_Size(IntPtr Handle,
|
||||
uint Size);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Data_Size")]
|
||||
private static extern uint OE_Message_get_Data_Size(IntPtr Handle,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Transmit_Timestamp")]
|
||||
private static extern coe.Status OE_Message_get_Transmit_Timestamp(IntPtr Handle,
|
||||
out ulong Seconds,
|
||||
out uint Fraction_Of_Second);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Receive_Timestamp")]
|
||||
private static extern coe.Status OE_Message_get_Receive_Timestamp(IntPtr Handle,
|
||||
out ulong Seconds,
|
||||
out uint Fraction_Of_Second);
|
||||
#endregion
|
||||
|
||||
private bool disposed = false;
|
||||
protected IntPtr m_Handle = IntPtr.Zero;
|
||||
protected IntPtr m_UnmanagedBuffer = IntPtr.Zero;
|
||||
protected int m_UnmanagedBufferSize = 0;
|
||||
protected int m_Size;
|
||||
protected byte[] m_Buffer;
|
||||
|
||||
//
|
||||
// The following routines are provided for testing and access purposes
|
||||
//
|
||||
public IntPtr GetUnmanagedBuffer() { return m_UnmanagedBuffer; }
|
||||
public byte[] GetManagedBuffer() { return m_Buffer; }
|
||||
|
||||
protected coeMessage(int size) : this(size, 0) { }
|
||||
protected coeMessage(int size, uint label) : this(size, label, 0) { }
|
||||
protected coeMessage(int size, uint label, int priority)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
size = getPayloadSize();
|
||||
}
|
||||
if (size > 0)
|
||||
{
|
||||
m_Buffer = new byte[size];
|
||||
m_UnmanagedBuffer = Marshal.AllocHGlobal((int)size);
|
||||
m_UnmanagedBufferSize = (int)size;
|
||||
}
|
||||
// Changed create_shared and app_context are not used in new version of dll.
|
||||
//m_Handle = OE_Message_Create(m_UnmanagedBuffer, (uint)size, coe.OE_FALSE, IntPtr.Zero, out coe.Status oe_status);
|
||||
m_Handle = OE_Message_Create(m_UnmanagedBuffer, (uint)size, out coe.Status oe_status);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
m_Handle = IntPtr.Zero;
|
||||
throw new Exception("Unable to create OE_Message. Error = " + oe_status);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Size = size;
|
||||
// The message was created successfully
|
||||
oe_status = OE_Message_set_Priority(m_Handle, priority);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
throw new Exception("Unable to set message priority to " + priority + ". Error = " + oe_status);
|
||||
}
|
||||
|
||||
oe_status = OE_Message_set_Label(m_Handle, label);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
throw new Exception("Unable to set message priority to " + label + ". Error = " + oe_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~coeMessage()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed) return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
if (m_UnmanagedBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(m_UnmanagedBuffer);
|
||||
m_UnmanagedBuffer = IntPtr.Zero;
|
||||
}
|
||||
if (m_Handle != IntPtr.Zero)
|
||||
{
|
||||
OE_Message_Delete(m_Handle);
|
||||
m_Handle = IntPtr.Zero;
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
internal IntPtr Handle
|
||||
{
|
||||
get { return m_Handle; }
|
||||
}
|
||||
|
||||
public uint Domain
|
||||
{
|
||||
get
|
||||
{
|
||||
return OE_Message_get_Domain(m_Handle, out coe.Status status);
|
||||
}
|
||||
set
|
||||
{
|
||||
coe.Status status = OE_Message_set_Domain(m_Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public uint Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return OE_Message_get_Label(m_Handle, out coe.Status status);
|
||||
}
|
||||
set
|
||||
{
|
||||
coe.Status status = OE_Message_set_Label(m_Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get
|
||||
{
|
||||
return OE_Message_get_Priority(m_Handle, out coe.Status status);
|
||||
}
|
||||
set
|
||||
{
|
||||
coe.Status status = OE_Message_set_Priority(m_Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public uint Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return OE_Message_get_Data_Size(m_Handle, out coe.Status status);
|
||||
}
|
||||
set
|
||||
{
|
||||
coe.Status status = OE_Message_set_Data_Size(m_Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int BufferSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_UnmanagedBufferSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > m_UnmanagedBufferSize)
|
||||
{
|
||||
uint savedDomain = Domain;
|
||||
uint savedLabel = Label;
|
||||
int savedPriority = Priority;
|
||||
uint savedSize = Size;
|
||||
|
||||
if (m_UnmanagedBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(m_UnmanagedBuffer);
|
||||
m_UnmanagedBuffer = IntPtr.Zero;
|
||||
}
|
||||
if (m_Handle != IntPtr.Zero)
|
||||
{
|
||||
OE_Message_Delete(m_Handle);
|
||||
m_Handle = IntPtr.Zero;
|
||||
}
|
||||
m_Buffer = new byte[value];
|
||||
m_UnmanagedBuffer = Marshal.AllocHGlobal((int)value);
|
||||
m_UnmanagedBufferSize = (int)value;
|
||||
// Changed create_shared and app_context are not used in new version of dll.
|
||||
//m_Handle = OE_Message_Create(m_UnmanagedBuffer, (uint)value, coe.OE_FALSE, IntPtr.Zero, out coe.Status oe_status);
|
||||
m_Handle = OE_Message_Create(m_UnmanagedBuffer, (uint)value, out coe.Status oe_status);
|
||||
m_Size = value;
|
||||
|
||||
Domain = savedDomain;
|
||||
Label = savedLabel;
|
||||
Priority = savedPriority;
|
||||
Size = savedSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSendTime(out ulong Seconds, out uint FractionOfSecond)
|
||||
{
|
||||
var status = OE_Message_get_Transmit_Timestamp(m_Handle, out ulong seconds, out uint fractionOfSecond);
|
||||
Seconds = seconds;
|
||||
FractionOfSecond = fractionOfSecond;
|
||||
}
|
||||
|
||||
public void GetReceiveTime(out ulong Seconds, out uint FractionOfSecond)
|
||||
{
|
||||
var status = OE_Message_get_Receive_Timestamp(m_Handle, out ulong seconds, out uint fractionOfSecond);
|
||||
Seconds = seconds;
|
||||
FractionOfSecond = fractionOfSecond;
|
||||
}
|
||||
|
||||
abstract public void Serialize();
|
||||
abstract public void Deserialize();
|
||||
|
||||
// Serialization/Deserialization support
|
||||
private void alignIndex(ref int dataBufferIndex,
|
||||
int alignment)
|
||||
{
|
||||
int indexMisalignment = dataBufferIndex % alignment;
|
||||
if (indexMisalignment > 0)
|
||||
{
|
||||
dataBufferIndex += alignment - indexMisalignment;
|
||||
}
|
||||
}
|
||||
|
||||
public int getPayloadSize()
|
||||
{
|
||||
int size = 0;
|
||||
return serializationSupport.getPayloadSize(this, GetType(), ref size);
|
||||
}
|
||||
|
||||
|
||||
protected void copyToMessageBuffer(byte[] data)
|
||||
{
|
||||
Marshal.Copy(data, 0, m_UnmanagedBuffer, data.Length);
|
||||
}
|
||||
|
||||
protected byte[] copyFromMessageBuffer()
|
||||
{
|
||||
byte[] data = null;
|
||||
uint dataSize = OE_Message_get_Data_Size(m_Handle, out coe.Status status);
|
||||
if (dataSize > 0)
|
||||
{
|
||||
Marshal.Copy(m_UnmanagedBuffer, m_Buffer, 0, (int)dataSize);
|
||||
data = m_Buffer;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//\\<Unclassified>
|
||||
//----------------------------------------------------------------------------//
|
||||
// UNCLASSIFIED //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\Unclassified>
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
/// <summary>
|
||||
/// The coeMessageBasic class is a template that can be used to create user messages
|
||||
@@ -66,7 +66,7 @@ using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
//
|
||||
//
|
||||
@@ -66,7 +66,7 @@ using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
//
|
||||
//
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
//
|
||||
//
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
public class coeString
|
||||
{
|
||||
@@ -65,7 +65,7 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
//
|
||||
//
|
||||
@@ -65,7 +65,7 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
namespace Raytheon.Common.Coe
|
||||
{
|
||||
//
|
||||
//
|
||||
@@ -31,7 +31,6 @@
|
||||
// ****************************************************************************//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@@ -200,7 +199,7 @@ namespace Raytheon.Common
|
||||
/// <returns>A list of all keys.</returns>
|
||||
public override List<string> ReadAllKeys(string section)
|
||||
{
|
||||
const int BUFFER_SIZE = 2500;
|
||||
const int BUFFER_SIZE = 100000;
|
||||
string temp = new('\0', BUFFER_SIZE);
|
||||
int numBytes = NativeMethods.GetPrivateProfileString(section, null, "", temp, BUFFER_SIZE, _fileName);
|
||||
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
// ******************************************************************************//
|
||||
// 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.
|
||||
//
|
||||
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
|
||||
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
|
||||
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
|
||||
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
|
||||
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
|
||||
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
|
||||
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
|
||||
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
|
||||
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
|
||||
// PENALTIES.
|
||||
//
|
||||
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
|
||||
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
|
||||
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
|
||||
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
|
||||
// RECONSTRUCTION OF THE DOCUMENT.
|
||||
// ****************************************************************************//
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Raytheon.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// RaytheonConfiguration class is used to read in XML file for each instrument.
|
||||
/// The XML file must have 2 main sections <IniConfiguration> and <XmlConfigurations>
|
||||
/// However, it's very limited in how it expects the tags to be structured as section and key
|
||||
/// which makes no sense for XML tags. There's no flexibility to traverse the tree and
|
||||
/// get values and attributes of a particular tag.
|
||||
/// So this class is going to allow that flexiblity
|
||||
/// </summary>
|
||||
public class RaytheonXmlConfigurationWrapper
|
||||
{
|
||||
private XElement _rootXelement;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="xElemString">
|
||||
/// This string contains the XML tags starting at <XmlConfiguration name="[section_name]">...</XmlConfiguration>
|
||||
/// This string is obtained from calling _configuration.GetXmlConfiguration("[section_name]");
|
||||
/// </param>
|
||||
public RaytheonXmlConfigurationWrapper(string xElemString)
|
||||
{
|
||||
_rootXelement = XElement.Parse(xElemString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
private RaytheonXmlConfigurationWrapper() { }
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of an attribute in the element at path
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// Specify / if want to access root element
|
||||
/// Specify /subtag1/subtag2 to access child elements
|
||||
/// </param>
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public string GetAttribute(string path, string attributeName)
|
||||
{
|
||||
XNode xNode = GetXNode(path);
|
||||
|
||||
XAttribute attr = ((XElement)xNode).Attribute(attributeName);
|
||||
|
||||
if (attr == null)
|
||||
{
|
||||
throw new Exception($"XML attribute {attributeName} not found");
|
||||
}
|
||||
|
||||
return attr.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of the element at path
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// Specify / if want to access root element
|
||||
/// Specify /subtag1/subtag2 to access child elements
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public string GetValue(string path)
|
||||
{
|
||||
XNode xNode = GetXNode(path);
|
||||
|
||||
return ((XElement)xNode).Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Xelement. This is useful for traversing sibling nodes
|
||||
/// Example:
|
||||
/// // get the first element
|
||||
/// XElement elem = raytheonConfig.GetXElement("/Fruit");
|
||||
/// // go to next sibling and get value
|
||||
/// str = ((XElement) elem.NextNode).Value;
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// Specify / if want to access root element
|
||||
/// Specify /subtag1/subtag2 to access child elements
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public XElement GetXElement(string path)
|
||||
{
|
||||
XNode xNode = GetXNode(path);
|
||||
|
||||
return ((XElement)xNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get XNode of the path
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// Specify / if want to access root element
|
||||
/// Specify /subtag1/subtag2 to access child elements
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
private XNode GetXNode(string path)
|
||||
{
|
||||
string[] tags = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
XNode xNode = _rootXelement;
|
||||
string traversePath = $"/{_rootXelement.Name.ToString()}/";
|
||||
foreach (string tag in tags)
|
||||
{
|
||||
xNode = ((XElement)xNode).FirstNode;
|
||||
|
||||
while (xNode != null && xNode.NodeType != System.Xml.XmlNodeType.Element)
|
||||
{
|
||||
xNode = xNode.NextNode;
|
||||
|
||||
if (xNode != null && xNode.NodeType == System.Xml.XmlNodeType.Element)
|
||||
{
|
||||
traversePath += $"{((XElement)xNode).Name}/";
|
||||
if (((XElement)xNode).Name != tag)
|
||||
{
|
||||
throw new Exception($"Unexpected XML path {traversePath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xNode == null)
|
||||
{
|
||||
throw new Exception($"XML path /{_rootXelement.Name}/{path} not found");
|
||||
}
|
||||
}
|
||||
|
||||
return xNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1,123 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// IDisplay.cs
|
||||
// 2/17/2023
|
||||
// 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.Collections.Generic;
|
||||
|
||||
namespace Raytheon.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum for tagging the logged data.
|
||||
/// </summary>
|
||||
public enum LogLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// (Ordinal = 0) : Most verbose level. Used for development and seldom enabled in production.
|
||||
/// </summary>
|
||||
TRACE,
|
||||
/// <summary>
|
||||
/// (Ordinal = 1) : Debugging the application behavior from internal events of interest.
|
||||
/// </summary>
|
||||
DEBUG,
|
||||
/// <summary>
|
||||
/// An informational log statement.
|
||||
/// (Ordinal = 2) : Information that highlights progress or application lifetime events.
|
||||
/// </summary>
|
||||
INFO,
|
||||
/// <summary>
|
||||
/// (Ordinal = 3) : Warnings about validation issues or temporary failures that can be recovered.
|
||||
/// </summary>
|
||||
WARN,
|
||||
/// <summary>
|
||||
/// (Ordinal = 4) : Errors where functionality has failed or <see cref="System.Exception"/> have been caught.
|
||||
/// an error log statement.
|
||||
/// </summary>
|
||||
ERROR,
|
||||
/// <summary>
|
||||
/// (Ordinal = 5) : Most critical level. Application is about to abort.
|
||||
/// </summary>
|
||||
FATAL,
|
||||
/// <summary>
|
||||
/// Off log level (Ordinal = 6)
|
||||
/// </summary>
|
||||
OFF
|
||||
}
|
||||
|
||||
public interface IDisplay
|
||||
{
|
||||
/// <summary>
|
||||
/// user interface capability with error logger
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="logLevel"></param>
|
||||
void ShowMessage(string message, LogLevel logLevel = LogLevel.INFO);
|
||||
}
|
||||
|
||||
public interface IChillerDisplay
|
||||
{
|
||||
void ChillerMonitorUiUpdate(ActiveHealthMonitorData data, int errorCode);
|
||||
}
|
||||
|
||||
public interface IDioDisplay
|
||||
{
|
||||
void DioControlUiUpdate(List<string> inputNames, List<string> outputNames);
|
||||
}
|
||||
|
||||
public interface IFpgaDisplay
|
||||
{
|
||||
void FpgaControlUiUpdate(List<string> fpgaNames);
|
||||
}
|
||||
|
||||
public interface IPowerControlDisplay
|
||||
{
|
||||
void PowerControlUiUpdate(List<string> powerFormNames);
|
||||
}
|
||||
|
||||
public interface IPowerMonitorDisplay
|
||||
{
|
||||
void PowerMonitorUiUpdate(List<PowerMonitorCallbackData> callBackDataList, int errorCode);
|
||||
}
|
||||
|
||||
public interface IHealthMonitorDisplay
|
||||
{
|
||||
void HealthMonitorControlUiUpdate(List<ActiveHealthMonitorData> callBackDataList);
|
||||
}
|
||||
|
||||
public interface INGIDisplay : IDisplay, IChillerDisplay, IDioDisplay, IFpgaDisplay, IPowerControlDisplay, IPowerMonitorDisplay, IHealthMonitorDisplay
|
||||
{
|
||||
}
|
||||
|
||||
public interface IHandleCriticalError
|
||||
{
|
||||
void HandleCriticalError(string message, bool shallWeStopThreads = true);
|
||||
}
|
||||
}
|
||||
@@ -121,29 +121,22 @@ namespace Raytheon.Common
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
try
|
||||
_msgProcessorWorker.QuitWork();
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
_msgProcessorThread.Abort();
|
||||
|
||||
if (_msgProcessorThread.IsAlive)
|
||||
{
|
||||
_msgProcessorWorker.QuitWork();
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
_msgProcessorThread.Abort();
|
||||
|
||||
if (_msgProcessorThread.IsAlive)
|
||||
{
|
||||
_msgProcessorThread.Join();
|
||||
}
|
||||
|
||||
_dataInBufferEvent.Dispose();
|
||||
|
||||
_msgProcessorWorker.Dispose();
|
||||
|
||||
_dataBuffer.Dispose();
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
_msgProcessorThread.Join();
|
||||
}
|
||||
|
||||
_dataInBufferEvent.Dispose();
|
||||
|
||||
_msgProcessorWorker.Dispose();
|
||||
|
||||
_dataBuffer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
namespace Raytheon.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// A spot to hold application constants
|
||||
///
|
||||
/// </summary>
|
||||
public static class Constants
|
||||
{
|
||||
public const string InstrumentConfigFolder = "InstrumentConfig";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Raytheon.Common
|
||||
/// those which were removed. A typical use of this is to AddData(), then use CheckOutStartOfData()/CheckInStartOfData to get
|
||||
/// a pointer to the data and the amount of bytes that the pointer points to.
|
||||
/// </summary>
|
||||
public class DataBuffer: IDisposable
|
||||
public class DataBuffer : IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private unsafe byte[] _buffer;
|
||||
@@ -220,25 +220,11 @@ namespace Raytheon.Common
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
lock (_syncObj)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,23 +286,9 @@ namespace Raytheon.Common
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
if (disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_pinnedArray.Free();
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
_pinnedArray.Free();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -1,123 +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.IO;
|
||||
using NLog;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Raytheon.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton for logging debug information and errors.
|
||||
/// </summary>
|
||||
public class ErrorLogger : IDisposable
|
||||
{
|
||||
#region PublicClassMembers
|
||||
|
||||
/// <summary>
|
||||
/// Enum for tagging the logged data.
|
||||
/// </summary>
|
||||
public enum LogLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// (Ordinal = 0) : Most verbose level. Used for development and seldom enabled in production.
|
||||
/// </summary>
|
||||
TRACE,
|
||||
/// <summary>
|
||||
/// (Ordinal = 1) : Debugging the application behavior from internal events of interest.
|
||||
/// </summary>
|
||||
DEBUG,
|
||||
/// <summary>
|
||||
/// An informational log statement.
|
||||
/// (Ordinal = 2) : Information that highlights progress or application lifetime events.
|
||||
/// </summary>
|
||||
INFO,
|
||||
/// <summary>
|
||||
/// (Ordinal = 3) : Warnings about validation issues or temporary failures that can be recovered.
|
||||
/// </summary>
|
||||
WARN,
|
||||
/// <summary>
|
||||
/// (Ordinal = 4) : Errors where functionality has failed or <see cref="System.Exception"/> have been caught.
|
||||
/// an error log statement.
|
||||
/// </summary>
|
||||
ERROR,
|
||||
/// <summary>
|
||||
/// (Ordinal = 5) : Most critical level. Application is about to abort.
|
||||
/// </summary>
|
||||
FATAL
|
||||
}
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PrivateClassMembers
|
||||
private static ErrorLogger _errorLoggerInstance;
|
||||
#endregion
|
||||
|
||||
#region PublicClassFunctions
|
||||
|
||||
/// <summary>
|
||||
/// Getter for this singleton.
|
||||
/// </summary>
|
||||
/// <param name="loggername">File location for Log.</param>
|
||||
/// <returns>The instance of this class.</returns>
|
||||
public static ErrorLogger Instance(string loggername = "CTS")
|
||||
{
|
||||
if (_errorLoggerInstance == null)
|
||||
{
|
||||
_errorLoggerInstance = new ErrorLogger(loggername);
|
||||
}
|
||||
|
||||
return _errorLoggerInstance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="logDestination">The logger destination</param>
|
||||
/// <param name="logname">The location of the file to write to.</param>
|
||||
/// <param name="form"></param>
|
||||
private ErrorLogger(string logname)
|
||||
{
|
||||
_logger = LogManager.GetLogger(logname);
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
//TODO: Unhandled exception if no nlog.config
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the log file.
|
||||
/// </summary>
|
||||
/// <param name="message">The data to write.</param>
|
||||
public void Write(string message, LogLevel logLevel = LogLevel.ERROR)
|
||||
{
|
||||
_logger.Log(NLog.LogLevel.FromOrdinal((int)logLevel), message);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,11 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using Microsoft.Office.Interop.Excel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Office.Interop.Excel;
|
||||
|
||||
namespace Raytheon.Common
|
||||
{
|
||||
@@ -85,23 +85,9 @@ namespace Raytheon.Common
|
||||
/// </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>
|
||||
@@ -315,8 +301,6 @@ namespace Raytheon.Common
|
||||
|
||||
try
|
||||
{
|
||||
ErrorLogger.Instance().Write("ExcelReader::ReadAllRows() - for sheet " + sheetName, ErrorLogger.LogLevel.INFO);
|
||||
|
||||
if (startingRow < 1 || startingCol < 1)
|
||||
{
|
||||
throw new Exception("ExcelReader::ReadAllRows() - startingRow and startingCol inputs must be greater than 0");
|
||||
@@ -414,34 +398,20 @@ namespace Raytheon.Common
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
if (disposing)
|
||||
{
|
||||
if (disposing)
|
||||
//close and release
|
||||
if (_excelWorkBook != null)
|
||||
{
|
||||
//close and release
|
||||
if (_excelWorkBook != null)
|
||||
{
|
||||
_excelWorkBook.Close();
|
||||
Marshal.ReleaseComObject(_excelWorkBook);
|
||||
}
|
||||
_excelWorkBook.Close();
|
||||
Marshal.ReleaseComObject(_excelWorkBook);
|
||||
}
|
||||
|
||||
//quit and release
|
||||
if (_excelApp != null)
|
||||
{
|
||||
_excelApp.Quit();
|
||||
Marshal.ReleaseComObject(_excelApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
try
|
||||
//quit and release
|
||||
if (_excelApp != null)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
_excelApp.Quit();
|
||||
Marshal.ReleaseComObject(_excelApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// ActiveHealthMonitorData.cs
|
||||
// 2/17/2023
|
||||
// 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)
|
||||
// **********************************************************************************************************
|
||||
|
||||
namespace Raytheon.Common
|
||||
{
|
||||
public enum MonitorStatus
|
||||
{
|
||||
NOMINAL,
|
||||
WARNING,
|
||||
ABORT
|
||||
}
|
||||
|
||||
public struct ActiveHealthMonitorData
|
||||
{
|
||||
public string itemName;
|
||||
public double dataValue;
|
||||
public MonitorStatus status;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// PowerMonitorCallbackData.cs
|
||||
// 2/17/2023
|
||||
// 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)
|
||||
// **********************************************************************************************************
|
||||
|
||||
|
||||
namespace Raytheon.Common
|
||||
{
|
||||
public struct PowerMonitorCallbackData
|
||||
{
|
||||
public string powerModule;
|
||||
|
||||
public double overVoltageProtectionValue;
|
||||
|
||||
public double overCurrentProtectionValue;
|
||||
|
||||
public double voltage;
|
||||
|
||||
public double voltageSetpoint;
|
||||
|
||||
public double current;
|
||||
|
||||
public bool outputStatus;
|
||||
|
||||
public int ovpocpStatus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Raytheon.Common.PdelWriter.Utilities
|
||||
{
|
||||
public enum PassFailStatus
|
||||
{
|
||||
Pass,
|
||||
|
||||
Fail,
|
||||
|
||||
Unknown
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Raytheon.Common.PdelWriter
|
||||
{
|
||||
public static class PdelDataFormatter
|
||||
{
|
||||
#region Public Members
|
||||
/// <summary>
|
||||
/// Formats the specified measurement data type.
|
||||
/// </summary>
|
||||
/// <param name="measuredValue">The measured value.</param>
|
||||
/// <returns>Returns a properly formatted string.</returns>
|
||||
public static string Format(string measuredValue)
|
||||
{
|
||||
string prefix = string.Empty;
|
||||
|
||||
string extension = string.Empty;
|
||||
|
||||
double value;
|
||||
|
||||
DateTime datetime = default(DateTime);
|
||||
|
||||
if (double.TryParse(measuredValue, out value))
|
||||
{
|
||||
prefix = "R";
|
||||
|
||||
if (measuredValue.IndexOf('.') != -1)
|
||||
{
|
||||
extension = measuredValue.Substring(measuredValue.IndexOf('.') + 1).Length.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we don't have a decimal point it must have converted to an integer value.
|
||||
prefix = "I";
|
||||
extension = measuredValue.Length.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
}
|
||||
else if (DateTime.TryParse(measuredValue, out datetime))
|
||||
{
|
||||
prefix = "T";
|
||||
extension = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
int dummy = Convert.ToInt32(measuredValue, 16);
|
||||
|
||||
prefix = "H";
|
||||
extension = measuredValue.Length.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
prefix = "S";
|
||||
extension = measuredValue.Length.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
}
|
||||
|
||||
return prefix + extension;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is null or empty] [the specified units].
|
||||
/// </summary>
|
||||
/// <param name="units">The units.</param>
|
||||
/// <returns>Returns a string value for the units.</returns>
|
||||
public static string IsNullOrEmpty(this string units)
|
||||
{
|
||||
var returnValue = "NONE";
|
||||
|
||||
if (!string.IsNullOrEmpty(units))
|
||||
{
|
||||
returnValue = units;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
311
Source/TSRealLib/Common/Raytheon.Common/Pdel/PdelInformation.cs
Normal file
311
Source/TSRealLib/Common/Raytheon.Common/Pdel/PdelInformation.cs
Normal file
@@ -0,0 +1,311 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Raytheon.Common.PdelWriter.Utilities
|
||||
{
|
||||
[XmlType("TestExecutive-PdelInformation")]
|
||||
public class PdelInformation
|
||||
{
|
||||
#region Public Properties
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Data Standard Version.
|
||||
/// </summary>
|
||||
/// <value>The Test Data Standard Version.</value>
|
||||
[XmlElement("TestDataStandardVersion")]
|
||||
public string TestDataStandardVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the UUT Identification.
|
||||
/// </summary>
|
||||
/// <value>The UUT Identification.</value>
|
||||
[XmlElement("UutIdentification")]
|
||||
public string UutIdentification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the UUT Revision.
|
||||
/// Drawing Number Revision of the Unit Under Test (also know as Dash Number)
|
||||
/// </summary>
|
||||
/// <value>The UUT Revision.</value>
|
||||
[XmlElement("UutRevision")]
|
||||
public string UutRevision { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the UUT Serial Number.
|
||||
/// </summary>
|
||||
/// <value>The UUT Serial Number.</value>
|
||||
[XmlElement("UutSerialNumber")]
|
||||
public string UutSerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Procedure Revision.
|
||||
/// </summary>
|
||||
/// <value>The Test Procedure Revision.</value>
|
||||
[XmlElement("TestProcedureRevision")]
|
||||
public string TestProcedureRevision { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Procedure Identification.
|
||||
/// </summary>
|
||||
/// <value>The Test Procedure Identification.</value>
|
||||
[XmlElement("TestProcedureIdentification")]
|
||||
public string TestProcedureIdentification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the work order.
|
||||
/// Work order number for the test being run
|
||||
/// </summary>
|
||||
/// <value>The work order.</value>
|
||||
[XmlElement("WorkOrder")]
|
||||
public string WorkOrder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Work Order Operation.
|
||||
/// </summary>
|
||||
/// <value>The Work Order Operation.</value>
|
||||
[XmlElement("WorkOrderOperation")]
|
||||
public string WorkOrderOperation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Software Identification.
|
||||
/// </summary>
|
||||
/// <value>The Test Software Identification.</value>
|
||||
[XmlElement("TestSoftwareIdentification")]
|
||||
public string TestSoftwareIdentification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Software Revision.
|
||||
/// </summary>
|
||||
/// <value>The Test Software Revision.</value>
|
||||
[XmlElement("TestSoftwareRevision")]
|
||||
public string TestSoftwareRevision { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Set Identification.
|
||||
/// </summary>
|
||||
/// <value>The Test Set Identification.</value>
|
||||
[XmlElement("TestSetIdentification")]
|
||||
public string TestSetIdentification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Set Revision.
|
||||
/// </summary>
|
||||
/// <value>The Test Set Revision.</value>
|
||||
[XmlElement("TestSetRevision")]
|
||||
public string TestSetRevision { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Set Serial Number.
|
||||
/// </summary>
|
||||
/// <value>The Test Set Serial Number.</value>
|
||||
[XmlElement("TestSetSerialNumber")]
|
||||
public string TestSetSerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Chamber Identification.
|
||||
/// </summary>
|
||||
/// <value>The Test Chamber Identification.</value>
|
||||
[XmlElement("TestChamberIdentification")]
|
||||
public string TestChamberIdentification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Chamber Revision.
|
||||
/// </summary>
|
||||
/// <value>The Test Chamber Revision.</value>
|
||||
[XmlElement("TestChamberRevision")]
|
||||
public string TestChamberRevision { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Chamber Serial Number.
|
||||
/// </summary>
|
||||
/// <value>The Test Chamber Serial Number.</value>
|
||||
[XmlElement("TestChamberSerialNumber")]
|
||||
public string TestChamberSerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Interface Adapter Identification.
|
||||
/// </summary>
|
||||
/// <value>The Interface Adapter Identification.</value>
|
||||
[XmlElement("InterfaceAdapterIdentification")]
|
||||
public string InterfaceAdapterIdentification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Interface Adapter Revision.
|
||||
/// </summary>
|
||||
/// <value>The Interface Adapter Revision.</value>
|
||||
[XmlElement("InterfaceAdapterRevision")]
|
||||
public string InterfaceAdapterRevision { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Interface Adapter Serial Number.
|
||||
/// </summary>
|
||||
/// <value>The Interface Adapter Serial Number.</value>
|
||||
[XmlElement("InterfaceAdapterSerialNumber")]
|
||||
public string InterfaceAdapterSerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the test category.
|
||||
/// </summary>
|
||||
/// <value>The test category.</value>
|
||||
[XmlElement("Address")]
|
||||
public TestCategory TestCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Location.
|
||||
/// </summary>
|
||||
/// <value>The Test Location.</value>
|
||||
[XmlElement("TestLocation")]
|
||||
public string TestLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test operator.
|
||||
/// </summary>
|
||||
/// <value>The Test Operator.</value>
|
||||
[XmlElement("TestOperator")]
|
||||
public string TestOperator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Temperature.
|
||||
/// </summary>
|
||||
/// <value>The Test Temperature.</value>
|
||||
[XmlElement("TestTemperature")]
|
||||
public string TestTemperature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Start Time.
|
||||
/// </summary>
|
||||
/// <value>The Test start time.</value>
|
||||
[XmlElement("TestStartTime")]
|
||||
public DateTime TestStartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Test Stop Time.
|
||||
/// </summary>
|
||||
/// <value>The Test Stop Time.</value>
|
||||
[XmlElement("TestStopTime")]
|
||||
public DateTime TestStopTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the UUT Test Status.
|
||||
/// </summary>
|
||||
/// <value>The UUT Test Status.</value>
|
||||
[XmlElement("UutTestStatus")]
|
||||
public PassFailStatus UutTestStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the test comments.
|
||||
/// </summary>
|
||||
/// <value>The test comments.</value>
|
||||
[XmlElement("TestComments")]
|
||||
public string TestComments { get; set; }
|
||||
|
||||
[XmlElement("ECIDNumber")]
|
||||
public string ECIDNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Physical slot number the UUT is tested in.
|
||||
/// </summary>
|
||||
[XmlElement("SlotNumber")]
|
||||
public int SlotNumber { get; set; } = 1;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public PdelInformation()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ICloneable is depreciated so we have to create a basic copy constructor.
|
||||
/// </summary>
|
||||
/// <param name="copyThis"></param>
|
||||
public PdelInformation(PdelInformation copyThis)
|
||||
{
|
||||
Clone(copyThis);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Members
|
||||
/// <summary>
|
||||
/// Clones the PdelInformation from copyThis to this.
|
||||
/// </summary>
|
||||
/// <param name="copyThis"></param>
|
||||
void Clone(PdelInformation cloneThis)
|
||||
{
|
||||
UutSerialNumber = cloneThis.UutSerialNumber;
|
||||
UutIdentification = cloneThis.UutIdentification;
|
||||
UutRevision = cloneThis.UutRevision;
|
||||
WorkOrder = cloneThis.WorkOrder;
|
||||
WorkOrderOperation = cloneThis.WorkOrderOperation;
|
||||
TestProcedureIdentification = cloneThis.TestProcedureIdentification;
|
||||
TestProcedureRevision = cloneThis.TestProcedureRevision;
|
||||
TestSetIdentification = cloneThis.TestSetIdentification;
|
||||
TestSoftwareRevision = cloneThis.TestSoftwareRevision;
|
||||
TestSoftwareIdentification = cloneThis.TestSoftwareIdentification;
|
||||
TestSetRevision = cloneThis.TestSetRevision;
|
||||
TestSetSerialNumber = cloneThis.TestSetSerialNumber;
|
||||
TestChamberIdentification = cloneThis.TestChamberIdentification;
|
||||
TestChamberRevision = cloneThis.TestChamberRevision;
|
||||
TestChamberSerialNumber = cloneThis.TestChamberSerialNumber;
|
||||
InterfaceAdapterIdentification = cloneThis.InterfaceAdapterIdentification;
|
||||
InterfaceAdapterRevision = cloneThis.InterfaceAdapterRevision;
|
||||
InterfaceAdapterSerialNumber = cloneThis.InterfaceAdapterSerialNumber;
|
||||
TestLocation = cloneThis.TestLocation;
|
||||
TestCategory = cloneThis.TestCategory;
|
||||
TestTemperature = cloneThis.TestTemperature;
|
||||
ECIDNumber = cloneThis.ECIDNumber;
|
||||
SlotNumber = cloneThis.SlotNumber;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all the public properties of the current System.Type.
|
||||
/// </summary>
|
||||
/// <returns>Dictionary of key/value pairs representing PDEL Header values.</returns>
|
||||
public Dictionary<string, string> GetDetails()
|
||||
{
|
||||
Dictionary<string, string> details = new Dictionary<string, string>();
|
||||
|
||||
PropertyInfo[] propertyInfos = this.GetType().GetProperties();
|
||||
|
||||
foreach (PropertyInfo info in propertyInfos)
|
||||
{
|
||||
var value = string.Empty;
|
||||
|
||||
foreach (var test in info.CustomAttributes)
|
||||
{
|
||||
if (test.NamedArguments != null && test.NamedArguments.Count > 0 && test.NamedArguments[0].MemberName == "EmitDefaultValue")
|
||||
{
|
||||
value = "DoNotWriteToPDEL";
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = info.GetValue(this) == null ? "NA" : info.GetValue(this).ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string name = Regex.Replace(info.Name, @"(?<!_|^)([A-Z])", "_$1").ToUpper();
|
||||
|
||||
// Some of the values might be blank. They are still allowed because when a replace gets done on the HTMLWriter,
|
||||
// the placeholders will be replaced with an empty string.
|
||||
details.Add(name, value);
|
||||
|
||||
// Look to see when the test start time label got added and set the time.
|
||||
if (name == "TEST_START_TIME" || name == "TEST_STOP_TIME")
|
||||
{
|
||||
details[name] = Convert.ToDateTime(value).ToString("yyyyMMdd:HHmmss");
|
||||
}
|
||||
}
|
||||
|
||||
return details;
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return TestProcedureRevision.Clone();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
202
Source/TSRealLib/Common/Raytheon.Common/Pdel/PdelWriter.cs
Normal file
202
Source/TSRealLib/Common/Raytheon.Common/Pdel/PdelWriter.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Raytheon.Common.PdelWriter.Utilities;
|
||||
|
||||
namespace Raytheon.Common.PdelWriter
|
||||
{
|
||||
public class PdelWriter
|
||||
{
|
||||
#region Private Class Members
|
||||
/// <summary>
|
||||
/// Will hold the PDEL header line length that this the longest.
|
||||
/// </summary>
|
||||
private int maxLength = 0;
|
||||
#endregion
|
||||
|
||||
#region Private Properties
|
||||
// Get Test Executive's PDEL report storage locations from the app.config file.
|
||||
public string TestResultsLocalFolder { get; set; }
|
||||
public string PdelDataResultsSubfolder { get; set; }
|
||||
public string TestResultsNetworkFolder { get; set; }
|
||||
public bool OutputTestResultsToSubfolder { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PdelWriter" /> class.
|
||||
/// </summary>
|
||||
public PdelWriter()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Members
|
||||
/// <summary>
|
||||
/// Remove extraneous punctuation that causes errors in the PDEL report generation.
|
||||
/// </summary>
|
||||
/// <param name="dataString - data to scan for and remove extraneous punctuation"></param>
|
||||
/// <returns>Returns a string without extraneous punctuation.</returns>
|
||||
public string RemovePunctuation(string dataString)
|
||||
{
|
||||
// Remove all commas, single quotes and double quotes and semi-colons from string.
|
||||
return Regex.Replace(dataString, "[,'\";]+", "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moved outside of CreatePdelFile to set the local properties that make up the PDEL report file path.
|
||||
/// </summary>
|
||||
/// <param name="pdelInformation"></param>
|
||||
/// <param name="filename"></param>
|
||||
/// <returns></returns>
|
||||
public string CreateFilePath(PdelInformation pdelInformation, string localFolderPath, out string filename)
|
||||
{
|
||||
// Get Test Executive's PDEL report storage locations from the app.config file.
|
||||
TestResultsLocalFolder = localFolderPath;
|
||||
return CreateTestResultsFolder(pdelInformation, out filename);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes PDEL data to a file.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public void CreatePdelFile(List<TestResult> testResults, PdelInformation pdelInformation, string localFolderPath)
|
||||
{
|
||||
if (pdelInformation != null)
|
||||
{
|
||||
var hasFailure = from s in testResults
|
||||
where s.Result == PassFailStatus.Fail
|
||||
select s;
|
||||
|
||||
pdelInformation.UutTestStatus = hasFailure.Count() > 0 ? PassFailStatus.Fail : PassFailStatus.Pass;
|
||||
|
||||
string filename = string.Empty;
|
||||
string testResultsFolder = CreateFilePath(pdelInformation, localFolderPath, out filename);
|
||||
|
||||
// Find the header line that is the longest. This will help us to align the headers items together.
|
||||
foreach (KeyValuePair<string, string> kvp in pdelInformation.GetDetails())
|
||||
{
|
||||
if (maxLength < kvp.Key.Length)
|
||||
{
|
||||
maxLength = kvp.Key.Length;
|
||||
}
|
||||
}
|
||||
|
||||
var startTime = new TimeSpan();
|
||||
|
||||
var stopTime = new TimeSpan();
|
||||
string pdelFilePath = Path.Combine(testResultsFolder, filename + ".pdel");
|
||||
|
||||
using (System.IO.StreamWriter writer = new StreamWriter(pdelFilePath))
|
||||
{
|
||||
string comment = string.Empty;
|
||||
|
||||
writer.Write(string.Format("COMMENT = **********START OF HEADER***************;{0}", Environment.NewLine));
|
||||
|
||||
foreach (KeyValuePair<string, string> kvp in pdelInformation.GetDetails())
|
||||
{
|
||||
// If there are test comments, the entry needs to be defined.
|
||||
if (kvp.Key == "TEST_COMMENTS")
|
||||
{
|
||||
writer.Write(string.Format("{0} {1} = {2}{3};{4}", "DEFINE_HEADER", kvp.Key, "User comments for test, ", pdelInformation.UutIdentification, Environment.NewLine));
|
||||
}
|
||||
else if (kvp.Key == "E_C_I_D_NUMBER")
|
||||
{
|
||||
writer.Write(string.Format("{0} {1} = {2}{3};{4}", "DEFINE_HEADER", kvp.Key, "ECID number for test, ", pdelInformation.ECIDNumber, Environment.NewLine));
|
||||
}
|
||||
else if
|
||||
(kvp.Key == "SLOT_NUMBER")
|
||||
{
|
||||
writer.Write(string.Format("{0} {1} = {2}{3};{4}", "DEFINE_HEADER", kvp.Key, "Slot number for test, ", pdelInformation.SlotNumber, Environment.NewLine));
|
||||
}
|
||||
|
||||
// Some UutDetails are used for housekeeping and do not get written to the PDEL file.
|
||||
if (kvp.Value != "DoNotWriteToPDEL")
|
||||
{
|
||||
writer.Write(string.Format("{0} = {1};{2}", kvp.Key.PadRight(maxLength), kvp.Value == string.Empty ? "N/A" : RemovePunctuation(kvp.Value), Environment.NewLine));
|
||||
}
|
||||
}
|
||||
|
||||
writer.Write(string.Format("COMMENT = **********END OF HEADER***************;{0}{1}", Environment.NewLine, Environment.NewLine));
|
||||
|
||||
writer.Write(string.Format("COMMENT = **********START OF DATA***************;{0}{1}", Environment.NewLine, Environment.NewLine));
|
||||
|
||||
foreach (var result in testResults)
|
||||
{
|
||||
writer.Write(string.Format(
|
||||
"DEFINE_DATA {0} = {1}, {2}, {3};{4}",
|
||||
result.PCode,
|
||||
RemovePunctuation(result.TestName),
|
||||
PdelDataFormatter.Format(result.MeasuredValue.ToString()),
|
||||
PdelDataFormatter.IsNullOrEmpty(result.UnitOfMeasure),
|
||||
Environment.NewLine));
|
||||
|
||||
writer.Write(string.Format("{0} = {1};{2}{3}", result.PCode, result.MeasuredValue.ToString(), Environment.NewLine, Environment.NewLine));
|
||||
}
|
||||
|
||||
writer.Write(string.Format("COMMENT = **********END OF DATA***************;{0}{1}", Environment.NewLine, Environment.NewLine));
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
public static string BuildFilename(PdelInformation pdelInformation, string separator)
|
||||
{
|
||||
return string.Format(!string.IsNullOrEmpty(pdelInformation.UutIdentification) ? (pdelInformation.UutIdentification + separator) : string.Empty)
|
||||
+ string.Format(!string.IsNullOrEmpty(pdelInformation.UutSerialNumber) ? (pdelInformation.UutSerialNumber + separator) : string.Empty)
|
||||
+ string.Format(!string.IsNullOrEmpty(pdelInformation.WorkOrder) ? (pdelInformation.WorkOrder + separator) : string.Empty)
|
||||
+ string.Format(!string.IsNullOrEmpty(pdelInformation.TestTemperature) ? (pdelInformation.TestTemperature + separator) : string.Empty)
|
||||
+ DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a PDEl report file based on information in the PdelInformation class and operator's values.
|
||||
/// </summary>
|
||||
/// <param name="pdelInformation"></param>
|
||||
/// <param name="filename"></param>
|
||||
/// <returns></returns>
|
||||
private string CreateTestResultsFolder(PdelInformation pdelInformation, out string filename)
|
||||
{
|
||||
var details = pdelInformation.GetDetails();
|
||||
|
||||
// Check to see if user selected to save data in a subfolder.
|
||||
var subFolder = PdelDataResultsSubfolder != null ? PdelDataResultsSubfolder : string.Empty;
|
||||
|
||||
// If the folder is not null or empty, get the matching UUT details value.
|
||||
if (!string.IsNullOrEmpty(subFolder) && subFolder != "None Selected")
|
||||
{
|
||||
subFolder = Regex.Replace(subFolder, @"(?<!_|^)([A-Z])", "_$1").ToUpper();
|
||||
|
||||
foreach (var detail in details)
|
||||
{
|
||||
if (subFolder == detail.Key)
|
||||
{
|
||||
subFolder = detail.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// subFolder is not being used set it to empty string.
|
||||
subFolder = string.Empty;
|
||||
}
|
||||
|
||||
filename = BuildFilename(pdelInformation, "_");
|
||||
|
||||
string testResultsFolder = Path.Combine(TestResultsLocalFolder, subFolder);
|
||||
|
||||
// Make sure the folder exists.
|
||||
if (!Directory.Exists(testResultsFolder))
|
||||
{
|
||||
Directory.CreateDirectory(testResultsFolder);
|
||||
}
|
||||
|
||||
return testResultsFolder;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
25
Source/TSRealLib/Common/Raytheon.Common/Pdel/TestCategory.cs
Normal file
25
Source/TSRealLib/Common/Raytheon.Common/Pdel/TestCategory.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace Raytheon.Common.PdelWriter.Utilities
|
||||
{
|
||||
public enum TestCategory
|
||||
{
|
||||
/// <summary>
|
||||
/// An Acceptance Test
|
||||
/// </summary>
|
||||
ACCEPTANCE_TEST,
|
||||
|
||||
/// <summary>
|
||||
/// A Manufacturing Test
|
||||
/// </summary>
|
||||
MANUFACTURING_TEST,
|
||||
|
||||
/// <summary>
|
||||
/// An Engineering Test
|
||||
/// </summary>
|
||||
ENGINEERING_TEST,
|
||||
|
||||
/// <summary>
|
||||
/// A Calibration Test
|
||||
/// </summary>
|
||||
CALIBRATION_TEST,
|
||||
}
|
||||
}
|
||||
140
Source/TSRealLib/Common/Raytheon.Common/Pdel/TestResult.cs
Normal file
140
Source/TSRealLib/Common/Raytheon.Common/Pdel/TestResult.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Raytheon.Common.PdelWriter.Utilities
|
||||
{
|
||||
[XmlType("ASICTestExecutive-UutTestConfiguration")]
|
||||
public class TestResultList
|
||||
{
|
||||
[XmlArray("TestResultList")]
|
||||
[XmlArrayItem("TestResult")]
|
||||
public List<TestResult> List { get; set; }
|
||||
public TestResultList()
|
||||
{
|
||||
List = new List<TestResult>();
|
||||
}
|
||||
}
|
||||
|
||||
public class TestResult : INotifyPropertyChanged
|
||||
{
|
||||
[XmlElement("PCode")]
|
||||
public string PCode { get; set; }
|
||||
|
||||
[XmlElement("TestName")]
|
||||
public string TestName { get; set; }
|
||||
|
||||
[XmlElement("UnitOfMeasure")]
|
||||
public string UnitOfMeasure { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public string MethodName { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
private string messages;
|
||||
|
||||
[XmlIgnore]
|
||||
public string Messages
|
||||
{
|
||||
get { return messages; }
|
||||
set
|
||||
{
|
||||
if (value != messages)
|
||||
{
|
||||
messages = value;
|
||||
OnPropertyChanged("Messages");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
[XmlIgnore]
|
||||
private PassFailStatus result;
|
||||
|
||||
[XmlIgnore]
|
||||
public PassFailStatus Result
|
||||
{
|
||||
get { return result; }
|
||||
set
|
||||
{
|
||||
if (value != result)
|
||||
{
|
||||
result = value;
|
||||
OnPropertyChanged("Result");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement]
|
||||
public object MeasuredValue { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public StringBuilder AdditionalInformation { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
private bool testHasAdditionalInformation;
|
||||
|
||||
[XmlIgnore]
|
||||
public bool TestHasAdditionalInformation
|
||||
{
|
||||
get { return testHasAdditionalInformation; }
|
||||
set
|
||||
{
|
||||
if (value != testHasAdditionalInformation)
|
||||
{
|
||||
testHasAdditionalInformation = value;
|
||||
OnPropertyChanged("TestHasAdditionalInformation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TestResult()
|
||||
{
|
||||
AdditionalInformation = new StringBuilder();
|
||||
Result = PassFailStatus.Unknown;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor.
|
||||
/// </summary>
|
||||
/// <param name="copyThis"></param>
|
||||
public TestResult(TestResult copyThis)
|
||||
{
|
||||
AdditionalInformation = new StringBuilder(copyThis.AdditionalInformation.ToString());
|
||||
result = copyThis.result;
|
||||
PCode = copyThis.PCode;
|
||||
MethodName = copyThis.MethodName;
|
||||
testHasAdditionalInformation = copyThis.testHasAdditionalInformation;
|
||||
TestName = copyThis.TestName;
|
||||
UnitOfMeasure = copyThis.UnitOfMeasure;
|
||||
messages = copyThis.messages;
|
||||
PropertyChanged = copyThis.PropertyChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles property change events for all public properties that are bound to the view.
|
||||
/// </summary>
|
||||
/// <param name="propertyName"></param>
|
||||
protected virtual void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChangedEventHandler handler = this.PropertyChanged;
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
var e = new PropertyChangedEventArgs(propertyName);
|
||||
handler(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the test results to the grid for the user to view.
|
||||
/// </summary>
|
||||
/// <param name="testHasAdditionalInformation"></param>
|
||||
public void SetTestResults(bool testHasAdditionalInformation)
|
||||
{
|
||||
TestHasAdditionalInformation = testHasAdditionalInformation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,16 +29,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<COMReference Include="Microsoft.Office.Core">
|
||||
<Guid>{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}</Guid>
|
||||
<VersionMajor>2</VersionMajor>
|
||||
<VersionMinor>8</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>primary</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
<COMReference Include="Microsoft.Office.Interop.Excel">
|
||||
<Reference Include="Microsoft.Office.Interop.Excel">
|
||||
<HintPath>Dependencies\Microsoft.Office.Interop.Excel.dll</HintPath>
|
||||
<Guid>{00020813-0000-0000-C000-000000000046}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>9</VersionMinor>
|
||||
@@ -46,16 +38,16 @@
|
||||
<WrapperTool>primary</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
<COMReference Include="VBIDE">
|
||||
<Guid>{0002E157-0000-0000-C000-000000000046}</Guid>
|
||||
<VersionMajor>5</VersionMajor>
|
||||
<VersionMinor>3</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>primary</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="AddDependenciesToPackage" AfterTargets="AfterBuild">
|
||||
<ItemGroup>
|
||||
<Content Include="COE\Dependecies\x86\*">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>lib\$(TargetFramework)</PackagePath>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@@ -17,6 +17,7 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
|
||||
namespace Raytheon.Common
|
||||
{
|
||||
@@ -32,6 +33,7 @@ namespace Raytheon.Common
|
||||
private AutoResetEvent _quitEvent;
|
||||
private bool _threadQuitControl;
|
||||
private MsgDevice.CompleteMessageCallback _completeMsgCallback;
|
||||
private readonly ILogger _logger;
|
||||
#endregion
|
||||
|
||||
#region PrivateFunctions
|
||||
@@ -41,23 +43,9 @@ namespace Raytheon.Common
|
||||
/// <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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +61,7 @@ namespace Raytheon.Common
|
||||
/// <param name="dataInBufferEvent">A singal to let us know that data has arrived</param>
|
||||
public MsgProcessorWorker(IMsgParser msgParser, ref DataBuffer dataBuffer, ref AutoResetEvent dataInBufferEvent)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_msgParser = msgParser;
|
||||
_dataBuffer = dataBuffer;
|
||||
_dataInBufferEvent = dataInBufferEvent;
|
||||
@@ -93,23 +82,9 @@ namespace Raytheon.Common
|
||||
/// </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>
|
||||
@@ -121,7 +96,7 @@ namespace Raytheon.Common
|
||||
{
|
||||
if (_completeMsgCallback == null)
|
||||
{
|
||||
throw new Exception("MsgProcessorWorker::DoWork() - Callback not set");
|
||||
throw new Exception("Callback not set");
|
||||
}
|
||||
|
||||
WaitHandle[] waithandles = new WaitHandle[2];
|
||||
@@ -170,9 +145,9 @@ namespace Raytheon.Common
|
||||
|
||||
if (_msgParser.Run(payLoadPtr, numBytesLeftInTempBuffer, ref numBytesToRemove, ref msgId, ref errorCode) == true)
|
||||
{
|
||||
string msg = "MsgProcessorWorker::DoWork() - removing " + numBytesToRemove.ToString() + " bytes, for msg id: " + msgId.ToString("X8");
|
||||
string msg = "removing " + numBytesToRemove.ToString() + " bytes, for msg id: " + msgId.ToString("X8");
|
||||
|
||||
ErrorLogger.Instance().Write(msg, ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug(msg);
|
||||
|
||||
// we have a complete message, invoke the call back
|
||||
_completeMsgCallback(msgId, payLoadPtr, numBytesToRemove, errorCode);
|
||||
@@ -192,18 +167,18 @@ namespace Raytheon.Common
|
||||
// were we signaled to quit?
|
||||
if (_threadQuitControl == true)
|
||||
{
|
||||
ErrorLogger.Instance().Write("MsgProcessorWorker::DoWork() - in the midst of procesing data, the quit event was detected, exiting", ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug("in the midst of procesing data, the quit event was detected, exiting");
|
||||
isTheWorkDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Check start of data back in since we are done with it
|
||||
_dataBuffer.CheckInStartOfData();
|
||||
}
|
||||
else if (eventIndex == 1) // _quitEvent
|
||||
{
|
||||
ErrorLogger.Instance().Write("MsgProcessorWorker::DoWork() - quit event was detected, exiting", ErrorLogger.LogLevel.INFO);
|
||||
_logger.Debug("quit event was detected, exiting");
|
||||
isTheWorkDone = true;
|
||||
}
|
||||
else if (eventIndex == WaitHandle.WaitTimeout)
|
||||
@@ -212,16 +187,11 @@ namespace Raytheon.Common
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorLogger.Instance().Write("MsgProcessorWorker::DoWork() - Unhandled return from WaitHandle.WaitAny(): " + eventIndex.ToString());
|
||||
_logger.Debug(" Unhandled return from WaitHandle.WaitAny(): " + eventIndex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
ErrorLogger.Instance().Write("MsgProcessorWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,135 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// ConfigurationHelper.cs
|
||||
// 7/5/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 Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// type conversion utility with a special case for enums
|
||||
/// </summary>
|
||||
public static class TypeConverter
|
||||
{
|
||||
public static T ChangeType<T>(object value)
|
||||
{
|
||||
return typeof(T).IsEnum ? (T)Enum.Parse(typeof(T), value.ToString()) : (T)ChangeType(typeof(T), value);
|
||||
}
|
||||
|
||||
public static object ChangeType(Type t, object value)
|
||||
{
|
||||
System.ComponentModel.TypeConverter tc = TypeDescriptor.GetConverter(t);
|
||||
return tc.ConvertFrom(value);
|
||||
}
|
||||
|
||||
public static void RegisterTypeConverter<T, TC>() where TC : System.ComponentModel.TypeConverter
|
||||
{
|
||||
TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class contains extention fuctions for reading types other than strings from configuration,
|
||||
/// as well as reading lists of values
|
||||
/// </summary>
|
||||
public static class ConfigurationHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// template function for reading different types from configuration
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="section"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetConfigurationValue<T>(this IConfiguration configuration, string section, string key, string defaultValue)
|
||||
{
|
||||
var tmpResult = configuration.GetConfigurationValue(section, key, defaultValue);
|
||||
return !string.IsNullOrEmpty(tmpResult) ? TypeConverter.ChangeType<T>(tmpResult) : default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns multivalue result (list of T) from configuration
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="section"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> GetConfigurationListValue<T>(this IConfiguration configuration, string section, string key, List<T> defaultValue)
|
||||
{
|
||||
var tmpResult = configuration.GetXmlConfiguration(section);
|
||||
if (string.IsNullOrEmpty(tmpResult))
|
||||
{
|
||||
var xmlStr = new StringBuilder();
|
||||
xmlStr.Append($"<{key}s>");
|
||||
foreach (var item in defaultValue)
|
||||
{
|
||||
xmlStr.Append($"<{key}>");
|
||||
xmlStr.Append(item.ToString());
|
||||
xmlStr.Append($"</{key}>");
|
||||
}
|
||||
xmlStr.Append($"</{key}s>");
|
||||
|
||||
configuration.SetXmlConfiguration(section, xmlStr.ToString());
|
||||
return defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var stringRes = BuildElementListFromXml(tmpResult, key);
|
||||
return new List<T>(stringRes.Select(x => TypeConverter.ChangeType<T>(x)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns values from XML section converted to string list
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
private static List<string> BuildElementListFromXml(string data, string key)
|
||||
{
|
||||
XElement doc = XElement.Parse(data);
|
||||
IEnumerable<XElement> xmlMessages = from m
|
||||
in doc.Elements($"{key}s").Elements(key)
|
||||
select m;
|
||||
var messages = xmlMessages.Select(x => x.Value);
|
||||
return messages?.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(SolutionDir)Solution.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AssemblyName>Raytheon.Instruments.COEComm</AssemblyName>
|
||||
<Description>C# wrapper for the COE Windows, integrated real-time software operating environment designed for use in embedded systems</Description>
|
||||
|
||||
<!-- Static versioning (Suitable for Development) -->
|
||||
<!-- Disable the line below for dynamic versioning -->
|
||||
<Version>1.0.0</Version>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>1701;1702;NU1803</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PrepareForRunDependsOn>$(PrepareForRunDependsOn);CopyFilesTargetName</PrepareForRunDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<coeDLLs>build\R04.$(Configuration)\x86\coeWindows-shared.dll</coeDLLs>
|
||||
<coeDLLs Condition="'$(Configuration)'=='Debug' OR '$(Configuration)'=='Release' OR '$(Configuration)'=='Deploy'">build\R04.06.05.02\x86\coeWindows-shared.dll;build\R04.06.05.02\x86\coeWindows-sharedd.dll</coeDLLs>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(coeDLLs)">
|
||||
<PackagePath>lib\$(TargetFramework)</PackagePath>
|
||||
<TargetPath></TargetPath>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
<Pack>True</Pack>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyFilesTargetName" BeforeTargets="Build">
|
||||
<Copy SourceFiles="$(coeDLLs)" DestinationFolder="$(OutDir)" />
|
||||
</Target>
|
||||
|
||||
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
|
||||
<Target Name="CopyFiles" AfterTargets="AfterBuild">
|
||||
<ItemGroup>
|
||||
<FILES_1 Include="$(OutDir)*.dll" />
|
||||
<FILES_2 Include="$(OutDir)*.pdb" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(FILES_1)" DestinationFolder="$(HalTempFolder)" />
|
||||
<Copy SourceFiles="@(FILES_2)" DestinationFolder="$(HalTempFolder)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@@ -1,502 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// BytePackingXml.cs
|
||||
// 5/18/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.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
namespace Raytheon.Instruments.MessagingUtilities
|
||||
{
|
||||
// Takes an XML ICD and adds in nodes to represent the byte packing
|
||||
// The padding added will be displayed in the tool as arrays of characters
|
||||
internal class BytePackingXml : XmlDocument
|
||||
{
|
||||
private readonly int m_Packing = 8;
|
||||
private readonly Dictionary<string, double> m_ConstMap;
|
||||
private readonly Dictionary<string, int> m_SizeMap;
|
||||
private readonly Dictionary<string, int> m_PadMap;
|
||||
|
||||
public BytePackingXml(string icdStr) : base()
|
||||
{
|
||||
// Create the dictionaries
|
||||
m_ConstMap = new Dictionary<string, double>();
|
||||
m_PadMap = new Dictionary<string, int>();
|
||||
m_SizeMap = new Dictionary<string, int>();
|
||||
|
||||
// Create an XML document from the string
|
||||
LoadXml(icdStr);
|
||||
|
||||
XPathNavigator node = CreateNavigator();
|
||||
//Get the type of packing
|
||||
XPathNodeIterator nodeset = node.Select("/interface/packing");
|
||||
if (nodeset.MoveNext() == true)
|
||||
{
|
||||
if (!Parse.Try(nodeset.Current.Value.Trim(), out m_Packing))
|
||||
{
|
||||
switch (nodeset.Current.Value.Trim())
|
||||
{
|
||||
case "char":
|
||||
case "1":
|
||||
m_Packing = 1;
|
||||
break;
|
||||
case "short":
|
||||
case "2":
|
||||
m_Packing = 2;
|
||||
break;
|
||||
case "long":
|
||||
case "4":
|
||||
m_Packing = 4;
|
||||
break;
|
||||
case "double":
|
||||
case "8":
|
||||
default:
|
||||
m_Packing = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle all of the constants
|
||||
nodeset = node.Select("/interface/constant");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
ProcessConstantNode(nodeset.Current);
|
||||
}
|
||||
|
||||
nodeset = node.Select("/interface/typedef");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
ProcessTypedefNode(nodeset.Current);
|
||||
}
|
||||
|
||||
nodeset = node.Select("/interface/enum");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
ProcessEnumerationNode(nodeset.Current);
|
||||
}
|
||||
|
||||
nodeset = node.Select("/interface/structure|/interface/message");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
ProcessStructureNode(nodeset.Current);
|
||||
}
|
||||
|
||||
NormalizeIcdLabels();
|
||||
}
|
||||
|
||||
// This function takes all of the messages in the ICD
|
||||
// and converts the labels into decimal, so when we do
|
||||
// a string lookup, they will all be in the same known format
|
||||
private void NormalizeIcdLabels()
|
||||
{
|
||||
XPathNavigator navigator = CreateNavigator();
|
||||
XPathNodeIterator nodeset;
|
||||
|
||||
nodeset = navigator.Select("/interface/message/label");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
double dLabel = GetConstFromString(nodeset.Current.Value);
|
||||
nodeset.Current.SetValue(((int)dLabel).ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("Message Label, " + nodeset.Current.Value + ", can not be converted to an integer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessConstantNode(XPathNavigator node)
|
||||
{
|
||||
string name = "";
|
||||
string constStr = "";
|
||||
double constNum = 0;
|
||||
|
||||
if (node.MoveToChild("name", ""))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
node.MoveToParent();
|
||||
}
|
||||
if (node.MoveToChild("value", ""))
|
||||
{
|
||||
constStr = node.Value.Trim();
|
||||
if ((constStr.Length != 0) && (constStr[0] != '\"'))
|
||||
{
|
||||
constNum = GetConstFromString(constStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
constNum = 0;
|
||||
}
|
||||
node.MoveToParent();
|
||||
}
|
||||
|
||||
// Verify the correctnes of the <constant> tag
|
||||
if ((name != "") && (constStr != ""))
|
||||
{
|
||||
AddItemToMap(m_ConstMap, name, constNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(
|
||||
"ERROR: Constant Definition Incorrect - <name>:" + name +
|
||||
" <value>:" + constStr);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessTypedefNode(XPathNavigator node)
|
||||
{
|
||||
string name = "";
|
||||
string type = "";
|
||||
int typeSize = 0; // Size of the item
|
||||
int typePad = 0; //Size of the largest item to pad to
|
||||
|
||||
if (node.MoveToChild("name", ""))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
node.MoveToParent();
|
||||
}
|
||||
if (node.MoveToChild("value", ""))
|
||||
{
|
||||
type = node.Value.Trim();
|
||||
GetSizeFromType(type, out typeSize, out typePad);
|
||||
node.MoveToParent();
|
||||
}
|
||||
|
||||
// Verify the correctnes of the <typedef> tag
|
||||
if ((name != "") && (type != ""))
|
||||
{
|
||||
AddItemToMap(m_PadMap, name, typePad);
|
||||
AddItemToMap(m_SizeMap, name, typeSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(
|
||||
"ERROR: Typedef Definition Incorrect - <name>:" + name +
|
||||
" <value>:" + type);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessEnumerationNode(XPathNavigator node)
|
||||
{
|
||||
string name;
|
||||
double constNum = 0;
|
||||
var constStr = string.Empty;
|
||||
|
||||
if (node.MoveToChild("name", ""))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
AddItemToMap(m_PadMap, name, 4);
|
||||
AddItemToMap(m_SizeMap, name, 4);
|
||||
node.MoveToParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("ERROR: Enumeration Definition Incorrect. No <name> tag present.");
|
||||
}
|
||||
|
||||
XPathNodeIterator nodeSet = node.Select("item|enum_item");
|
||||
while (nodeSet.MoveNext())
|
||||
{
|
||||
name = string.Empty;
|
||||
|
||||
if ((nodeSet.Current.MoveToChild("name", "")) ||
|
||||
(nodeSet.Current.MoveToChild("item_name", "")))
|
||||
{
|
||||
name = nodeSet.Current.Value.Trim();
|
||||
nodeSet.Current.MoveToParent();
|
||||
}
|
||||
if (nodeSet.Current.MoveToChild("value", ""))
|
||||
{
|
||||
constStr = nodeSet.Current.Value.Trim();
|
||||
constNum = GetConstFromString(constStr);
|
||||
nodeSet.Current.MoveToParent();
|
||||
}
|
||||
|
||||
// Verify the correctnes of the <enum><item> tag
|
||||
if ((name != "") && (constStr != ""))
|
||||
{
|
||||
AddItemToMap(m_ConstMap, name, constNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"ERROR: Enumeration Item Definition Incorrect - <name>: {name} <value>: {constStr}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessStructureNode(XPathNavigator node)
|
||||
{
|
||||
string name;
|
||||
|
||||
if (node.MoveToChild("name", ""))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
node.MoveToParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("ERROR: Stucture/Message Definition Incorrect. No <name> tag present.");
|
||||
}
|
||||
|
||||
int maxSize = 0;
|
||||
int padCount = 0;
|
||||
uint bitCount = 0; // Used to see how many bits have been processed.
|
||||
int lastItemSize = 0;
|
||||
|
||||
var nodeSet = node.Select("item|struct_item|msg_item");
|
||||
while (nodeSet.MoveNext())
|
||||
{
|
||||
GetItemSize(nodeSet.Current, out int padSize, out int itemSize, out int reps, out uint bits);
|
||||
if ((lastItemSize != itemSize) || ((bitCount + bits) > (uint)(itemSize * 8)))
|
||||
{
|
||||
bitCount = 0; // Size changed or bit rollover
|
||||
}
|
||||
|
||||
if (bitCount == 0)
|
||||
{
|
||||
padCount += AddPadding(node, nodeSet.Current, padSize, padCount);
|
||||
|
||||
// Set maxSize
|
||||
if (padSize > maxSize)
|
||||
{
|
||||
maxSize = padSize;
|
||||
}
|
||||
|
||||
// Keep up with the pad count
|
||||
padCount += (itemSize * reps);
|
||||
}
|
||||
|
||||
lastItemSize = itemSize;
|
||||
bitCount += bits;
|
||||
}
|
||||
|
||||
if (maxSize != 0)
|
||||
{
|
||||
// Add final padding
|
||||
padCount += AddPadding(node, null, maxSize, padCount);
|
||||
}
|
||||
|
||||
AddItemToMap(m_PadMap, name, maxSize);
|
||||
AddItemToMap(m_SizeMap, name, padCount);
|
||||
}
|
||||
|
||||
private void GetItemSize(XPathNavigator node, out int padSize, out int itemSize, out int reps, out uint bits)
|
||||
{
|
||||
string name = "";
|
||||
|
||||
if ((node.MoveToChild("name", "")) ||
|
||||
(node.MoveToChild("item_name", "")))
|
||||
{
|
||||
name = node.Value.Trim();
|
||||
node.MoveToParent();
|
||||
}
|
||||
|
||||
itemSize = -1;
|
||||
padSize = -1;
|
||||
reps = 1;
|
||||
bits = 0;
|
||||
|
||||
var nodeSet = node.Select("type");
|
||||
while (nodeSet.MoveNext())
|
||||
{
|
||||
GetSizeFromType(nodeSet.Current.Value.Trim(), out padSize, out itemSize);
|
||||
}
|
||||
|
||||
nodeSet = node.Select("bits");
|
||||
if (nodeSet.MoveNext())
|
||||
{
|
||||
bits = (uint)GetConstFromString(nodeSet.Current.Value.Trim());
|
||||
}
|
||||
|
||||
nodeSet = node.Select("arrayLength|imageWidth|imageHeight");
|
||||
while (nodeSet.MoveNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
reps *= (int)GetConstFromString(nodeSet.Current.Value.Trim());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception
|
||||
(e.Message + " item name = \"" + name + "\", tag = <" +
|
||||
nodeSet.Current.Name + ">.");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ((itemSize == -1) || (padSize == -1))
|
||||
{
|
||||
throw new Exception
|
||||
("ERROR: Item named " + name + "does not contain a <type> tag.");
|
||||
}
|
||||
|
||||
if (bits == 0)
|
||||
bits = (uint)padSize * 8;
|
||||
}
|
||||
|
||||
private double GetConstFromString(string constStr)
|
||||
{
|
||||
if ((constStr.Length > 0) && (constStr[0] == '\''))
|
||||
{
|
||||
byte charData = (byte)constStr[1];
|
||||
constStr = charData.ToString();
|
||||
}
|
||||
|
||||
if (Parse.Try(constStr, out double data) == false)
|
||||
{
|
||||
if (Parse.Try(constStr, out int iData) == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
data = m_ConstMap[constStr];
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("ERROR: ConstantValue - \"" + constStr + "\" does not resolve to a number.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = (double)iData;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private void AddItemToMap(Dictionary<string, int> map, string name, int value)
|
||||
{
|
||||
if (map.ContainsKey(name))
|
||||
{
|
||||
throw new Exception("ERROR: Element " + name + " is defined multiple times.");
|
||||
}
|
||||
else
|
||||
{
|
||||
map.Add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddItemToMap(Dictionary<string, double> map, string name, double value)
|
||||
{
|
||||
if (map.ContainsKey(name))
|
||||
{
|
||||
throw new Exception("ERROR: Element " + name + " is defined multiple times.");
|
||||
}
|
||||
else
|
||||
{
|
||||
map.Add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetSizeFromType(string type, out int typePad, out int typeSize)
|
||||
{
|
||||
// Remove all whitespace
|
||||
type = type.Replace(" ", "");
|
||||
|
||||
if ((type == "char") || (type == "unsignedchar"))
|
||||
{
|
||||
typePad = 1;
|
||||
typeSize = 1;
|
||||
}
|
||||
else if ((type == "short") || (type == "unsignedshort"))
|
||||
{
|
||||
typePad = 2;
|
||||
typeSize = 2;
|
||||
}
|
||||
else if ((type == "unsigned") || (type == "unsignedint") ||
|
||||
(type == "int") || (type == "float") ||
|
||||
(type == "boolean") || (type == "address"))
|
||||
{
|
||||
typePad = 4;
|
||||
typeSize = 4;
|
||||
}
|
||||
else if ((type == "double") || (type == "longlong") ||
|
||||
(type == "unsignedlonglong"))
|
||||
{
|
||||
typePad = 8;
|
||||
typeSize = 8;
|
||||
}
|
||||
else // The type is complex and has already been defined
|
||||
{
|
||||
try
|
||||
{
|
||||
typePad = m_PadMap[type];
|
||||
typeSize = m_SizeMap[type];
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("ERROR: <type> - " + type + " used without being defined.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int AddPadding(XPathNavigator ParentElement, XPathNavigator CurrentElement, int padSize, int padCount)
|
||||
{
|
||||
int padAdd = 0;
|
||||
int padTo = padSize;
|
||||
|
||||
if (m_Packing < padSize)
|
||||
{
|
||||
padTo = m_Packing;
|
||||
}
|
||||
|
||||
if ((padTo != 0) && (padCount % padTo != 0))
|
||||
{
|
||||
padAdd = padTo - (padCount % padTo);
|
||||
InsertPaddingNode(ParentElement, CurrentElement, padAdd);
|
||||
}
|
||||
|
||||
return padAdd;
|
||||
}
|
||||
|
||||
private void InsertPaddingNode(XPathNavigator ParentElement, XPathNavigator CurrentElement, int padAdd)
|
||||
{
|
||||
string pad = "<item>" +
|
||||
"<name>" + Message.PADDING_ITEM_NAME + "</name>" +
|
||||
"<type>char</type>" +
|
||||
"<arrayLength>" + padAdd + "</arrayLength>" +
|
||||
"<instruType>S</instruType>" +
|
||||
"</item>";
|
||||
if (CurrentElement != null)
|
||||
{
|
||||
CurrentElement.InsertBefore(pad);
|
||||
}
|
||||
else // End padding
|
||||
{
|
||||
ParentElement.AppendChild(pad);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,600 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// MessageData.cs
|
||||
// 5/18/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.IO;
|
||||
|
||||
using Raytheon.Instruments.coeCSharp;
|
||||
|
||||
namespace Raytheon.Instruments.MessagingUtilities
|
||||
{
|
||||
public class MessageData : ICloneable
|
||||
{
|
||||
public string FieldName;
|
||||
public string FieldType;
|
||||
public string FieldValue;
|
||||
public string FieldArrayValue;
|
||||
public string FieldDefaultValue;
|
||||
public string FieldMaxValue;
|
||||
public string FieldMinValue;
|
||||
public string FieldBitValue;
|
||||
public string FieldInstruType;
|
||||
public string Variable;
|
||||
public string MaxOffset;
|
||||
public string MinOffset;
|
||||
public string VerifyType;
|
||||
public bool isSelected;
|
||||
public bool isArray;
|
||||
public bool isStructure;
|
||||
public bool isArrayOfStructures;
|
||||
public bool isEnum;
|
||||
public bool usesRegister;
|
||||
public bool isValid;
|
||||
public bool useRange;
|
||||
public int arrayLength;
|
||||
public uint imageWidth;
|
||||
public uint imageHeight;
|
||||
public uint imagePixelSize;
|
||||
public ulong bitMask;
|
||||
public bool expanded;
|
||||
public int depth;
|
||||
public byte[] imageBuffer;
|
||||
public uint imageBufferSize;
|
||||
public MessageData[] MessageArray;
|
||||
|
||||
public delegate coe.Status ReadImageDelegate
|
||||
(
|
||||
string filename,
|
||||
uint columns,
|
||||
uint rows,
|
||||
uint pixel_size,
|
||||
byte[] buffer
|
||||
);
|
||||
|
||||
private MessageXmlDocument m_Icd;
|
||||
|
||||
internal int m_BitCounter = 0; // used to calculate the bit mask
|
||||
|
||||
internal static Dictionary<string, ReadImageDelegate> m_ReadFunctions = null;
|
||||
private MessageData() { }
|
||||
private MessageData(MessageXmlDocument Icd)
|
||||
{
|
||||
FieldName = null;
|
||||
FieldType = null;
|
||||
FieldValue = null;
|
||||
FieldArrayValue = null;
|
||||
FieldDefaultValue = null;
|
||||
FieldMaxValue = null;
|
||||
FieldMinValue = null;
|
||||
FieldBitValue = null;
|
||||
Variable = null;
|
||||
MaxOffset = null;
|
||||
MinOffset = null;
|
||||
VerifyType = null;
|
||||
isSelected = false;
|
||||
isArray = false;
|
||||
isStructure = false;
|
||||
isArrayOfStructures = false;
|
||||
usesRegister = false;
|
||||
useRange = false;
|
||||
arrayLength = 0;
|
||||
imageWidth = 0;
|
||||
imageHeight = 0;
|
||||
imagePixelSize = 0;
|
||||
bitMask = 0;
|
||||
expanded = false;
|
||||
depth = 0;
|
||||
imageBufferSize = 0;
|
||||
imageBuffer = null;
|
||||
|
||||
m_Icd = Icd;
|
||||
}
|
||||
|
||||
public MessageData(string fieldname,
|
||||
string fieldtype,
|
||||
string fieldvalue,
|
||||
string fielddefaultvalue,
|
||||
MessageXmlDocument Icd) :
|
||||
this(Icd)
|
||||
{
|
||||
FieldName = fieldname;
|
||||
FieldType = fieldtype;
|
||||
FieldValue = fieldvalue;
|
||||
|
||||
SetInstruType(null);
|
||||
SetDefaultValue(fielddefaultvalue);
|
||||
|
||||
}
|
||||
|
||||
public MessageData(string fieldname,
|
||||
string fieldtype,
|
||||
string fieldvalue,
|
||||
string fielddefaultvalue,
|
||||
string fieldmaxvalue,
|
||||
string fieldminvalue,
|
||||
MessageXmlDocument Icd) :
|
||||
this(fieldname, fieldtype, fieldvalue, fielddefaultvalue, Icd)
|
||||
{
|
||||
SetMaxValue(fieldmaxvalue);
|
||||
SetMinValue(fieldminvalue);
|
||||
}
|
||||
|
||||
public string FormattedValue
|
||||
{
|
||||
get { return FormatValue(FieldValue); }
|
||||
}
|
||||
public string FormattedMinValue
|
||||
{
|
||||
get { return FormatValue(FieldMinValue); }
|
||||
}
|
||||
public string FormattedMaxValue
|
||||
{
|
||||
get { return FormatValue(FieldMaxValue); }
|
||||
}
|
||||
|
||||
public static string ImageFileReadTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
string fileTypes = "";
|
||||
if (m_ReadFunctions == null) return null;
|
||||
foreach (string type in m_ReadFunctions.Keys)
|
||||
{
|
||||
if (fileTypes != "")
|
||||
fileTypes += "|";
|
||||
|
||||
fileTypes += type.ToUpper() + " files (*." + type.ToLower() + ")|*." + type.ToLower();
|
||||
}
|
||||
|
||||
return fileTypes;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddReadExtension(string extension, ReadImageDelegate readFunc)
|
||||
{
|
||||
if (m_ReadFunctions == null)
|
||||
m_ReadFunctions = new Dictionary<string, ReadImageDelegate>();
|
||||
|
||||
if (m_ReadFunctions.ContainsKey(extension))
|
||||
m_ReadFunctions[extension] = readFunc;
|
||||
else
|
||||
m_ReadFunctions.Add(extension, readFunc);
|
||||
}
|
||||
|
||||
public void UpdateImage()
|
||||
{
|
||||
if (FieldInstruType == "P")
|
||||
{
|
||||
if (File.Exists(FieldValue))
|
||||
{
|
||||
string extension = FieldValue.Substring(FieldValue.LastIndexOf(".") + 1);
|
||||
m_ReadFunctions[extension](FieldValue,
|
||||
imageWidth,
|
||||
imageHeight,
|
||||
imagePixelSize,
|
||||
imageBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO add error message
|
||||
//MessageBox.Show("Unable to open file " + FieldValue +
|
||||
// " to populate " + FieldName,
|
||||
// "File Read Error",
|
||||
// MessageBoxButtons.OK,
|
||||
// MessageBoxIcon.Error);
|
||||
FieldValue = "";
|
||||
for (int i = 0; i < imageBuffer.Length; i++)
|
||||
{
|
||||
imageBuffer[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetDefaultValue(string fieldDefaultValue)
|
||||
{
|
||||
// Initialize uninitialized value
|
||||
if (fieldDefaultValue == null)
|
||||
{
|
||||
fieldDefaultValue = "";
|
||||
}
|
||||
|
||||
if ((FieldType == "char") && (fieldDefaultValue.Contains("\"")))
|
||||
{
|
||||
FieldInstruType = "S";
|
||||
}
|
||||
|
||||
FieldDefaultValue = RemoveCharFromString(fieldDefaultValue, '\"');
|
||||
}
|
||||
|
||||
public void SetMaxValue(string fieldmaxvalue)
|
||||
{
|
||||
if (fieldmaxvalue == null) return; /* Bad argument */
|
||||
|
||||
if ((FieldType == "char") && (fieldmaxvalue.Contains("\"")))
|
||||
{
|
||||
FieldInstruType = "S";
|
||||
}
|
||||
|
||||
FieldMaxValue = RemoveCharFromString(fieldmaxvalue, '\"');
|
||||
}
|
||||
|
||||
public void SetMinValue(string fieldminvalue)
|
||||
{
|
||||
if (fieldminvalue == null) return; /* Bad argument */
|
||||
|
||||
if ((FieldType == "char") && (fieldminvalue.Contains("\"")))
|
||||
{
|
||||
FieldInstruType = "S";
|
||||
}
|
||||
|
||||
FieldMinValue = RemoveCharFromString(fieldminvalue, '\"');
|
||||
}
|
||||
|
||||
public void SetBitValue(int bits)
|
||||
{
|
||||
int size = (int)Message.GetTypeSize(FieldType, isEnum);
|
||||
|
||||
// Determine the bitMask
|
||||
if (bits == 0)
|
||||
{
|
||||
m_BitCounter = 0;
|
||||
FieldBitValue = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
FieldBitValue = bits.ToString();
|
||||
|
||||
// If bits overflow across the type boundary, then
|
||||
// they start at the next boundary.
|
||||
//
|
||||
// MSDN :
|
||||
// "Note that nYear is 8 bits long and would overflow
|
||||
// the word boundary of the declared type, unsigned short.
|
||||
// Therefore, it is begun at the beginning of a
|
||||
// new unsigned short."
|
||||
if (m_BitCounter + bits > size * 8)
|
||||
{
|
||||
m_BitCounter = 0;
|
||||
}
|
||||
|
||||
// 2^bits-1 will give a bit mask with bit# of 1's
|
||||
// ex: bits = 5, bitMask = 11111
|
||||
bitMask = (ulong)Math.Pow(2, (double)bits) - 1;
|
||||
|
||||
// We must slide the bitMask left to put it in place
|
||||
bitMask <<= m_BitCounter;
|
||||
m_BitCounter += bits;
|
||||
|
||||
// If we have used all the bits in the type that was defined, then
|
||||
// restart the counter
|
||||
if (m_BitCounter == size * 8)
|
||||
m_BitCounter = 0;
|
||||
}
|
||||
|
||||
if (bitMask == 0xffffff)
|
||||
{
|
||||
bitMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetArraySize(int size)
|
||||
{
|
||||
char result;
|
||||
|
||||
arrayLength = size; // Save the size
|
||||
|
||||
if (!isArray && !isStructure)
|
||||
{
|
||||
// Don't handle strings as arrays
|
||||
if ((FieldInstruType != "S") && (FieldInstruType != "P"))
|
||||
{
|
||||
isArray = true;
|
||||
|
||||
MessageArray = new MessageData[size];
|
||||
// If the field type is char or unsigned char and the default value
|
||||
// exists and is a string then write one char of the string to
|
||||
// each element of the array
|
||||
if ((FieldType == "char" || FieldType == "unsigned char") &&
|
||||
FieldDefaultValue != null &&
|
||||
!Parse.Try(FieldDefaultValue, out result))
|
||||
{
|
||||
for (uint index = 0; index < size; index++)
|
||||
{
|
||||
//Only the elements that are required to spell out the string should
|
||||
//receive default values.
|
||||
if (index < FieldDefaultValue.Length)
|
||||
{
|
||||
MessageArray[index] = new MessageData(FieldName + "[" + index + "]",
|
||||
FieldType, FieldValue, FieldDefaultValue[(int)index].ToString(),
|
||||
FieldMaxValue, FieldMinValue, m_Icd);
|
||||
MessageArray[index].FieldInstruType = FieldInstruType;
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageArray[index] = new MessageData(FieldName + "[" + index + "]",
|
||||
FieldType, FieldValue, "0",
|
||||
FieldMaxValue, FieldMinValue, m_Icd);
|
||||
MessageArray[index].FieldInstruType = FieldInstruType;
|
||||
}
|
||||
MessageArray[index].depth = depth + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint index = 0; index < size; index++)
|
||||
{
|
||||
MessageArray[index] = new MessageData(FieldName + "[" + index + "]",
|
||||
FieldType, FieldValue, FieldDefaultValue, FieldMaxValue,
|
||||
FieldMinValue, m_Icd);
|
||||
MessageArray[index].FieldInstruType = FieldInstruType;
|
||||
MessageArray[index].depth = depth + 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStructureSize(int size)
|
||||
{
|
||||
if (!isArray && !isStructure)
|
||||
{
|
||||
isStructure = true;
|
||||
MessageArray = new MessageData[size];
|
||||
for (uint index = 0; index < size; index++)
|
||||
{
|
||||
MessageArray[index] = new MessageData(FieldName + ".", null, null, null, m_Icd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetInstruType(string Type)
|
||||
{
|
||||
if (Type != null)
|
||||
{
|
||||
FieldInstruType = Type;
|
||||
|
||||
// Ensure 'S' is used properly
|
||||
if ((Type == "S") && (FieldType != "char"))
|
||||
{
|
||||
return; /* << EXIT >> */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((FieldType != null) &&
|
||||
((FieldType.Trim() == "float") || (FieldType.Trim() == "double")))
|
||||
{
|
||||
FieldInstruType = "F";
|
||||
}
|
||||
else
|
||||
{
|
||||
FieldInstruType = "I";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetPixelSize()
|
||||
{
|
||||
// Only do this if the user did not define a size
|
||||
if (imagePixelSize == 0)
|
||||
{
|
||||
switch (FieldType)
|
||||
{
|
||||
case "char":
|
||||
case "unsigned char":
|
||||
case "unsignedchar":
|
||||
imagePixelSize = 1;
|
||||
break;
|
||||
|
||||
case "short":
|
||||
case "unsigned short":
|
||||
case "unsignedshort":
|
||||
imagePixelSize = 2;
|
||||
break;
|
||||
|
||||
case "int":
|
||||
case "unsigned int":
|
||||
case "unsignedint":
|
||||
case "unsigned":
|
||||
case "boolean":
|
||||
case "address":
|
||||
case "float":
|
||||
imagePixelSize = 4;
|
||||
break;
|
||||
|
||||
case "double":
|
||||
case "long long":
|
||||
case "longlong":
|
||||
case "unsigned long long":
|
||||
case "unsignedlonglong":
|
||||
imagePixelSize = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isEnum)
|
||||
{
|
||||
imagePixelSize = 4;
|
||||
}
|
||||
else // Error case
|
||||
{
|
||||
imagePixelSize = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string FormatValue(string Value)
|
||||
{
|
||||
if ((Value == null) || (Value == ""))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
else // Value exists
|
||||
{
|
||||
if (isEnum == false)
|
||||
{
|
||||
if (FieldInstruType == "I")
|
||||
{
|
||||
// This is being represented as a decimal
|
||||
if (Parse.Try(Value, out long dec) == true)
|
||||
{
|
||||
return dec.ToString();
|
||||
}
|
||||
}
|
||||
else if (FieldInstruType == "F")
|
||||
{
|
||||
// This is being represented as floating point
|
||||
if (Parse.Try(Value, out double flt) == true)
|
||||
{
|
||||
return flt.ToString();
|
||||
}
|
||||
}
|
||||
else if ((FieldInstruType == "X") ||
|
||||
(FieldInstruType == "B") ||
|
||||
(FieldInstruType == "T"))
|
||||
{
|
||||
// This is being represented as a hexadecimal value
|
||||
if (Parse.Try(Value, out long hex) == true)
|
||||
{
|
||||
return "0x" + hex.ToString("X");
|
||||
}
|
||||
}
|
||||
else if (FieldInstruType == "N")
|
||||
{
|
||||
// This is being represented as a binary number
|
||||
if (Parse.Try(Value, out long bin) == true)
|
||||
{
|
||||
return Convert.ToString(bin, 2) + "b";
|
||||
}
|
||||
}
|
||||
// else InstruType == 'S' or 'P' or anything else return the value
|
||||
}
|
||||
else // This value is an enumeration
|
||||
{
|
||||
Dictionary<string, string> enums = m_Icd.GetEnumerations(FieldType);
|
||||
if (enums.ContainsValue(Value) == true)
|
||||
{
|
||||
foreach (KeyValuePair<string, string> pair in enums)
|
||||
{
|
||||
if (pair.Value.Trim() == Value.Trim())
|
||||
{
|
||||
return pair.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Value; // If nothing above applies, simply return the value string
|
||||
}
|
||||
|
||||
private String RemoveCharFromString(String str, char c)
|
||||
{
|
||||
if (str == null) return null; // Handle null case
|
||||
|
||||
int index = str.IndexOf(c);
|
||||
while (index != -1)
|
||||
{
|
||||
str = str.Remove(index, 1);
|
||||
index = str.IndexOf(c);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#region ICloneable Members
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
MessageData clone = new MessageData();
|
||||
|
||||
clone.FieldName = FieldName;
|
||||
clone.FieldType = FieldType;
|
||||
clone.FieldValue = FieldValue;
|
||||
clone.FieldArrayValue = FieldArrayValue;
|
||||
clone.FieldDefaultValue = FieldDefaultValue;
|
||||
clone.FieldMaxValue = FieldMaxValue;
|
||||
clone.FieldMinValue = FieldMinValue;
|
||||
clone.FieldBitValue = FieldBitValue;
|
||||
clone.FieldInstruType = FieldInstruType;
|
||||
clone.Variable = Variable;
|
||||
clone.MaxOffset = MaxOffset;
|
||||
clone.MinOffset = MinOffset;
|
||||
clone.VerifyType = VerifyType;
|
||||
clone.isSelected = isSelected;
|
||||
clone.isArray = isArray;
|
||||
clone.isStructure = isStructure;
|
||||
clone.isArrayOfStructures = isArrayOfStructures;
|
||||
clone.isEnum = isEnum;
|
||||
clone.usesRegister = usesRegister;
|
||||
clone.isValid = isValid;
|
||||
clone.useRange = useRange;
|
||||
clone.arrayLength = arrayLength;
|
||||
clone.bitMask = bitMask;
|
||||
clone.expanded = expanded;
|
||||
clone.depth = depth;
|
||||
clone.m_Icd = m_Icd;
|
||||
clone.imageWidth = imageWidth;
|
||||
clone.imageHeight = imageHeight;
|
||||
clone.imagePixelSize = imagePixelSize;
|
||||
clone.imageBufferSize = imageBufferSize;
|
||||
if (imageBufferSize > 0)
|
||||
{
|
||||
clone.imageBuffer = new byte[imageBufferSize];
|
||||
imageBuffer.CopyTo(clone.imageBuffer, 0);
|
||||
}
|
||||
|
||||
if (MessageArray == null)
|
||||
{
|
||||
clone.MessageArray = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
clone.MessageArray = new MessageData[MessageArray.Length];
|
||||
for (int i = 0; i < MessageArray.Length; i++)
|
||||
{
|
||||
clone.MessageArray[i] = (MessageData)MessageArray[i].Clone();
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,426 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// MessageXmlDocument.cs
|
||||
// 5/18/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.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
|
||||
namespace Raytheon.Instruments.MessagingUtilities
|
||||
{
|
||||
public class MessageXmlDocument : XmlDocument
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly string _XmlFileName;
|
||||
private string BuiltXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><?xml-stylesheet type=\"text/xsl\" ?><interface>";
|
||||
|
||||
private uint m_MaxMsgSize = 0;
|
||||
private readonly List<string> m_IncludeList;
|
||||
|
||||
private MessageXmlDocument() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public MessageXmlDocument(string Pathname,
|
||||
ILogger logger) :
|
||||
base()
|
||||
{
|
||||
_logger = logger;
|
||||
_XmlFileName = Pathname;
|
||||
|
||||
m_IncludeList = new List<string>();
|
||||
RecurseProcessing(Pathname);
|
||||
|
||||
BuiltXML = string.Concat(BuiltXML, "</interface>");
|
||||
BytePackingXml addPacking = new BytePackingXml(BuiltXML);
|
||||
LoadXml(addPacking.OuterXml);
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetEnumerations(string Type)
|
||||
{
|
||||
Dictionary<string, string> enumList = new Dictionary<string, string>();
|
||||
|
||||
// Get XML nodes to parse the XML ICD document
|
||||
XPathNavigator Node = CreateNavigator();
|
||||
XPathNodeIterator Nodeset = Node.Select("interface/enum/name");
|
||||
|
||||
while (Nodeset.MoveNext())
|
||||
{
|
||||
// Find the enumeration with the name of the type
|
||||
if (Nodeset.Current.Value.Trim().Equals(Type.Trim()))
|
||||
{
|
||||
// Find all the enumeration items
|
||||
XPathNavigator enumNode = Nodeset.Current.Clone();
|
||||
while (enumNode.MoveToNext())
|
||||
{
|
||||
if (enumNode.Name.Trim().Equals("item") ||
|
||||
enumNode.Name.Trim().Equals("enum_item"))
|
||||
{
|
||||
string name = null;
|
||||
string value = null;
|
||||
|
||||
// Find all name nodes
|
||||
XPathNavigator childNode = enumNode.Clone();
|
||||
childNode.MoveToFirstChild();
|
||||
do
|
||||
{
|
||||
if (childNode.Name.Trim().Equals("name"))
|
||||
{
|
||||
name = childNode.Value.Trim();
|
||||
}
|
||||
else if (childNode.Name.Trim().Equals("item_name"))
|
||||
{
|
||||
name = childNode.Value.Trim();
|
||||
}
|
||||
|
||||
if (childNode.Name.Trim().Equals("value"))
|
||||
{
|
||||
value = childNode.Value.Trim();
|
||||
}
|
||||
|
||||
// Once we find the name & value, add it to the list
|
||||
if ((name != null) && (value != null))
|
||||
{
|
||||
enumList.Add(name, value);
|
||||
break;
|
||||
}
|
||||
} while (childNode.MoveToNext());
|
||||
}
|
||||
}
|
||||
|
||||
break; // We found the enumeration we wanted
|
||||
}
|
||||
}
|
||||
|
||||
return enumList;
|
||||
}
|
||||
|
||||
private void RecurseProcessing(string pathName)
|
||||
{
|
||||
string directory;
|
||||
string IncludePathname;
|
||||
XPathNodeIterator nodeset;
|
||||
|
||||
// Only process each file once
|
||||
pathName = pathName.Replace('/', '\\');
|
||||
if (m_IncludeList.Contains(pathName))
|
||||
{
|
||||
return; // This file has already been processed
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IncludeList.Add(pathName);
|
||||
}
|
||||
|
||||
_logger.Log(LogLevel.Info, $"Loading File: {pathName}");
|
||||
XPathDocument document = new XPathDocument(pathName);
|
||||
XPathNavigator navigator = document.CreateNavigator();
|
||||
|
||||
// Verify this is a COE XML ICD
|
||||
nodeset = navigator.Select("/interface");
|
||||
if (nodeset.Count == 0)
|
||||
{
|
||||
// This is not an XML ICD
|
||||
throw new Exception($"Invalid COE XML Format. Unable to process {pathName}" +
|
||||
"\nEnsure this is a properly formatted ICD.");
|
||||
}
|
||||
|
||||
nodeset = navigator.Select("/interface/include/file");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
directory = DirectoryOf(pathName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
directory = ".\\";
|
||||
}
|
||||
|
||||
IncludePathname = nodeset.Current.Value.Trim();
|
||||
if ((!IncludePathname.StartsWith("\\")) && (!IncludePathname.Contains(":")))
|
||||
{
|
||||
while (IncludePathname.StartsWith("."))
|
||||
{
|
||||
if ((IncludePathname.StartsWith("..\\")) || (IncludePathname.StartsWith("../")))
|
||||
{
|
||||
directory = DirectoryOf(directory);
|
||||
IncludePathname = IncludePathname.Remove(0, 3);
|
||||
}
|
||||
else if ((IncludePathname.StartsWith(".\\")) || (IncludePathname.StartsWith("./")))
|
||||
{
|
||||
IncludePathname = IncludePathname.Remove(0, 2);
|
||||
}
|
||||
}
|
||||
IncludePathname = string.Concat(directory, "\\", IncludePathname);
|
||||
}
|
||||
RecurseProcessing(IncludePathname);
|
||||
}
|
||||
|
||||
nodeset = navigator.Select("/interface/packing|/interface/typedef|/interface/constant|interface/enum|/interface/structure|/interface/message");
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
string item = nodeset.Current.OuterXml;
|
||||
int index;
|
||||
while ((index = item.IndexOf("<description>")) != -1)
|
||||
{
|
||||
item = item.Remove(index, item.IndexOf("</description>") + 14 - index);
|
||||
}
|
||||
while ((index = item.IndexOf("<!--")) != -1)
|
||||
{
|
||||
item = item.Remove(index, item.IndexOf("-->") + 3 - index);
|
||||
}
|
||||
while (item.IndexOf("> ") != -1)
|
||||
{
|
||||
item = item.Replace("> ", ">");
|
||||
}
|
||||
while (item.IndexOf(" <") != -1)
|
||||
{
|
||||
item = item.Replace(" <", "<");
|
||||
}
|
||||
//_logger.Log(LogLevel.Trace, $"Loading Node :\n{item}");
|
||||
Thread.Sleep(1);
|
||||
BuiltXML = string.Concat(BuiltXML, item);
|
||||
}
|
||||
}
|
||||
|
||||
private string DirectoryOf(string Pathname)
|
||||
{
|
||||
return Pathname.Remove(Pathname.LastIndexOf("\\"));
|
||||
}
|
||||
|
||||
//
|
||||
// From the XML document, the definition of a single message can be identified
|
||||
// from the Message Name and returned as an XML string.
|
||||
//
|
||||
public string XmlFileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _XmlFileName;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetMessage(string messageName)
|
||||
{
|
||||
string message;
|
||||
|
||||
messageName = messageName.Trim();
|
||||
_logger.Log(LogLevel.Info, $"Searching for message : {messageName}");
|
||||
try
|
||||
{
|
||||
message = SelectSingleNode($"/interface/message[name='{messageName}']").OuterXml;
|
||||
message = TranslateValue(message);
|
||||
_logger.Log(LogLevel.Trace, $"Found by name: {message}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
message = null;
|
||||
_logger.Log(LogLevel.Error, "Message not found");
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
//
|
||||
// From the XML document, the definition of a single message can be identified
|
||||
// from the Message Label and returned as an XML string.
|
||||
//
|
||||
public string GetMessageFromLabel(string messageLabel)
|
||||
{
|
||||
string message;
|
||||
string msgLabel = "";
|
||||
|
||||
if (Parse.Try(messageLabel, out int label) == true)
|
||||
{
|
||||
msgLabel = label.ToString();
|
||||
}
|
||||
|
||||
_logger.Log(LogLevel.Info, $"Searching for message: {msgLabel}");
|
||||
try
|
||||
{
|
||||
// Search by message label
|
||||
message = SelectSingleNode($"/interface/message[label='{msgLabel}']").OuterXml;
|
||||
message = TranslateValue(message);
|
||||
_logger.Log(LogLevel.Trace, $"Found by label: {message}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
// Search by instruLabel
|
||||
message = SelectSingleNode($"/interface/message[instruLabel='{messageLabel}']").OuterXml;
|
||||
message = TranslateValue(message);
|
||||
_logger.Log(LogLevel.Trace, $"Found by instrument Label: {message}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
message = null;
|
||||
_logger.Log(LogLevel.Error, "Message not found");
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
//
|
||||
// From the XML document, the definition of a single message can be identified
|
||||
// from the Message InstruLabel and returned as an XML string.
|
||||
//
|
||||
public string GetMessageFromInstruLabel(string messageInstruLabel)
|
||||
{
|
||||
string message;
|
||||
|
||||
messageInstruLabel = messageInstruLabel.Trim();
|
||||
_logger.Log(LogLevel.Info, $"Searching for message: {messageInstruLabel}");
|
||||
try
|
||||
{
|
||||
message = SelectSingleNode($"/interface/message[instruLabel='{messageInstruLabel}']").OuterXml;
|
||||
message = TranslateValue(message);
|
||||
_logger.Log(LogLevel.Trace, $"Found by instrument label: {message}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
message = null;
|
||||
_logger.Log(LogLevel.Error, "Message not found");
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public uint GetLargestMessageSize()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// return the max message size if we have already calculated it
|
||||
if (m_MaxMsgSize != 0)
|
||||
{
|
||||
return m_MaxMsgSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
DateTime t1 = DateTime.Now;
|
||||
|
||||
XPathNavigator navigator = CreateNavigator();
|
||||
XPathNodeIterator nodeset = navigator.Select("/interface/message/name");
|
||||
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
Message msg = new Message(nodeset.Current.Value.Trim(), this);
|
||||
uint msgSize = msg.GetMessageSize();
|
||||
if (msgSize > m_MaxMsgSize)
|
||||
{
|
||||
m_MaxMsgSize = msgSize;
|
||||
}
|
||||
}
|
||||
|
||||
DateTime t2 = DateTime.Now;
|
||||
TimeSpan duration = t2 - t1;
|
||||
Debug.WriteLine("Max Msg Size Algorithm Time = " + duration);
|
||||
}
|
||||
}
|
||||
|
||||
return m_MaxMsgSize;
|
||||
}
|
||||
|
||||
public uint GetMessageSize(string MsgName)
|
||||
{
|
||||
uint msg_size = 0;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
XPathNavigator navigator = CreateNavigator();
|
||||
XPathNodeIterator nodeset = navigator.Select("/interface/message/name");
|
||||
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
if (MsgName == nodeset.Current.Value.Trim())
|
||||
{
|
||||
Message msg = new Message(nodeset.Current.Value.Trim(), this);
|
||||
msg_size = msg.GetMessageSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return msg_size;
|
||||
}
|
||||
|
||||
//
|
||||
// Since the XML message definitions contain the definitions of all the enumerations and constants,
|
||||
// this object is the only one containing the knowledge to interpret strings using enumerations and/or
|
||||
// constants. This method will substitute enumerations and constants with their respective base values
|
||||
// in a specified string.
|
||||
//
|
||||
public string TranslateValue(string Value)
|
||||
{
|
||||
XPathNavigator navigator = CreateNavigator();
|
||||
XPathNavigator position;
|
||||
string NewValue = Value;
|
||||
|
||||
//
|
||||
// Substitute enumeration
|
||||
//
|
||||
try
|
||||
{
|
||||
position = navigator.SelectSingleNode("/interface/enum/item[name='" + NewValue + "']");
|
||||
if (position == null)
|
||||
{
|
||||
position = navigator.SelectSingleNode("/interface/enum/item[item_name='" + NewValue + "']");
|
||||
}
|
||||
if (position != null)
|
||||
{
|
||||
position.MoveToChild("value", "");
|
||||
NewValue = position.Value;
|
||||
}
|
||||
|
||||
//
|
||||
// Substitute constants
|
||||
//
|
||||
position = navigator.SelectSingleNode("/interface/constant[name='" + NewValue + "']");
|
||||
if (position != null)
|
||||
{
|
||||
NewValue = position.Value;
|
||||
_logger.Log(LogLevel.Info, "Translating field value : " + Value + " -> " + NewValue);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e.Message);
|
||||
}
|
||||
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,309 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// coeEndpoint.cs
|
||||
// 6/1/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)
|
||||
// **********************************************************************************************************
|
||||
|
||||
//\\<Unclassified>
|
||||
//----------------------------------------------------------------------------//
|
||||
// UNCLASSIFIED //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\Unclassified>
|
||||
|
||||
//\\<UnlimitedRights>
|
||||
//----------------------------------------------------------------------------//
|
||||
// Copyright %(copyright)s Raytheon Company. //
|
||||
// This software was developed pursuant to Contract Number %(contractNumber)s //
|
||||
// with the U.S. government. The U.S. government's rights in and to this //
|
||||
// copyrighted software are as specified in DFARS 252.227-7014 which was made //
|
||||
// part of the above contract. //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\UnlimitedRights>
|
||||
|
||||
//\\<EximUndetermined>
|
||||
//----------------------------------------------------------------------------//
|
||||
// WARNING - This document contains technical data and / or technology whose //
|
||||
// export or disclosure to Non-U.S. Persons, wherever located, is restricted //
|
||||
// by the International Traffic in Arms Regulations (ITAR) (22 C.F.R. //
|
||||
// Section 120-130) or the Export Administration Regulations (EAR) (15 C.F.R. //
|
||||
// Section 730-774). This document CANNOT be exported (e.g., provided to a //
|
||||
// supplier outside of the United States) or disclosed to a Non-U.S. Person, //
|
||||
// wherever located, until a final jurisdiction and classification //
|
||||
// determination has been completed and approved by Raytheon, and any //
|
||||
// required U.S. Government approvals have been obtained. Violations are //
|
||||
// subject to severe criminal penalties. //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\EximUndetermined>
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
{
|
||||
//
|
||||
//
|
||||
//
|
||||
// Endpoint
|
||||
//
|
||||
//
|
||||
//
|
||||
public class coeEndpoint : IDisposable
|
||||
{
|
||||
#region DLLImports
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Create_Dynamic_With_Domain")]
|
||||
private static extern IntPtr OE_Endpoint_Create_Dynamic_With_Domain(IntPtr Name,
|
||||
coe.ScopeType Scope,
|
||||
IntPtr Router,
|
||||
uint Domain,
|
||||
uint MaximumTransmitMessages,
|
||||
uint MaximumReceiveMessages,
|
||||
uint MaximumTransmitMessageSize,
|
||||
uint MaximumReceiveMessageSize,
|
||||
IntPtr ApplicationContext,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Delete")]
|
||||
private static extern coe.Status OE_Endpoint_Delete(IntPtr _obj);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Associate")]
|
||||
private static extern coe.Status OE_Endpoint_Associate(IntPtr _obj,
|
||||
IntPtr Event,
|
||||
TriggerType Trigger);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Send_Labeled")]
|
||||
private static extern coe.Status OE_Endpoint_Send_Labeled(IntPtr _obj,
|
||||
IntPtr Message,
|
||||
uint Options,
|
||||
uint Handling_Policy);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Peek")]
|
||||
private static extern coe.Status OE_Endpoint_Peek(IntPtr _obj,
|
||||
out uint Message_Label,
|
||||
out uint Message_Size,
|
||||
out int Message_Priority);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Wait")]
|
||||
private static extern coe.Status OE_Endpoint_Wait(IntPtr _obj,
|
||||
int Timeout);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Receive")]
|
||||
private static extern coe.Status OE_Endpoint_Receive(IntPtr _obj,
|
||||
ref IntPtr Message,
|
||||
uint Handling_Policy,
|
||||
int Timeout,
|
||||
IntPtr Source);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Register_Ex2")]
|
||||
private static extern coe.Status OE_Endpoint_Register_Ex2(IntPtr _obj,
|
||||
uint Label,
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
coe.CallBackDelegate callbackD);
|
||||
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Deregister")]
|
||||
private static extern coe.Status OE_Endpoint_Deregister(IntPtr _obj,
|
||||
uint Label);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Endpoint_Empty")]
|
||||
private static extern coe.Status OE_Endpoint_Empty(IntPtr _obj);
|
||||
|
||||
#endregion
|
||||
|
||||
public enum TriggerType : int
|
||||
{
|
||||
DATA_RECEIVED = 0,
|
||||
BUFFER_EMPTY = 1,
|
||||
DATA_DISCARDED = 2
|
||||
};
|
||||
|
||||
private bool _disposed;
|
||||
private IntPtr _handle;
|
||||
private readonly coeEvent[] _events;
|
||||
private const int MaximumNumberOfEvents = 4;
|
||||
private int _numberOfEvents;
|
||||
|
||||
// Constant to be used for a non-queued endpoint
|
||||
public const uint NON_QUEUED_SIZE = 0;
|
||||
|
||||
public coeEndpoint(uint maxMessageSize, IntPtr router = default) : this(0, maxMessageSize, 0, router) { }
|
||||
public coeEndpoint(uint maxMessageSize, uint maxBufferMessages, IntPtr router = default)
|
||||
: this(0, maxMessageSize, maxBufferMessages, router) { }
|
||||
public coeEndpoint(uint domain, uint maxMessageSize, uint maxBufferMessages, IntPtr router = default)
|
||||
{
|
||||
_handle = OE_Endpoint_Create_Dynamic_With_Domain(IntPtr.Zero, coe.ScopeType.OE_Local, router, domain,
|
||||
maxBufferMessages, maxBufferMessages, maxMessageSize, maxMessageSize, IntPtr.Zero, out coe.Status oe_status);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
_handle = IntPtr.Zero;
|
||||
throw new Exception("Unable to create OE_Endpoint. Error = " + oe_status);
|
||||
}
|
||||
else
|
||||
{
|
||||
_numberOfEvents = 0;
|
||||
_events = new coeEvent[MaximumNumberOfEvents];
|
||||
}
|
||||
}
|
||||
|
||||
~coeEndpoint()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
if (_handle != IntPtr.Zero)
|
||||
{
|
||||
for (int index = 0; index < _numberOfEvents; index++)
|
||||
{
|
||||
_events[index].Disable();
|
||||
}
|
||||
OE_Endpoint_Delete(_handle);
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public IntPtr Handle
|
||||
{
|
||||
get { return _handle; }
|
||||
}
|
||||
|
||||
public coe.Status Register(uint label)
|
||||
{
|
||||
coe.Status status = OE_Endpoint_Register_Ex2(_handle, label, null);
|
||||
return status;
|
||||
}
|
||||
|
||||
public coe.Status Register(uint label, coeDataInterchange.FormatPacketType packet)
|
||||
{
|
||||
|
||||
coe._dataInterchangePackets.Add(label, packet);
|
||||
coe.Status status = OE_Endpoint_Register_Ex2(_handle, label, coe._dataInterchangePackets._delegate);
|
||||
return status;
|
||||
}
|
||||
|
||||
public coe.Status Deregister(uint label)
|
||||
{
|
||||
coe.Status status = OE_Endpoint_Deregister(_handle, label);
|
||||
return status;
|
||||
}
|
||||
|
||||
public coe.Status Send(coeMessage message)
|
||||
{
|
||||
return Send(message, 0);
|
||||
}
|
||||
|
||||
public coe.Status Send(coeMessage message, uint options)
|
||||
{
|
||||
message.Serialize();
|
||||
return OE_Endpoint_Send_Labeled(_handle, message.Handle, options, 0);
|
||||
}
|
||||
|
||||
public coe.Status Peek(out uint message_Label,
|
||||
out uint message_Size,
|
||||
out int message_Priority)
|
||||
{
|
||||
coe.Status status;
|
||||
status = OE_Endpoint_Peek(_handle, out uint messageLabel, out uint messageSize, out int messagePriority);
|
||||
message_Label = messageLabel;
|
||||
message_Size = messageSize;
|
||||
message_Priority = messagePriority;
|
||||
return status;
|
||||
}
|
||||
|
||||
public coe.Status Wait(int timeout)
|
||||
{
|
||||
return OE_Endpoint_Wait(_handle, timeout);
|
||||
}
|
||||
|
||||
public coe.Status Clear()
|
||||
{
|
||||
return OE_Endpoint_Empty(_handle);
|
||||
}
|
||||
|
||||
public coe.Status Receive(coeMessage message, int timeout)
|
||||
{
|
||||
coe.Status Status;
|
||||
IntPtr coeMessageHandle = message != null ? message.Handle : IntPtr.Zero;
|
||||
Status = OE_Endpoint_Receive(_handle, ref coeMessageHandle, 0, timeout, IntPtr.Zero);
|
||||
if (Status == coe.Status.SUCCESS)
|
||||
{
|
||||
message.Deserialize();
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
public coe.Status Receive(coeMessage message)
|
||||
{
|
||||
return Receive(message, coe.OE_Wait_Forever);
|
||||
}
|
||||
|
||||
public coe.Status Associate(coeEventFlag eventFlag, uint mask, TriggerType trigger)
|
||||
{
|
||||
coe.Status status;
|
||||
|
||||
if (_numberOfEvents >= MaximumNumberOfEvents)
|
||||
{
|
||||
status = coe.Status.FAILED_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
_events[_numberOfEvents] = new coeEvent();
|
||||
_events[_numberOfEvents].SetNotification(eventFlag, mask);
|
||||
status = OE_Endpoint_Associate(_handle, _events[_numberOfEvents].Handle, trigger);
|
||||
if (status == coe.Status.SUCCESS)
|
||||
{
|
||||
status = _events[_numberOfEvents].Enable();
|
||||
_numberOfEvents++;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//\\<Unclassified>
|
||||
//----------------------------------------------------------------------------//
|
||||
// UNCLASSIFIED //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\Unclassified>
|
||||
|
||||
@@ -1,392 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// coeMessage.cs
|
||||
// 6/1/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)
|
||||
// **********************************************************************************************************
|
||||
|
||||
//\\<Unclassified>
|
||||
//----------------------------------------------------------------------------//
|
||||
// UNCLASSIFIED //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\Unclassified>
|
||||
|
||||
//\\<UnlimitedRights>
|
||||
//----------------------------------------------------------------------------//
|
||||
// Copyright %(copyright)s Raytheon Company. //
|
||||
// This software was developed pursuant to Contract Number %(contractNumber)s //
|
||||
// with the U.S. government. The U.S. government's rights in and to this //
|
||||
// copyrighted software are as specified in DFARS 252.227-7014 which was made //
|
||||
// part of the above contract. //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\UnlimitedRights>
|
||||
|
||||
//\\<EximUndetermined>
|
||||
//----------------------------------------------------------------------------//
|
||||
// WARNING - This document contains technical data and / or technology whose //
|
||||
// export or disclosure to Non-U.S. Persons, wherever located, is restricted //
|
||||
// by the International Traffic in Arms Regulations (ITAR) (22 C.F.R. //
|
||||
// Section 120-130) or the Export Administration Regulations (EAR) (15 C.F.R. //
|
||||
// Section 730-774). This document CANNOT be exported (e.g., provided to a //
|
||||
// supplier outside of the United States) or disclosed to a Non-U.S. Person, //
|
||||
// wherever located, until a final jurisdiction and classification //
|
||||
// determination has been completed and approved by Raytheon, and any //
|
||||
// required U.S. Government approvals have been obtained. Violations are //
|
||||
// subject to severe criminal penalties. //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\EximUndetermined>
|
||||
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments.coeCSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Message Attributes
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class MessageOffset : Attribute
|
||||
{
|
||||
readonly uint _bufferOffset;
|
||||
public MessageOffset(uint bufferOffset)
|
||||
{
|
||||
_bufferOffset = bufferOffset;
|
||||
}
|
||||
public uint Offset
|
||||
{
|
||||
get { return _bufferOffset; }
|
||||
}
|
||||
}
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class MessageSize : Attribute
|
||||
{
|
||||
readonly int _bufferSize;
|
||||
public MessageSize(int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
}
|
||||
public int Size
|
||||
{
|
||||
get { return _bufferSize; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Message: base class
|
||||
/// </summary>
|
||||
public abstract class coeMessage : IDisposable
|
||||
{
|
||||
#region DLLImports
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_Create")]
|
||||
private static extern IntPtr OE_Message_Create(IntPtr Buffer_Address,
|
||||
uint Size,
|
||||
int Create_Shared,
|
||||
IntPtr ApplicationContext,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_Delete")]
|
||||
private static extern coe.Status OE_Message_Delete(IntPtr Handle);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_set_Priority")]
|
||||
private static extern coe.Status OE_Message_set_Priority(IntPtr Handle,
|
||||
int Priority);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Priority")]
|
||||
private static extern int OE_Message_get_Priority(IntPtr Handle,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_set_Domain")]
|
||||
private static extern coe.Status OE_Message_set_Domain(IntPtr Handle,
|
||||
uint Domain);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Domain")]
|
||||
private static extern uint OE_Message_get_Domain(IntPtr Handle,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_set_Label")]
|
||||
private static extern coe.Status OE_Message_set_Label(IntPtr Handle,
|
||||
uint Label);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Label")]
|
||||
private static extern uint OE_Message_get_Label(IntPtr Handle,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_set_Data_Size")]
|
||||
private static extern coe.Status OE_Message_set_Data_Size(IntPtr Handle,
|
||||
uint Size);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Data_Size")]
|
||||
private static extern uint OE_Message_get_Data_Size(IntPtr Handle,
|
||||
out coe.Status Status);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Transmit_Timestamp")]
|
||||
private static extern coe.Status OE_Message_get_Transmit_Timestamp(IntPtr Handle,
|
||||
out ulong Seconds,
|
||||
out uint Fraction_Of_Second);
|
||||
|
||||
[DllImport(coe.coeDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OE_Message_get_Receive_Timestamp")]
|
||||
private static extern coe.Status OE_Message_get_Receive_Timestamp(IntPtr Handle,
|
||||
out ulong Seconds,
|
||||
out uint Fraction_Of_Second);
|
||||
#endregion
|
||||
|
||||
private bool disposed = false;
|
||||
protected IntPtr m_Handle = IntPtr.Zero;
|
||||
protected IntPtr m_UnmanagedBuffer = IntPtr.Zero;
|
||||
protected int m_UnmanagedBufferSize = 0;
|
||||
protected int m_Size;
|
||||
protected byte[] m_Buffer;
|
||||
|
||||
//
|
||||
// The following routines are provided for testing and access purposes
|
||||
//
|
||||
public IntPtr GetUnmanagedBuffer() { return m_UnmanagedBuffer; }
|
||||
public byte[] GetManagedBuffer() { return m_Buffer; }
|
||||
|
||||
protected coeMessage(int size) : this(size, 0) { }
|
||||
protected coeMessage(int size, uint label) : this(size, label, 0) { }
|
||||
protected coeMessage(int size, uint label, int priority)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
size = getPayloadSize();
|
||||
}
|
||||
if (size > 0)
|
||||
{
|
||||
m_Buffer = new byte[size];
|
||||
m_UnmanagedBuffer = Marshal.AllocHGlobal((int)size);
|
||||
m_UnmanagedBufferSize = (int)size;
|
||||
}
|
||||
m_Handle = OE_Message_Create(m_UnmanagedBuffer, (uint)size, coe.OE_FALSE, IntPtr.Zero, out coe.Status oe_status);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
m_Handle = IntPtr.Zero;
|
||||
throw new Exception("Unable to create OE_Message. Error = " + oe_status);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Size = size;
|
||||
// The message was created successfully
|
||||
oe_status = OE_Message_set_Priority(m_Handle, priority);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
throw new Exception("Unable to set message priority to " + priority + ". Error = " + oe_status);
|
||||
}
|
||||
|
||||
oe_status = OE_Message_set_Label(m_Handle, label);
|
||||
if (oe_status != coe.Status.SUCCESS)
|
||||
{
|
||||
throw new Exception("Unable to set message priority to " + label + ". Error = " + oe_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~coeMessage()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed) return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
if (m_UnmanagedBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(m_UnmanagedBuffer);
|
||||
m_UnmanagedBuffer = IntPtr.Zero;
|
||||
}
|
||||
if (m_Handle != IntPtr.Zero)
|
||||
{
|
||||
OE_Message_Delete(m_Handle);
|
||||
m_Handle = IntPtr.Zero;
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
internal IntPtr Handle
|
||||
{
|
||||
get { return m_Handle; }
|
||||
}
|
||||
|
||||
public uint Domain
|
||||
{
|
||||
get
|
||||
{
|
||||
return OE_Message_get_Domain(m_Handle, out coe.Status status);
|
||||
}
|
||||
set
|
||||
{
|
||||
coe.Status status = OE_Message_set_Domain(m_Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public uint Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return OE_Message_get_Label(m_Handle, out coe.Status status);
|
||||
}
|
||||
set
|
||||
{
|
||||
coe.Status status = OE_Message_set_Label(m_Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get
|
||||
{
|
||||
return OE_Message_get_Priority(m_Handle, out coe.Status status);
|
||||
}
|
||||
set
|
||||
{
|
||||
coe.Status status = OE_Message_set_Priority(m_Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public uint Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return OE_Message_get_Data_Size(m_Handle, out coe.Status status);
|
||||
}
|
||||
set
|
||||
{
|
||||
coe.Status status = OE_Message_set_Data_Size(m_Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int BufferSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_UnmanagedBufferSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > m_UnmanagedBufferSize)
|
||||
{
|
||||
uint savedDomain = Domain;
|
||||
uint savedLabel = Label;
|
||||
int savedPriority = Priority;
|
||||
uint savedSize = Size;
|
||||
|
||||
if (m_UnmanagedBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(m_UnmanagedBuffer);
|
||||
m_UnmanagedBuffer = IntPtr.Zero;
|
||||
}
|
||||
if (m_Handle != IntPtr.Zero)
|
||||
{
|
||||
OE_Message_Delete(m_Handle);
|
||||
m_Handle = IntPtr.Zero;
|
||||
}
|
||||
m_Buffer = new byte[value];
|
||||
m_UnmanagedBuffer = Marshal.AllocHGlobal((int)value);
|
||||
m_UnmanagedBufferSize = (int)value;
|
||||
m_Handle = OE_Message_Create(m_UnmanagedBuffer, (uint)value, coe.OE_FALSE, IntPtr.Zero, out coe.Status oe_status);
|
||||
m_Size = value;
|
||||
|
||||
Domain = savedDomain;
|
||||
Label = savedLabel;
|
||||
Priority = savedPriority;
|
||||
Size = savedSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSendTime(out ulong Seconds, out uint FractionOfSecond)
|
||||
{
|
||||
var status = OE_Message_get_Transmit_Timestamp(m_Handle, out ulong seconds, out uint fractionOfSecond);
|
||||
Seconds = seconds;
|
||||
FractionOfSecond = fractionOfSecond;
|
||||
}
|
||||
|
||||
public void GetReceiveTime(out ulong Seconds, out uint FractionOfSecond)
|
||||
{
|
||||
var status = OE_Message_get_Receive_Timestamp(m_Handle, out ulong seconds, out uint fractionOfSecond);
|
||||
Seconds = seconds;
|
||||
FractionOfSecond = fractionOfSecond;
|
||||
}
|
||||
|
||||
abstract public void Serialize();
|
||||
abstract public void Deserialize();
|
||||
|
||||
// Serialization/Deserialization support
|
||||
private void alignIndex(ref int dataBufferIndex,
|
||||
int alignment)
|
||||
{
|
||||
int indexMisalignment = dataBufferIndex % alignment;
|
||||
if (indexMisalignment > 0)
|
||||
{
|
||||
dataBufferIndex += alignment - indexMisalignment;
|
||||
}
|
||||
}
|
||||
|
||||
public int getPayloadSize()
|
||||
{
|
||||
int size = 0;
|
||||
return serializationSupport.getPayloadSize(this, GetType(), ref size);
|
||||
}
|
||||
|
||||
|
||||
protected void copyToMessageBuffer(byte[] data)
|
||||
{
|
||||
Marshal.Copy(data, 0, m_UnmanagedBuffer, data.Length);
|
||||
}
|
||||
|
||||
protected byte[] copyFromMessageBuffer()
|
||||
{
|
||||
byte[] data = null;
|
||||
uint dataSize = OE_Message_get_Data_Size(m_Handle, out coe.Status status);
|
||||
if (dataSize > 0)
|
||||
{
|
||||
Marshal.Copy(m_UnmanagedBuffer, m_Buffer, 0, (int)dataSize);
|
||||
data = m_Buffer;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//\\<Unclassified>
|
||||
//----------------------------------------------------------------------------//
|
||||
// UNCLASSIFIED //
|
||||
//----------------------------------------------------------------------------//
|
||||
//\\<\Unclassified>
|
||||
@@ -1,859 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// COECommDeviceInstrument.cs
|
||||
// 7/11/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 Raytheon.Instruments.MessagingUtilities;
|
||||
using System.Xml.XPath;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Raytheon.Common;
|
||||
using Raytheon.Instruments.coeCSharp;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
using NLog;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// This device supports different ways of communicating with other COE nodes
|
||||
/// TCP
|
||||
/// UDP
|
||||
/// Serial
|
||||
/// </summary>
|
||||
public enum DriverType
|
||||
{
|
||||
Undefined,
|
||||
TCP,
|
||||
UDP,
|
||||
Serial
|
||||
};
|
||||
|
||||
public class COECommDeviceInstrument : ICommDevice
|
||||
{
|
||||
/// <summary>
|
||||
/// Nlog Logger
|
||||
/// </summary>
|
||||
readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Cancellation token to stop reading incoming messages
|
||||
/// </summary>
|
||||
private CancellationTokenSource _cancellationTokenSource = null;
|
||||
|
||||
/// <summary>
|
||||
/// collection of the messages received
|
||||
/// </summary>
|
||||
private readonly Dictionary<Tuple<string, DateTime>, OeMessage> _messages;
|
||||
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// UDP, TCP, Serial or Undefined
|
||||
/// </summary>
|
||||
private DriverType _driverType;
|
||||
|
||||
/// <summary>
|
||||
/// dictionary of options when initializing COE endpoint and router
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, List<KeyValuePair<string, string>>> _options = new Dictionary<string, List<KeyValuePair<string, string>>>();
|
||||
|
||||
/// <summary>
|
||||
/// reference to the main wrapper class for Common Operating Environment
|
||||
/// </summary>
|
||||
private readonly coe _coe;
|
||||
|
||||
/// <summary>
|
||||
/// COE endpoint
|
||||
/// </summary>
|
||||
private coeEndpoint _endpoint;
|
||||
|
||||
/// <summary>
|
||||
/// used for initialization of the endpoint
|
||||
/// </summary>
|
||||
private uint _maxMessageSize;
|
||||
private uint _epQueueDepth;
|
||||
|
||||
/// <summary>
|
||||
/// collection of all labels with message names per every XML file
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, Dictionary<uint, string>> _icds = new Dictionary<string, Dictionary<uint, string>>();
|
||||
|
||||
/// <summary>
|
||||
/// timeout can be set for the reader in a separate call
|
||||
/// </summary>
|
||||
private uint _receiverTimeout;
|
||||
|
||||
/// <summary>
|
||||
/// Number of milliseconds to wake up and check the message when receiving
|
||||
/// </summary>
|
||||
private int _checkForMessageIntervalMs;
|
||||
|
||||
/// <summary>
|
||||
/// collection of response labels or messages that COE endpoint should be registered for
|
||||
/// </summary>
|
||||
private List<uint> _responseLabels = new List<uint>();
|
||||
|
||||
/// <summary>
|
||||
/// collection of message XML documents (processed XML files) used in COE communications
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, MessageXmlDocument> _xmlDocs = new Dictionary<string, MessageXmlDocument>();
|
||||
|
||||
/// <summary>
|
||||
/// instrument constructor
|
||||
/// </summary>
|
||||
public COECommDeviceInstrument(string name, IConfigurationManager configurationManager, DriverType driverType = DriverType.Undefined, ILogger logger = null)
|
||||
{
|
||||
Info = new InstrumentMetadata
|
||||
{
|
||||
ModelNumber = "COECommDevice"
|
||||
};
|
||||
|
||||
if(logger == null)
|
||||
logger = LogManager.GetCurrentClassLogger();
|
||||
_logger = logger;
|
||||
|
||||
Status = State.Uninitialized;
|
||||
DetailedStatus = "COE Uninitialized";
|
||||
|
||||
Name = name;
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
if (configurationManager == null)
|
||||
{
|
||||
_logger.Error($"Cannot create {Name} without a configuration manager");
|
||||
return;
|
||||
}
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
_messages = new Dictionary<Tuple<string, DateTime>, OeMessage>();
|
||||
|
||||
_driverType = driverType;
|
||||
|
||||
_coe = new coe();
|
||||
}
|
||||
|
||||
public string DetailedStatus { get; protected set; }
|
||||
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
|
||||
public InstrumentMetadata Info { get; set; }
|
||||
|
||||
public string Name { get; protected set; }
|
||||
|
||||
public SelfTestResult SelfTestResult => PerformSelfTest();
|
||||
|
||||
public State Status { get; set; }
|
||||
|
||||
public bool ClearErrors()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes COE instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
_logger.Trace($"{Name}({_driverType}) Initializing...");
|
||||
|
||||
if (_driverType == DriverType.Undefined)
|
||||
_driverType = _configuration.GetConfigurationValue<DriverType>("Parameters", "DriverType", "TCP");
|
||||
|
||||
_options.Clear();
|
||||
_options.Add("ROUTER_CONFIG", new List<KeyValuePair<string, string>>
|
||||
{
|
||||
{ new KeyValuePair<string, string>("NODE_ID", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "NODE_ID", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_STATE", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "DISPLAY_DEBUG_STATE", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_LABEL_MESSAGE", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "DISPLAY_DEBUG_LABEL_MESSAGE", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_BRIDGE_REGISTRATION", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "DISPLAY_DEBUG_BRIDGE_REGISTRATION", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_ROUTER_DATABASE", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "DISPLAY_DEBUG_ROUTER_DATABASE", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_SEND", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "DISPLAY_DEBUG_SEND", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_RECV", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "DISPLAY_DEBUG_RECV", "0")) },
|
||||
{ new KeyValuePair<string, string>("BUFFER_SIZE", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "BUFFER_SIZE", "256")) },
|
||||
{ new KeyValuePair<string, string>("ENABLE_REGISTRATION_MESSAGES", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "ENABLE_REGISTRATION_MESSAGES", "1")) },
|
||||
{ new KeyValuePair<string, string>("THREAD_STACK_SIZE", _configuration.GetConfigurationValue<string>("ROUTER_CONFIG", "THREAD_STACK_SIZE", "16384")) },
|
||||
});
|
||||
|
||||
_options.Add("ROUTER_PROTOCOL_CONFIG", new List<KeyValuePair<string, string>>
|
||||
{
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_SEND", _configuration.GetConfigurationValue<string>("ROUTER_PROTOCOL_CONFIG", "DISPLAY_DEBUG_SEND", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_RECV", _configuration.GetConfigurationValue<string>("ROUTER_PROTOCOL_CONFIG", "DISPLAY_DEBUG_RECV", "0")) },
|
||||
{ new KeyValuePair<string, string>("THREAD_STACK_SIZE", _configuration.GetConfigurationValue<string>("ROUTER_PROTOCOL_CONFIG", "THREAD_STACK_SIZE", "16384")) },
|
||||
});
|
||||
|
||||
var poolEntry = _configuration.GetConfigurationValue<string>("ROUTER_BUFFER_POOLS", "POOL_ENTRY", "100,32|50,128|100,384|150,1536|10,65535");
|
||||
if (!string.IsNullOrEmpty(poolEntry))
|
||||
{
|
||||
var poolEntries = poolEntry.Split('|');
|
||||
if (poolEntries.Any())
|
||||
{
|
||||
var entries = new List<KeyValuePair<string, string>>();
|
||||
foreach (var entry in poolEntries)
|
||||
{
|
||||
entries.Add(new KeyValuePair<string, string>("POOL_ENTRY", entry));
|
||||
}
|
||||
_options.Add("ROUTER_BUFFER_POOLS", entries);
|
||||
}
|
||||
}
|
||||
|
||||
_options.Add("BASIC_REGISTRATION_CONFIG", new List<KeyValuePair<string, string>>
|
||||
{
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_SEND", _configuration.GetConfigurationValue<string>("BASIC_REGISTRATION_CONFIG", "DISPLAY_DEBUG_SEND", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_SEND_BUFFER", _configuration.GetConfigurationValue<string>("BASIC_REGISTRATION_CONFIG", "DISPLAY_DEBUG_SEND_BUFFER", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_RECV", _configuration.GetConfigurationValue<string>("BASIC_REGISTRATION_CONFIG", "DISPLAY_DEBUG_RECV", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_RECV_BUFFER", _configuration.GetConfigurationValue<string>("BASIC_REGISTRATION_CONFIG", "DISPLAY_DEBUG_RECV_BUFFER", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_STATE", _configuration.GetConfigurationValue<string>("BASIC_REGISTRATION_CONFIG", "DISPLAY_DEBUG_STATE", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_PING_SEND", _configuration.GetConfigurationValue<string>("BASIC_REGISTRATION_CONFIG", "DISPLAY_DEBUG_PING_SEND", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_PING_RECV", _configuration.GetConfigurationValue<string>("BASIC_REGISTRATION_CONFIG", "DISPLAY_DEBUG_PING_RECV", "0")) },
|
||||
{ new KeyValuePair<string, string>("THREAD_STACK_SIZE", _configuration.GetConfigurationValue<string>("BASIC_REGISTRATION_CONFIG", "THREAD_STACK_SIZE", "16384")) },
|
||||
});
|
||||
|
||||
switch (_driverType)
|
||||
{
|
||||
case DriverType.UDP:
|
||||
_options.Add("UDP_MEDIA_BINDING_CONFIG", new List<KeyValuePair<string, string>>
|
||||
{
|
||||
{ new KeyValuePair<string, string>("LOCAL_IP_ADDRESS", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "LOCAL_IP_ADDRESS", "127.0.0.1")) },
|
||||
{ new KeyValuePair<string, string>("REMOTE_IP_ADDRESS", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "REMOTE_IP_ADDRESS", "127.0.0.1")) },
|
||||
{ new KeyValuePair<string, string>("LOCAL_SEND_PORT", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "LOCAL_SEND_PORT", "32010")) },
|
||||
{ new KeyValuePair<string, string>("LOCAL_RECV_PORT", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "LOCAL_RECV_PORT", "32020")) },
|
||||
{ new KeyValuePair<string, string>("REMOTE_SEND_PORT", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "REMOTE_SEND_PORT", "32011")) },
|
||||
{ new KeyValuePair<string, string>("REMOTE_RECV_PORT", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "REMOTE_RECV_PORT", "32021")) },
|
||||
{ new KeyValuePair<string, string>("RECV_TIMEOUT", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "RECV_TIMEOUT", "200")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_SEND", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_SEND", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_RECV", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_RECV", "0")) },
|
||||
{ new KeyValuePair<string, string>("MTU_SIZE", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "MTU_SIZE", "1472")) },
|
||||
{ new KeyValuePair<string, string>("THREAD_STACK_SIZE", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "THREAD_STACK_SIZE", "16384")) },
|
||||
{ new KeyValuePair<string, string>("THREAD_NAME", _configuration.GetConfigurationValue<string>("UDP_MEDIA_BINDING_CONFIG", "THREAD_NAME", "UDP_MB_RCV")) },
|
||||
});
|
||||
break;
|
||||
|
||||
case DriverType.TCP:
|
||||
_options.Add("TCP_MEDIA_BINDING_CONFIG", new List<KeyValuePair<string, string>>
|
||||
{
|
||||
{ new KeyValuePair<string, string>("LOCAL_PORT", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "LOCAL_PORT", "9990")) },
|
||||
{ new KeyValuePair<string, string>("NUM_PORTS", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "NUM_PORTS", "32")) },
|
||||
{ new KeyValuePair<string, string>("NUM_DYNAMIC_NODES", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "NUM_DYNAMIC_NODES", "32")) },
|
||||
{ new KeyValuePair<string, string>("SERVER_ADDRESS", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "SERVER_ADDRESS", "127.0.0.1:9990")) },
|
||||
{ new KeyValuePair<string, string>("UDP_TX_BUFFER_SIZE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "UDP_TX_BUFFER_SIZE", "5000")) },
|
||||
{ new KeyValuePair<string, string>("UDP_RX_BUFFER_SIZE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "UDP_RX_BUFFER_SIZE", "32768")) },
|
||||
{ new KeyValuePair<string, string>("TCP_TX_BUFFER_SIZE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "TCP_TX_BUFFER_SIZE", "5000")) },
|
||||
{ new KeyValuePair<string, string>("TCP_RX_BUFFER_SIZE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "TCP_RX_BUFFER_SIZE", "4096")) },
|
||||
{ new KeyValuePair<string, string>("PACKET_SIZE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "PACKET_SIZE", "5128")) },
|
||||
{ new KeyValuePair<string, string>("TCP_SELECT_VALUE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "TCP_SELECT_VALUE", "1")) },
|
||||
{ new KeyValuePair<string, string>("DISABLE_NAG_DELAY", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "DISABLE_NAG_DELAY", "1")) },
|
||||
{ new KeyValuePair<string, string>("TIMER_RATE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "TIMER_RATE", "1000")) },
|
||||
{ new KeyValuePair<string, string>("CONNECT_KA_RATE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "CONNECT_KA_RATE", "1")) },
|
||||
{ new KeyValuePair<string, string>("RECV_KA_RATE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "RECV_KA_RATE", "1")) },
|
||||
{ new KeyValuePair<string, string>("SERVER_CONNECT_RATE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "SERVER_CONNECT_RATE", "1")) },
|
||||
{ new KeyValuePair<string, string>("RECV_THREAD_STACK_SIZE", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "RECV_THREAD_STACK_SIZE", "4096")) },
|
||||
{ new KeyValuePair<string, string>("RECV_THREAD_PRIORITY", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "RECV_THREAD_PRIORITY", "0")) },
|
||||
{ new KeyValuePair<string, string>("RECV_THREAD_AFFINITY", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "RECV_THREAD_AFFINITY", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_SEND", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_SEND", "1")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_SEND_BUFFER", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_SEND_BUFFER", "1")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_UDP_RECV", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_UDP_RECV", "1")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_UDP_RECV_BUFFER", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_UDP_RECV_BUFFER", "1")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_TCP_RECV", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_TCP_RECV", "1")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_TCP_RECV_BUFFER", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_TCP_RECV_BUFFER", "1")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_RECV", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_RECV", "1")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_RECV_BUFFER", _configuration.GetConfigurationValue<string>("TCP_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_RECV_BUFFER", "1")) },
|
||||
});
|
||||
break;
|
||||
|
||||
case DriverType.Serial:
|
||||
_options.Add("SERIAL_MEDIA_BINDING_CONFIG", new List<KeyValuePair<string, string>>
|
||||
{
|
||||
{ new KeyValuePair<string, string>("DEVICE_NAME", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "DEVICE_NAME", "\\\\.\\COM1")) },
|
||||
{ new KeyValuePair<string, string>("BAUD_RATE", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "BAUD_RATE", "9600")) },
|
||||
{ new KeyValuePair<string, string>("DATA_BITS", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "DATA_BITS", "8")) },
|
||||
{ new KeyValuePair<string, string>("STOP_BITS", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "STOP_BITS", "1")) },
|
||||
{ new KeyValuePair<string, string>("PARITY", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "PARITY", "0")) },
|
||||
{ new KeyValuePair<string, string>("FLOW_CONTROL", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "FLOW_CONTROL", "0")) },
|
||||
{ new KeyValuePair<string, string>("MTU_SIZE", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "MTU_SIZE", "256")) },
|
||||
{ new KeyValuePair<string, string>("RECV_PROCESSING_DELAY", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "RECV_PROCESSING_DELAY", "100")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_SEND", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_SEND", "0")) },
|
||||
{ new KeyValuePair<string, string>("DISPLAY_DEBUG_RECV", _configuration.GetConfigurationValue<string>("SERIAL_MEDIA_BINDING_CONFIG", "DISPLAY_DEBUG_RECV", "0")) },
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
_logger.Error($"{Name}({_driverType}) Configured driver type not valid");
|
||||
break;
|
||||
}
|
||||
|
||||
_maxMessageSize = _configuration.GetConfigurationValue<uint>("Parameters", "MaxMessageSize", "5000");
|
||||
_epQueueDepth = _configuration.GetConfigurationValue<uint>("Parameters", "EPQueueDepth", "5000");
|
||||
_checkForMessageIntervalMs = _configuration.GetConfigurationValue<int>("Parameters", "CheckForMessageIntervalMs", "100");
|
||||
|
||||
var responseLabels = _configuration.GetConfigurationListValue("ResponseMessageIds", "ResponseLabel", new List<string> { "1", "2" });
|
||||
|
||||
var bitFilePaths = _configuration.GetConfigurationListValue("BitFilePaths", "FilePath", new List<string> { "File1", "File2" });
|
||||
|
||||
_xmlDocs.Clear();
|
||||
foreach (var path in bitFilePaths)
|
||||
{
|
||||
_xmlDocs.Add(path, new MessageXmlDocument(path, _logger));
|
||||
}
|
||||
|
||||
_icds.Clear();
|
||||
foreach (var path in bitFilePaths)
|
||||
{
|
||||
_icds.Add(path, ProcessFileForNamesAndLabels(path));
|
||||
}
|
||||
|
||||
foreach (var strLabel in responseLabels)
|
||||
{
|
||||
uint label = GetLabelFromMessageId(strLabel);
|
||||
if(label > 0)
|
||||
_responseLabels.Add(label);
|
||||
}
|
||||
|
||||
DetailedStatus = "COE Initialized";
|
||||
Status = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// performs self-test
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
_logger.Trace($"{Name}({_driverType}) Performing Self Test...");
|
||||
|
||||
// TODO implement method
|
||||
return SelfTestResult.Pass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets COE device comms
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void Reset()
|
||||
{
|
||||
_logger.Trace($"{Name}({_driverType}) Resetting...");
|
||||
|
||||
Close();
|
||||
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down COE device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
_logger.Trace($"{Name}({_driverType}) Shutting Down...");
|
||||
|
||||
try
|
||||
{
|
||||
Close();
|
||||
|
||||
//coe.UnloadImportedDll("coeWindows-shared.dll");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"{Name}({_driverType}) Error while closing");
|
||||
}
|
||||
}
|
||||
|
||||
#region ICommDevice functions
|
||||
/// <summary>
|
||||
/// Opens COE connection
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void Open()
|
||||
{
|
||||
_logger.Trace($"{Name}({_driverType}) Opening...");
|
||||
|
||||
try
|
||||
{
|
||||
switch (_driverType)
|
||||
{
|
||||
case DriverType.TCP:
|
||||
|
||||
if (_coe.tcp_media_binding_configure(_options, _logger) != coe.Status.SUCCESS)
|
||||
{
|
||||
_logger.Error($"{Name}({_driverType}) COE TCP media binding initialization failure.\nTry checking your connection configuration.\nYou could have a port collision.");
|
||||
Status = State.CommunicationFailure;
|
||||
throw new Exception($"{Name}({_driverType}) COE TCP media binding initialization failure");
|
||||
}
|
||||
_logger.Trace($"{Name}({_driverType}) COE TCP media binding initialization, {_coe.ProtocolCmitName}");
|
||||
break;
|
||||
case DriverType.UDP:
|
||||
if (_coe.udp_media_binding_configure(_options, _logger) != coe.Status.SUCCESS)
|
||||
{
|
||||
_logger.Error($"{Name}({_driverType}) COE UDP media binding initialization failure.\nTry checking your connection configuration.\nYou could have a port collision.");
|
||||
Status = State.CommunicationFailure;
|
||||
throw new Exception($"{Name}({_driverType}) COE UDP media binding initialization failure");
|
||||
}
|
||||
_logger.Trace($"{Name}({_driverType}) COE UDP media binding initialization, Local: {_coe.ProtocolCmitName} Remote: {_coe.ProtocolName}");
|
||||
break;
|
||||
case DriverType.Serial:
|
||||
if (_coe.serial_media_binding_configure(_options, _logger) != coe.Status.SUCCESS)
|
||||
{
|
||||
_logger.Error($"{Name}({_driverType}) COE Serial media binding initialization failure.\nTry checking your connection configuration.\nYou could have a port collision.");
|
||||
Status = State.CommunicationFailure;
|
||||
throw new Exception($"{Name}({_driverType}) COE Serial media binding initialization failure");
|
||||
}
|
||||
_logger.Trace($"{Name}({_driverType}) COE Serial media binding initialization, {_coe.ProtocolCmitName}");
|
||||
break;
|
||||
default:
|
||||
_logger.Error($"{Name}({_driverType}) Configured driver type not valid");
|
||||
throw new Exception($"{Name}({_driverType}) Configured driver type not valid");
|
||||
}
|
||||
|
||||
foreach (var item in _options)
|
||||
{
|
||||
_logger.Trace($"{item.Key}:");
|
||||
foreach (var pair in item.Value)
|
||||
{
|
||||
_logger.Trace(string.Format("{0,-50} {1, -40}", pair.Key, pair.Value));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex);
|
||||
Status = State.CommunicationFailure;
|
||||
DetailedStatus = "Unable to Open";
|
||||
throw;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_coe.SetConnected(true);
|
||||
|
||||
//_endpoint = new coeEndpoint(_maxMessageSize, _epQueueDepth, coe.Router);
|
||||
_endpoint = new coeEndpoint(_maxMessageSize, _epQueueDepth);
|
||||
|
||||
_logger.Info($"{Name}({_driverType}) Endpoint Created, Max Message Size: {_maxMessageSize}, Queue Depth: {_epQueueDepth}");
|
||||
|
||||
foreach (var item in _responseLabels)
|
||||
{
|
||||
var fileName = WhichFileContainsTheLabel(item);
|
||||
if (!string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
var msgName = _icds[fileName][item];
|
||||
if (!string.IsNullOrEmpty(msgName))
|
||||
{
|
||||
_endpoint.Register(item);
|
||||
_logger.Debug($"{Name}({_driverType}) Registering new message with the endpoint, {item}: {msgName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn($"{Name}({_driverType}) Message with label {item} is not located in file {fileName}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn($"{Name}({_driverType}) Unable to locate label {item} in any of the XML files registered for COE device");
|
||||
}
|
||||
}
|
||||
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
Task.Run(() => ReadMessages(_cancellationTokenSource.Token));
|
||||
|
||||
DetailedStatus = "Opened";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Status = State.CommunicationFailure;
|
||||
DetailedStatus = "Unable to Open";
|
||||
_logger.Error(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close COE endpoint
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void Close()
|
||||
{
|
||||
_logger.Trace($"{Name}({_driverType}) Closing ...");
|
||||
|
||||
_cancellationTokenSource?.Cancel();
|
||||
|
||||
Thread.Sleep(1000);
|
||||
|
||||
lock (this)
|
||||
{
|
||||
_messages.Clear();
|
||||
}
|
||||
|
||||
_coe.SetConnected(false);
|
||||
var status = _driverType == DriverType.TCP ?
|
||||
_coe.TCP_media_binding_shutdown(_logger) : _driverType == DriverType.UDP ?
|
||||
_coe.UDP_media_binding_shutdown(_logger) : _coe.SERIAL_media_binding_shutdown(_logger);
|
||||
|
||||
if (status != coe.Status.SUCCESS)
|
||||
{
|
||||
_logger.Error($"{_driverType} media binding shutdown failure, status {status}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug($"{_driverType} shutdown was successful");
|
||||
}
|
||||
|
||||
_endpoint?.Dispose();
|
||||
|
||||
_cancellationTokenSource?.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
|
||||
Status = State.Uninitialized;
|
||||
DetailedStatus = "COE Closed";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sets the timeout value for COE reading operation
|
||||
/// </summary>
|
||||
/// <param name="timeout"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void SetReadTimeout(uint timeout)
|
||||
{
|
||||
_logger.Trace($"{Name}({_driverType}) Setting read timeout {timeout} ms ...");
|
||||
|
||||
_receiverTimeout = timeout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// reads COE message either based on the label or just top message
|
||||
/// </summary>
|
||||
/// <param name="dataRead">
|
||||
/// might contain a COE label
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
_logger.Trace($"{Name}({_driverType}) Reading ...");
|
||||
|
||||
if (!_coe.IsConnected)
|
||||
{
|
||||
_logger.Error("Error reading COE message, COE not connected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if the label was provided in the byte array use it to locate the first message with that name
|
||||
// else just fetch the top message
|
||||
var label = FromByteArrayToXml(dataRead);
|
||||
KeyValuePair<Tuple<string, DateTime>, OeMessage> message;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
message = string.IsNullOrEmpty(label) ? _messages.FirstOrDefault() : _messages.FirstOrDefault(m => m.Key.Item1 == label);
|
||||
}
|
||||
|
||||
if (message.Value != null)
|
||||
{
|
||||
// make a copy of the buffer
|
||||
var buffer = message.Value.GetManagedBuffer();
|
||||
if(buffer != null)
|
||||
{
|
||||
Array.Copy(buffer, 0, dataRead, 0, buffer.Length);
|
||||
|
||||
lock (this)
|
||||
{
|
||||
if (!_messages.Remove(message.Key))
|
||||
_logger.Warn($"{Name}({_driverType}) Unable to remove a message from the dictionary, label = {message.Key}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error($"{Name}({_driverType}) Found a message with label {label}, but the Buffer is empty");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error(string.IsNullOrEmpty(label) ? $"{Name}({_driverType}) No messages available to read at this time" : $"{Name}({_driverType}) Unable to find message with label {label}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (uint)dataRead.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keep reading messages and stash them in _messages dictionary with label and timestamp as a key
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
private void ReadMessages(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Debug($"{Name}({_driverType}) Starting to read messages.");
|
||||
|
||||
try
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
_logger.Debug($"{Name}({_driverType}) Checking for messages...");
|
||||
var status = _endpoint.Wait(1000);
|
||||
|
||||
if (status == coe.Status.SUCCESS)
|
||||
{
|
||||
_logger.Debug($"{Name}({_driverType}) Message Received...");
|
||||
|
||||
while (_endpoint.Peek(out uint label, out uint size, out int priority) == coe.Status.SUCCESS)
|
||||
{
|
||||
_logger.Debug($"{Name}({_driverType}) Identified message by peeking...");
|
||||
|
||||
var xmlDoc = WhichFileContainsTheLabel(label);
|
||||
|
||||
var message = new OeMessage((int)size + 1)
|
||||
{
|
||||
XmlMessage = new Message(_xmlDocs[xmlDoc], label.ToString())
|
||||
};
|
||||
|
||||
status = _endpoint.Receive(message);
|
||||
|
||||
if (status == coe.Status.SUCCESS)
|
||||
{
|
||||
_logger.Debug($"{Name}({_driverType}) Successfully read message...");
|
||||
lock (this)
|
||||
{
|
||||
_messages.Add(new Tuple<string, DateTime>(message.Label, DateTime.Now), message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error($"{Name}({_driverType}) Endpoint Receive Failed. Status = {status}");
|
||||
}
|
||||
}
|
||||
}
|
||||
// If not timeout and no cancellation requested
|
||||
else if (status != coe.Status.FAILED_TIMEOUT && !cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
_logger.Error($"{Name}({_driverType}) Event Flag Wait Failed. Status = {status}");
|
||||
}
|
||||
}
|
||||
_logger.Debug($"{Name}({_driverType}) Stopping to read messages. Cancellation was requested.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes COE message
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public uint Write(byte[] data, uint numBytesToWrite)
|
||||
{
|
||||
_logger.Debug($"{Name}({_driverType}) Starting to write messages.");
|
||||
|
||||
if (!_coe.IsConnected)
|
||||
{
|
||||
_logger.Error($"{Name}({_driverType}) Error sending COE message, COE not connected");
|
||||
return (uint)coe.Status.FAILED_NOT_ENABLED;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var xmlData = FromByteArrayToXml(data);
|
||||
var messageName = GetMessageNameFromXml(xmlData);
|
||||
var message = new OeMessage(new Message(messageName, new MessageXmlDocument(xmlData, _logger)));
|
||||
|
||||
//var status = _endpoint.Send(message, (uint)(_driverType == DriverType.TCP ? 0x01 : 0));
|
||||
var status = _endpoint.Send(message);
|
||||
|
||||
if (status != coe.Status.SUCCESS)
|
||||
{
|
||||
_logger.Error($"{Name}({_driverType}) Error sending COE message, error code: {status}");
|
||||
}
|
||||
|
||||
return status == coe.Status.ERROR ? (uint)coe.Status.FAILED_INTERNAL_ERROR : (uint)status;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"{Name}({_driverType}) Error while writing a message");
|
||||
return (uint)coe.Status.FAILED_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// if byte array contains byte representation of XML then returns XML string
|
||||
/// else returns empty string
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
private static string FromByteArrayToXml(byte[] data) => System.Text.Encoding.Default.GetString(data);
|
||||
private static byte[] FromStringToByteArray(string data) => System.Text.Encoding.UTF8.GetBytes(data);
|
||||
|
||||
/// <summary>
|
||||
/// Extract message node from XML for the OeMessage class
|
||||
/// </summary>
|
||||
/// <param name="xmlData"></param>
|
||||
/// <returns></returns>
|
||||
private string GetMessageNameFromXml(string xmlData)
|
||||
{
|
||||
var doc = new XPathDocument(xmlData);
|
||||
XPathNavigator navigator = doc.CreateNavigator();
|
||||
|
||||
var nodeset = navigator.Select("//@Message");
|
||||
|
||||
nodeset.MoveNext();
|
||||
|
||||
return nodeset.Current.InnerXml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// if message id can be converted to uint returns the value
|
||||
/// otherwise returns the related label from the message id by dictionary lookup
|
||||
/// </summary>
|
||||
/// <param name="label"></param>
|
||||
/// <returns></returns>
|
||||
private uint GetLabelFromMessageId(string messageId)
|
||||
{
|
||||
uint labelId = FromStringToUint(messageId);
|
||||
|
||||
if (labelId == 0)
|
||||
{
|
||||
foreach (var file in _icds)
|
||||
{
|
||||
var item = file.Value.FirstOrDefault(l => l.Value == messageId);
|
||||
if (!string.IsNullOrEmpty(item.Value))
|
||||
return item.Key;
|
||||
}
|
||||
}
|
||||
|
||||
return labelId;
|
||||
}
|
||||
/// <summary>
|
||||
/// return file path for the file that contains the label
|
||||
/// </summary>
|
||||
/// <param name="label"></param>
|
||||
/// <returns></returns>
|
||||
private string WhichFileContainsTheLabel(uint label)
|
||||
{
|
||||
foreach (var item in _icds)
|
||||
{
|
||||
if (item.Value.Keys.Contains(label))
|
||||
{
|
||||
return item.Key;
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// reads xml file and extracts all message names with associated labels
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
private Dictionary<uint, string> ProcessFileForNamesAndLabels(string filePath)
|
||||
{
|
||||
var doc = new XPathDocument(filePath);
|
||||
|
||||
XPathNavigator node = doc.CreateNavigator();
|
||||
XPathNodeIterator nodeset = node.Select("interface/message");
|
||||
|
||||
var result = new Dictionary<uint, string>();
|
||||
|
||||
while (nodeset.MoveNext())
|
||||
{
|
||||
var children = nodeset.Current.SelectChildren(XPathNodeType.Element);
|
||||
if (children.Count > 0)
|
||||
{
|
||||
string strName = string.Empty;
|
||||
string strLabel = string.Empty;
|
||||
|
||||
while (children.MoveNext())
|
||||
{
|
||||
if (children.Current.Name == "name")
|
||||
{
|
||||
strName = children.Current.Value;
|
||||
if (!string.IsNullOrEmpty(strName))
|
||||
strName = strName.Trim();
|
||||
}
|
||||
else if (children.Current.Name == "label")
|
||||
{
|
||||
strLabel = children.Current.Value;
|
||||
if (!string.IsNullOrEmpty(strLabel))
|
||||
strLabel = strLabel.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
uint iLabel = FromStringToUint(strLabel);
|
||||
|
||||
if (!string.IsNullOrEmpty(strName) && iLabel > 0)
|
||||
{
|
||||
result.Add(iLabel, strName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// converts from string representation of a label to uint value
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
private uint FromStringToUint(string data)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(data))
|
||||
{
|
||||
if (data.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase) || data.StartsWith("&H", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
if (uint.TryParse(data.Substring(2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out uint uiValue))
|
||||
return uiValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uint.TryParse(data, out uint uiValuel))
|
||||
return uiValuel;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
// **********************************************************************************************************
|
||||
// ConfigurationHelper.cs
|
||||
// 7/5/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 Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// type conversion utility with a special case for enums
|
||||
/// </summary>
|
||||
public static class TypeConverter
|
||||
{
|
||||
public static T ChangeType<T>(object value)
|
||||
{
|
||||
return typeof(T).IsEnum ? (T)Enum.Parse(typeof(T), value.ToString()) : (T)ChangeType(typeof(T), value);
|
||||
}
|
||||
|
||||
public static object ChangeType(Type t, object value)
|
||||
{
|
||||
System.ComponentModel.TypeConverter tc = TypeDescriptor.GetConverter(t);
|
||||
return tc.ConvertFrom(value);
|
||||
}
|
||||
|
||||
public static void RegisterTypeConverter<T, TC>() where TC : System.ComponentModel.TypeConverter
|
||||
{
|
||||
TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class contains extension fictions for reading types other than strings from configuration,
|
||||
/// as well as reading lists of values
|
||||
/// </summary>
|
||||
public static class ConfigurationHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// template function for reading different types from configuration
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="section"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetConfigurationValue<T>(this IConfiguration configuration, string section, string key, string defaultValue)
|
||||
{
|
||||
var tmpResult = configuration.GetConfigurationValue(section, key, defaultValue);
|
||||
return !string.IsNullOrEmpty(tmpResult) ? TypeConverter.ChangeType<T>(tmpResult) : default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns multi-value result (list of T) from configuration
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="section"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> GetConfigurationListValue<T>(this IConfiguration configuration, string section, string key, List<T> defaultValue)
|
||||
{
|
||||
var tmpResult = configuration.GetXmlConfiguration(section);
|
||||
if (string.IsNullOrEmpty(tmpResult))
|
||||
{
|
||||
var xmlStr = new StringBuilder();
|
||||
xmlStr.Append($"<{key}s>");
|
||||
foreach (var item in defaultValue)
|
||||
{
|
||||
xmlStr.Append($"<{key}>");
|
||||
xmlStr.Append(item.ToString());
|
||||
xmlStr.Append($"</{key}>");
|
||||
}
|
||||
xmlStr.Append($"</{key}s>");
|
||||
|
||||
configuration.SetXmlConfiguration(section, xmlStr.ToString());
|
||||
return defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var stringRes = BuildElementListFromXml(tmpResult, key);
|
||||
return new List<T>(stringRes.Select(x => TypeConverter.ChangeType<T>(x)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns values from XML section converted to string list
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
private static List<string> BuildElementListFromXml(string data, string key)
|
||||
{
|
||||
XElement doc = XElement.Parse(data);
|
||||
IEnumerable<XElement> xmlMessages = from m
|
||||
in doc.Elements($"{key}s").Elements(key)
|
||||
select m;
|
||||
var messages = xmlMessages.Select(x => x.Value);
|
||||
return messages?.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,8 @@
|
||||
<Import Project="$(SolutionDir)Solution.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AssemblyName>Raytheon.Instruments.BITCOEDeviceNode</AssemblyName>
|
||||
<Description>Specialized instrument implementation of IBit interface for running real time Build In Tests via COE</Description>
|
||||
<AssemblyName>Raytheon.Instruments.CoeCommDevice</AssemblyName>
|
||||
<Description>Instrument implementation of GenSoft COE (Common Operating Environment)</Description>
|
||||
|
||||
<!-- Static versioning (Suitable for Development) -->
|
||||
<!-- Disable the line below for dynamic versioning -->
|
||||
@@ -12,18 +12,10 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Deploy|AnyCPU'">
|
||||
<Optimize>False</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.BIT.Contracts" Version="1.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\COEComm\COEComm.csproj" />
|
||||
<PackageReference Include="Raytheon.Instruments.CoeComm.Contracts" Version="1.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
|
||||
@@ -30,47 +30,35 @@
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "BITCOEDeviceInstrumentFactory")]
|
||||
public class BITCOEDeviceInstrumentFactory : IInstrumentFactory
|
||||
[ExportInstrumentFactory(ModelNumber = "CoeCommDeviceFactory")]
|
||||
public class CoeCommDeviceFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private ILogger _logger;
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
private readonly DriverType _driverType;
|
||||
|
||||
public BITCOEDeviceInstrumentFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
public CoeCommDeviceFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// CoeCommDeviceFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public BITCOEDeviceInstrumentFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null,
|
||||
[Import(AllowDefault = true)] DriverType driverType = DriverType.TCP)
|
||||
public CoeCommDeviceFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
@@ -81,8 +69,7 @@ namespace Raytheon.Instruments
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_driverType = driverType;
|
||||
_supportedInterfaces.Add(typeof(IBit));
|
||||
_supportedInterfaces.Add(typeof(CoeComm));
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
@@ -93,8 +80,7 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new BITCOEDeviceInstrument(name, _configurationManager, _driverType, _logger);
|
||||
return new CoeCommDevice(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -111,9 +97,7 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
return new BITCOEDeviceInstrument(name, _configurationManager, _driverType, _logger);
|
||||
return new CoeCommDevice(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -0,0 +1,124 @@
|
||||
// **********************************************************************************************************
|
||||
// ConfigurationHelper.cs
|
||||
// 7/5/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 Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// type conversion utility with a special case for enums
|
||||
/// </summary>
|
||||
public static class TypeConverter
|
||||
{
|
||||
public static T ChangeType<T>(object value)
|
||||
{
|
||||
return typeof(T).IsEnum ? (T)Enum.Parse(typeof(T), value.ToString()) : (T)ChangeType(typeof(T), value);
|
||||
}
|
||||
|
||||
public static object ChangeType(Type t, object value)
|
||||
{
|
||||
System.ComponentModel.TypeConverter tc = TypeDescriptor.GetConverter(t);
|
||||
return tc.ConvertFrom(value);
|
||||
}
|
||||
|
||||
public static void RegisterTypeConverter<T, TC>() where TC : System.ComponentModel.TypeConverter
|
||||
{
|
||||
TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class contains extention fuctions for reading types other than strings from configuration,
|
||||
/// as well as reading lists of values
|
||||
/// </summary>
|
||||
public static class ConfigurationHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// template function for reading different types from configuration
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="section"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetConfigurationValue<T>(this IConfiguration configuration, string section, string key)
|
||||
{
|
||||
var tmpResult = configuration.GetConfigurationValue(section, key);
|
||||
return !string.IsNullOrEmpty(tmpResult) ? TypeConverter.ChangeType<T>(tmpResult) : default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns multivalue result (list of T) from configuration
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="section"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> GetConfigurationListValue<T>(this IConfiguration configuration, string section, string key, List<T> defaultValue)
|
||||
{
|
||||
var tmpResult = configuration.GetXmlConfiguration(section);
|
||||
if (string.IsNullOrEmpty(tmpResult))
|
||||
{
|
||||
return new List<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
var stringRes = BuildElementListFromXml(tmpResult, key);
|
||||
return new List<T>(stringRes.Select(x => TypeConverter.ChangeType<T>(x)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns values from XML section converted to string list
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
private static List<string> BuildElementListFromXml(string data, string key)
|
||||
{
|
||||
XElement doc = XElement.Parse(data);
|
||||
IEnumerable<XElement> xmlMessages = from m
|
||||
in doc.Elements($"{key}s").Elements(key)
|
||||
select m;
|
||||
var messages = xmlMessages.Select(x => x.Value);
|
||||
return messages?.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
@@ -0,0 +1,5 @@
|
||||
To test this COECommDevice, use the CMIT tool in this folder to send/received COE messages. Both nodes must be using the same COE XML files to send/receive COE messages.
|
||||
|
||||
Configure CMIT tool as server since COECommDevice will configure itself as client by default(whether using TCP or UDP)
|
||||
|
||||
This COE instrument also calls into lower level COE code from Raytheon.Common library. Read the COE code from there if interested to know how it works.
|
||||
@@ -15,380 +15,347 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// Chiller class used to interact with the FTS chiller.
|
||||
/// </summary>
|
||||
public class ChillerFTS : IChiller, IDisposable
|
||||
{
|
||||
#region PrivateMembers
|
||||
private enum DEGREES
|
||||
{
|
||||
Celsius = 0,
|
||||
Fahrenheit = 1,
|
||||
Kevin = 2
|
||||
}
|
||||
/// <summary>
|
||||
/// Chiller class used to interact with the FTS chiller.
|
||||
/// </summary>
|
||||
public class ChillerFTS : IChiller, IDisposable
|
||||
{
|
||||
#region PrivateMembers
|
||||
private enum DEGREES
|
||||
{
|
||||
Celsius = 0,
|
||||
Fahrenheit = 1,
|
||||
Kevin = 2
|
||||
}
|
||||
|
||||
private static object m_sync = new object();
|
||||
private static object m_sync = new object();
|
||||
|
||||
private const string _CARRIAGE_RETURN = "\r";
|
||||
private const string _FLOWDISABLE = "STOP";
|
||||
private const string _FLOWENABLE = "START";
|
||||
private const string _TEMPREAD = "PT?";
|
||||
private const string _TEMPREADSETPOINT = "SP?";
|
||||
private const string _TEMPSET = "SP=";
|
||||
private const string _DEGREES = "DEGREES=";
|
||||
private const string _SUCCESS = "OK";
|
||||
private const string _EXC_POINT = "!";
|
||||
private const string _CARRIAGE_RETURN = "\r";
|
||||
private const string _FLOWDISABLE = "STOP";
|
||||
private const string _FLOWENABLE = "START";
|
||||
private const string _TEMPREAD = "PT?";
|
||||
private const string _TEMPREADSETPOINT = "SP?";
|
||||
private const string _TEMPSET = "SP=";
|
||||
private const string _DEGREES = "DEGREES=";
|
||||
private const string _SUCCESS = "OK";
|
||||
private const string _EXC_POINT = "!";
|
||||
|
||||
private readonly string _ipAddr;
|
||||
private readonly int _port;
|
||||
private const int _READ_BUFFER_SIZE = 128;
|
||||
private const int _READ_TIMEOUT = 5000;
|
||||
private byte[] _readBuffer;
|
||||
private NetworkStream _tcpStream;
|
||||
private readonly string _ipAddr;
|
||||
private readonly int _port;
|
||||
private const int _READ_BUFFER_SIZE = 128;
|
||||
private const int _READ_TIMEOUT = 5000;
|
||||
private byte[] _readBuffer;
|
||||
private NetworkStream _tcpStream;
|
||||
|
||||
public string DetailedStatus { get; protected set; }
|
||||
public string DetailedStatus { get; protected set; }
|
||||
|
||||
public bool DisplayEnabled { get; set; }
|
||||
public bool FrontPanelEnabled { get; set; }
|
||||
public bool DisplayEnabled { get; set; }
|
||||
public bool FrontPanelEnabled { get; set; }
|
||||
|
||||
public InstrumentMetadata Info { get; set; }
|
||||
public InstrumentMetadata Info { get; set; }
|
||||
|
||||
public string Name { get; protected set; }
|
||||
public string Name { get; protected set; }
|
||||
|
||||
public SelfTestResult SelfTestResult => PerformSelfTest();
|
||||
public SelfTestResult SelfTestResult => PerformSelfTest();
|
||||
|
||||
public State Status { get; set; }
|
||||
public State Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#region PrivateFunctions
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
~ChillerFTS()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Open socket to the chiller
|
||||
/// </summary>
|
||||
private void ConnectEthernet()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
#region PrivateFunctions
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
~ChillerFTS()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
//Create and open a socket to chiller cart server
|
||||
TcpClient chillerSocket = new TcpClient(_ipAddr, _port);
|
||||
_tcpStream = chillerSocket.GetStream();
|
||||
_tcpStream.ReadTimeout = _READ_TIMEOUT;
|
||||
}
|
||||
/// <summary>
|
||||
/// Open socket to the chiller
|
||||
/// </summary>
|
||||
private void ConnectEthernet()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the object's resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Currently disposing.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
//Close Connection (if available)
|
||||
_tcpStream?.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Initialize()
|
||||
{
|
||||
//Create and open a socket to chiller cart server
|
||||
TcpClient chillerSocket = new TcpClient(_ipAddr, _port);
|
||||
_tcpStream = chillerSocket.GetStream();
|
||||
_tcpStream.ReadTimeout = _READ_TIMEOUT;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a command to the chiller and request a response
|
||||
/// </summary>
|
||||
/// <param name="cmd">Command to send.</param>
|
||||
/// <returns>Response from the chiller.</returns>
|
||||
private string SendMessageGetResponse(string cmd)
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Format the command before sending
|
||||
string commandString = cmd + _CARRIAGE_RETURN;
|
||||
/// <summary>
|
||||
/// Dispose of the object's resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Currently disposing.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
//Close Connection (if available)
|
||||
_tcpStream?.Close();
|
||||
}
|
||||
}
|
||||
|
||||
//convert to byte array for sending
|
||||
byte[] commandBuffer = Encoding.ASCII.GetBytes(commandString);
|
||||
/// <summary>
|
||||
/// Send a command to the chiller and request a response
|
||||
/// </summary>
|
||||
/// <param name="cmd">Command to send.</param>
|
||||
/// <returns>Response from the chiller.</returns>
|
||||
private string SendMessageGetResponse(string cmd)
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Format the command before sending
|
||||
string commandString = cmd + _CARRIAGE_RETURN;
|
||||
|
||||
//send the data
|
||||
_tcpStream.Write(commandBuffer, 0, commandBuffer.Length);
|
||||
//convert to byte array for sending
|
||||
byte[] commandBuffer = Encoding.ASCII.GetBytes(commandString);
|
||||
|
||||
//clear the buffer
|
||||
Array.Clear(_readBuffer, 0, _readBuffer.Length);
|
||||
//send the data
|
||||
_tcpStream.Write(commandBuffer, 0, commandBuffer.Length);
|
||||
|
||||
//read from the response buffer
|
||||
int numBytesRead = _tcpStream.Read(_readBuffer, 0, _readBuffer.Length);
|
||||
//clear the buffer
|
||||
Array.Clear(_readBuffer, 0, _readBuffer.Length);
|
||||
|
||||
//convert response to a string
|
||||
string rspStr = Encoding.ASCII.GetString(_readBuffer);
|
||||
//read from the response buffer
|
||||
int numBytesRead = _tcpStream.Read(_readBuffer, 0, _readBuffer.Length);
|
||||
|
||||
//Check Response
|
||||
if (rspStr.Contains(_SUCCESS))
|
||||
{
|
||||
//Remove !
|
||||
rspStr = rspStr.Replace(_EXC_POINT, "");
|
||||
//convert response to a string
|
||||
string rspStr = Encoding.ASCII.GetString(_readBuffer);
|
||||
|
||||
//Parse string ("/r")
|
||||
char[] delimit = { '\r' };
|
||||
string[] parsed = rspStr.Split(delimit, StringSplitOptions.RemoveEmptyEntries);
|
||||
//Check Response
|
||||
if (rspStr.Contains(_SUCCESS))
|
||||
{
|
||||
//Remove !
|
||||
rspStr = rspStr.Replace(_EXC_POINT, "");
|
||||
|
||||
//Return parsed message
|
||||
return parsed[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("SendMessageGetResponse::SendMessageGetResponse() - Command message not successful");
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Change the units of measurement for the chiller.
|
||||
/// </summary>
|
||||
/// <param name="units">Celsius/Fahrenheit</param>
|
||||
private void SetDegreesUnits(DEGREES units)
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Set the units of measurement to Celsius
|
||||
string rsp = SendMessageGetResponse(_DEGREES + units.ToString());
|
||||
}
|
||||
}
|
||||
//Parse string ("/r")
|
||||
char[] delimit = { '\r' };
|
||||
string[] parsed = rspStr.Split(delimit, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
#endregion
|
||||
//Return parsed message
|
||||
return parsed[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("SendMessageGetResponse::SendMessageGetResponse() - Command message not successful");
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Change the units of measurement for the chiller.
|
||||
/// </summary>
|
||||
/// <param name="units">Celsius/Fahrenheit</param>
|
||||
private void SetDegreesUnits(DEGREES units)
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Set the units of measurement to Celsius
|
||||
string rsp = SendMessageGetResponse(_DEGREES + units.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ChillerFTS factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public ChillerFTS(string deviceName, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
Name = deviceName;
|
||||
/// <summary>
|
||||
/// ChillerFTS factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public ChillerFTS(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
Name = deviceName;
|
||||
|
||||
_logger = logger;
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
|
||||
_ipAddr = _configuration.GetConfigurationValue("ChillerFTS", "IpAddr", "");
|
||||
_port = _configuration.GetConfigurationValue("ChillerFTS", "Port", 0);
|
||||
|
||||
_readBuffer = new byte[_READ_BUFFER_SIZE];
|
||||
_ipAddr = _configuration.GetConfigurationValue("ChillerFTS", "IpAddr", "");
|
||||
_port = _configuration.GetConfigurationValue("ChillerFTS", "Port", 0);
|
||||
|
||||
//Connect to device
|
||||
ConnectEthernet();
|
||||
}
|
||||
_readBuffer = new byte[_READ_BUFFER_SIZE];
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the chiller. It makes a socket connection to the chiller and sets the degrees to Celsius
|
||||
/// </summary>
|
||||
/// <param name="name">The name</param>
|
||||
/// <param name="ipAddress">IP Address of the equipment</param>
|
||||
/// <param name="port">Port of the equipment</param>
|
||||
public ChillerFTS(string name, string ipAddress, int port)
|
||||
{
|
||||
Name = name;
|
||||
_ipAddr = ipAddress;
|
||||
_port = port;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
//Connect to device
|
||||
ConnectEthernet();
|
||||
}
|
||||
|
||||
_readBuffer = new byte[_READ_BUFFER_SIZE];
|
||||
/// <summary>
|
||||
/// Constructor for the chiller. It makes a socket connection to the chiller and sets the degrees to Celsius
|
||||
/// </summary>
|
||||
/// <param name="deviceName">The name</param>
|
||||
/// <param name="ipAddress">IP Address of the equipment</param>
|
||||
/// <param name="port">Port of the equipment</param>
|
||||
public ChillerFTS(string deviceName, string ipAddress, int port)
|
||||
{
|
||||
Name = deviceName;
|
||||
_ipAddr = ipAddress;
|
||||
_port = port;
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
//Connect to device
|
||||
ConnectEthernet();
|
||||
}
|
||||
_readBuffer = new byte[_READ_BUFFER_SIZE];
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="comPortName"></param>
|
||||
/// <param name="delayBeforeReadMs"></param>
|
||||
/// <param name="baudRate"></param>
|
||||
/// <param name="parity"></param>
|
||||
/// <param name="dataBits"></param>
|
||||
/// <param name="stopBits"></param>
|
||||
public ChillerFTS(string name, string comPortName, uint delayBeforeReadMs, int baudRate = 115200, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.One)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
//Connect to device
|
||||
ConnectEthernet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the chiller pump.
|
||||
/// </summary>
|
||||
public void DisableFlow()
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Send the command to stop coolant flow
|
||||
string rsp = SendMessageGetResponse(_FLOWDISABLE);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="comPortName"></param>
|
||||
/// <param name="delayBeforeReadMs"></param>
|
||||
/// <param name="baudRate"></param>
|
||||
/// <param name="parity"></param>
|
||||
/// <param name="dataBits"></param>
|
||||
/// <param name="stopBits"></param>
|
||||
public ChillerFTS(string name, string comPortName, uint delayBeforeReadMs, int baudRate = 115200, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.One)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this objects resources
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
/// <summary>
|
||||
/// Stop the chiller pump.
|
||||
/// </summary>
|
||||
public void DisableFlow()
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Send the command to stop coolant flow
|
||||
string rsp = SendMessageGetResponse(_FLOWDISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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>
|
||||
/// Dispose of this objects resources
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
/// <summary>
|
||||
/// Start the chiller pump.
|
||||
/// </summary>
|
||||
public void EnableFlow()
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Send the command to start coolant flow
|
||||
string rsp = SendMessageGetResponse(_FLOWENABLE);
|
||||
}
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the current setting for the coolant.
|
||||
/// </summary>
|
||||
/// <returns>The current coolant setting.</returns>
|
||||
public double GetCoolantSetpoint()
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Name of the function
|
||||
const string SETPOINT_RESPONSE = "F057=";
|
||||
/// <summary>
|
||||
/// Start the chiller pump.
|
||||
/// </summary>
|
||||
public void EnableFlow()
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Send the command to start coolant flow
|
||||
string rsp = SendMessageGetResponse(_FLOWENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
//Request the setpoint
|
||||
string results = SendMessageGetResponse(_TEMPREADSETPOINT);
|
||||
/// <summary>
|
||||
/// Query the current setting for the coolant.
|
||||
/// </summary>
|
||||
/// <returns>The current coolant setting.</returns>
|
||||
public double GetCoolantSetpoint()
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Name of the function
|
||||
const string SETPOINT_RESPONSE = "F057=";
|
||||
|
||||
//Not connected. No results
|
||||
if (results == "")
|
||||
{
|
||||
return double.MaxValue;
|
||||
}
|
||||
//Request the setpoint
|
||||
string results = SendMessageGetResponse(_TEMPREADSETPOINT);
|
||||
|
||||
//Remove function header
|
||||
results = results.Replace(SETPOINT_RESPONSE, "");
|
||||
//Not connected. No results
|
||||
if (results == "")
|
||||
{
|
||||
return double.MaxValue;
|
||||
}
|
||||
|
||||
return double.Parse(results);
|
||||
}
|
||||
}
|
||||
//Remove function header
|
||||
results = results.Replace(SETPOINT_RESPONSE, "");
|
||||
|
||||
/// <summary>
|
||||
/// Query the temperature of the coolant reservoir.
|
||||
/// </summary>
|
||||
/// <returns>The temperature of the coolant.</returns>
|
||||
public double GetCoolantTemperature()
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Name of the function
|
||||
const string TEMP_RESPONSE = "F043=";
|
||||
return double.Parse(results);
|
||||
}
|
||||
}
|
||||
|
||||
//Request the temperature
|
||||
string results = SendMessageGetResponse(_TEMPREAD);
|
||||
/// <summary>
|
||||
/// Query the temperature of the coolant reservoir.
|
||||
/// </summary>
|
||||
/// <returns>The temperature of the coolant.</returns>
|
||||
public double GetCoolantTemperature()
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Name of the function
|
||||
const string TEMP_RESPONSE = "F043=";
|
||||
|
||||
//Not connected. No results
|
||||
if (results == "")
|
||||
{
|
||||
return double.MaxValue;
|
||||
}
|
||||
//Request the temperature
|
||||
string results = SendMessageGetResponse(_TEMPREAD);
|
||||
|
||||
//Remove function header
|
||||
results = results.Replace(TEMP_RESPONSE, "");
|
||||
//Not connected. No results
|
||||
if (results == "")
|
||||
{
|
||||
return double.MaxValue;
|
||||
}
|
||||
|
||||
return double.Parse(results);
|
||||
}
|
||||
}
|
||||
//Remove function header
|
||||
results = results.Replace(TEMP_RESPONSE, "");
|
||||
|
||||
/// <summary>
|
||||
/// Set the coolant temperature to a desired setpoint.
|
||||
/// </summary>
|
||||
/// <param name="temp">The desired coolant temperature.</param>
|
||||
public void SetCoolantTemperature(double temp)
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Set the coolant temperature
|
||||
string rsp = SendMessageGetResponse(_TEMPSET + temp.ToString());
|
||||
}
|
||||
}
|
||||
return double.Parse(results);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <summary>
|
||||
/// Set the coolant temperature to a desired setpoint.
|
||||
/// </summary>
|
||||
/// <param name="temp">The desired coolant temperature.</param>
|
||||
public void SetCoolantTemperature(double temp)
|
||||
{
|
||||
lock (m_sync)
|
||||
{
|
||||
//Set the coolant temperature
|
||||
string rsp = SendMessageGetResponse(_TEMPSET + temp.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
return SelfTestResult.Unknown;
|
||||
}
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Shutdown();
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
return SelfTestResult.Unknown;
|
||||
}
|
||||
|
||||
Initialize();
|
||||
}
|
||||
public void Reset()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,71 +30,64 @@
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "ChillerFTSFactory")]
|
||||
public class ChillerFTSFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
[ExportInstrumentFactory(ModelNumber = "ChillerFTSFactory")]
|
||||
public class ChillerFTSFactory : IInstrumentFactory
|
||||
{
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
|
||||
public ChillerFTSFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public ChillerFTSFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
public ChillerFTSFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
/// <summary>
|
||||
/// ChillerFTSFactory injection constructor
|
||||
/// </summary>
|
||||
[ImportingConstructor]
|
||||
public ChillerFTSFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(IChiller));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new ChillerFTS(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(IChiller));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ChillerFTS(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
@@ -105,12 +98,10 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
if (simulateHw)
|
||||
return new ChillerSim(name, _configurationManager, _logger);
|
||||
return new ChillerSim(name, _configurationManager);
|
||||
else
|
||||
return new ChillerFTS(name, _configurationManager, _logger);
|
||||
return new ChillerFTS(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -123,17 +114,17 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,210 +15,175 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// A simulated chiller
|
||||
/// </summary>
|
||||
public class ChillerSim : IChiller, IDisposable
|
||||
{
|
||||
#region PrivateMembers
|
||||
private double _setPoint;
|
||||
private static object _sync = new object();
|
||||
/// <summary>
|
||||
/// A simulated chiller
|
||||
/// </summary>
|
||||
public class ChillerSim : IChiller, IDisposable
|
||||
{
|
||||
#region PrivateMembers
|
||||
private double _setPoint;
|
||||
private static object _sync = new object();
|
||||
|
||||
public string DetailedStatus { get; protected set; }
|
||||
public string DetailedStatus { get; protected set; }
|
||||
|
||||
public bool DisplayEnabled { get; set; }
|
||||
public bool FrontPanelEnabled { get; set; }
|
||||
public bool DisplayEnabled { get; set; }
|
||||
public bool FrontPanelEnabled { get; set; }
|
||||
|
||||
public InstrumentMetadata Info { get; set; }
|
||||
public InstrumentMetadata Info { get; set; }
|
||||
|
||||
public string Name { get; protected set; }
|
||||
public string Name { get; protected set; }
|
||||
|
||||
public SelfTestResult SelfTestResult => PerformSelfTest();
|
||||
public SelfTestResult SelfTestResult => PerformSelfTest();
|
||||
|
||||
public State Status { get; set; }
|
||||
public State Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#region PrivateFunctions
|
||||
~ChillerSim()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
/// <summary>
|
||||
/// Dispose of the object's resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Currently disposing.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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
|
||||
#endregion
|
||||
|
||||
#region PublicFunctions
|
||||
#region PrivateFunctions
|
||||
~ChillerSim()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
/// <summary>
|
||||
/// Dispose of the object's resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Currently disposing.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// ChillerFTS factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public ChillerSim(string deviceName, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
Name = deviceName;
|
||||
}
|
||||
#endregion
|
||||
|
||||
_logger = logger;
|
||||
#region PublicFunctions
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
}
|
||||
/// <summary>
|
||||
/// ChillerFTS factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public ChillerSim(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
Name = deviceName;
|
||||
|
||||
/// <summary>
|
||||
/// The constructor
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public ChillerSim(string name)
|
||||
{
|
||||
Name = name;
|
||||
_setPoint = 20.0;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
public ChillerSim(string deviceName)
|
||||
{
|
||||
Name = deviceName;
|
||||
_setPoint = 20.0;
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Stop the chiller pump.
|
||||
/// </summary>
|
||||
public void DisableFlow()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Stop the chiller pump.
|
||||
/// </summary>
|
||||
public void DisableFlow()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this objects resources
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
/// <summary>
|
||||
/// Dispose of this objects resources
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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>
|
||||
/// Start the chiller pump.
|
||||
/// </summary>
|
||||
public void EnableFlow()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Start the chiller pump.
|
||||
/// </summary>
|
||||
public void EnableFlow()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the current setting for the coolant.
|
||||
/// </summary>
|
||||
/// <returns>The current coolant setting.</returns>
|
||||
public double GetCoolantSetpoint()
|
||||
{
|
||||
return _setPoint;
|
||||
}
|
||||
/// <summary>
|
||||
/// Query the current setting for the coolant.
|
||||
/// </summary>
|
||||
/// <returns>The current coolant setting.</returns>
|
||||
public double GetCoolantSetpoint()
|
||||
{
|
||||
return _setPoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the temperature of the coolant reservoir.
|
||||
/// </summary>
|
||||
/// <returns>The temperature of the coolant.</returns>
|
||||
public double GetCoolantTemperature()
|
||||
{
|
||||
double max = _setPoint + 5;
|
||||
/// <summary>
|
||||
/// Query the temperature of the coolant reservoir.
|
||||
/// </summary>
|
||||
/// <returns>The temperature of the coolant.</returns>
|
||||
public double GetCoolantTemperature()
|
||||
{
|
||||
double max = _setPoint + 5;
|
||||
|
||||
double min = _setPoint - 5;
|
||||
double min = _setPoint - 5;
|
||||
|
||||
Random rnd = new Random();
|
||||
Random rnd = new Random();
|
||||
|
||||
double seed = rnd.NextDouble();
|
||||
double seed = rnd.NextDouble();
|
||||
|
||||
double dataToReturn = (seed * (max - min)) + min;
|
||||
double dataToReturn = (seed * (max - min)) + min;
|
||||
|
||||
Thread.Sleep(100);
|
||||
Thread.Sleep(100);
|
||||
|
||||
return dataToReturn;
|
||||
}
|
||||
return dataToReturn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the coolant temperature to a desired setpoint.
|
||||
/// </summary>
|
||||
/// <param name="temp">The desired coolant temperature.</param>
|
||||
public void SetCoolantTemperature(double temp)
|
||||
{
|
||||
_setPoint = temp;
|
||||
}
|
||||
/// <summary>
|
||||
/// Set the coolant temperature to a desired setpoint.
|
||||
/// </summary>
|
||||
/// <param name="temp">The desired coolant temperature.</param>
|
||||
public void SetCoolantTemperature(double temp)
|
||||
{
|
||||
_setPoint = temp;
|
||||
}
|
||||
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public void Initialize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public void Shutdown()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,71 +30,64 @@
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "ChillerSimFactory")]
|
||||
public class ChillerSimFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
[ExportInstrumentFactory(ModelNumber = "ChillerSimFactory")]
|
||||
public class ChillerSimFactory : IInstrumentFactory
|
||||
{
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
|
||||
public ChillerSimFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public ChillerSimFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
public ChillerSimFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
/// <summary>
|
||||
/// ChillerSimFactory injection constructor
|
||||
/// </summary>
|
||||
[ImportingConstructor]
|
||||
public ChillerSimFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(IChiller));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new ChillerSim(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(IChiller));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ChillerSim(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
@@ -105,9 +98,7 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
return new ChillerSim(name, _configurationManager, _logger);
|
||||
return new ChillerSim(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -120,17 +111,17 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,360 +1,348 @@
|
||||
// Ignore Spelling: Geu Sdlc
|
||||
|
||||
using System;
|
||||
using Raytheon.GuidedElectronicsUnit;
|
||||
using System.Threading;
|
||||
using Raytheon.Common;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using Raytheon.GuidedElectronicsUnit;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
public class CommDeviceGeuSdlc : ICommDevice, IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
public class CommDeviceGeuSdlc : ICommDevice, IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
|
||||
private GuidedElectronicsUnit.GuidedElectronicsUnit _guidanceElectronicsUnit;
|
||||
private readonly bool _idQuery = false;
|
||||
private readonly bool _reset = false;
|
||||
private readonly SelfTestResult _selfTestResult;
|
||||
private State _state;
|
||||
private readonly string _instrumentDriverSetup;
|
||||
private readonly int _pollingRate;
|
||||
private readonly string _resourceName;
|
||||
private static readonly object _syncObj = new object();
|
||||
private GuidedElectronicsUnit.GuidedElectronicsUnit _guidanceElectronicsUnit;
|
||||
private readonly bool _idQuery = false;
|
||||
private readonly bool _reset = false;
|
||||
private readonly SelfTestResult _selfTestResult;
|
||||
private State _state;
|
||||
private readonly string _instrumentDriverSetup;
|
||||
private readonly int _pollingRate;
|
||||
private static readonly object _syncObj = new object();
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#region PrivatelassFunctions
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~CommDeviceGeuSdlc()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
#region PrivatelassFunctions
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close resources
|
||||
try
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_guidanceElectronicsUnit.Close();
|
||||
_guidanceElectronicsUnit.Dispose();
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~CommDeviceGeuSdlc()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Some HSS corrections
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="numDWords"></param>
|
||||
private static unsafe void PerformHssSwirl(ref byte[] data, uint numDWords)
|
||||
{
|
||||
fixed (byte* pBytePtr = &data[0])
|
||||
{
|
||||
for (int i = 0; i < numDWords; i++)
|
||||
{
|
||||
// swap the first word
|
||||
ushort* pWord1 = (ushort*)pBytePtr + (i * 2);
|
||||
*pWord1 = Util.Swap(*pWord1);
|
||||
|
||||
//swap the second word
|
||||
ushort* pWord2 = (ushort*)pBytePtr + ((i * 2) + 1);
|
||||
*pWord2 = Util.Swap(*pWord2);
|
||||
|
||||
// now swap the dword
|
||||
uint* pDWord = (uint*)pBytePtr + i;
|
||||
*pDWord = Util.SwapHighAndLowBytes(*pDWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PublicClassFunctions
|
||||
|
||||
bool IInstrument.DisplayEnabled { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
bool IInstrument.FrontPanelEnabled { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
InstrumentMetadata IInstrument.Info => throw new NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceGeuSdlc(string deviceName, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
_resourceName = deviceName;
|
||||
_guidanceElectronicsUnit = null;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_logger = logger;
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
_idQuery = _configuration.GetConfigurationValue("CommDeviceGeuSdlc", "IdQuery", true);
|
||||
_reset = _configuration.GetConfigurationValue("CommDeviceGeuSdlc", "Reset", true);
|
||||
_instrumentDriverSetup = _configuration.GetConfigurationValue("CommDeviceGeuSdlc", "InstrumentDriverSetup", "");
|
||||
_pollingRate = _configuration.GetConfigurationValue("CommDeviceGeuSdlc", "PollingRate", 10);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The constructor. Does not initialize anything. Use Initialize() to create the handle to the hardware
|
||||
/// </summary>
|
||||
/// <param name="resourceName"></param>
|
||||
/// <param name="idQuery"></param>
|
||||
/// <param name="reset"></param>
|
||||
public CommDeviceGeuSdlc(string resourceName, bool idQuery, bool reset, string instrumentDriverSetup = "", int pollingRate = 10)
|
||||
{
|
||||
_resourceName = resourceName;
|
||||
_idQuery = idQuery;
|
||||
_reset = reset;
|
||||
_guidanceElectronicsUnit = null;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
_instrumentDriverSetup = instrumentDriverSetup;
|
||||
_pollingRate = pollingRate;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool IInstrument.ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a HSS GEU SDLC Device called " + _resourceName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a handle to the hardware
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
const uint AUTO_FWDING_ADDR = 0x00080100;
|
||||
const uint WRITE_OFFSET = 0x00200000;
|
||||
const uint ENABLE_AUTO_FWDING = 0b0000_0001;
|
||||
const uint ENABLE_TLP_HDR = 0b0000_0010;
|
||||
//const uint INSERT_MSG_CNT = 0b0000_0100;
|
||||
|
||||
_guidanceElectronicsUnit = new GuidedElectronicsUnit.GuidedElectronicsUnit(_resourceName, _idQuery, _reset,
|
||||
$"QueryInstrStatus=true, Simulate=false, DriverSetup= {_instrumentDriverSetup}, PollingInterval={_pollingRate}");
|
||||
|
||||
_guidanceElectronicsUnit.LowLevel.HSSub9100.EnableIO = ControlState.Enabled;
|
||||
|
||||
_guidanceElectronicsUnit.LowLevel.HSSub9100.WriteRegister(AUTO_FWDING_ADDR + WRITE_OFFSET, ENABLE_AUTO_FWDING | ENABLE_TLP_HDR);
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _resourceName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
SelfTestResult IInstrument.PerformSelfTest()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dataRead"></param>
|
||||
/// <returns></returns>
|
||||
uint ICommDevice.Read(ref byte[] dataRead)
|
||||
{
|
||||
|
||||
if (_guidanceElectronicsUnit == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte[] sdlcMsgs = new byte[0];
|
||||
lock (_syncObj)
|
||||
{
|
||||
// read all of the data that is available
|
||||
sdlcMsgs = _guidanceElectronicsUnit.GsKwSyncronousDataLinkControl.FetchMessageData();
|
||||
}
|
||||
|
||||
if (sdlcMsgs.Length > dataRead.Length)
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close resources
|
||||
try
|
||||
{
|
||||
throw new Exception("The data buffer that the host provided is: " + dataRead.Length + " bytes, there are: " + sdlcMsgs.Length + " bytes of SDLC data. Need to increase the host buffer size");
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_guidanceElectronicsUnit.Close();
|
||||
_guidanceElectronicsUnit.Dispose();
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(sdlcMsgs, 0, dataRead, 0, sdlcMsgs.Length);
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (uint)sdlcMsgs.Length;
|
||||
}
|
||||
/// <summary>
|
||||
/// Some HSS corrections
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="numDWords"></param>
|
||||
private static unsafe void PerformHssSwirl(ref byte[] data, uint numDWords)
|
||||
{
|
||||
fixed (byte* pBytePtr = &data[0])
|
||||
{
|
||||
for (int i = 0; i < numDWords; i++)
|
||||
{
|
||||
// swap the first word
|
||||
ushort* pWord1 = (ushort*)pBytePtr + (i * 2);
|
||||
*pWord1 = Util.Swap(*pWord1);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void IInstrument.Reset()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_guidanceElectronicsUnit.Close();
|
||||
_state = State.Uninitialized;
|
||||
Thread.Sleep(500);
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
//swap the second word
|
||||
ushort* pWord2 = (ushort*)pBytePtr + ((i * 2) + 1);
|
||||
*pWord2 = Util.Swap(*pWord2);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public SelfTestResult SelfTestResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
// now swap the dword
|
||||
uint* pDWord = (uint*)pBytePtr + i;
|
||||
*pDWord = Util.SwapHighAndLowBytes(*pDWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
void ICommDevice.SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void IInstrument.Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_guidanceElectronicsUnit != null)
|
||||
{
|
||||
_guidanceElectronicsUnit.LowLevel.HSSub9100.EnableIO = ControlState.Disabled;
|
||||
#region PublicClassFunctions
|
||||
|
||||
_guidanceElectronicsUnit.Close();
|
||||
_guidanceElectronicsUnit.Dispose();
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool IInstrument.DisplayEnabled { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
bool IInstrument.FrontPanelEnabled { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
InstrumentMetadata IInstrument.Info => throw new NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public State Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceGeuSdlc(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
Name = deviceName;
|
||||
_guidanceElectronicsUnit = null;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
uint ICommDevice.Write(byte[] data, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (numBytesToWrite % 4 != 0)
|
||||
{
|
||||
throw new Exception("Data is not dword aligned");
|
||||
}
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
// do all of the HSS Tx only byte order corrections
|
||||
PerformHssSwirl(ref data, numBytesToWrite / 4);
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
var tempArr = new uint[data.Length / 4];
|
||||
Buffer.BlockCopy(data, 0, tempArr, 0, (int)numBytesToWrite);
|
||||
_guidanceElectronicsUnit.GsKwSyncronousDataLinkControl.SendMessage(tempArr);
|
||||
}
|
||||
return numBytesToWrite;
|
||||
}
|
||||
_idQuery = _configuration.GetConfigurationValue("CommDeviceGeuSdlc", "IdQuery", true);
|
||||
_reset = _configuration.GetConfigurationValue("CommDeviceGeuSdlc", "Reset", true);
|
||||
_instrumentDriverSetup = _configuration.GetConfigurationValue("CommDeviceGeuSdlc", "InstrumentDriverSetup", "");
|
||||
_pollingRate = _configuration.GetConfigurationValue("CommDeviceGeuSdlc", "PollingRate", 10);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// The constructor. Does not initialize anything. Use Initialize() to create the handle to the hardware
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="idQuery"></param>
|
||||
/// <param name="reset"></param>
|
||||
public CommDeviceGeuSdlc(string deviceName, bool idQuery, bool reset, string instrumentDriverSetup = "", int pollingRate = 10)
|
||||
{
|
||||
Name = deviceName;
|
||||
_idQuery = idQuery;
|
||||
_reset = reset;
|
||||
_guidanceElectronicsUnit = null;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
_instrumentDriverSetup = instrumentDriverSetup;
|
||||
_pollingRate = pollingRate;
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool IInstrument.ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a HSS GEU SDLC Device called " + Name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a handle to the hardware
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
const uint AUTO_FWDING_ADDR = 0x00080100;
|
||||
const uint WRITE_OFFSET = 0x00200000;
|
||||
const uint ENABLE_AUTO_FWDING = 0b0000_0001;
|
||||
const uint ENABLE_TLP_HDR = 0b0000_0010;
|
||||
//const uint INSERT_MSG_CNT = 0b0000_0100;
|
||||
|
||||
_guidanceElectronicsUnit = new GuidedElectronicsUnit.GuidedElectronicsUnit(Name, _idQuery, _reset,
|
||||
$"QueryInstrStatus=true, Simulate=false, DriverSetup= {_instrumentDriverSetup}, PollingInterval={_pollingRate}");
|
||||
|
||||
_guidanceElectronicsUnit.LowLevel.HSSub9100.EnableIO = ControlState.Enabled;
|
||||
|
||||
_guidanceElectronicsUnit.LowLevel.HSSub9100.WriteRegister(AUTO_FWDING_ADDR + WRITE_OFFSET, ENABLE_AUTO_FWDING | ENABLE_TLP_HDR);
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
SelfTestResult IInstrument.PerformSelfTest()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dataRead"></param>
|
||||
/// <returns></returns>
|
||||
uint ICommDevice.Read(ref byte[] dataRead)
|
||||
{
|
||||
|
||||
if (_guidanceElectronicsUnit == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte[] sdlcMsgs = new byte[0];
|
||||
lock (_syncObj)
|
||||
{
|
||||
// read all of the data that is available
|
||||
sdlcMsgs = _guidanceElectronicsUnit.GsKwSyncronousDataLinkControl.FetchMessageData();
|
||||
}
|
||||
|
||||
if (sdlcMsgs.Length > dataRead.Length)
|
||||
{
|
||||
throw new Exception("The data buffer that the host provided is: " + dataRead.Length + " bytes, there are: " + sdlcMsgs.Length + " bytes of SDLC data. Need to increase the host buffer size");
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(sdlcMsgs, 0, dataRead, 0, sdlcMsgs.Length);
|
||||
|
||||
return (uint)sdlcMsgs.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void IInstrument.Reset()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_guidanceElectronicsUnit.Close();
|
||||
_state = State.Uninitialized;
|
||||
Thread.Sleep(500);
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public SelfTestResult SelfTestResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
void ICommDevice.SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void IInstrument.Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_guidanceElectronicsUnit != null)
|
||||
{
|
||||
_guidanceElectronicsUnit.LowLevel.HSSub9100.EnableIO = ControlState.Disabled;
|
||||
|
||||
_guidanceElectronicsUnit.Close();
|
||||
_guidanceElectronicsUnit.Dispose();
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public State Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
uint ICommDevice.Write(byte[] data, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (numBytesToWrite % 4 != 0)
|
||||
{
|
||||
throw new Exception("Data is not dword aligned");
|
||||
}
|
||||
|
||||
// do all of the HSS Tx only byte order corrections
|
||||
PerformHssSwirl(ref data, numBytesToWrite / 4);
|
||||
|
||||
var tempArr = new uint[data.Length / 4];
|
||||
Buffer.BlockCopy(data, 0, tempArr, 0, (int)numBytesToWrite);
|
||||
_guidanceElectronicsUnit.GsKwSyncronousDataLinkControl.SendMessage(tempArr);
|
||||
}
|
||||
return numBytesToWrite;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,71 +32,64 @@
|
||||
// **********************************************************************************************************
|
||||
// Ignore Spelling: Sdlc Geu
|
||||
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceGeuSdlcFactory")]
|
||||
public class CommDeviceGeuSdlcFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceGeuSdlcFactory")]
|
||||
public class CommDeviceGeuSdlcFactory : IInstrumentFactory
|
||||
{
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
|
||||
public CommDeviceGeuSdlcFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceGeuSdlcFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null )
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
public CommDeviceGeuSdlcFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
/// <summary>
|
||||
/// CommDeviceGeuSdlcFactory injection constructor
|
||||
/// </summary>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceGeuSdlcFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new CommDeviceGeuSdlc(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CommDeviceGeuSdlc(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
@@ -107,12 +100,10 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
if (simulateHw)
|
||||
return new CommDeviceSim(name, _configurationManager, _logger);
|
||||
return new CommDeviceSim(name, _configurationManager);
|
||||
else
|
||||
return new CommDeviceGeuSdlc(name, _configurationManager, _logger);
|
||||
return new CommDeviceGeuSdlc(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -125,17 +116,17 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
// **********************************************************************************************************
|
||||
// CommDeviceSerialAsync.cs
|
||||
// 4/3/2024
|
||||
// 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.IO.Ports;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// A sim communication device
|
||||
/// </summary>
|
||||
public class CommDeviceSerial : ICommDevice
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
|
||||
private int _defaultReadTimeout;
|
||||
private int _defaultReadBufferSize;
|
||||
private object _syncObj = new object();
|
||||
|
||||
private SerialPort _serialPort;
|
||||
|
||||
private string _comPortName;
|
||||
private int _baudRate;
|
||||
private Parity _parity;
|
||||
private int _dataBits;
|
||||
private StopBits _stopBits;
|
||||
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#endregion
|
||||
|
||||
public bool ClearErrors() => false;
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
|
||||
public InstrumentMetadata Info => throw new NotImplementedException();
|
||||
public State Status => _state;
|
||||
public string Name => _name;
|
||||
public SelfTestResult PerformSelfTest() => SelfTestResult;
|
||||
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
|
||||
|
||||
public void Close() => Shutdown();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
|
||||
#region Public Functions
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceSerial(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
_name = deviceName;
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(deviceName);
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
_comPortName = _configuration.GetConfigurationValue(_name, "COMPortName");
|
||||
int.TryParse(_configuration.GetConfigurationValue(_name, "BaudRate"), out _baudRate);
|
||||
Enum.TryParse(_configuration.GetConfigurationValue(_name, "Parity"), true, out _parity);
|
||||
int.TryParse(_configuration.GetConfigurationValue(_name, "DataBits"), out _dataBits);
|
||||
Enum.TryParse(_configuration.GetConfigurationValue(_name, "StopBits"), true, out _stopBits);
|
||||
|
||||
int.TryParse(_configuration.GetConfigurationValue(_name, "ReadTimeout"), out _defaultReadTimeout);
|
||||
int.TryParse(_configuration.GetConfigurationValue(_name, "BufferSize"), out _defaultReadBufferSize);
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
~CommDeviceSerial()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens COM serial port for communications
|
||||
/// </summary>
|
||||
public void Open()
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_serialPort = new SerialPort(_comPortName, _baudRate, _parity, _dataBits, _stopBits);
|
||||
_serialPort.Open();
|
||||
_serialPort.ReadTimeout = _defaultReadTimeout;
|
||||
_state = State.Ready;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// shuts down the device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
if (_serialPort != null)
|
||||
_serialPort.Close();
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
if (dataRead == null)
|
||||
dataRead = new byte[_defaultReadBufferSize];
|
||||
|
||||
var bytesRead = _serialPort.Read(dataRead, 0, dataRead.Length);
|
||||
return (uint)bytesRead;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
if (timeoutMs > 0)
|
||||
_serialPort.ReadTimeout = (int)timeoutMs;
|
||||
else
|
||||
_serialPort.ReadTimeout = _defaultReadTimeout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="dataToSend"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public uint Write(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
_serialPort.Write(dataToSend, 0, (int)numBytesToWrite);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -3,25 +3,24 @@
|
||||
<Import Project="$(SolutionDir)Solution.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AssemblyName>Raytheon.Instruments.COECommDevice</AssemblyName>
|
||||
<Description>Specialized instrument for running real time Build In Tests via COE implementing ICommDevice interface</Description>
|
||||
|
||||
<AssemblyName>Raytheon.Instruments.CommDeviceSerial</AssemblyName>
|
||||
<Product>CommDevice Serial implementation</Product>
|
||||
<Description>CommDevice Serial COM implementation</Description>
|
||||
<OutputType>Library</OutputType>
|
||||
|
||||
<!-- Static versioning (Suitable for Development) -->
|
||||
<!-- Disable the line below for dynamic versioning -->
|
||||
<Version>1.0.0</Version>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.BIT.Contracts" Version="1.4.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.CommDevice.Contracts" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\COEComm\COEComm.csproj" />
|
||||
<ProjectReference Include="..\CommDeviceSim\CommDeviceSim.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
|
||||
@@ -1,6 +1,6 @@
|
||||
// **********************************************************************************************************
|
||||
// COECommDeviceInstrumentFactory.cs
|
||||
// 5/18/2022
|
||||
// CommDeviceSerialAsyncFactory.cs
|
||||
// 4/3/2024
|
||||
// NGI - Next Generation Interceptor
|
||||
//
|
||||
// Contract No. HQ0856-21-C-0003/1022000209
|
||||
@@ -30,47 +30,35 @@
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "COECommDeviceInstrumentFactory")]
|
||||
public class COECommDeviceInstrumentFactory : IInstrumentFactory
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceSerialFactory")]
|
||||
public class CommDeviceSerialFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private ILogger _logger;
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
private readonly DriverType _driverType;
|
||||
|
||||
public COECommDeviceInstrumentFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
public CommDeviceSerialFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// CommDeviceSerialFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public COECommDeviceInstrumentFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null,
|
||||
[Import(AllowDefault = true)] DriverType driverType = DriverType.TCP)
|
||||
public CommDeviceSerialFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
@@ -81,11 +69,10 @@ namespace Raytheon.Instruments
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_driverType = driverType;
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
@@ -93,13 +80,11 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new COECommDeviceInstrument(name, _configurationManager, _driverType);
|
||||
return new CommDeviceSerial(name, _configurationManager);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
_logger.Error(ex, $"Unable to construct {name} instrument instance");
|
||||
return null;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,9 +97,10 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
return new COECommDeviceInstrument(name, _configurationManager, _driverType, _logger);
|
||||
if (simulateHw)
|
||||
return new CommDeviceSim(name, _configurationManager);
|
||||
else
|
||||
return new CommDeviceSerial(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -123,7 +109,7 @@ namespace Raytheon.Instruments
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Gets supported interfaces
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
@@ -132,13 +118,12 @@ namespace Raytheon.Instruments
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,387 +30,314 @@
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Reflection;
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// A sim communication device
|
||||
/// </summary>
|
||||
public class CommDeviceSerialAsync : ICommAsync
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
/// <summary>
|
||||
/// A sim communication device
|
||||
/// </summary>
|
||||
public class CommDeviceSerialAsync : ICommAsync
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
|
||||
private uint _defaultReadTimeout;
|
||||
private uint _defaultSendTimeout;
|
||||
private uint _defaultReadBufferSize;
|
||||
private static readonly object _syncObj = new object();
|
||||
private uint _defaultReadTimeout;
|
||||
private uint _defaultSendTimeout;
|
||||
private uint _defaultReadBufferSize;
|
||||
private object _syncObj = new object();
|
||||
|
||||
private SerialPort _serialPort;
|
||||
private SerialPort _serialPort;
|
||||
|
||||
private readonly string _comPortName;
|
||||
private readonly int _baudRate;
|
||||
private readonly Parity _parity;
|
||||
private readonly int _dataBits;
|
||||
private readonly StopBits _stopBits;
|
||||
private string _comPortName;
|
||||
private int _baudRate;
|
||||
private Parity _parity;
|
||||
private int _dataBits;
|
||||
private StopBits _stopBits;
|
||||
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public bool ClearErrors() => false;
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
|
||||
public InstrumentMetadata Info => throw new NotImplementedException();
|
||||
public State Status => _state;
|
||||
public string Name => _name;
|
||||
public SelfTestResult PerformSelfTest() => SelfTestResult;
|
||||
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
|
||||
#endregion
|
||||
|
||||
public void Close() => Shutdown();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
public bool ClearErrors() => false;
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
|
||||
public InstrumentMetadata Info => throw new NotImplementedException();
|
||||
public State Status => _state;
|
||||
public string Name => _name;
|
||||
public SelfTestResult PerformSelfTest() => SelfTestResult;
|
||||
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
|
||||
|
||||
#region Private Functions
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
public void Close() => Shutdown();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close the socket
|
||||
try
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
#region Public Functions
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceSerialAsync(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
_name = deviceName;
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(deviceName);
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
#region Public Functions
|
||||
_comPortName = _configuration.GetConfigurationValue(_name, "COMPortName");
|
||||
int.TryParse(_configuration.GetConfigurationValue(_name, "BaudRate"), out _baudRate);
|
||||
Enum.TryParse(_configuration.GetConfigurationValue(_name, "Parity"), true, out _parity);
|
||||
int.TryParse(_configuration.GetConfigurationValue(_name, "DataBits"), out _dataBits);
|
||||
Enum.TryParse(_configuration.GetConfigurationValue(_name, "StopBits"), true, out _stopBits);
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceSerialAsync(string name, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
_name = name;
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(name);
|
||||
_logger = logger;
|
||||
uint.TryParse(_configuration.GetConfigurationValue(_name, "ReadTimeout"), out _defaultReadTimeout);
|
||||
uint.TryParse(_configuration.GetConfigurationValue(_name, "SendTimeout"), out _defaultSendTimeout);
|
||||
uint.TryParse(_configuration.GetConfigurationValue(_name, "BufferSize"), out _defaultReadBufferSize);
|
||||
|
||||
_comPortName = _configuration.GetConfigurationValue("CommDeviceSerialAsync", "COMPortName", "COM15");
|
||||
_baudRate = _configuration.GetConfigurationValue("CommDeviceSerialAsync", "BaudRate", 115200);
|
||||
_parity = _configuration.GetConfigurationValue("CommDeviceSerialAsync", "Parity", Parity.None);
|
||||
_dataBits = _configuration.GetConfigurationValue("CommDeviceSerialAsync", "DataBits", 8);
|
||||
_stopBits = _configuration.GetConfigurationValue("CommDeviceSerialAsync", "StopBits", StopBits.One);
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
_defaultReadTimeout = _configuration.GetConfigurationValue<uint>("CommDeviceSerialAsync", "ReadTimeout", 25);
|
||||
_defaultSendTimeout = _configuration.GetConfigurationValue<uint>("CommDeviceSerialAsync", "SendTimeout", 5000);
|
||||
_defaultReadBufferSize = _configuration.GetConfigurationValue<uint>("CommDeviceSerialAsync", "BufferSize", 1024);
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
~CommDeviceSerialAsync()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
if (_state != State.Uninitialized)
|
||||
{
|
||||
_logger.Warn("Reinitialization of existing Serial Async Connection. Attempting to call Shutdown.");
|
||||
Shutdown();
|
||||
}
|
||||
/// <summary>
|
||||
/// Opens COM serial port for communications
|
||||
/// </summary>
|
||||
public void Open()
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_serialPort = new SerialPort(_comPortName, _baudRate, _parity, _dataBits, _stopBits);
|
||||
_serialPort.Open();
|
||||
_state = State.Ready;
|
||||
}
|
||||
}
|
||||
|
||||
_serialPort = new SerialPort(_comPortName, _baudRate, _parity, _dataBits, _stopBits);
|
||||
/// <summary>
|
||||
/// shuts down the device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
if (_serialPort != null)
|
||||
_serialPort.Close();
|
||||
|
||||
Open();
|
||||
}
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens COM serial port for communications
|
||||
/// </summary>
|
||||
public void Open()
|
||||
{
|
||||
try
|
||||
{
|
||||
_serialPort.Open();
|
||||
_state = State.Ready;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, ex.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Read data from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<uint> ReadAsync(byte[] dataRead, CancellationToken token = default)
|
||||
{
|
||||
var bytesRead = await _serialPort.BaseStream.ReadAsync(dataRead, 0, dataRead.Length, token);
|
||||
return (uint)bytesRead;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// shuts down the device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
_logger.Debug("Shutting down");
|
||||
/// <summary>
|
||||
/// Read string from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<string> ReadAsync(CancellationToken token = default)
|
||||
{
|
||||
var data = await ReadLineAsync(token);
|
||||
return data;
|
||||
}
|
||||
|
||||
_serialPort.Close();
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
if (_serialPort == null)
|
||||
return;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
_serialPort.ReadTimeout = (int)timeoutMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<uint> ReadAsync(byte[] dataRead, CancellationToken token = default)
|
||||
{
|
||||
var bytesRead = await _serialPort.BaseStream.ReadAsync(dataRead, 0, dataRead.Length, token);
|
||||
return (uint)bytesRead;
|
||||
}
|
||||
/// <summary>
|
||||
/// Write data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="dataToSend"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite, CancellationToken token = default)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return 0;
|
||||
|
||||
/// <summary>
|
||||
/// Read string from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<string> ReadAsync(CancellationToken token = default)
|
||||
{
|
||||
var data = await ReadLineAsync(token);
|
||||
return data;
|
||||
}
|
||||
await _serialPort.BaseStream.WriteAsync(dataToSend, 0, (int)numBytesToWrite, token);
|
||||
return numBytesToWrite;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
if (_serialPort == null)
|
||||
return;
|
||||
/// <summary>
|
||||
/// Write string data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteAsync(string message, CancellationToken token = default)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return;
|
||||
|
||||
_logger.Trace($"Setting Reader Timeout: {timeoutMs} Ms");
|
||||
_serialPort.ReadTimeout = (int)timeoutMs;
|
||||
}
|
||||
await WriteLineAsync(message, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="dataToSend"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite, CancellationToken token = default)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return 0;
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> SendCommandGetResponseAsync(string message, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return null;
|
||||
|
||||
_logger.Trace($"Writing message to ({_comPortName}), bytes: {dataToSend?.Length}");
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(message, cancellationToken);
|
||||
string readResponse = await ReadAsync(cancellationToken);
|
||||
return readResponse;
|
||||
}
|
||||
}
|
||||
|
||||
await _serialPort.BaseStream.WriteAsync(dataToSend, 0, (int)numBytesToWrite, token);
|
||||
return numBytesToWrite;
|
||||
}
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<byte[]> SendCommandGetResponseAsync(byte[] data, CancellationToken token = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return null;
|
||||
|
||||
/// <summary>
|
||||
/// Write string data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteAsync(string message, CancellationToken token = default)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return;
|
||||
await WriteAsync(data, (uint)data.Length, token);
|
||||
_serialPort.ReadTimeout = timeoutInMs;
|
||||
var response = new byte[data.Length];
|
||||
await ReadAsync(response, token);
|
||||
return response;
|
||||
}
|
||||
|
||||
_logger.Trace($"Writing message to ({_comPortName}), message: {message}");
|
||||
await WriteLineAsync(message, token);
|
||||
}
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return;
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> SendCommandGetResponseAsync(string message, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return null;
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var data = await ReadAsync(cancellationToken);
|
||||
dataReceived?.Invoke(data);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_comPortName}), message: {message}");
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<byte[]> dataReceived)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return;
|
||||
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(message, cancellationToken);
|
||||
string readResponse = await ReadAsync(cancellationToken);
|
||||
_logger.Trace($"Received response: {readResponse}");
|
||||
return readResponse;
|
||||
}
|
||||
}
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var data = new byte[_defaultReadBufferSize]; // Adjust buffer size as needed
|
||||
var bytesRead = await ReadAsync(data, cancellationToken);
|
||||
Array.Resize(ref data, (int)bytesRead);
|
||||
dataReceived?.Invoke(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<byte[]> SendCommandGetResponseAsync(byte[] data, CancellationToken token = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return null;
|
||||
#endregion
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_comPortName}), message: {data}");
|
||||
#region private functions
|
||||
/// <summary>
|
||||
/// reads line async
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> ReadLineAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var line = await Task.Run(() => _serialPort.ReadLine(), cancellationToken);
|
||||
return line;
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
_logger.Error(ex, ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
await WriteAsync(data, (uint)data.Length, token);
|
||||
_serialPort.ReadTimeout = timeoutInMs;
|
||||
var response = new byte[data.Length];
|
||||
await ReadAsync(response, token);
|
||||
return response;
|
||||
}
|
||||
/// <summary>
|
||||
/// writes line async
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
private async Task WriteLineAsync(string message, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
await Task.Run(() => _serialPort.WriteLine(message), cancellationToken);
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
_logger.Error(ex, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return;
|
||||
|
||||
_logger.Debug($"Starting continuous reading from {_comPortName} ...");
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var data = await ReadAsync(cancellationToken);
|
||||
dataReceived?.Invoke(data);
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_comPortName} ...");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<byte[]> dataReceived)
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
return;
|
||||
|
||||
_logger.Debug($"Starting continuous reading from {_comPortName} ...");
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var data = new byte[_defaultReadBufferSize]; // Adjust buffer size as needed
|
||||
var bytesRead = await ReadAsync(data, cancellationToken);
|
||||
Array.Resize(ref data, (int)bytesRead);
|
||||
dataReceived?.Invoke(data);
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_comPortName} ...");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region private functions
|
||||
/// <summary>
|
||||
/// reads line async
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> ReadLineAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var line = await Task.Run(() => _serialPort.ReadLine(), cancellationToken);
|
||||
return line;
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
_logger.Error(ex, ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// writes line async
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
private async Task WriteLineAsync(string message, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
await Task.Run(() => _serialPort.WriteLine(message), cancellationToken);
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
_logger.Error(ex, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,71 +30,63 @@
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceSerialAsyncFactory")]
|
||||
public class CommDeviceSerialAsyncFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceSerialAsyncFactory")]
|
||||
public class CommDeviceSerialAsyncFactory : IInstrumentFactory
|
||||
{
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
public CommDeviceSerialAsyncFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
public CommDeviceSerialAsyncFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceSerialAsyncFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
/// <summary>
|
||||
/// CommDeviceSerialAsyncFactory injection constructor
|
||||
/// </summary>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceSerialAsyncFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommAsync));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new CommDeviceSerialAsync(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommAsync));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CommDeviceSerialAsync(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
@@ -105,9 +97,7 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
return new CommDeviceSerialAsync(name, _configurationManager, _logger);
|
||||
return new CommDeviceSerialAsync(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -120,17 +110,17 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,301 +15,296 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using System;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// A sim communication device
|
||||
/// </summary>
|
||||
public class CommDeviceSim : ICommDevice
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private static object _syncObj = new Object();
|
||||
private readonly string _name;
|
||||
private SelfTestResult _selfTestResult;
|
||||
private State _state;
|
||||
/// <summary>
|
||||
/// A sim communication device
|
||||
/// </summary>
|
||||
public class CommDeviceSim : ICommDevice
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private static object _syncObj = new Object();
|
||||
private readonly string _name;
|
||||
private SelfTestResult _selfTestResult;
|
||||
private State _state;
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#region PrivateFunctions
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~CommDeviceSim()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
#region PrivateFunctions
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~CommDeviceSim()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
|
||||
#region PublicFuctions
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceSim(string name, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
_name = name;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
#region PublicFuctions
|
||||
|
||||
_logger = logger;
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceSim(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
_name = deviceName;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
}
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public CommDeviceSim(string name)
|
||||
{
|
||||
_name = name;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
public CommDeviceSim(string deviceName)
|
||||
{
|
||||
_name = deviceName;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DisplayEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DisplayEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a Comm Device Sim called " + _name;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a Comm Device Sim called " + _name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
/// <summary>
|
||||
/// Dispose of the resources
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
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()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_state = State.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on device " + _name);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_state = State.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on device " + _name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/*public void Open()
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/*public void Open()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_selfTestResult = SelfTestResult.Pass;
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_selfTestResult = SelfTestResult.Pass;
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
return (uint)dataRead.Length;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Read data from the device.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
return (uint)dataRead.Length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeout"></param>
|
||||
public void SetReadTimeout(uint timeout)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeout"></param>
|
||||
public void SetReadTimeout(uint timeout)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device
|
||||
/// </summary>
|
||||
/// <param name="dataToSend">The data to write</param>
|
||||
/// <param name="numBytesToWrite">The number of bytes to write</param>
|
||||
/// <returns>THe number of bytes that were written</returns>
|
||||
public uint Write(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
return numBytesToWrite;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Write data to the device
|
||||
/// </summary>
|
||||
/// <param name="dataToSend">The data to write</param>
|
||||
/// <param name="numBytesToWrite">The number of bytes to write</param>
|
||||
/// <returns>THe number of bytes that were written</returns>
|
||||
public uint Write(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
return numBytesToWrite;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public void Close()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
public void Open()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +1,61 @@
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceSimFactory")]
|
||||
public class CommDeviceSimFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceSimFactory")]
|
||||
public class CommDeviceSimFactory : IInstrumentFactory
|
||||
{
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
|
||||
public CommDeviceSimFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceSimFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
public CommDeviceSimFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceSimFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new CommDeviceSim(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CommDeviceSim(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
@@ -73,9 +66,7 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
return new CommDeviceSim(name, _configurationManager, _logger);
|
||||
return new CommDeviceSim(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -88,17 +79,17 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,503 +15,497 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using System;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for controlling a Commtech SUPERFSCC/4-PCIE-11
|
||||
/// </summary>
|
||||
public class CommDeviceSuperFscc422 : ICommDevice, IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
/// <summary>
|
||||
/// Class for controlling a Commtech SUPERFSCC/4-PCIE-11
|
||||
/// </summary>
|
||||
public class CommDeviceSuperFscc422 : ICommDevice, IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
|
||||
private const uint _DEFAULT_READ_TIMEOUT = 10;
|
||||
private const uint _RX_FIFO_BUFFER_SIZE = 8192;
|
||||
private const uint _TX_FIFO_BUFFER_SIZE = 4096;
|
||||
// The Super FSCC can DMA can stream data at 50 Mbits/sec
|
||||
// The driver automatically transfers data from the FIFO into the MemoryCap which has a configurable size. Default to ~GB
|
||||
private const uint _DEFAULT_READ_TIMEOUT = 10;
|
||||
private const uint _RX_FIFO_BUFFER_SIZE = 8192;
|
||||
private const uint _TX_FIFO_BUFFER_SIZE = 4096;
|
||||
// The Super FSCC can DMA can stream data at 50 Mbits/sec
|
||||
// The driver automatically transfers data from the FIFO into the MemoryCap which has a configurable size. Default to ~GB
|
||||
|
||||
private uint _readTimeout;
|
||||
private Fscc.Port _fscc;
|
||||
private static object _syncObj = new Object();
|
||||
private readonly string _name;
|
||||
private SelfTestResult _selfTestResult;
|
||||
private State _state;
|
||||
private readonly uint _portNum;
|
||||
private readonly uint _clockFreq;
|
||||
private readonly bool _shallWeReceiveMultiple;
|
||||
private readonly bool _shallWeAppendStatus;
|
||||
private readonly uint _bgrRegister;
|
||||
private readonly uint _ccr0Register;
|
||||
private readonly uint _ccr0SofResetValue;
|
||||
private readonly uint _ccr1Register;
|
||||
private readonly uint _ccr2Register;
|
||||
private readonly uint _dpllrRegister;
|
||||
private readonly uint _fcrRegister;
|
||||
private readonly uint _fifotRegister;
|
||||
private readonly uint _imrRegister;
|
||||
private readonly uint _pprRegister;
|
||||
private readonly uint _ramrRegister;
|
||||
private readonly uint _rarRegister;
|
||||
private readonly uint _smrRegister;
|
||||
private readonly uint _ssrRegister;
|
||||
private readonly uint _tcrRegister;
|
||||
private readonly uint _tmrRegister;
|
||||
private readonly uint _tsrRegister;
|
||||
private uint _readTimeout;
|
||||
private Fscc.Port _fscc;
|
||||
private static object _syncObj = new Object();
|
||||
private readonly string _name;
|
||||
private SelfTestResult _selfTestResult;
|
||||
private State _state;
|
||||
private readonly uint _portNum;
|
||||
private readonly uint _clockFreq;
|
||||
private readonly bool _shallWeReceiveMultiple;
|
||||
private readonly bool _shallWeAppendStatus;
|
||||
private readonly uint _bgrRegister;
|
||||
private readonly uint _ccr0Register;
|
||||
private readonly uint _ccr0SofResetValue;
|
||||
private readonly uint _ccr1Register;
|
||||
private readonly uint _ccr2Register;
|
||||
private readonly uint _dpllrRegister;
|
||||
private readonly uint _fcrRegister;
|
||||
private readonly uint _fifotRegister;
|
||||
private readonly uint _imrRegister;
|
||||
private readonly uint _pprRegister;
|
||||
private readonly uint _ramrRegister;
|
||||
private readonly uint _rarRegister;
|
||||
private readonly uint _smrRegister;
|
||||
private readonly uint _ssrRegister;
|
||||
private readonly uint _tcrRegister;
|
||||
private readonly uint _tmrRegister;
|
||||
private readonly uint _tsrRegister;
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PrivateFuctions
|
||||
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~CommDeviceSuperFscc422()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_fscc.Dispose();
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Error(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>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceSuperFscc422(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
_name = deviceName;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
_portNum = _configuration.GetConfigurationValue<uint>("SuperFscc422", "PortNum", 0);
|
||||
_clockFreq = _configuration.GetConfigurationValue<uint>("SuperFscc422", "ClockFreq", 0);
|
||||
_shallWeReceiveMultiple = _configuration.GetConfigurationValue("SuperFscc422", "ShallWeReceiveMultiple", false);
|
||||
_shallWeAppendStatus = _configuration.GetConfigurationValue("SuperFscc422", "ShallWeAppendStatus", false);
|
||||
_bgrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "BgrRegister", 0);
|
||||
_ccr0Register = _configuration.GetConfigurationValue<uint>("SuperFscc422", "Ccr0Register", 0);
|
||||
_ccr0SofResetValue = _configuration.GetConfigurationValue<uint>("SuperFscc422", "Ccr0SofResetValue", 0);
|
||||
_ccr1Register = _configuration.GetConfigurationValue<uint>("SuperFscc422", "Ccr1Register", 0);
|
||||
_ccr2Register = _configuration.GetConfigurationValue<uint>("SuperFscc422", "Ccr2Register", 0);
|
||||
_dpllrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "DpllrRegister", 0);
|
||||
_fcrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "FcrRegister", 0);
|
||||
_fifotRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "FifotRegister", 0);
|
||||
_imrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "ImrRegister", 0);
|
||||
_pprRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "PprRegister", 0);
|
||||
_ramrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "RamrRegister", 0);
|
||||
_rarRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "RarRegister", 0);
|
||||
_smrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "SmrRegister", 0);
|
||||
_ssrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "SsrRegister", 0);
|
||||
_tcrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "TcrRegister", 0);
|
||||
_tmrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "TmrRegister", 0);
|
||||
_tsrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "TsrRegister", 0);
|
||||
|
||||
_readTimeout = _DEFAULT_READ_TIMEOUT;
|
||||
|
||||
// created in Initialize()
|
||||
_fscc = null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
/// <summary>
|
||||
/// Opens the port and initializes the registers
|
||||
/// </summary>
|
||||
/// <param name="portNum"></param>
|
||||
/// <param name="clockFreq"></param>
|
||||
/// <param name="shallWeReceiveMultiple"></param>
|
||||
/// <param name="shallWeAppendStatus"></param>
|
||||
/// <param name="bgrRegister"></param>
|
||||
/// <param name="ccr0Register"></param>
|
||||
/// <param name="ccr0SofResetValue"></param>
|
||||
/// <param name="ccr1Register"></param>
|
||||
/// <param name="ccr2Register"></param>
|
||||
/// <param name="dpllrRegister"></param>
|
||||
/// <param name="fcrRegister"></param>
|
||||
/// <param name="fifotRegister"></param>
|
||||
/// <param name="imrRegister"></param>
|
||||
/// <param name="pprRegister"></param>
|
||||
/// <param name="ramrRegister"></param>
|
||||
/// <param name="rarRegister"></param>
|
||||
/// <param name="smrRegister"></param>
|
||||
/// <param name="ssrRegister"></param>
|
||||
/// <param name="tcrRegister"></param>
|
||||
/// <param name="tmrRegister"></param>
|
||||
/// <param name="tsrRegister"></param>
|
||||
public CommDeviceSuperFscc422(string deviceName, uint portNum, uint clockFreq, bool shallWeReceiveMultiple, bool shallWeAppendStatus, uint bgrRegister, uint ccr0Register,
|
||||
uint ccr0SofResetValue, uint ccr1Register, uint ccr2Register, uint dpllrRegister, uint fcrRegister, uint fifotRegister,
|
||||
uint imrRegister, uint pprRegister, uint ramrRegister, uint rarRegister, uint smrRegister, uint ssrRegister, uint tcrRegister, uint tmrRegister, uint tsrRegister)
|
||||
{
|
||||
_name = deviceName;
|
||||
_portNum = portNum;
|
||||
_clockFreq = clockFreq;
|
||||
_shallWeReceiveMultiple = shallWeReceiveMultiple;
|
||||
_shallWeAppendStatus = shallWeAppendStatus;
|
||||
_bgrRegister = bgrRegister;
|
||||
_ccr0Register = ccr0Register;
|
||||
_ccr0SofResetValue = ccr0SofResetValue;
|
||||
_ccr1Register = ccr1Register;
|
||||
_ccr2Register = ccr2Register;
|
||||
_dpllrRegister = dpllrRegister;
|
||||
_fcrRegister = fcrRegister;
|
||||
_fifotRegister = fifotRegister;
|
||||
_imrRegister = imrRegister;
|
||||
_pprRegister = pprRegister;
|
||||
_ramrRegister = ramrRegister;
|
||||
_rarRegister = rarRegister;
|
||||
_smrRegister = smrRegister;
|
||||
_ssrRegister = ssrRegister;
|
||||
_tcrRegister = tcrRegister;
|
||||
_tmrRegister = tmrRegister;
|
||||
_tsrRegister = tsrRegister;
|
||||
|
||||
#endregion
|
||||
_readTimeout = _DEFAULT_READ_TIMEOUT;
|
||||
|
||||
#region PrivateFuctions
|
||||
// created in Initialize()
|
||||
_fscc = null;
|
||||
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~CommDeviceSuperFscc422()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_fscc.Dispose();
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DisplayEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#region PublicFuctions
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceSuperFscc422(string name, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
_name = name;
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a FSCC 422 Device called " + _name;
|
||||
}
|
||||
}
|
||||
|
||||
_logger = logger;
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_portNum = _configuration.GetConfigurationValue<uint>("SuperFscc422", "PortNum", 0);
|
||||
_clockFreq = _configuration.GetConfigurationValue<uint>("SuperFscc422", "ClockFreq", 0);
|
||||
_shallWeReceiveMultiple = _configuration.GetConfigurationValue("SuperFscc422", "ShallWeReceiveMultiple", false);
|
||||
_shallWeAppendStatus = _configuration.GetConfigurationValue("SuperFscc422", "ShallWeAppendStatus", false);
|
||||
_bgrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "BgrRegister", 0);
|
||||
_ccr0Register = _configuration.GetConfigurationValue<uint>("SuperFscc422", "Ccr0Register", 0);
|
||||
_ccr0SofResetValue = _configuration.GetConfigurationValue<uint>("SuperFscc422", "Ccr0SofResetValue", 0);
|
||||
_ccr1Register = _configuration.GetConfigurationValue<uint>("SuperFscc422", "Ccr1Register", 0);
|
||||
_ccr2Register = _configuration.GetConfigurationValue<uint>("SuperFscc422", "Ccr2Register", 0);
|
||||
_dpllrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "DpllrRegister", 0);
|
||||
_fcrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "FcrRegister", 0);
|
||||
_fifotRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "FifotRegister", 0);
|
||||
_imrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "ImrRegister", 0);
|
||||
_pprRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "PprRegister", 0);
|
||||
_ramrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "RamrRegister", 0);
|
||||
_rarRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "RarRegister", 0);
|
||||
_smrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "SmrRegister", 0);
|
||||
_ssrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "SsrRegister", 0);
|
||||
_tcrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "TcrRegister", 0);
|
||||
_tmrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "TmrRegister", 0);
|
||||
_tsrRegister = _configuration.GetConfigurationValue<uint>("SuperFscc422", "TsrRegister", 0);
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
_readTimeout = _DEFAULT_READ_TIMEOUT;
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
// created in Initialize()
|
||||
_fscc = null;
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public InstrumentMetadata Info
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_fscc = new Fscc.Port(_portNum);
|
||||
|
||||
/// <summary>
|
||||
/// Opens the port and initializes the registers
|
||||
/// </summary>
|
||||
/// <param name="portNum"></param>
|
||||
/// <param name="clockFreq"></param>
|
||||
/// <param name="shallWeReceiveMultiple"></param>
|
||||
/// <param name="shallWeAppendStatus"></param>
|
||||
/// <param name="bgrRegister"></param>
|
||||
/// <param name="ccr0Register"></param>
|
||||
/// <param name="ccr0SofResetValue"></param>
|
||||
/// <param name="ccr1Register"></param>
|
||||
/// <param name="ccr2Register"></param>
|
||||
/// <param name="dpllrRegister"></param>
|
||||
/// <param name="fcrRegister"></param>
|
||||
/// <param name="fifotRegister"></param>
|
||||
/// <param name="imrRegister"></param>
|
||||
/// <param name="pprRegister"></param>
|
||||
/// <param name="ramrRegister"></param>
|
||||
/// <param name="rarRegister"></param>
|
||||
/// <param name="smrRegister"></param>
|
||||
/// <param name="ssrRegister"></param>
|
||||
/// <param name="tcrRegister"></param>
|
||||
/// <param name="tmrRegister"></param>
|
||||
/// <param name="tsrRegister"></param>
|
||||
public CommDeviceSuperFscc422(string name, uint portNum, uint clockFreq, bool shallWeReceiveMultiple, bool shallWeAppendStatus, uint bgrRegister, uint ccr0Register,
|
||||
uint ccr0SofResetValue, uint ccr1Register, uint ccr2Register, uint dpllrRegister, uint fcrRegister, uint fifotRegister,
|
||||
uint imrRegister, uint pprRegister, uint ramrRegister, uint rarRegister, uint smrRegister, uint ssrRegister, uint tcrRegister, uint tmrRegister, uint tsrRegister)
|
||||
{
|
||||
_name = name;
|
||||
_portNum = portNum;
|
||||
_clockFreq = clockFreq;
|
||||
_shallWeReceiveMultiple = shallWeReceiveMultiple;
|
||||
_shallWeAppendStatus = shallWeAppendStatus;
|
||||
_bgrRegister = bgrRegister;
|
||||
_ccr0Register = ccr0Register;
|
||||
_ccr0SofResetValue = ccr0SofResetValue;
|
||||
_ccr1Register = ccr1Register;
|
||||
_ccr2Register = ccr2Register;
|
||||
_dpllrRegister = dpllrRegister;
|
||||
_fcrRegister = fcrRegister;
|
||||
_fifotRegister = fifotRegister;
|
||||
_imrRegister = imrRegister;
|
||||
_pprRegister = pprRegister;
|
||||
_ramrRegister = ramrRegister;
|
||||
_rarRegister = rarRegister;
|
||||
_smrRegister = smrRegister;
|
||||
_ssrRegister = ssrRegister;
|
||||
_tcrRegister = tcrRegister;
|
||||
_tmrRegister = tmrRegister;
|
||||
_tsrRegister = tsrRegister;
|
||||
// false means that each read will return a single sdlc packet
|
||||
// true means that each read will return everything in the buffer (multiple packets)
|
||||
_fscc.RxMultiple = _shallWeReceiveMultiple;
|
||||
|
||||
_readTimeout = _DEFAULT_READ_TIMEOUT;
|
||||
// if this to true...extra 2 bytes arrive at the end of every frame (first two bytes of STAR)
|
||||
// The class processing the data needs to be aware of the extra two bytes
|
||||
_fscc.AppendStatus = _shallWeAppendStatus;
|
||||
|
||||
// created in Initialize()
|
||||
_fscc = null;
|
||||
// ignore timeouts
|
||||
_fscc.IgnoreTimeout = true;
|
||||
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
// purge the port
|
||||
_fscc.Purge(true, true);
|
||||
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
// set the registers
|
||||
_fscc.Registers.BGR = _bgrRegister;
|
||||
_fscc.Registers.CCR0 = _ccr0Register;
|
||||
_fscc.Registers.CCR1 = _ccr1Register;
|
||||
_fscc.Registers.CCR2 = _ccr2Register;
|
||||
_fscc.Registers.DPLLR = _dpllrRegister;
|
||||
_fscc.Registers.FCR = _fcrRegister;
|
||||
_fscc.Registers.FIFOT = _fifotRegister;
|
||||
_fscc.Registers.IMR = _imrRegister;
|
||||
_fscc.Registers.PPR = _pprRegister;
|
||||
_fscc.Registers.RAMR = _ramrRegister;
|
||||
_fscc.Registers.RAR = _rarRegister;
|
||||
_fscc.Registers.SMR = _smrRegister;
|
||||
_fscc.Registers.SSR = _ssrRegister;
|
||||
_fscc.Registers.TCR = _tcrRegister;
|
||||
_fscc.Registers.TMR = _tmrRegister;
|
||||
_fscc.Registers.TSR = _tsrRegister;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
// false means that each read will return a single sdlc packet
|
||||
// true means that each read will return everything in the buffer (multiple packets)
|
||||
_fscc.RxMultiple = _shallWeReceiveMultiple;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DisplayEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
_fscc.ClockFrequency = _clockFreq;
|
||||
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
// if this to true...extra 2 bytes arrive at the end of every frame (first two bytes of STAR)
|
||||
// The class processing the data needs to be aware of the extra two bytes
|
||||
_fscc.AppendStatus = _shallWeAppendStatus;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a FSCC 422 Device called " + _name;
|
||||
}
|
||||
}
|
||||
_state = State.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on device " + _name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <summary>
|
||||
/// Read data from the device.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
uint numBytesRead = _fscc.Read(dataRead, (uint)dataRead.Length, _readTimeout);
|
||||
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
return numBytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public InstrumentMetadata Info
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Soft reset procedure as suggested by the vendor
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_fscc.Registers.CCR0 = _ccr0SofResetValue;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_fscc = new Fscc.Port(_portNum);
|
||||
_fscc.Purge(true, true);
|
||||
|
||||
// false means that each read will return a single sdlc packet
|
||||
// true means that each read will return everything in the buffer (multiple packets)
|
||||
_fscc.RxMultiple = _shallWeReceiveMultiple;
|
||||
_fscc.Registers.CCR0 = _ccr0Register;
|
||||
}
|
||||
}
|
||||
|
||||
// if this to true...extra 2 bytes arrive at the end of every frame (first two bytes of STAR)
|
||||
// The class processing the data needs to be aware of the extra two bytes
|
||||
_fscc.AppendStatus = _shallWeAppendStatus;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_readTimeout = timeoutMs;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore timeouts
|
||||
_fscc.IgnoreTimeout = true;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public SelfTestResult SelfTestResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
|
||||
// purge the port
|
||||
_fscc.Purge(true, true);
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public State Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
|
||||
// set the registers
|
||||
_fscc.Registers.BGR = _bgrRegister;
|
||||
_fscc.Registers.CCR0 = _ccr0Register;
|
||||
_fscc.Registers.CCR1 = _ccr1Register;
|
||||
_fscc.Registers.CCR2 = _ccr2Register;
|
||||
_fscc.Registers.DPLLR = _dpllrRegister;
|
||||
_fscc.Registers.FCR = _fcrRegister;
|
||||
_fscc.Registers.FIFOT = _fifotRegister;
|
||||
_fscc.Registers.IMR = _imrRegister;
|
||||
_fscc.Registers.PPR = _pprRegister;
|
||||
_fscc.Registers.RAMR = _ramrRegister;
|
||||
_fscc.Registers.RAR = _rarRegister;
|
||||
_fscc.Registers.SMR = _smrRegister;
|
||||
_fscc.Registers.SSR = _ssrRegister;
|
||||
_fscc.Registers.TCR = _tcrRegister;
|
||||
_fscc.Registers.TMR = _tmrRegister;
|
||||
_fscc.Registers.TSR = _tsrRegister;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_fscc.Dispose();
|
||||
|
||||
// false means that each read will return a single sdlc packet
|
||||
// true means that each read will return everything in the buffer (multiple packets)
|
||||
_fscc.RxMultiple = _shallWeReceiveMultiple;
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_fscc.ClockFrequency = _clockFreq;
|
||||
/// <summary>
|
||||
/// Write data to the device
|
||||
/// </summary>
|
||||
/// <param name="dataToSend">The data to write</param>
|
||||
/// <param name="numBytesToWrite">The number of bytes to write</param>
|
||||
/// <returns>THe number of bytes that were written</returns>
|
||||
public uint Write(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
uint numWritten = _fscc.Write(dataToSend, numBytesToWrite);
|
||||
|
||||
// if this to true...extra 2 bytes arrive at the end of every frame (first two bytes of STAR)
|
||||
// The class processing the data needs to be aware of the extra two bytes
|
||||
_fscc.AppendStatus = _shallWeAppendStatus;
|
||||
if (numWritten != numBytesToWrite)
|
||||
{
|
||||
throw new Exception("num written " + numWritten + " not as expected: " + numBytesToWrite);
|
||||
}
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on device " + _name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return numWritten;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
public void Close()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
public void Open()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
uint numBytesRead = _fscc.Read(dataRead, (uint)dataRead.Length, _readTimeout);
|
||||
|
||||
return numBytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Soft reset procedure as suggested by the vendor
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_fscc.Registers.CCR0 = _ccr0SofResetValue;
|
||||
|
||||
_fscc.Purge(true, true);
|
||||
|
||||
_fscc.Registers.CCR0 = _ccr0Register;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_readTimeout = timeoutMs;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public SelfTestResult SelfTestResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public State Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_fscc.Dispose();
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device
|
||||
/// </summary>
|
||||
/// <param name="dataToSend">The data to write</param>
|
||||
/// <param name="numBytesToWrite">The number of bytes to write</param>
|
||||
/// <returns>THe number of bytes that were written</returns>
|
||||
public uint Write(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
uint numWritten = _fscc.Write(dataToSend, numBytesToWrite);
|
||||
|
||||
if (numWritten != numBytesToWrite)
|
||||
{
|
||||
throw new Exception("num written " + numWritten + " not as expected: " + numBytesToWrite);
|
||||
}
|
||||
|
||||
return numWritten;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +1,60 @@
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceSuperFscc422Factory")]
|
||||
public class CommDeviceSuperFscc422Factory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceSuperFscc422Factory")]
|
||||
public class CommDeviceSuperFscc422Factory : IInstrumentFactory
|
||||
{
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
public CommDeviceSuperFscc422Factory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
public CommDeviceSuperFscc422Factory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceSuperFscc422Factory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
/// <summary>
|
||||
/// CommDeviceSuperFscc422Factory injection constructor
|
||||
/// </summary>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceSuperFscc422Factory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new CommDeviceSuperFscc422(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CommDeviceSuperFscc422(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
@@ -73,12 +65,10 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
if (simulateHw)
|
||||
return new CommDeviceSim(name, _configurationManager, _logger);
|
||||
return new CommDeviceSim(name, _configurationManager);
|
||||
else
|
||||
return new CommDeviceSuperFscc422(name, _configurationManager, _logger);
|
||||
return new CommDeviceSuperFscc422(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -91,71 +81,71 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="instrumentDefFile"></param>
|
||||
/// <param name="iniSectionName"></param>
|
||||
/// <param name="isThereHardware"></param>
|
||||
/// <returns></returns>
|
||||
public static ICommDevice CreateFastCommDevice(string instrumentDefFile, string iniSectionName, bool isThereHardware)
|
||||
{
|
||||
const string FAST_COMM_FSCC = "FAST_COMM_FSCC";
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="instrumentDefFile"></param>
|
||||
/// <param name="iniSectionName"></param>
|
||||
/// <param name="isThereHardware"></param>
|
||||
/// <returns></returns>
|
||||
public static ICommDevice CreateFastCommDevice(string instrumentDefFile, string iniSectionName, bool isThereHardware)
|
||||
{
|
||||
const string FAST_COMM_FSCC = "FAST_COMM_FSCC";
|
||||
|
||||
IniFile iniReader = new IniFile(instrumentDefFile);
|
||||
IniFile iniReader = new IniFile(instrumentDefFile);
|
||||
|
||||
bool shallWeDebug = Convert.ToBoolean(iniReader.ReadValue(FAST_COMM_FSCC, "SHALL_WE_DEBUG"));
|
||||
uint port = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "PORT"));
|
||||
uint clock = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CLOCK_FREQUENCY"), 16);
|
||||
uint bgr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "BGR_REGISTER"), 16);
|
||||
uint ccr0 = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR0_REGISTER"), 16);
|
||||
uint ccr0Reset = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR0_SOF_RESET_VALUE"), 16);
|
||||
uint ccr1 = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR1_REGISTER"), 16);
|
||||
uint ccr2 = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR2_REGISTER"), 16);
|
||||
uint dpllr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "DPLLR_REGISTER"), 16);
|
||||
uint fcr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "FCR_REGISTER"), 16);
|
||||
uint fifot = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "FIFO_T_REGISTER"), 16);
|
||||
uint imr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "IMR_REGISTER"), 16);
|
||||
uint ppr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "PPR_REGISTER"), 16);
|
||||
uint ramr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "RAMR_REGISTER"), 16);
|
||||
uint rar = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "RAR_REGISTER"), 16);
|
||||
uint smr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "SMR_REGISTER"), 16);
|
||||
uint ssr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "SSR_REGISTER"), 16);
|
||||
uint tcr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "TCR_REGISTER"), 16);
|
||||
uint tmr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "TMR_REGISTER"), 16);
|
||||
uint tsr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "TSR_REGISTER"), 16);
|
||||
bool shallWeDebug = Convert.ToBoolean(iniReader.ReadValue(FAST_COMM_FSCC, "SHALL_WE_DEBUG"));
|
||||
uint port = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "PORT"));
|
||||
uint clock = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CLOCK_FREQUENCY"), 16);
|
||||
uint bgr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "BGR_REGISTER"), 16);
|
||||
uint ccr0 = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR0_REGISTER"), 16);
|
||||
uint ccr0Reset = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR0_SOF_RESET_VALUE"), 16);
|
||||
uint ccr1 = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR1_REGISTER"), 16);
|
||||
uint ccr2 = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR2_REGISTER"), 16);
|
||||
uint dpllr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "DPLLR_REGISTER"), 16);
|
||||
uint fcr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "FCR_REGISTER"), 16);
|
||||
uint fifot = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "FIFO_T_REGISTER"), 16);
|
||||
uint imr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "IMR_REGISTER"), 16);
|
||||
uint ppr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "PPR_REGISTER"), 16);
|
||||
uint ramr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "RAMR_REGISTER"), 16);
|
||||
uint rar = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "RAR_REGISTER"), 16);
|
||||
uint smr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "SMR_REGISTER"), 16);
|
||||
uint ssr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "SSR_REGISTER"), 16);
|
||||
uint tcr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "TCR_REGISTER"), 16);
|
||||
uint tmr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "TMR_REGISTER"), 16);
|
||||
uint tsr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "TSR_REGISTER"), 16);
|
||||
|
||||
bool shallWeReceiveMultiple = true;
|
||||
bool shallWeAppendStatus = false;
|
||||
bool shallWeReceiveMultiple = true;
|
||||
bool shallWeAppendStatus = false;
|
||||
|
||||
if (shallWeDebug == true)
|
||||
{
|
||||
shallWeReceiveMultiple = false;
|
||||
shallWeAppendStatus = true;
|
||||
}
|
||||
if (shallWeDebug == true)
|
||||
{
|
||||
shallWeReceiveMultiple = false;
|
||||
shallWeAppendStatus = true;
|
||||
}
|
||||
|
||||
if (isThereHardware == true)
|
||||
{
|
||||
return new CommDeviceSuperFscc422(iniSectionName, port, clock, shallWeReceiveMultiple, shallWeAppendStatus, bgr, ccr0, ccr0Reset, ccr1, ccr2, dpllr, fcr, fifot, imr, ppr, ramr, rar, smr, ssr, tcr, tmr, tsr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new CommDeviceSim(iniSectionName);
|
||||
}
|
||||
}
|
||||
if (isThereHardware == true)
|
||||
{
|
||||
return new CommDeviceSuperFscc422(iniSectionName, port, clock, shallWeReceiveMultiple, shallWeAppendStatus, bgr, ccr0, ccr0Reset, ccr1, ccr2, dpllr, fcr, fifot, imr, ppr, ramr, rar, smr, ssr, tcr, tmr, tsr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new CommDeviceSim(iniSectionName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,436 +30,431 @@
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// A sim communication device
|
||||
/// </summary>
|
||||
public class CommDeviceTcpAsync : ICommAsync
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
|
||||
private uint _defaultReadTimeout;
|
||||
private uint _defaultSendTimeout;
|
||||
private uint _defaultReadBufferSize;
|
||||
private static readonly object _syncObj = new object();
|
||||
private TcpClient _tcpClient;
|
||||
private TcpListener _tcpListener;
|
||||
private NetworkStream _tcpIpStream;
|
||||
private int _port;
|
||||
private string _remoteAddress;
|
||||
private int _remotePort;
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#endregion
|
||||
|
||||
public bool ClearErrors() => false;
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
|
||||
public InstrumentMetadata Info => throw new NotImplementedException();
|
||||
public State Status => _state;
|
||||
public string Name => _name;
|
||||
public SelfTestResult PerformSelfTest() => SelfTestResult;
|
||||
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
|
||||
public void Open() => Initialize();
|
||||
public void Close() => Shutdown();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
|
||||
#region Private Functions
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close the socket
|
||||
try
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceTcpAsync(string name, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
_name = name;
|
||||
|
||||
// _tcpClient is created in Initialize()
|
||||
_tcpClient = null;
|
||||
_tcpIpStream = null;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_logger = logger;
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
if (_state != State.Uninitialized)
|
||||
{
|
||||
_logger.Warn("Reinitialization of existing TCP Async Connection. Attempting to call Shutdown.");
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
_defaultReadTimeout = _configuration.GetConfigurationValue<uint>("TcpClient", "ReadTimeout", 25);
|
||||
_defaultSendTimeout = _configuration.GetConfigurationValue<uint>("TcpClient", "SendTimeout", 5000);
|
||||
_defaultReadBufferSize = _configuration.GetConfigurationValue<uint>("TcpClient", "BufferSize", 1024);
|
||||
|
||||
_remoteAddress = _configuration.GetConfigurationValue("TcpClient", "RemoteAddress", "127.0.0.1");
|
||||
_port = _configuration.GetConfigurationValue("TcpClient", "Port", 0);
|
||||
|
||||
if (string.IsNullOrEmpty(_remoteAddress))
|
||||
{
|
||||
_tcpListener = new TcpListener(IPAddress.Any, _port);
|
||||
_tcpListener.Start();
|
||||
|
||||
_logger.Debug($"{MethodBase.GetCurrentMethod().Name} Started Listening on Port: {_port}");
|
||||
|
||||
Task.Run(async () => await _tcpListener.AcceptTcpClientAsync()).ContinueWith(t =>
|
||||
{
|
||||
_tcpClient = t.Result;
|
||||
|
||||
_remoteAddress = ((IPEndPoint)_tcpClient.Client.RemoteEndPoint).Address.ToString();
|
||||
_remotePort = ((IPEndPoint)_tcpClient.Client.RemoteEndPoint).Port;
|
||||
|
||||
_logger.Debug($"{MethodBase.GetCurrentMethod().Name} Connection Established from Remote Address: {_remoteAddress}:{_remotePort}");
|
||||
|
||||
// set timeouts
|
||||
_tcpClient.Client.SendTimeout = (int)_defaultSendTimeout;
|
||||
_tcpClient.Client.ReceiveTimeout = (int)_defaultReadTimeout;
|
||||
|
||||
// get the stream
|
||||
_tcpIpStream = _tcpClient.GetStream();
|
||||
|
||||
_state = State.Ready;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_remotePort = _port;
|
||||
_tcpClient = new TcpClient(_remoteAddress, _remotePort);
|
||||
|
||||
_logger.Debug($"{MethodBase.GetCurrentMethod().Name} Connected to Remote Address {_remoteAddress}:{_remotePort}");
|
||||
|
||||
// set timeouts
|
||||
_tcpClient.Client.SendTimeout = (int)_defaultSendTimeout;
|
||||
_tcpClient.Client.ReceiveTimeout = (int)_defaultReadTimeout;
|
||||
|
||||
// get the stream
|
||||
_tcpIpStream = _tcpClient.GetStream();
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// shuts down the device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
_logger.Debug("Shutting down");
|
||||
_tcpClient?.Dispose();
|
||||
_tcpClient = null;
|
||||
|
||||
_tcpListener?.Stop();
|
||||
_tcpListener = null;
|
||||
|
||||
_tcpIpStream?.Dispose();
|
||||
_tcpIpStream = null;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<uint> ReadAsync(byte[] dataRead, CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return 0;
|
||||
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var bytesRead = await _tcpIpStream.ReadAsync(dataRead, 0, dataRead.Length, token);
|
||||
|
||||
_logger.Trace($"Reading Data, bytes received: {bytesRead}");
|
||||
|
||||
_state = State.Ready;
|
||||
return (uint)bytesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read string from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<string> ReadAsync(CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return null;
|
||||
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var buffer = new byte[_defaultReadBufferSize];
|
||||
var bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, token);
|
||||
_state = State.Ready;
|
||||
|
||||
var message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||
|
||||
_logger.Trace($"Reading Data, message received: {message}");
|
||||
|
||||
return message;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
_logger.Trace($"Setting Reader Timeout: {timeoutMs} Ms");
|
||||
|
||||
_tcpClient.Client.ReceiveTimeout = (int)timeoutMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="dataToSend"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite, CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return 0;
|
||||
|
||||
_logger.Trace($"Writing message to ({_remoteAddress}:{_remotePort}), bytes: {dataToSend?.Length}");
|
||||
|
||||
_state = State.Busy;
|
||||
await _tcpIpStream.WriteAsync(dataToSend, 0, (int)numBytesToWrite, token);
|
||||
_state = State.Ready;
|
||||
return numBytesToWrite;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write string data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteAsync(string message, CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return;
|
||||
|
||||
_logger.Trace($"Writing message to ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
|
||||
_state = State.Busy;
|
||||
var buffer = Encoding.UTF8.GetBytes(message);
|
||||
await _tcpIpStream.WriteAsync(buffer, 0, buffer.Length, token);
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> SendCommandGetResponseAsync(string message, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return null;
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(message, cancellationToken);
|
||||
string readResponse = await ReadAsync(cancellationToken);
|
||||
_logger.Trace($"Received response: {readResponse}");
|
||||
return readResponse;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<byte[]> SendCommandGetResponseAsync(byte[] data, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return null;
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_remoteAddress}:{_remotePort}), message: {data}");
|
||||
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(data, (uint)data.Length, cancellationToken);
|
||||
byte[] buffer = new byte[_defaultReadBufferSize];
|
||||
uint bytesRead = await ReadAsync(buffer, cancellationToken);
|
||||
_logger.Trace($"Received response of size: {bytesRead}");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
|
||||
{
|
||||
_logger.Debug($"Starting continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
|
||||
byte[] buffer = new byte[_defaultReadBufferSize];
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint bytesRead = await ReadAsync(buffer, cancellationToken);
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
string data = Encoding.UTF8.GetString(buffer, 0, (int)bytesRead);
|
||||
|
||||
_logger.Trace($"Message received from {_remoteAddress}:{_remotePort}: {data}");
|
||||
|
||||
dataReceived(data);
|
||||
Array.Clear(buffer, 0, (int)bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<byte[]> dataReceived)
|
||||
{
|
||||
_logger.Debug($"Starting continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
|
||||
byte[] buffer = new byte[_defaultReadBufferSize];
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint bytesRead = await ReadAsync(buffer, cancellationToken);
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
_logger.Trace($"Message received from {_remoteAddress}:{_remotePort}: size {bytesRead}");
|
||||
byte[] bufferCopy = new byte[bytesRead];
|
||||
Array.Copy(buffer, bufferCopy, bytesRead);
|
||||
dataReceived(bufferCopy);
|
||||
Array.Clear(buffer, 0, (int)bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
/// <summary>
|
||||
/// A sim communication device
|
||||
/// </summary>
|
||||
public class CommDeviceTcpAsync : ICommAsync
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
|
||||
private uint _defaultReadTimeout;
|
||||
private uint _defaultSendTimeout;
|
||||
private uint _defaultReadBufferSize;
|
||||
private static readonly object _syncObj = new object();
|
||||
private TcpClient _tcpClient;
|
||||
private TcpListener _tcpListener;
|
||||
private NetworkStream _tcpIpStream;
|
||||
private int _port;
|
||||
private string _remoteAddress;
|
||||
private int _remotePort;
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#endregion
|
||||
|
||||
public bool ClearErrors() => false;
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
|
||||
public InstrumentMetadata Info => throw new NotImplementedException();
|
||||
public State Status => _state;
|
||||
public string Name => _name;
|
||||
public SelfTestResult PerformSelfTest() => SelfTestResult;
|
||||
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
|
||||
public void Open() => Initialize();
|
||||
public void Close() => Shutdown();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
|
||||
#region Private Functions
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close the socket
|
||||
try
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceTcpAsync(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
_name = deviceName;
|
||||
|
||||
// _tcpClient is created in Initialize()
|
||||
_tcpClient = null;
|
||||
_tcpIpStream = null;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
if (_state != State.Uninitialized)
|
||||
{
|
||||
_logger.Warn("Reinitialization of existing TCP Async Connection. Attempting to call Shutdown.");
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
_defaultReadTimeout = _configuration.GetConfigurationValue<uint>("TcpClient", "ReadTimeout", 25);
|
||||
_defaultSendTimeout = _configuration.GetConfigurationValue<uint>("TcpClient", "SendTimeout", 5000);
|
||||
_defaultReadBufferSize = _configuration.GetConfigurationValue<uint>("TcpClient", "BufferSize", 1024);
|
||||
|
||||
_remoteAddress = _configuration.GetConfigurationValue("TcpClient", "RemoteAddress", "127.0.0.1");
|
||||
_port = _configuration.GetConfigurationValue("TcpClient", "Port", 0);
|
||||
|
||||
if (string.IsNullOrEmpty(_remoteAddress))
|
||||
{
|
||||
_tcpListener = new TcpListener(IPAddress.Any, _port);
|
||||
_tcpListener.Start();
|
||||
|
||||
_logger.Debug($"{MethodBase.GetCurrentMethod().Name} Started Listening on Port: {_port}");
|
||||
|
||||
Task.Run(async () => await _tcpListener.AcceptTcpClientAsync()).ContinueWith(t =>
|
||||
{
|
||||
_tcpClient = t.Result;
|
||||
|
||||
_remoteAddress = ((IPEndPoint)_tcpClient.Client.RemoteEndPoint).Address.ToString();
|
||||
_remotePort = ((IPEndPoint)_tcpClient.Client.RemoteEndPoint).Port;
|
||||
|
||||
_logger.Debug($"{MethodBase.GetCurrentMethod().Name} Connection Established from Remote Address: {_remoteAddress}:{_remotePort}");
|
||||
|
||||
// set timeouts
|
||||
_tcpClient.Client.SendTimeout = (int)_defaultSendTimeout;
|
||||
_tcpClient.Client.ReceiveTimeout = (int)_defaultReadTimeout;
|
||||
|
||||
// get the stream
|
||||
_tcpIpStream = _tcpClient.GetStream();
|
||||
|
||||
_state = State.Ready;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_remotePort = _port;
|
||||
_tcpClient = new TcpClient(_remoteAddress, _remotePort);
|
||||
|
||||
_logger.Debug($"{MethodBase.GetCurrentMethod().Name} Connected to Remote Address {_remoteAddress}:{_remotePort}");
|
||||
|
||||
// set timeouts
|
||||
_tcpClient.Client.SendTimeout = (int)_defaultSendTimeout;
|
||||
_tcpClient.Client.ReceiveTimeout = (int)_defaultReadTimeout;
|
||||
|
||||
// get the stream
|
||||
_tcpIpStream = _tcpClient.GetStream();
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// shuts down the device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
_logger.Debug("Shutting down");
|
||||
_tcpClient?.Dispose();
|
||||
_tcpClient = null;
|
||||
|
||||
_tcpListener?.Stop();
|
||||
_tcpListener = null;
|
||||
|
||||
_tcpIpStream?.Dispose();
|
||||
_tcpIpStream = null;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<uint> ReadAsync(byte[] dataRead, CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return 0;
|
||||
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var bytesRead = await _tcpIpStream.ReadAsync(dataRead, 0, dataRead.Length, token);
|
||||
|
||||
_logger.Trace($"Reading Data, bytes received: {bytesRead}");
|
||||
|
||||
_state = State.Ready;
|
||||
return (uint)bytesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read string from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<string> ReadAsync(CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return null;
|
||||
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var buffer = new byte[_defaultReadBufferSize];
|
||||
var bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, token);
|
||||
_state = State.Ready;
|
||||
|
||||
var message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||
|
||||
_logger.Trace($"Reading Data, message received: {message}");
|
||||
|
||||
return message;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
_logger.Trace($"Setting Reader Timeout: {timeoutMs} Ms");
|
||||
|
||||
_tcpClient.Client.ReceiveTimeout = (int)timeoutMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="dataToSend"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite, CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return 0;
|
||||
|
||||
_logger.Trace($"Writing message to ({_remoteAddress}:{_remotePort}), bytes: {dataToSend?.Length}");
|
||||
|
||||
_state = State.Busy;
|
||||
await _tcpIpStream.WriteAsync(dataToSend, 0, (int)numBytesToWrite, token);
|
||||
_state = State.Ready;
|
||||
return numBytesToWrite;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write string data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteAsync(string message, CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return;
|
||||
|
||||
_logger.Trace($"Writing message to ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
|
||||
_state = State.Busy;
|
||||
var buffer = Encoding.UTF8.GetBytes(message);
|
||||
await _tcpIpStream.WriteAsync(buffer, 0, buffer.Length, token);
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> SendCommandGetResponseAsync(string message, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return null;
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(message, cancellationToken);
|
||||
string readResponse = await ReadAsync(cancellationToken);
|
||||
_logger.Trace($"Received response: {readResponse}");
|
||||
return readResponse;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<byte[]> SendCommandGetResponseAsync(byte[] data, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
return null;
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_remoteAddress}:{_remotePort}), message: {data}");
|
||||
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(data, (uint)data.Length, cancellationToken);
|
||||
byte[] buffer = new byte[_defaultReadBufferSize];
|
||||
uint bytesRead = await ReadAsync(buffer, cancellationToken);
|
||||
_logger.Trace($"Received response of size: {bytesRead}");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
|
||||
{
|
||||
_logger.Debug($"Starting continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
|
||||
byte[] buffer = new byte[_defaultReadBufferSize];
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint bytesRead = await ReadAsync(buffer, cancellationToken);
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
string data = Encoding.UTF8.GetString(buffer, 0, (int)bytesRead);
|
||||
|
||||
_logger.Trace($"Message received from {_remoteAddress}:{_remotePort}: {data}");
|
||||
|
||||
dataReceived(data);
|
||||
Array.Clear(buffer, 0, (int)bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<byte[]> dataReceived)
|
||||
{
|
||||
_logger.Debug($"Starting continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
|
||||
byte[] buffer = new byte[_defaultReadBufferSize];
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (_tcpIpStream == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint bytesRead = await ReadAsync(buffer, cancellationToken);
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
_logger.Trace($"Message received from {_remoteAddress}:{_remotePort}: size {bytesRead}");
|
||||
byte[] bufferCopy = new byte[bytesRead];
|
||||
Array.Copy(buffer, bufferCopy, bytesRead);
|
||||
dataReceived(bufferCopy);
|
||||
Array.Clear(buffer, 0, (int)bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,71 +30,64 @@
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceTcpAsyncFactory")]
|
||||
public class CommDeviceTcpAsyncFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceTcpAsyncFactory")]
|
||||
public class CommDeviceTcpAsyncFactory : IInstrumentFactory
|
||||
{
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
|
||||
public CommDeviceTcpAsyncFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceTcpAsyncFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
public CommDeviceTcpAsyncFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
/// <summary>
|
||||
/// CommDeviceTcpAsyncFactory injection constructor
|
||||
/// </summary>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceTcpAsyncFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommAsync));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new CommDeviceTcpAsync(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommAsync));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CommDeviceTcpAsync(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
@@ -105,9 +98,7 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
return new CommDeviceTcpAsync(name, _configurationManager, _logger);
|
||||
return new CommDeviceTcpAsync(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -120,17 +111,17 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,375 +15,370 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for controlling a TCP client communication device
|
||||
/// </summary>
|
||||
public class CommDeviceTcpClient : ICommDevice, IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private const uint _DEFAULT_READ_TIMEOUT = 25;
|
||||
private const uint _DEFAULT_SEND_TIMEOUT = 5000;
|
||||
private const uint _DEFAULT_READ_BUFFER_SIZE = 1024;
|
||||
private static object _syncObj = new object();
|
||||
private TcpClient _tcpClient;
|
||||
private NetworkStream _tcpIpStream;
|
||||
private readonly int _remotePort;
|
||||
private readonly string _remoteAddress;
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
/// <summary>
|
||||
/// Class for controlling a TCP client communication device
|
||||
/// </summary>
|
||||
public class CommDeviceTcpClient : ICommDevice, IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private const uint _DEFAULT_READ_TIMEOUT = 25;
|
||||
private const uint _DEFAULT_SEND_TIMEOUT = 5000;
|
||||
private const uint _DEFAULT_READ_BUFFER_SIZE = 1024;
|
||||
private static object _syncObj = new object();
|
||||
private TcpClient _tcpClient;
|
||||
private NetworkStream _tcpIpStream;
|
||||
private readonly int _remotePort;
|
||||
private readonly string _remoteAddress;
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public bool ClearErrors() => false;
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
|
||||
public InstrumentMetadata Info => throw new NotImplementedException();
|
||||
public State Status => _state;
|
||||
public string Name => _name;
|
||||
public SelfTestResult PerformSelfTest() => SelfTestResult;
|
||||
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
|
||||
public void Open() => Initialize();
|
||||
public void Close() => Shutdown();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Functions
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
public bool ClearErrors() => false;
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
|
||||
public InstrumentMetadata Info => throw new NotImplementedException();
|
||||
public State Status => _state;
|
||||
public string Name => _name;
|
||||
public SelfTestResult PerformSelfTest() => SelfTestResult;
|
||||
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
|
||||
public void Open() => Initialize();
|
||||
public void Close() => Shutdown();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close the socket
|
||||
try
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
#region Private Functions
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close the socket
|
||||
try
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Public Functions
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceTcpClient(string name, IConfigurationManager configurationManager, ILogger logger, string remoteAddress = "", int remotePort = 0)
|
||||
{
|
||||
_name = name;
|
||||
#region Public Functions
|
||||
|
||||
// _tcpClient is created in Initialize()
|
||||
_tcpClient = null;
|
||||
_tcpIpStream = null;
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceTcpClient(string deviceName, IConfigurationManager configurationManager, string remoteAddress = "", int remotePort = 0)
|
||||
{
|
||||
_name = deviceName;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
// _tcpClient is created in Initialize()
|
||||
_tcpClient = null;
|
||||
_tcpIpStream = null;
|
||||
|
||||
_logger = logger;
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
if(string.IsNullOrEmpty(remoteAddress))
|
||||
{
|
||||
_remoteAddress = _configuration.GetConfigurationValue("TcpClient", "RemoteAddress", "127.0.0.1");
|
||||
}
|
||||
else
|
||||
{
|
||||
_remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
if(remotePort == 0)
|
||||
{
|
||||
_remotePort = _configuration.GetConfigurationValue("TcpClient", "RemotePort", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_remotePort = remotePort;
|
||||
}
|
||||
}
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
/// <summary>
|
||||
/// legacy constructor
|
||||
/// </summary>
|
||||
/// <param name="name">The name of this device</param>
|
||||
/// <param name="remoteAddress">The address of the server</param>
|
||||
/// <param name="remotePort">The port that the server is listening on</param>
|
||||
public CommDeviceTcpClient(string name, string remoteAddress, int remotePort)
|
||||
{
|
||||
_name = name;
|
||||
_remotePort = remotePort;
|
||||
_remoteAddress = remoteAddress;
|
||||
if (string.IsNullOrEmpty(remoteAddress))
|
||||
{
|
||||
_remoteAddress = _configuration.GetConfigurationValue("TcpClient", "RemoteAddress", "127.0.0.1");
|
||||
}
|
||||
else
|
||||
{
|
||||
_remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
// _tcpClient is created in Initialize()
|
||||
_tcpClient = null;
|
||||
_tcpIpStream = null;
|
||||
if (remotePort == 0)
|
||||
{
|
||||
_remotePort = _configuration.GetConfigurationValue("TcpClient", "RemotePort", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_remotePort = remotePort;
|
||||
}
|
||||
}
|
||||
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
/// <summary>
|
||||
/// legacy constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName">The name of this device</param>
|
||||
/// <param name="remoteAddress">The address of the server</param>
|
||||
/// <param name="remotePort">The port that the server is listening on</param>
|
||||
public CommDeviceTcpClient(string deviceName, string remoteAddress, int remotePort)
|
||||
{
|
||||
_name = deviceName;
|
||||
_remotePort = remotePort;
|
||||
_remoteAddress = remoteAddress;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
// _tcpClient is created in Initialize()
|
||||
_tcpClient = null;
|
||||
_tcpIpStream = null;
|
||||
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_tcpClient = new TcpClient(_remoteAddress, _remotePort);
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
// set timeouts
|
||||
_tcpClient.Client.SendTimeout = (int)_DEFAULT_SEND_TIMEOUT;
|
||||
_tcpClient.Client.ReceiveTimeout = (int)_DEFAULT_READ_TIMEOUT;
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
// get the stream
|
||||
_tcpIpStream = _tcpClient.GetStream();
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_tcpClient = new TcpClient(_remoteAddress, _remotePort);
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"expected the state to be Uninitialized, state was: {_state} on device {_name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
// set timeouts
|
||||
_tcpClient.Client.SendTimeout = (int)_DEFAULT_SEND_TIMEOUT;
|
||||
_tcpClient.Client.ReceiveTimeout = (int)_DEFAULT_READ_TIMEOUT;
|
||||
|
||||
/// <summary>
|
||||
/// shuts down the device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_tcpIpStream.Dispose();
|
||||
_tcpClient.Dispose();
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
// get the stream
|
||||
_tcpIpStream = _tcpClient.GetStream();
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
uint numBytesRead = (uint)(_tcpIpStream.Read(dataRead, 0, dataRead.Length));
|
||||
_state = State.Ready;
|
||||
return numBytesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
_state = State.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"expected the state to be Uninitialized, state was: {_state} on device {_name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<uint> ReadAsync(byte[] dataRead)
|
||||
{
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var bytesRead = await _tcpIpStream.ReadAsync(dataRead, 0, dataRead.Length);
|
||||
_state = State.Ready;
|
||||
return (uint)bytesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// shuts down the device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_tcpIpStream.Dispose();
|
||||
_tcpClient.Dispose();
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read string from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<string> ReadAsync(CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var buffer = new byte[_DEFAULT_READ_BUFFER_SIZE];
|
||||
var bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, token);
|
||||
_state = State.Ready;
|
||||
return Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Read data from the device.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
uint numBytesRead = (uint)(_tcpIpStream.Read(dataRead, 0, dataRead.Length));
|
||||
_state = State.Ready;
|
||||
return numBytesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<uint> ReadAsync(byte[] dataRead)
|
||||
{
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var bytesRead = await _tcpIpStream.ReadAsync(dataRead, 0, dataRead.Length);
|
||||
_state = State.Ready;
|
||||
return (uint)bytesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read string from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<string> ReadAsync(CancellationToken token = default)
|
||||
{
|
||||
if (_tcpIpStream.DataAvailable == true)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var buffer = new byte[_DEFAULT_READ_BUFFER_SIZE];
|
||||
var bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, token);
|
||||
_state = State.Ready;
|
||||
return Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
_tcpClient.Client.ReceiveTimeout = (int)timeoutMs;
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
_tcpClient.Client.ReceiveTimeout = (int)timeoutMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device
|
||||
/// </summary>
|
||||
/// <param name="dataToSend">The data to write</param>
|
||||
/// <param name="numBytesToWrite">The number of bytes to write</param>
|
||||
/// <returns>The number of bytes that were written</returns>
|
||||
public uint Write(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_state = State.Busy;
|
||||
_tcpIpStream.Write(dataToSend, 0, (int)numBytesToWrite);
|
||||
_state = State.Ready;
|
||||
return numBytesToWrite;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Write data to the device
|
||||
/// </summary>
|
||||
/// <param name="dataToSend">The data to write</param>
|
||||
/// <param name="numBytesToWrite">The number of bytes to write</param>
|
||||
/// <returns>The number of bytes that were written</returns>
|
||||
public uint Write(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_state = State.Busy;
|
||||
_tcpIpStream.Write(dataToSend, 0, (int)numBytesToWrite);
|
||||
_state = State.Ready;
|
||||
return numBytesToWrite;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="dataToSend"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
_state = State.Busy;
|
||||
await _tcpIpStream.WriteAsync(dataToSend, 0, (int)numBytesToWrite);
|
||||
_state = State.Ready;
|
||||
return numBytesToWrite;
|
||||
}
|
||||
/// <summary>
|
||||
/// Write data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="dataToSend"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
_state = State.Busy;
|
||||
await _tcpIpStream.WriteAsync(dataToSend, 0, (int)numBytesToWrite);
|
||||
_state = State.Ready;
|
||||
return numBytesToWrite;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write string data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteAsync(string message)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var buffer = Encoding.UTF8.GetBytes(message);
|
||||
await _tcpIpStream.WriteAsync(buffer, 0, buffer.Length);
|
||||
_state = State.Ready;
|
||||
}
|
||||
/// <summary>
|
||||
/// Write string data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteAsync(string message)
|
||||
{
|
||||
_state = State.Busy;
|
||||
var buffer = Encoding.UTF8.GetBytes(message);
|
||||
await _tcpIpStream.WriteAsync(buffer, 0, buffer.Length);
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> SendCommandGetResponseAsync(string message, int timeoutInMs = 5000)
|
||||
{
|
||||
_logger.Info($"Sending command waiting for response ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> SendCommandGetResponseAsync(string message, int timeoutInMs = 5000)
|
||||
{
|
||||
_logger.Info($"Sending command waiting for response ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
|
||||
await WriteAsync(message);
|
||||
await WriteAsync(message);
|
||||
|
||||
CancellationTokenSource tokenSource = new CancellationTokenSource(new TimeSpan(0, 0, 0, 0, milliseconds:timeoutInMs));
|
||||
CancellationTokenSource tokenSource = new CancellationTokenSource(new TimeSpan(0, 0, 0, 0, milliseconds: timeoutInMs));
|
||||
|
||||
string readResponse = await ReadAsync(tokenSource.Token);
|
||||
string readResponse = await ReadAsync(tokenSource.Token);
|
||||
|
||||
_logger.Info($"Received response: {readResponse}");
|
||||
_logger.Info($"Received response: {readResponse}");
|
||||
|
||||
return readResponse;
|
||||
}
|
||||
return readResponse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
|
||||
{
|
||||
_logger.Info($"About to start continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
|
||||
{
|
||||
_logger.Info($"About to start continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
|
||||
byte[] buffer = new byte[_DEFAULT_READ_BUFFER_SIZE];
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
int bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||
byte[] buffer = new byte[_DEFAULT_READ_BUFFER_SIZE];
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
int bytesRead = await _tcpIpStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||
|
||||
_logger.Info($"Message received from {_remoteAddress}:{_remotePort}: {data}");
|
||||
_logger.Info($"Message received from {_remoteAddress}:{_remotePort}: {data}");
|
||||
|
||||
dataReceived(data);
|
||||
Array.Clear(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
dataReceived(data);
|
||||
Array.Clear(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +1,61 @@
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceTcpClientFactory")]
|
||||
public class CommDeviceTcpClientFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceTcpClientFactory")]
|
||||
public class CommDeviceTcpClientFactory : IInstrumentFactory
|
||||
{
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
|
||||
public CommDeviceTcpClientFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceTcpClientFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
public CommDeviceTcpClientFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
/// <summary>
|
||||
/// CommDeviceTcpClientFactory injection constructor
|
||||
/// </summary>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceTcpClientFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new CommDeviceTcpClient(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CommDeviceTcpClient(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
@@ -73,9 +66,7 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
return new CommDeviceTcpClient(name, _configurationManager, _logger);
|
||||
return new CommDeviceTcpClient(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -88,17 +79,17 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,421 +15,402 @@ GOVERNMENT.
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for controlling a UDP communication device
|
||||
/// </summary>
|
||||
public class CommDeviceUdp : ICommDevice, IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private const uint _DEFAULT_SEND_TIMEOUT = 5000;
|
||||
/// <summary>
|
||||
/// Class for controlling a UDP communication device
|
||||
/// </summary>
|
||||
public class CommDeviceUdp : ICommDevice, IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private const uint _DEFAULT_SEND_TIMEOUT = 5000;
|
||||
|
||||
private static readonly object _syncObj = new Object();
|
||||
private UdpClient _udpClient;
|
||||
private readonly int _localPort;
|
||||
private readonly int _remotePort;
|
||||
private readonly string _remoteAddress;
|
||||
private IPEndPoint _remoteIPEndPoint;
|
||||
private string _name;
|
||||
private readonly SelfTestResult _selfTestResult;
|
||||
private State _state;
|
||||
private static readonly object _syncObj = new Object();
|
||||
private UdpClient _udpClient;
|
||||
private readonly int _localPort;
|
||||
private readonly int _remotePort;
|
||||
private readonly string _remoteAddress;
|
||||
private IPEndPoint _remoteIPEndPoint;
|
||||
private string _name;
|
||||
private readonly SelfTestResult _selfTestResult;
|
||||
private State _state;
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
#endregion
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#region PrivateFunctions
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~CommDeviceUdp()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close the socket and threads
|
||||
try
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_udpClient.Close();
|
||||
#region PrivateFunctions
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~CommDeviceUdp()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
_udpClient.Dispose();
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close the socket and threads
|
||||
try
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_udpClient.Close();
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_udpClient.Dispose();
|
||||
|
||||
#endregion
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region PublicFuctions
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceUdp(string deviceName, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
Name = deviceName;
|
||||
#region PublicFuctions
|
||||
|
||||
_logger = logger;
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceUdp(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
Name = deviceName;
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
_localPort = _configuration.GetConfigurationValue("CommDeviceUdp", "LocalPort", 0);
|
||||
_remotePort = _configuration.GetConfigurationValue("CommDeviceUdp", "RemotePort", 0);
|
||||
_remoteAddress = _configuration.GetConfigurationValue("CommDeviceUdp", "RemoteAddress", "127.0.0.1");
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
// created in Initialize()
|
||||
_udpClient = null;
|
||||
_localPort = _configuration.GetConfigurationValue("CommDeviceUdp", "LocalPort", 0);
|
||||
_remotePort = _configuration.GetConfigurationValue("CommDeviceUdp", "RemotePort", 0);
|
||||
_remoteAddress = _configuration.GetConfigurationValue("CommDeviceUdp", "RemoteAddress", "127.0.0.1");
|
||||
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
// created in Initialize()
|
||||
_udpClient = null;
|
||||
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name">The name of this instance</param>
|
||||
/// <param name="localPort">the port on the local computer to use</param>
|
||||
/// <param name="remotePort">the port on the remote computer to send to</param>
|
||||
/// <param name="remoteAddress">the address to send to</param>
|
||||
public CommDeviceUdp(string name, int localPort, int remotePort, string remoteAddress)
|
||||
{
|
||||
_name = name;
|
||||
_localPort = localPort;
|
||||
_remotePort = remotePort;
|
||||
_remoteAddress = remoteAddress;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="deviceName">The name of this instance</param>
|
||||
/// <param name="localPort">the port on the local computer to use</param>
|
||||
/// <param name="remotePort">the port on the remote computer to send to</param>
|
||||
/// <param name="remoteAddress">the address to send to</param>
|
||||
public CommDeviceUdp(string deviceName, int localPort, int remotePort, string remoteAddress)
|
||||
{
|
||||
_name = deviceName;
|
||||
_localPort = localPort;
|
||||
_remotePort = remotePort;
|
||||
_remoteAddress = remoteAddress;
|
||||
|
||||
// created in Initialize()
|
||||
_udpClient = null;
|
||||
// created in Initialize()
|
||||
_udpClient = null;
|
||||
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ClearErrors()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DisplayEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DisplayEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a UDP Device called " + _name;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a UDP Device called " + _name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
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()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_udpClient = new UdpClient(_localPort);
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_udpClient = new UdpClient(_localPort);
|
||||
|
||||
_udpClient.Client.ReceiveBufferSize = int.MaxValue;
|
||||
_udpClient.Client.SendBufferSize = int.MaxValue;
|
||||
_udpClient.Client.ReceiveBufferSize = int.MaxValue;
|
||||
_udpClient.Client.SendBufferSize = int.MaxValue;
|
||||
|
||||
_udpClient.Client.SendTimeout = (int)_DEFAULT_SEND_TIMEOUT;
|
||||
_udpClient.Client.SendTimeout = (int)_DEFAULT_SEND_TIMEOUT;
|
||||
|
||||
// set an arbitrary short receive timeout. Don't want the read call to block
|
||||
_udpClient.Client.ReceiveTimeout = 5;
|
||||
// set an arbitrary short receive timeout. Don't want the read call to block
|
||||
_udpClient.Client.ReceiveTimeout = 5;
|
||||
|
||||
IPAddress remoteAddy = IPAddress.Parse(_remoteAddress);
|
||||
_remoteIPEndPoint = new IPEndPoint(remoteAddy, _remotePort);
|
||||
IPAddress remoteAddy = IPAddress.Parse(_remoteAddress);
|
||||
_remoteIPEndPoint = new IPEndPoint(remoteAddy, _remotePort);
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on device " + _name);
|
||||
}
|
||||
}
|
||||
}
|
||||
_state = State.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on device " + _name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set { _name = value; }
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set { _name = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
try
|
||||
{
|
||||
dataRead = _udpClient.Receive(ref _remoteIPEndPoint);
|
||||
/// <summary>
|
||||
/// Read data from the device.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataRead)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
try
|
||||
{
|
||||
dataRead = _udpClient.Receive(ref _remoteIPEndPoint);
|
||||
|
||||
uint numBytesRead = (uint)(dataRead.Length);
|
||||
uint numBytesRead = (uint)(dataRead.Length);
|
||||
|
||||
return numBytesRead;
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
if (e.SocketErrorCode == SocketError.TimedOut)
|
||||
{
|
||||
// expected, do nothing
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return numBytesRead;
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
if (e.SocketErrorCode == SocketError.TimedOut)
|
||||
{
|
||||
// expected, do nothing
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_udpClient.Client.ReceiveTimeout = (int)timeoutMs;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
_udpClient.Client.ReceiveTimeout = (int)timeoutMs;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_udpClient.Close();
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_udpClient.Close();
|
||||
|
||||
_udpClient.Dispose();
|
||||
_udpClient.Dispose();
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device
|
||||
/// </summary>
|
||||
/// <param name="dataToSend">The data to write</param>
|
||||
/// <param name="numBytesToWrite">The number of bytes to write</param>
|
||||
/// <returns>THe number of bytes that were written</returns>
|
||||
public uint Write(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
const uint MAX_BYTES_PER_PACKET = 65400;
|
||||
/// <summary>
|
||||
/// Write data to the device
|
||||
/// </summary>
|
||||
/// <param name="dataToSend">The data to write</param>
|
||||
/// <param name="numBytesToWrite">The number of bytes to write</param>
|
||||
/// <returns>THe number of bytes that were written</returns>
|
||||
public uint Write(byte[] dataToSend, uint numBytesToWrite)
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
const uint MAX_BYTES_PER_PACKET = 65400;
|
||||
|
||||
uint index = 0;
|
||||
uint index = 0;
|
||||
|
||||
if (numBytesToWrite > MAX_BYTES_PER_PACKET)
|
||||
{
|
||||
uint numPacketsToSend = numBytesToWrite / MAX_BYTES_PER_PACKET;
|
||||
int packetsSent = 0;
|
||||
if (numBytesToWrite > MAX_BYTES_PER_PACKET)
|
||||
{
|
||||
uint numPacketsToSend = numBytesToWrite / MAX_BYTES_PER_PACKET;
|
||||
int packetsSent = 0;
|
||||
|
||||
while (packetsSent < numPacketsToSend)
|
||||
{
|
||||
Byte[] segment1 = new Byte[MAX_BYTES_PER_PACKET];
|
||||
Array.Copy(dataToSend, index, segment1, 0, MAX_BYTES_PER_PACKET);
|
||||
uint count = (uint)(_udpClient.Send(segment1, (int)MAX_BYTES_PER_PACKET, _remoteIPEndPoint));
|
||||
index += count;
|
||||
packetsSent++;
|
||||
}
|
||||
while (packetsSent < numPacketsToSend)
|
||||
{
|
||||
Byte[] segment1 = new Byte[MAX_BYTES_PER_PACKET];
|
||||
Array.Copy(dataToSend, index, segment1, 0, MAX_BYTES_PER_PACKET);
|
||||
uint count = (uint)(_udpClient.Send(segment1, (int)MAX_BYTES_PER_PACKET, _remoteIPEndPoint));
|
||||
index += count;
|
||||
packetsSent++;
|
||||
}
|
||||
|
||||
Byte[] segment = new Byte[MAX_BYTES_PER_PACKET];
|
||||
uint numBytesRemaining = numBytesToWrite - index;
|
||||
Array.Copy(dataToSend, index, segment, 0, numBytesRemaining);
|
||||
index += (uint)(_udpClient.Send(segment, (int)numBytesRemaining, _remoteIPEndPoint));
|
||||
}
|
||||
else
|
||||
{
|
||||
index = (uint)(_udpClient.Send(dataToSend, (int)numBytesToWrite, _remoteIPEndPoint));
|
||||
}
|
||||
Byte[] segment = new Byte[MAX_BYTES_PER_PACKET];
|
||||
uint numBytesRemaining = numBytesToWrite - index;
|
||||
Array.Copy(dataToSend, index, segment, 0, numBytesRemaining);
|
||||
index += (uint)(_udpClient.Send(segment, (int)numBytesRemaining, _remoteIPEndPoint));
|
||||
}
|
||||
else
|
||||
{
|
||||
index = (uint)(_udpClient.Send(dataToSend, (int)numBytesToWrite, _remoteIPEndPoint));
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
public void Close()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
public void Open()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +1,61 @@
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceUdpFactory")]
|
||||
public class CommDeviceUdpFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
[ExportInstrumentFactory(ModelNumber = "CommDeviceUdpFactory")]
|
||||
public class CommDeviceUdpFactory : IInstrumentFactory
|
||||
{
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
|
||||
public CommDeviceUdpFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceUdpFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
public CommDeviceUdpFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
/// <summary>
|
||||
/// CommDeviceUdpFactory injection constructor
|
||||
/// </summary>
|
||||
[ImportingConstructor]
|
||||
public CommDeviceUdpFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
return new CommDeviceUdp(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(ICommDevice));
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CommDeviceUdp(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
@@ -73,9 +66,7 @@ namespace Raytheon.Instruments
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = LogManager.GetLogger(name);
|
||||
|
||||
return new CommDeviceUdp(name, _configurationManager, _logger);
|
||||
return new CommDeviceUdp(name, _configurationManager);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -88,17 +79,17 @@ namespace Raytheon.Instruments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,439 +30,434 @@
|
||||
// DISTRIBUTION/DISSEMINATION CONTROL: F
|
||||
// POC: Alex Kravchenko (1118268)
|
||||
// **********************************************************************************************************
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// A sim communication device
|
||||
/// </summary>
|
||||
public class CommDeviceUdpAsync : ICommAsync
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private uint _defaultReadTimeout;
|
||||
private uint _defaultSendTimeout;
|
||||
private uint _defaultReadBufferSize;
|
||||
private static readonly object _syncObj = new object();
|
||||
|
||||
private UdpClient _udpClient;
|
||||
private IPEndPoint _remoteEndPoint;
|
||||
|
||||
private int _localPort;
|
||||
private int _remotePort;
|
||||
private string _remoteAddress;
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#endregion
|
||||
|
||||
public bool ClearErrors() => false;
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
|
||||
public InstrumentMetadata Info => throw new NotImplementedException();
|
||||
public State Status => _state;
|
||||
public string Name => _name;
|
||||
public SelfTestResult PerformSelfTest() => SelfTestResult;
|
||||
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
|
||||
public void Open() => Initialize();
|
||||
public void Close() => Shutdown();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
|
||||
#region Private Functions
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close the socket
|
||||
try
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceUdpAsync(string name, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
_name = name;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_logger = logger;
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
if (_state != State.Uninitialized)
|
||||
{
|
||||
_logger.Warn("Reinitialization of existing UDP Async Connection. Attempting to call Shutdown.");
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
_defaultReadTimeout = _configuration.GetConfigurationValue<uint>("UdpClient", "ReadTimeout", 25);
|
||||
_defaultSendTimeout = _configuration.GetConfigurationValue<uint>("UdpClient", "SendTimeout", 5000);
|
||||
_defaultReadBufferSize = _configuration.GetConfigurationValue<uint>("UdpClient", "BufferSize", 1024);
|
||||
|
||||
_localPort = _configuration.GetConfigurationValue("UdpClient", "LocalPort", 0);
|
||||
|
||||
_remoteAddress = _configuration.GetConfigurationValue("UdpClient", "RemoteAddress", "127.0.0.1");
|
||||
_remotePort = _configuration.GetConfigurationValue("UdpClient", "RemotePort", 0);
|
||||
|
||||
_udpClient = new UdpClient();
|
||||
|
||||
if (string.IsNullOrEmpty(_remoteAddress))
|
||||
{
|
||||
_logger.Debug($"Initializing as UDP Server. Listening on port: {_localPort}");
|
||||
_udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, _localPort));
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug($"Initializing as UDP Client. Ready to Talk to: {_remoteAddress}:{_remotePort}");
|
||||
// get the remote endpoint
|
||||
_remoteEndPoint = new IPEndPoint(IPAddress.Parse(_remoteAddress), _remotePort);
|
||||
}
|
||||
|
||||
// set timeouts
|
||||
_udpClient.Client.SendTimeout = (int)_defaultSendTimeout;
|
||||
_udpClient.Client.ReceiveTimeout = (int)_defaultReadTimeout;
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// shuts down the device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
_logger.Debug("Shutting Down...");
|
||||
_state = State.Uninitialized;
|
||||
_udpClient?.Dispose();
|
||||
_udpClient = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<uint> ReadAsync(byte[] dataRead, CancellationToken token = default)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return 0;
|
||||
|
||||
var received = await _udpClient.ReceiveAsync();
|
||||
Array.Copy(received.Buffer, dataRead, Math.Min(dataRead.Length, received.Buffer.Length));
|
||||
|
||||
UpdateRemoteAddressAndPort(received.RemoteEndPoint);
|
||||
|
||||
_logger.Trace($"Reading Data, bytes received: {received.Buffer?.Length}");
|
||||
|
||||
return (uint)received.Buffer.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read string from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<string> ReadAsync(CancellationToken token = default)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return null;
|
||||
|
||||
var received = await _udpClient.ReceiveAsync();
|
||||
|
||||
UpdateRemoteAddressAndPort(received.RemoteEndPoint);
|
||||
|
||||
var data = Encoding.UTF8.GetString(received.Buffer);
|
||||
|
||||
_logger.Trace($"Reading Data, message received: {data}");
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return;
|
||||
|
||||
_logger.Trace($"Setting Reader Timeout: {timeoutMs} Ms");
|
||||
|
||||
_udpClient.Client.ReceiveTimeout = (int)timeoutMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="dataToSend"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite, CancellationToken token = default)
|
||||
{
|
||||
if (_udpClient == null || _remoteEndPoint == null)
|
||||
return 0;
|
||||
|
||||
_logger.Trace($"Writing message to ({_remoteAddress}:{_remotePort}), bytes: {dataToSend?.Length}");
|
||||
|
||||
_state = State.Busy;
|
||||
await _udpClient.SendAsync(dataToSend, (int)numBytesToWrite, _remoteEndPoint);
|
||||
_state = State.Ready;
|
||||
return numBytesToWrite;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write string data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteAsync(string message, CancellationToken token = default)
|
||||
{
|
||||
if (_udpClient == null || _remoteEndPoint == null)
|
||||
return;
|
||||
|
||||
_logger.Trace($"Writing message to ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
|
||||
_state = State.Busy;
|
||||
var dataToSend = Encoding.UTF8.GetBytes(message);
|
||||
await _udpClient.SendAsync(dataToSend, dataToSend.Length, _remoteEndPoint);
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> SendCommandGetResponseAsync(string message, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return null;
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
|
||||
using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(message, cancellationToken);
|
||||
string readResponse = await ReadAsync(cancellationToken);
|
||||
_logger.Trace($"Received response: {readResponse}");
|
||||
|
||||
return readResponse;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<byte[]> SendCommandGetResponseAsync(byte[] data, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return null;
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_remoteAddress}:{_remotePort}), message length: {data.Length}");
|
||||
|
||||
using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(data, (uint)data.Length, cancellationToken);
|
||||
byte[] buffer = new byte[_defaultReadBufferSize];
|
||||
uint bytesRead = await ReadAsync(buffer, cancellationToken);
|
||||
_logger.Trace($"Received response of size: {bytesRead}");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return;
|
||||
|
||||
_logger.Debug($"Starting continuous reading from port: {_localPort} ...");
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
break;
|
||||
|
||||
var received = await ReceiveAsync(_udpClient, cancellationToken);
|
||||
|
||||
if (received != null && received.Buffer != null)
|
||||
{
|
||||
UpdateRemoteAddressAndPort(received.RemoteEndPoint);
|
||||
_logger.Trace($"Incoming Data from {_remoteAddress}:{_remotePort}: size {received.Buffer.Length}");
|
||||
string data = Encoding.UTF8.GetString(received.Buffer, 0, received.Buffer.Length);
|
||||
dataReceived(data);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<byte[]> dataReceived)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return;
|
||||
|
||||
_logger.Debug($"Starting continuous reading from port: {_localPort} ...");
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
break;
|
||||
|
||||
var received = await ReceiveAsync(_udpClient, cancellationToken);
|
||||
if (received != null && received.Buffer != null)
|
||||
{
|
||||
UpdateRemoteAddressAndPort(received.RemoteEndPoint);
|
||||
_logger.Trace($"Incoming Data from {_remoteAddress}:{_remotePort}: size {received.Buffer.Length}");
|
||||
dataReceived(received.Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Functions
|
||||
/// <summary>
|
||||
/// Update client information for logging
|
||||
/// </summary>
|
||||
/// <param name="remoteEndPoint"></param>
|
||||
private void UpdateRemoteAddressAndPort(IPEndPoint remoteEndPoint)
|
||||
{
|
||||
if (remoteEndPoint == null)
|
||||
return;
|
||||
|
||||
if (_remotePort == 0 || string.IsNullOrEmpty(_remoteAddress))
|
||||
{
|
||||
_remotePort = remoteEndPoint.Port;
|
||||
_remoteAddress = remoteEndPoint.Address.ToString();
|
||||
}
|
||||
|
||||
if(_remoteEndPoint == null || _remoteEndPoint.Port != remoteEndPoint.Port )
|
||||
{
|
||||
// get the remote endpoint
|
||||
_remoteEndPoint = remoteEndPoint;
|
||||
|
||||
_logger.Debug($"Starting to receive data from {_remoteAddress}:{_remotePort}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ReceiveAsyc with cancellation token implementation
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="breakToken"></param>
|
||||
/// <returns></returns>
|
||||
private Task<UdpReceiveResult> ReceiveAsync(UdpClient client, CancellationToken breakToken) => breakToken.IsCancellationRequested
|
||||
? Task.Run(() => new UdpReceiveResult())
|
||||
: Task<UdpReceiveResult>.Factory.FromAsync
|
||||
((callback, state) => client.BeginReceive(callback, state), (ar) =>
|
||||
{
|
||||
if (breakToken.IsCancellationRequested)
|
||||
return new UdpReceiveResult();
|
||||
|
||||
IPEndPoint remoteEP = null;
|
||||
var buffer = client.EndReceive(ar, ref remoteEP);
|
||||
return new UdpReceiveResult(buffer, remoteEP);
|
||||
},null);
|
||||
|
||||
#endregion
|
||||
}
|
||||
/// <summary>
|
||||
/// A sim communication device
|
||||
/// </summary>
|
||||
public class CommDeviceUdpAsync : ICommAsync
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private uint _defaultReadTimeout;
|
||||
private uint _defaultSendTimeout;
|
||||
private uint _defaultReadBufferSize;
|
||||
private static readonly object _syncObj = new object();
|
||||
|
||||
private UdpClient _udpClient;
|
||||
private IPEndPoint _remoteEndPoint;
|
||||
|
||||
private int _localPort;
|
||||
private int _remotePort;
|
||||
private string _remoteAddress;
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#endregion
|
||||
|
||||
public bool ClearErrors() => false;
|
||||
public bool FrontPanelEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public bool DisplayEnabled { get => false; set => throw new NotImplementedException(); }
|
||||
public string DetailedStatus => $"This is a TCP/IP Device called {_name}";
|
||||
public InstrumentMetadata Info => throw new NotImplementedException();
|
||||
public State Status => _state;
|
||||
public string Name => _name;
|
||||
public SelfTestResult PerformSelfTest() => SelfTestResult;
|
||||
public SelfTestResult SelfTestResult => SelfTestResult.Unknown;
|
||||
public void Open() => Initialize();
|
||||
public void Close() => Shutdown();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
|
||||
#region Private Functions
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of the resources contained by this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// close the socket
|
||||
try
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.Error(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommDeviceUdpAsync(string deviceName, IConfigurationManager configurationManager)
|
||||
{
|
||||
_name = deviceName;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
if (_state != State.Uninitialized)
|
||||
{
|
||||
_logger.Warn("Reinitialization of existing UDP Async Connection. Attempting to call Shutdown.");
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
_defaultReadTimeout = _configuration.GetConfigurationValue<uint>("UdpClient", "ReadTimeout", 25);
|
||||
_defaultSendTimeout = _configuration.GetConfigurationValue<uint>("UdpClient", "SendTimeout", 5000);
|
||||
_defaultReadBufferSize = _configuration.GetConfigurationValue<uint>("UdpClient", "BufferSize", 1024);
|
||||
|
||||
_localPort = _configuration.GetConfigurationValue("UdpClient", "LocalPort", 0);
|
||||
|
||||
_remoteAddress = _configuration.GetConfigurationValue("UdpClient", "RemoteAddress", "127.0.0.1");
|
||||
_remotePort = _configuration.GetConfigurationValue("UdpClient", "RemotePort", 0);
|
||||
|
||||
_udpClient = new UdpClient();
|
||||
|
||||
if (string.IsNullOrEmpty(_remoteAddress))
|
||||
{
|
||||
_logger.Debug($"Initializing as UDP Server. Listening on port: {_localPort}");
|
||||
_udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, _localPort));
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug($"Initializing as UDP Client. Ready to Talk to: {_remoteAddress}:{_remotePort}");
|
||||
// get the remote endpoint
|
||||
_remoteEndPoint = new IPEndPoint(IPAddress.Parse(_remoteAddress), _remotePort);
|
||||
}
|
||||
|
||||
// set timeouts
|
||||
_udpClient.Client.SendTimeout = (int)_defaultSendTimeout;
|
||||
_udpClient.Client.ReceiveTimeout = (int)_defaultReadTimeout;
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// shuts down the device
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
_logger.Debug("Shutting Down...");
|
||||
_state = State.Uninitialized;
|
||||
_udpClient?.Dispose();
|
||||
_udpClient = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<uint> ReadAsync(byte[] dataRead, CancellationToken token = default)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return 0;
|
||||
|
||||
var received = await _udpClient.ReceiveAsync();
|
||||
Array.Copy(received.Buffer, dataRead, Math.Min(dataRead.Length, received.Buffer.Length));
|
||||
|
||||
UpdateRemoteAddressAndPort(received.RemoteEndPoint);
|
||||
|
||||
_logger.Trace($"Reading Data, bytes received: {received.Buffer?.Length}");
|
||||
|
||||
return (uint)received.Buffer.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read string from the device asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The buffer to put the data in</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public async Task<string> ReadAsync(CancellationToken token = default)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return null;
|
||||
|
||||
var received = await _udpClient.ReceiveAsync();
|
||||
|
||||
UpdateRemoteAddressAndPort(received.RemoteEndPoint);
|
||||
|
||||
var data = Encoding.UTF8.GetString(received.Buffer);
|
||||
|
||||
_logger.Trace($"Reading Data, message received: {data}");
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return;
|
||||
|
||||
_logger.Trace($"Setting Reader Timeout: {timeoutMs} Ms");
|
||||
|
||||
_udpClient.Client.ReceiveTimeout = (int)timeoutMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="dataToSend"></param>
|
||||
/// <param name="numBytesToWrite"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<uint> WriteAsync(byte[] dataToSend, uint numBytesToWrite, CancellationToken token = default)
|
||||
{
|
||||
if (_udpClient == null || _remoteEndPoint == null)
|
||||
return 0;
|
||||
|
||||
_logger.Trace($"Writing message to ({_remoteAddress}:{_remotePort}), bytes: {dataToSend?.Length}");
|
||||
|
||||
_state = State.Busy;
|
||||
await _udpClient.SendAsync(dataToSend, (int)numBytesToWrite, _remoteEndPoint);
|
||||
_state = State.Ready;
|
||||
return numBytesToWrite;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write string data to the device asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteAsync(string message, CancellationToken token = default)
|
||||
{
|
||||
if (_udpClient == null || _remoteEndPoint == null)
|
||||
return;
|
||||
|
||||
_logger.Trace($"Writing message to ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
|
||||
_state = State.Busy;
|
||||
var dataToSend = Encoding.UTF8.GetBytes(message);
|
||||
await _udpClient.SendAsync(dataToSend, dataToSend.Length, _remoteEndPoint);
|
||||
_state = State.Ready;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> SendCommandGetResponseAsync(string message, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return null;
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_remoteAddress}:{_remotePort}), message: {message}");
|
||||
|
||||
using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(message, cancellationToken);
|
||||
string readResponse = await ReadAsync(cancellationToken);
|
||||
_logger.Trace($"Received response: {readResponse}");
|
||||
|
||||
return readResponse;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Command and Get Response asynchronously
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="timeoutInMs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<byte[]> SendCommandGetResponseAsync(byte[] data, CancellationToken cancellationToken = default, int timeoutInMs = 5000)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return null;
|
||||
|
||||
_logger.Trace($"Sending command waiting for response from ({_remoteAddress}:{_remotePort}), message length: {data.Length}");
|
||||
|
||||
using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutInMs)))
|
||||
{
|
||||
if (cancellationToken == default)
|
||||
{
|
||||
cancellationToken = cts.Token;
|
||||
}
|
||||
await WriteAsync(data, (uint)data.Length, cancellationToken);
|
||||
byte[] buffer = new byte[_defaultReadBufferSize];
|
||||
uint bytesRead = await ReadAsync(buffer, cancellationToken);
|
||||
_logger.Trace($"Received response of size: {bytesRead}");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<string> dataReceived)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return;
|
||||
|
||||
_logger.Debug($"Starting continuous reading from port: {_localPort} ...");
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
break;
|
||||
|
||||
var received = await ReceiveAsync(_udpClient, cancellationToken);
|
||||
|
||||
if (received != null && received.Buffer != null)
|
||||
{
|
||||
UpdateRemoteAddressAndPort(received.RemoteEndPoint);
|
||||
_logger.Trace($"Incoming Data from {_remoteAddress}:{_remotePort}: size {received.Buffer.Length}");
|
||||
string data = Encoding.UTF8.GetString(received.Buffer, 0, received.Buffer.Length);
|
||||
dataReceived(data);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// keeps reading until canceled via token,
|
||||
/// received messages sent to dataReceived function
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <param name="dataReceived"></param>
|
||||
/// <returns></returns>
|
||||
public async Task KeepReadingAsync(CancellationToken cancellationToken, Action<byte[]> dataReceived)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
return;
|
||||
|
||||
_logger.Debug($"Starting continuous reading from port: {_localPort} ...");
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (_udpClient == null)
|
||||
break;
|
||||
|
||||
var received = await ReceiveAsync(_udpClient, cancellationToken);
|
||||
if (received != null && received.Buffer != null)
|
||||
{
|
||||
UpdateRemoteAddressAndPort(received.RemoteEndPoint);
|
||||
_logger.Trace($"Incoming Data from {_remoteAddress}:{_remotePort}: size {received.Buffer.Length}");
|
||||
dataReceived(received.Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug($"Finished continuous reading from {_remoteAddress}:{_remotePort} ...");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Functions
|
||||
/// <summary>
|
||||
/// Update client information for logging
|
||||
/// </summary>
|
||||
/// <param name="remoteEndPoint"></param>
|
||||
private void UpdateRemoteAddressAndPort(IPEndPoint remoteEndPoint)
|
||||
{
|
||||
if (remoteEndPoint == null)
|
||||
return;
|
||||
|
||||
if (_remotePort == 0 || string.IsNullOrEmpty(_remoteAddress))
|
||||
{
|
||||
_remotePort = remoteEndPoint.Port;
|
||||
_remoteAddress = remoteEndPoint.Address.ToString();
|
||||
}
|
||||
|
||||
if (_remoteEndPoint == null || _remoteEndPoint.Port != remoteEndPoint.Port)
|
||||
{
|
||||
// get the remote endpoint
|
||||
_remoteEndPoint = remoteEndPoint;
|
||||
|
||||
_logger.Debug($"Starting to receive data from {_remoteAddress}:{_remotePort}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ReceiveAsyc with cancellation token implementation
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="breakToken"></param>
|
||||
/// <returns></returns>
|
||||
private Task<UdpReceiveResult> ReceiveAsync(UdpClient client, CancellationToken breakToken) => breakToken.IsCancellationRequested
|
||||
? Task.Run(() => new UdpReceiveResult())
|
||||
: Task<UdpReceiveResult>.Factory.FromAsync
|
||||
((callback, state) => client.BeginReceive(callback, state), (ar) =>
|
||||
{
|
||||
if (breakToken.IsCancellationRequested)
|
||||
return new UdpReceiveResult();
|
||||
|
||||
IPEndPoint remoteEP = null;
|
||||
var buffer = client.EndReceive(ar, ref remoteEP);
|
||||
return new UdpReceiveResult(buffer, remoteEP);
|
||||
}, null);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user