Big changes

This commit is contained in:
Duc
2025-03-13 12:04:22 -07:00
parent c689fcb7f9
commit ffa9905494
748 changed files with 199255 additions and 3743 deletions

View File

@@ -0,0 +1,287 @@
// 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.Ports;
using System.Net.Sockets;
using System.Threading;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
/// <summary>
/// Flow Meter class used to interact with flow meter.
/// It supports the Omega DPF20 when configured to slave mode (where data is pulled as opposed to pushed).
/// Set to slave mode on the front panel
/// </summary>
public class FlowMeterOmegaDPF20 : IFlowMeter
{
#region PublicMembers
public enum FlowMeterMode
{
MASTER,
SLAVE
};
#endregion
#region PrivateMembers
//Prevent Collisions
private static object _sync = new object();
//Ethernet Communication
private readonly string _ipAddr;
private readonly int _port;
private readonly byte _flowMeterAddress;
private readonly FlowMeterOmegaDPF20.FlowMeterMode _mode;
private const int _READ_BUFFER_SIZE = 1024;
private const int _READ_TIMEOUT = 5500;
private byte[] _readBuffer;
private NetworkStream _tcpStream;
TcpClient _flowSocket;
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
public string DetailedStatus => throw new NotImplementedException();
public bool DisplayEnabled { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public bool FrontPanelEnabled { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public InstrumentMetadata Info => throw new NotImplementedException();
public string Name {get; set;}
public SelfTestResult SelfTestResult => throw new NotImplementedException();
public State Status => throw new NotImplementedException();
#endregion
#region PrivateFunctions
/// <summary>
/// Destructor
/// </summary>
~FlowMeterOmegaDPF20()
{
Dispose(false);
}
/// <summary>
/// Dispose of this 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();
_flowSocket?.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
}
}
}
#endregion
#region PublicFunctions
/// <summary>
/// FlowMeterOmegaDPF20 factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public FlowMeterOmegaDPF20(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
_ipAddr = _configuration.GetConfigurationValue("FlowMeterOmegaDPF20", "IpAddr", "");
_port = _configuration.GetConfigurationValue("FlowMeterOmegaDPF20", "Port", 0);
_readBuffer = new byte[_READ_BUFFER_SIZE];
//Create and open a socket to flow meter
_flowSocket = new TcpClient(_ipAddr, _port);
_tcpStream = _flowSocket.GetStream();
_tcpStream.ReadTimeout = _READ_TIMEOUT;
}
/// <summary>
/// Constructor for the DPF20 flow meter. It makes a socket connection upon construction
/// </summary>
/// <param name="name">The name. Anything the hosts wants it to be</param>
/// <param name="ipAddress">IP Address of the flow meter server</param>
/// <param name="port">Port of the flow meter server</param>
/// <param name="flowMeterAddress">The address on the front display of the flow meter</param>
/// <param name="mode">The mode on the front display of the flow meter</param>
public FlowMeterOmegaDPF20(string name, string ipAddress, int port, byte flowMeterAddress, FlowMeterOmegaDPF20.FlowMeterMode mode)
{
Name = name;
_logger = LogManager.GetCurrentClassLogger();
_ipAddr = ipAddress;
_port = port;
_flowMeterAddress = flowMeterAddress;
_mode = mode;
//Initialize read buffer
_readBuffer = new byte[_READ_BUFFER_SIZE];
//Create and open a socket to flow meter
_flowSocket = new TcpClient(_ipAddr, _port);
_tcpStream = _flowSocket.GetStream();
_tcpStream.ReadTimeout = _READ_TIMEOUT;
}
/// <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>
/// <param name="flowMeterAddress">The address on the front display of the flow meter</param>
/// <param name="mode">The mode on the front display of the flow meter</param>
public FlowMeterOmegaDPF20(string name, string comPortName, uint delayBeforeReadMs, int baudRate = 115200, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.One, byte flowMeterAddress = 128, FlowMeterOmegaDPF20.FlowMeterMode mode = FlowMeterMode.SLAVE)
{
throw new NotImplementedException();
}
// This code added to correctly implement the disposable pattern.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
public void Dispose()
{
try
{
lock (_sync)
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
catch (Exception ex)
{
_logger.Error(ex.Message);
}
}
/// <summary>
/// Query the flow rate from the flow meter
/// </summary>
/// <returns>the flow rate.</returns>
public double ReadFlow()
{
lock (_sync)
{
if (_mode == FlowMeterMode.SLAVE)
{
byte[] cmd = FlowMeterOmegaDPF20DataParser.CreateReadFlowCmd(_flowMeterAddress);
_tcpStream.Write(cmd, 0, cmd.Length);
int numBytesRead = _tcpStream.Read(_readBuffer, 0, _readBuffer.Length);
double flow = FlowMeterOmegaDPF20DataParser.ParseReadFlowRsp(_readBuffer, numBytesRead);
return flow;
}
else if (_mode == FlowMeterMode.MASTER)
{
const int EXPECTED_DATA_LEN = 18;
// ensure we have at least one full message
// need at least 35 bytes (worst case partial msg plus a full message)
int numBytesAvailable = _flowSocket.Available;
while (numBytesAvailable < (EXPECTED_DATA_LEN * 2) - 1)
{
Thread.Sleep(5);
numBytesAvailable = _flowSocket.Available;
}
byte[] readBuf = new byte[numBytesAvailable];
int numBytesRead = _tcpStream.Read(readBuf, 0, readBuf.Length);
double flow = FlowMeterOmegaDPF20DataParser.ParseMasterFlowMsg(readBuf, numBytesRead);
return flow;
}
else
{
throw new Exception("unknown mode: " + _mode.ToString());
}
}
}
public bool ClearErrors()
{
throw new NotImplementedException();
}
public void Initialize()
{
throw new NotImplementedException();
}
public SelfTestResult PerformSelfTest()
{
throw new NotImplementedException();
}
public void Reset()
{
throw new NotImplementedException();
}
public void Shutdown()
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.FlowMeterOmegaDPF20</AssemblyName>
<Product>Flow Meter Omega DPF20 implementation</Product>
<Description>Flow Meter Omega DPF20 implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.FlowMeter.Contracts" Version="1.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FlowMeterSim\FlowMeterSim.csproj" />
</ItemGroup>
<!-- 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>

View File

@@ -0,0 +1,304 @@
// 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.Runtime.InteropServices;
using System.Text;
using Raytheon.Common;
namespace Raytheon.Instruments
{
/// <summary>
/// Parse and Format Util for the DPF2 flow meter serial interface
/// </summary>
internal static class FlowMeterOmegaDPF20DataParser
{
#region PublicMembers
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct HeaderStruct
{
public byte startOfFrame;//2
public byte frameType;//32,33,35,36,37,38
public byte reserved;//32
public byte orginAddress;//32 + real value
public byte destinationAddress;//32 + real value
public byte registerLocation;//32 + real value
public byte reserved2;//32
public byte dataLength;//num data bytes that follow
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ReadDisplayCmdStruct
{
public HeaderStruct header;
public FooterStruct footer;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ReadDisplayRspStruct
{
public HeaderStruct header;
public byte byte1;
public byte byte2;
public byte byte3;
public byte byte4;
public byte byte5;
public byte byte6;
public byte byte7;
public byte byte8;
public FooterStruct footer;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct FooterStruct
{
public byte crc;
public byte endOfFrame;//3
};
#endregion
#region PublicFunctions
/// <summary>
/// Calculate the CRC per the DPF20 manual
/// </summary>
/// <param name="data">The data to run the crc on</param>
/// <param name="numBytesToProcess">The number of bytes to use for the crc</param>
/// <returns></returns>
public static byte PerformCrc(byte[] data, int numBytesToProcess)
{
byte crc = 0;
for (int i = 0; i < numBytesToProcess; i++)
{
crc = (byte)(crc ^ data[i]);
}
if (crc < 32)
{
crc = (byte)~crc;
}
return crc;
}
/// <summary>
/// Creates the byte array for the read display command
/// </summary>
/// <returns>a byte array that is the command to send to the meter to read the display</returns>
public static byte[] CreateReadFlowCmd(byte flowMeterAddress)
{
// populate the header per the manual
HeaderStruct header = new HeaderStruct();
header.startOfFrame = 2;
header.frameType = 36;
header.reserved = 32;
header.orginAddress = 32;
header.destinationAddress = (byte)(flowMeterAddress + 32);
header.registerLocation = 32;
header.reserved2 = 32;
header.dataLength = 32;
// populate the footer
FooterStruct footer = new FooterStruct();
footer.crc = 0;// set at end of function
footer.endOfFrame = 3;
// create the message
ReadDisplayCmdStruct cmd = new ReadDisplayCmdStruct();
cmd.header = header;
cmd.footer = footer;
// allocate the final buffer
int messageSize = (int)(System.Runtime.InteropServices.Marshal.SizeOf(typeof(ReadDisplayCmdStruct)));
byte[] buff = new byte[messageSize];
//Get a pointer to the Buffer
GCHandle pinnedArray = GCHandle.Alloc(buff, GCHandleType.Pinned);
//Pinned pointer to array
IntPtr pData = pinnedArray.AddrOfPinnedObject();
//Place message into buffer
Marshal.StructureToPtr(cmd, pData, true);
//Release array pointer
pinnedArray.Free();
// calculate and set crc
byte calculatedCrc = PerformCrc(buff, 8);
buff[8] = calculatedCrc;
return buff;
}
/// <summary>
/// Parse out the flow from the read display response
/// </summary>
/// <param name="data"></param>
/// <param name="numBytes"></param>
/// <returns></returns>
public static double ParseReadFlowRsp(byte[] data, int numBytes)
{
const int DISPLAY_REGISTER = 32;
const int DATA_OFFSET = 32;
const int EXPECTED_MSG_ID = 37;
const int EXPECTED_DATA_LEN = 18;
if (numBytes < 18)
{
throw new Exception("Need at least " + EXPECTED_DATA_LEN + " to form the rsp message, received: " + numBytes);
}
// get a pointer to the data
GCHandle messagePinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr pMessageData = messagePinnedArray.AddrOfPinnedObject();
// populate the structure
ReadDisplayRspStruct msgStruct = (ReadDisplayRspStruct)Marshal.PtrToStructure(pMessageData, typeof(ReadDisplayRspStruct));
// free the ptr
messagePinnedArray.Free();
if (msgStruct.header.frameType != EXPECTED_MSG_ID)
{
throw new Exception("expected msg id: " + EXPECTED_MSG_ID + ", received: " + msgStruct.header.frameType);
}
// subtract the DATA_OFFSET because that is what the manual says to do:)
int numDataBytes = msgStruct.header.dataLength - DATA_OFFSET;
int headerSize = (int)(System.Runtime.InteropServices.Marshal.SizeOf(typeof(HeaderStruct)));
byte calculatedCrc = PerformCrc(data, numDataBytes + headerSize);
byte receivedCrc = msgStruct.footer.crc;
if (calculatedCrc != receivedCrc)
{
throw new Exception("calculated crc: " + calculatedCrc + ", is not equal to the received crc: " + receivedCrc);
}
// confirm the from register
int fromRegister = msgStruct.header.registerLocation;
if (fromRegister != DISPLAY_REGISTER)
{
throw new Exception("from register: " + fromRegister + ", is not the expected register: " + DISPLAY_REGISTER);
}
// get the data
byte[] dataPayload = new byte[numDataBytes];
Array.Copy(data, headerSize, dataPayload, 0, numDataBytes);
// convert it to a string
string rspStr = Encoding.ASCII.GetString(dataPayload);
//Convert string value to double and return
return double.Parse(rspStr);
}
/// <summary>
/// parse out flow from the master flow message (ID 35)
/// </summary>
/// <returns>the flow rate.</returns>
public static double ParseMasterFlowMsg(byte[] data, int numBytes)
{
const int DISPLAY_REGISTER = 32;
const int DATA_OFFSET = 32;
const int EXPECTED_MSG_ID = 35;
const int EXPECTED_DATA_LEN = 18;
// start of message data pattern
byte[] startOfMesage = new byte[] { 2, 35 };
// data search index
int searchIndex = 0;
// need at least 18 bytes
if (numBytes < EXPECTED_DATA_LEN)
{
throw new Exception("Need at least " + EXPECTED_DATA_LEN + " to form the rsp message, received: " + numBytes);
}
// if there are more than two messages, just need the end of the buffer
// worst case scenario for 1 complete message would be 35 bytes (17 from an incomplete message and then 18 for the complete one)
else if (numBytes >= (EXPECTED_DATA_LEN * 2) - 1)
{
searchIndex = numBytes - ((EXPECTED_DATA_LEN * 2) - 1);
}
int finalMsgStartIndex = Util.ByteArraySearch(data, searchIndex, startOfMesage);
if (finalMsgStartIndex == -1)
{
throw new Exception("Could not find start of message");
}
else if((numBytes - finalMsgStartIndex) < EXPECTED_DATA_LEN)
{
throw new Exception("Found start of message, but not enough bytes for a complete message");
}
byte[] messagePayload = new byte[EXPECTED_DATA_LEN];
Array.Copy(data, finalMsgStartIndex, messagePayload, 0, EXPECTED_DATA_LEN);
// get a pointer to the data
GCHandle messagePinnedArray = GCHandle.Alloc(messagePayload, GCHandleType.Pinned);
IntPtr pMessageData = messagePinnedArray.AddrOfPinnedObject();
// populate the structure
HeaderStruct headerStruct = (HeaderStruct)Marshal.PtrToStructure(pMessageData, typeof(HeaderStruct));
// free the ptr
messagePinnedArray.Free();
if (headerStruct.frameType != EXPECTED_MSG_ID)
{
throw new Exception("expected msg id: " + EXPECTED_MSG_ID + ", received: " + headerStruct.frameType);
}
// subtract the DATA_OFFSET because that is what the manual says to do:)
int numDataBytes = headerStruct.dataLength - DATA_OFFSET;
int headerSize = (int)(System.Runtime.InteropServices.Marshal.SizeOf(typeof(HeaderStruct)));
// confirm the crc
byte calculatedCrc = PerformCrc(messagePayload, numDataBytes + headerSize);
byte receivedCrc = messagePayload[numDataBytes + headerSize];
if (calculatedCrc != receivedCrc)
{
throw new Exception("calculated crc: " + calculatedCrc + ", is not equal to the received crc: " + receivedCrc);
}
// confirm the from register
int fromRegister = headerStruct.registerLocation;
if (fromRegister != DISPLAY_REGISTER)
{
throw new Exception("from register: " + fromRegister + ", is not the expected register: " + DISPLAY_REGISTER);
}
// get the data
byte[] dataPayload = new byte[numDataBytes];
Array.Copy(messagePayload, headerSize, dataPayload, 0, numDataBytes);
// convert to a string
string rspStr = Encoding.ASCII.GetString(dataPayload);
//Convert string value to double and return
return double.Parse(rspStr);
}
#endregion
}
}

View File

@@ -0,0 +1,139 @@
// **********************************************************************************************************
// FlowMeterOmegaDPF20Factory.cs
// 2/20/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 NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "FlowMeterOmegaDPF20Factory")]
public class FlowMeterOmegaDPF20Factory : 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;
public FlowMeterOmegaDPF20Factory(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 FlowMeterOmegaDPF20Factory([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");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IFlowMeter));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new FlowMeterOmegaDPF20(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new FlowMeterSim(name, _configurationManager, _logger);
else
return new FlowMeterOmegaDPF20(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
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);
}
}
}