Initial check-in
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// 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 NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.EthernetSockets
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for controlling a TCP client communication device
|
||||
/// </summary>
|
||||
public class TcpClient : ICommDevice
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
|
||||
private Socket _sock;
|
||||
private string _remoteAddress;
|
||||
private int _remotePort;
|
||||
private IPEndPoint _remoteEP = null;
|
||||
private IPAddress _ipAddress = null;
|
||||
private object _syncObj = new object();
|
||||
|
||||
private readonly string _name;
|
||||
private State _state;
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private static 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() => Disconnect();
|
||||
public void Shutdown() => Disconnect();
|
||||
public void Reset()
|
||||
{
|
||||
Close();
|
||||
Open();
|
||||
}
|
||||
|
||||
#region Public Functions
|
||||
|
||||
/// <summary>
|
||||
/// CommDevice factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceInstanceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public TcpClient(string deviceInstanceName, IConfigurationManager configurationManager, ILogger logger, string remoteAddress = "", int remotePort = 0)
|
||||
{
|
||||
_name = deviceInstanceName;
|
||||
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_logger = logger;
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
|
||||
// configuration obtained from [deviceInstanceName].xml file
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
if (string.IsNullOrEmpty(remoteAddress))
|
||||
{
|
||||
_remoteAddress = _configuration.GetConfigurationValue(deviceInstanceName, TcpClientConfigXml.REMOTE_ADDRESS.ToString(), "127.0.0.1");
|
||||
}
|
||||
else
|
||||
{
|
||||
_remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
if (remotePort == 0)
|
||||
{
|
||||
_remotePort = _configuration.GetConfigurationValue(deviceInstanceName, TcpClientConfigXml.REMOTE_PORT.ToString(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_remotePort = remotePort;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="remoteAddress"></param>
|
||||
/// <param name="remotePort"></param>
|
||||
public TcpClient(string remoteAddress, int remotePort)
|
||||
{
|
||||
_remoteAddress = remoteAddress;
|
||||
_remotePort = remotePort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initialize instrument
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
// if remoteAddress is a hostname
|
||||
if (!IPAddress.TryParse(_remoteAddress, out _ipAddress))
|
||||
{
|
||||
string preferredSubnet = "";
|
||||
|
||||
IPHostEntry host = Dns.GetHostEntry(_remoteAddress);
|
||||
foreach (IPAddress ip in host.AddressList)
|
||||
{
|
||||
AddressFamily af = ip.AddressFamily;
|
||||
if (af == AddressFamily.InterNetwork)
|
||||
{
|
||||
if (preferredSubnet != String.Empty)
|
||||
{
|
||||
if (Regex.IsMatch(ip.ToString(), preferredSubnet, RegexOptions.IgnoreCase))
|
||||
_ipAddress = ip;
|
||||
}
|
||||
else
|
||||
_ipAddress = ip;
|
||||
|
||||
if (_ipAddress != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_ipAddress != null)
|
||||
{
|
||||
if (_remoteEP == null)
|
||||
_remoteEP = new IPEndPoint(_ipAddress, _remotePort);
|
||||
}
|
||||
else
|
||||
throw new Exception($"Unable to create IPEndPoint to {_remoteAddress}, port {_remotePort}");
|
||||
|
||||
if (_sock == null)
|
||||
_sock = new Socket(_ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connect to remote host
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void Connect()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_sock.Connected && IsRemoteHostAlive())
|
||||
_sock.Connect(_remoteEP);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
_sock = new Socket(_ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
if (IsRemoteHostAlive())
|
||||
_sock.Connect(_remoteEP);
|
||||
}
|
||||
catch (Exception) { throw; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect from remote host
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void Disconnect()
|
||||
{
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_sock.Connected)
|
||||
{
|
||||
_sock.Shutdown(SocketShutdown.Both);
|
||||
_sock.Disconnect(true);
|
||||
_sock.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ping if remote host is alive
|
||||
/// </summary>
|
||||
/// <returns>true/false</returns>
|
||||
bool IsRemoteHostAlive()
|
||||
{
|
||||
bool isRemoteHostAlive = true;
|
||||
|
||||
//Do a ping test to see if the server is reachable
|
||||
try
|
||||
{
|
||||
Ping pingTest = new Ping();
|
||||
PingReply reply = pingTest.Send(_ipAddress);
|
||||
if (reply.Status != IPStatus.Success)
|
||||
isRemoteHostAlive = false;
|
||||
}
|
||||
catch (PingException)
|
||||
{
|
||||
isRemoteHostAlive = false;
|
||||
}
|
||||
|
||||
//See if the tcp state is ok
|
||||
if (_sock.Poll(5000, SelectMode.SelectRead) && (_sock.Available == 0))
|
||||
{
|
||||
isRemoteHostAlive = false;
|
||||
}
|
||||
|
||||
return isRemoteHostAlive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the device.
|
||||
/// </summary>
|
||||
/// <param name="dataBuf"></param>
|
||||
/// <param name="responseTimeOutMs"></param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
public uint Read(ref byte[] dataBuf)
|
||||
{
|
||||
int bytesRec = 0;
|
||||
lock (_syncObj)
|
||||
{
|
||||
try
|
||||
{
|
||||
bytesRec = _sock.Receive(dataBuf);
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
bytesRec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (uint)bytesRec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the read timeout
|
||||
/// </summary>
|
||||
/// <param name="timeoutMs"></param>
|
||||
public void SetReadTimeout(uint timeoutMs)
|
||||
{
|
||||
_sock.ReceiveTimeout = (int)timeoutMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to device.
|
||||
/// </summary>
|
||||
/// <param name="dataBuf"></param>
|
||||
/// <returns>The number of bytes written</returns>
|
||||
public uint Write(byte[] dataBuf, uint numBytesToWrite)
|
||||
{
|
||||
int bytesWritten = 0;
|
||||
lock (_syncObj)
|
||||
{
|
||||
try
|
||||
{
|
||||
bytesWritten = _sock.Send(dataBuf, (int)numBytesToWrite, SocketFlags.None);
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
bytesWritten = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (uint)bytesWritten;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(SolutionDir)Program.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<AssemblyName>Raytheon.Instruments.EthernetSockets.TcpClient</AssemblyName>
|
||||
<RootNamespace>Raytheon.Instruments</RootNamespace>
|
||||
<Product>CommDevice TCP implementation</Product>
|
||||
<Description>CommDevice TCP implementation</Description>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<Company>Raytheon Technologies</Company>
|
||||
<Authors>TEEC</Authors>
|
||||
<Copyright>Copyright © Raytheon Technologies $([System.DateTime]::get_now().ToString("yyyy"))</Copyright>
|
||||
|
||||
<!-- Dynamic Versioning (Suitable for Release) -->
|
||||
<!-- <Version>$(Version)$(Suffix)</Version> -->
|
||||
|
||||
<!-- Static Versioning (Suitable for Development) -->
|
||||
<Version>1.0.0</Version>
|
||||
<Configurations>Debug;Release;Deploy</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
<PackageReference Include="Raytheon.Configuration" Version="2.6.1" />
|
||||
<PackageReference Include="Raytheon.Configuration.Contracts" Version="2.3.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.CommDevice.Contracts" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,32 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// UNCLASSIFIED
|
||||
/*-------------------------------------------------------------------------
|
||||
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||
COMPANY.
|
||||
|
||||
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||
GOVERNMENT.
|
||||
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.EthernetSockets
|
||||
{
|
||||
public enum TcpClientConfigXml
|
||||
{
|
||||
// List all the keys here
|
||||
REMOTE_ADDRESS,
|
||||
REMOTE_PORT
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// 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 NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Raytheon.Instruments.EthernetSockets
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "EthernetSocketsTcpClientFactory")]
|
||||
public class TcpClientFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private static ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
public TcpClientFactory(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 TcpClientFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
if (NLog.LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
NLog.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 TcpClient(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"Unable to construct {name} instrument instance");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public object GetInstrument(string name, bool simulateHw)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new TcpClient(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"Unable to construct {name} instrument instance");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets supported interfaces
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns confiuration 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,878 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// UNCLASSIFIED
|
||||
/*-------------------------------------------------------------------------
|
||||
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||
COMPANY.
|
||||
|
||||
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||
GOVERNMENT.
|
||||
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using Raytheon.Communication;
|
||||
using Raytheon.Communication.Rpc;
|
||||
using Raytheon.Logging;
|
||||
using Raytheon.Composition;
|
||||
using Raytheon.Common;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Win32;
|
||||
using System.IO;
|
||||
using System.ServiceProcess;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
public enum Mode
|
||||
{
|
||||
/// <summary>
|
||||
/// instruments must be managed by the service (like RINSS)
|
||||
/// </summary>
|
||||
Service,
|
||||
/// <summary>
|
||||
/// ignore the service and initialize instruments directly
|
||||
/// </summary>
|
||||
StandAlone,
|
||||
/// <summary>
|
||||
/// dynamically identify if instrument service is running
|
||||
/// </summary>
|
||||
Auto
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// hybrid implementation of the instrument manager interface
|
||||
/// will check if
|
||||
/// </summary>
|
||||
public class GeneralInstrumentManager : IInstrumentManager, IPartImportsSatisfiedNotification
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private readonly bool _haveService;
|
||||
|
||||
private IUms _umsHost;
|
||||
private IUmsClient<IInstrumentManager> _instrumentManager;
|
||||
private IUmsClient<IRpcInstrumentManagerHost> _rpcInstrumentManagerHost;
|
||||
|
||||
private bool _partsLoaded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// PartsLocation - where the instrument manager should get it's MEF components
|
||||
/// </summary>
|
||||
public string _partsLocation { get; set; }
|
||||
/// <summary>
|
||||
/// ConfigLocation - where the configuration manager stores config files
|
||||
/// specifically Instruments.xml
|
||||
/// </summary>
|
||||
public string _configLocation { get; set; }
|
||||
|
||||
private List<RpcInstrumentDescriptor> _availableInstruments = new List<RpcInstrumentDescriptor>();
|
||||
private readonly Dictionary<string, IInstrumentProxyFactory> _factoryMap = new Dictionary<string, IInstrumentProxyFactory>();
|
||||
|
||||
private readonly Dictionary<string, object> _instruments = new Dictionary<string, object>();
|
||||
private readonly HashSet<Type> _instrumentTypes = new HashSet<Type>();
|
||||
|
||||
// simulation
|
||||
private readonly bool _isThereHardware;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
|
||||
private const string NO_SERVER = "Client for communication to the server has not been setup";
|
||||
private const string SECTION = "RpcClient";
|
||||
|
||||
private const string RegistryValue = @"ConsumerInstrumentManagerPartsDirectory";
|
||||
|
||||
private const string RegistryValueNoRINSS = @"InstrumentManagerPartsDirectory";
|
||||
|
||||
private const string RegistryKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Raytheon";
|
||||
|
||||
private const string DefaultName = "Default";
|
||||
private const string DefaultIP = "127.0.0.1";
|
||||
private const string DefaultPort = "8006";
|
||||
private const string DefaultMedia = "Tcp";
|
||||
private const string DefaultSerializer = "Fusion";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
[ImportMany(typeof(IInstrumentFactory))]
|
||||
private Lazy<IInstrumentFactory, IInstrumentFactoryInfo>[] InstrumentFactories { get; set; }
|
||||
|
||||
[Import(typeof(IUmsFactory))]
|
||||
private Lazy<IUmsFactory> LazyUmsFactory { get; set; }
|
||||
private IUmsFactory UmsFactory { get { return LazyUmsFactory?.Value; } }
|
||||
|
||||
[Import(typeof(IConfigurationManager))]
|
||||
private Lazy<IConfigurationManager> LazyConfigManager { get; set; }
|
||||
private IConfigurationManager ConfigManager { get { return LazyConfigManager?.Value; } }
|
||||
|
||||
[Import(typeof(IUmsClientFactory))]
|
||||
private Lazy<IUmsClientFactory> LazyUmsClientFactory { get; set; }
|
||||
private IUmsClientFactory UmsClientFactory { get { return LazyUmsClientFactory?.Value; } }
|
||||
|
||||
[Import(typeof(ILogFactory), AllowDefault = true)]
|
||||
private Lazy<ILogFactory> LazyLogFactory { get; set; }
|
||||
private ILogFactory LogFactory { get { return LazyLogFactory?.Value; } }
|
||||
|
||||
|
||||
[ImportMany(typeof(IInstrumentProxyFactory))]
|
||||
private Lazy<IInstrumentProxyFactory>[] ProxyFactories { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Logging
|
||||
private static ILogger _logger;
|
||||
|
||||
private static ILogger GetLogger()
|
||||
{
|
||||
FusionLogManager.Changed += l => _logger = l.GetLogger();
|
||||
return _logger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// default constructor
|
||||
/// in Auto mode the Instrument Manager will use RINSS based on the service running status
|
||||
/// in Service mode the Instrument Manager must have the RINSS Service running
|
||||
/// in StandAlone mode the Instrument Manager will ignore RINSS
|
||||
/// </summary>
|
||||
public GeneralInstrumentManager(Mode mode = Mode.Auto)
|
||||
{
|
||||
_haveService = CheckServiceRunningStatus("RINSS");
|
||||
if (mode == Mode.Service && !_haveService)
|
||||
{
|
||||
throw new Exception("RINSS Service is not running for Service mode");
|
||||
}
|
||||
|
||||
if (mode == Mode.StandAlone)
|
||||
{
|
||||
_haveService = false;
|
||||
}
|
||||
|
||||
_logger = GetLogger();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// constructor to be used when no RINSS available to set parts location
|
||||
/// </summary>
|
||||
/// <param name="partsLocation"></param>
|
||||
public GeneralInstrumentManager(string partsLocation, Mode mode = Mode.Auto)
|
||||
: this(mode)
|
||||
{
|
||||
_partsLocation = partsLocation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// constructor to be used when no RINSS available to set parts location and configuration location
|
||||
/// </summary>
|
||||
/// <param name="partsLocation"></param>
|
||||
/// <param name="configLocation"></param>
|
||||
/// <param name="mode"></param>
|
||||
public GeneralInstrumentManager(string partsLocation, string configLocation, bool isThereHardware = true, Mode mode = Mode.Auto)
|
||||
: this(partsLocation, mode)
|
||||
{
|
||||
_configLocation= configLocation;
|
||||
_isThereHardware = isThereHardware;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this instance.
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Setup the instrument part path
|
||||
if (!string.IsNullOrWhiteSpace(_partsLocation) && !Directory.Exists(_partsLocation))
|
||||
{
|
||||
_logger.Error($"Unable to id parts in this location: {_partsLocation}");
|
||||
_partsLocation = string.Empty;
|
||||
}
|
||||
|
||||
SetupPath();
|
||||
|
||||
//load the instruments
|
||||
if (!_partsLoaded)
|
||||
{
|
||||
LoadParts();
|
||||
}
|
||||
|
||||
if(_haveService)
|
||||
{
|
||||
// 1. Create the Ums Client
|
||||
CreateUmsClient();
|
||||
_logger.Debug("created client");
|
||||
|
||||
// 2. Find out what instruments are available
|
||||
_availableInstruments = new List<RpcInstrumentDescriptor>(_rpcInstrumentManagerHost.Contract.EnumRpcInstruments());
|
||||
_logger.Debug("geting list of availible instruments");
|
||||
|
||||
// 3. Find all the instrument interfaces supported by proxy factories
|
||||
InitializeFactories();
|
||||
_logger.Debug("initialized all the factories");
|
||||
}
|
||||
else
|
||||
{
|
||||
//configure all the instruments found
|
||||
ConfigureInstruments();
|
||||
}
|
||||
}
|
||||
catch (CompositionException ex)
|
||||
{
|
||||
_logger.ErrorException(ex, "Error in composition during Consumer Instrument Manager initialization");
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException(ex, "Error initializing the instrument manager");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// InitializeInstruments - init all the instruments
|
||||
/// </summary>
|
||||
public void InitializeInstruments()
|
||||
{
|
||||
_logger.Info("Instrument initialization complete");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// InitializeInstrument - inits a specific instrument
|
||||
/// </summary>
|
||||
/// <param name="instName">instrument's unique name</param>
|
||||
public void InitializeInstrument(string instName)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// implementation for IPartImportsSatisfiedNotification interface
|
||||
/// </summary>
|
||||
public void OnImportsSatisfied()
|
||||
{
|
||||
if (LogFactory != null && LogFactory != null)
|
||||
{
|
||||
FusionLogManager.Current = LogFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the generic instrument.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetGenericInstrument(string name)
|
||||
{
|
||||
_logger.Trace("In ConsumerInstrumentManager in method GetGenericInstrument with name: {0} ", name);
|
||||
return GetInstrument<IInstrument>(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// gets a specific instrument by name
|
||||
/// the name should match one of the names in Instruments.xml file
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public T GetInstrument<T>(string name) where T : class
|
||||
{
|
||||
_logger.Trace($"Starting GetInstrument with name: {name}");
|
||||
|
||||
object inst = null;
|
||||
if (_haveService)
|
||||
{
|
||||
try
|
||||
{
|
||||
string interfaceName = typeof(T).FullName;
|
||||
if (typeof(IInstrument).FullName == interfaceName)
|
||||
{
|
||||
_logger.Trace($"GetInstrument with typeof(IInstrument).FullName == interfaceName: {interfaceName}");
|
||||
|
||||
//get the real interface behind the scenes
|
||||
//first find the appropriate factory
|
||||
RpcInstrumentDescriptor correctDesc = _availableInstruments.FirstOrDefault((desc) => 0 == string.Compare(name, desc.InstrumentName, true));
|
||||
if (null != correctDesc)
|
||||
{
|
||||
_logger.Trace($"GetInstrument with correctDesc.name: {correctDesc.InstrumentName}");
|
||||
|
||||
string temp = correctDesc.InstrumentInterfaces.FirstOrDefault();
|
||||
if (!string.IsNullOrWhiteSpace(temp))
|
||||
{
|
||||
interfaceName = temp;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug("Requested generic instrument, found {0} to be the correct interface", interfaceName);
|
||||
}
|
||||
|
||||
if (InstrumentIsAvailable(name) && FactoryIsAvailable(interfaceName))
|
||||
{
|
||||
_logger.Trace($"GetInstrument with InstrumentIsAvailable(name) && FactoryIsAvailable(interfaceName) name: {name}, interfaceName: {interfaceName}");
|
||||
|
||||
IInstrumentProxyFactory factory = _factoryMap.Where((t) => 0 == string.Compare(t.Key, interfaceName, true))
|
||||
.Select(t => t.Value)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (null != factory)
|
||||
{
|
||||
inst = factory.GetInstrument(name);
|
||||
_logger.Trace($"GetInstrument got an instrument (name: {name}) from factory: {factory}, interfaceName: {interfaceName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn($"Could not find factory for interface: {interfaceName}, instrument: {name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InstrumentException ex)
|
||||
{
|
||||
_logger.WarnException(ex, ex.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_instruments.TryGetValue(name.ToLower(), out inst);
|
||||
}
|
||||
|
||||
_logger.Trace($"GetInstrument returning with inst: {inst}");
|
||||
|
||||
return inst as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns a collection of instrument names
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<string> GetInstrumentNames()
|
||||
{
|
||||
_logger.Trace("Returning instrument list");
|
||||
|
||||
if (_haveService)
|
||||
{
|
||||
return _instrumentManager.Contract.GetInstrumentNames();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ReadOnlyCollection<string>(_instruments.Keys.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
public string[] GetInstrumentNamesArray()
|
||||
{
|
||||
_logger.Debug("Getting Instrument Names Array");
|
||||
return GetInstrumentNames().ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets instruments collection
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<object> GetInstruments()
|
||||
{
|
||||
_logger.Debug("GetInstruments with null");
|
||||
return GetInstruments(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets instruments collection by type
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public ICollection<object> GetInstruments(Type type)
|
||||
{
|
||||
_logger.Debug($"Entering GetInstruments with type {type}");
|
||||
|
||||
var instruments = new List<object>();
|
||||
|
||||
if (_haveService)
|
||||
{
|
||||
if (null == _rpcInstrumentManagerHost)
|
||||
{
|
||||
_logger.Warn(NO_SERVER);
|
||||
}
|
||||
else
|
||||
{
|
||||
//gather all the instruments of the requested type
|
||||
if (null == type)
|
||||
{
|
||||
type = typeof(IInstrument);
|
||||
}
|
||||
|
||||
_logger.Debug("GetInstruments geting collection");
|
||||
|
||||
var collection = from avail in _availableInstruments
|
||||
where avail.InstrumentInterfaces.Contains(type.FullName)
|
||||
select avail;
|
||||
|
||||
_logger.Debug("GetInstruments got collection count = " + collection.Count());
|
||||
|
||||
MethodInfo method = typeof(GeneralInstrumentManager).GetMethod("GetInstrument");
|
||||
MethodInfo generic = method.MakeGenericMethod(type);
|
||||
|
||||
foreach (var item in collection)
|
||||
{
|
||||
object[] objs = { item.InstrumentName };
|
||||
IInstrument created = generic.Invoke(this, objs) as IInstrument;
|
||||
instruments.Add(created);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(type == null)
|
||||
{
|
||||
instruments.AddRange(_instruments.Values);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var inst in _instruments.Values)
|
||||
{
|
||||
if (type.IsAssignableFrom(inst.GetType()))
|
||||
{
|
||||
instruments.Add(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ReadOnlyCollection<object>(instruments);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns instrument array of specific type
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public object[] GetInstrumentsArray(Type type)
|
||||
{
|
||||
if (null == type)
|
||||
{
|
||||
throw new ArgumentNullException("type", "GetInstrumentsArray, cannot get null instrument types");
|
||||
}
|
||||
|
||||
_logger.Debug($"GetInstrumentsArray with type {type}");
|
||||
|
||||
return GetInstruments(type).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns instrument array
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public object[] GetInstrumentsArray()
|
||||
{
|
||||
_logger.Debug("Get Instruments Array");
|
||||
return GetInstruments().ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down this instance.
|
||||
/// Close out the RPC host connection. Does not close / shutdown RINSS or any
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
_logger.Info("Shutting down instruments");
|
||||
|
||||
if (_haveService)
|
||||
{
|
||||
_rpcInstrumentManagerHost.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShutdownInstruments();
|
||||
}
|
||||
_logger.Info("Instrument shut down complete");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down the instruments.
|
||||
/// </summary>
|
||||
public void ShutdownInstruments()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shutdowns the instrument.
|
||||
/// </summary>
|
||||
/// <param name="instName">Name of the inst.</param>
|
||||
public void ShutdownInstrument(string instName)
|
||||
{
|
||||
}
|
||||
|
||||
#region Private Functions
|
||||
|
||||
/// <summary>
|
||||
/// for the Auto mode will check if RINSS available
|
||||
/// </summary>
|
||||
/// <param name="serviceName"></param>
|
||||
/// <returns></returns>
|
||||
private bool CheckServiceRunningStatus(string serviceName)
|
||||
{
|
||||
if(!DoesServiceExist(serviceName))
|
||||
return false;
|
||||
|
||||
ServiceController sc = new ServiceController(serviceName);
|
||||
return sc.Status == ServiceControllerStatus.Running;
|
||||
}
|
||||
private static bool DoesServiceExist(string serviceName)
|
||||
{
|
||||
return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals(serviceName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load parts with RINSS running or without RINSS
|
||||
/// </summary>
|
||||
private void LoadParts()
|
||||
{
|
||||
_logger.Debug($"Loading Parts from path {_partsLocation}");
|
||||
|
||||
//install we are assuming will put the needed parts into a directory ./Parts just off the
|
||||
//directory where the assembly is
|
||||
MefHelper helper = new MefHelper(false, false);
|
||||
try
|
||||
{
|
||||
helper.AddCatalog(_partsLocation, true);
|
||||
helper.Container.ComposeParts(this);
|
||||
|
||||
if(_haveService)
|
||||
{
|
||||
if (null == ConfigManager || null == UmsClientFactory || null == UmsFactory)
|
||||
{
|
||||
throw new CompositionException($"General Instrument Manager has null MEF components, please check MEF plugin location: {_partsLocation}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (null == ConfigManager || null == InstrumentFactories)
|
||||
{
|
||||
throw new CompositionException($"Error during MEF composition, check MEF Part Location: {_partsLocation}");
|
||||
}
|
||||
}
|
||||
|
||||
_partsLoaded = true;
|
||||
if(!string.IsNullOrEmpty(_configLocation))
|
||||
ConfigManager.ConfigurationStoragePath = _configLocation;
|
||||
}
|
||||
catch (CompositionException ex)
|
||||
{
|
||||
_logger.ErrorException(ex, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// will set up path where either proxy instruments are (in case when RINSS running)
|
||||
/// or where the actual instruments are (in case RINSS not running)
|
||||
/// </summary>
|
||||
/// <param name="defaultPathWinNew"></param>
|
||||
/// <param name="defaultPathWinOld"></param>
|
||||
/// <param name="keyName"></param>
|
||||
/// <param name="valueName"></param>
|
||||
private void SetupPath()
|
||||
{
|
||||
_logger.Trace("Setting up Instrument Manager parts location");
|
||||
if (string.IsNullOrEmpty(_partsLocation))
|
||||
{
|
||||
string pf86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
|
||||
string pf = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
|
||||
//ATEasy and other apps are messing with the previously used ./Parts locations
|
||||
//so we have moved to using a registry entry that is created on install and refers
|
||||
//to the directory installed to, the PartsLocation property still allows for custom directories
|
||||
//to be used for the Consumer Instrument Manager
|
||||
string defaultPath = _haveService ? $"{pf86}\\Raytheon\\RINSS-ConsumerIM\\Parts" : $"{pf86}\\Raytheon\\RINSS\\Parts\\CommonModuleInstruments";
|
||||
if (Environment.OSVersion.Version.Major < 6)
|
||||
{
|
||||
//if we are windows xp, then we need to look in a different default directory
|
||||
defaultPath = _haveService ? $"{pf}\\Raytheon\\RINSS-ConsumerIM\\Parts" : $"{pf}\\Raytheon\\RINSS\\Parts\\CommonModuleInstruments";
|
||||
}
|
||||
|
||||
var keyName = RegistryKey;
|
||||
var valueName = _haveService ? RegistryValue : RegistryValueNoRINSS;
|
||||
|
||||
string path = (string)Registry.GetValue(keyName, valueName, defaultPath);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(path) || !Directory.Exists(path))
|
||||
{
|
||||
path = defaultPath;
|
||||
}
|
||||
|
||||
_partsLocation = path;
|
||||
}
|
||||
_logger.Trace($"Mef parts load Location is: {_partsLocation}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// creates Umc client used in remote procedure calls
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
private void CreateUmsClient()
|
||||
{
|
||||
_logger.Trace("Loading Proxy Instrument Configuration Settings");
|
||||
|
||||
string configName = "ProxyInstruments";
|
||||
IConfiguration config = ConfigManager.GetConfiguration(configName);
|
||||
|
||||
if (null == config)
|
||||
{
|
||||
string errorMessage = string.Format(@"Could not get configuration file, check configuration location for file: {0}", configName);
|
||||
_logger.Error(errorMessage);
|
||||
throw new ArgumentNullException(errorMessage);
|
||||
}
|
||||
|
||||
string rpcName = config.GetConfigurationValue(SECTION, "Name", string.Empty);
|
||||
|
||||
//if the configuration element does not exist, then create the defaults
|
||||
if (string.IsNullOrWhiteSpace(rpcName))
|
||||
{
|
||||
_logger.Info("No Rpc Client Instrument Manager configuration found, creating default");
|
||||
config.SetConfigurationValue(SECTION, "Name", DefaultName);
|
||||
config.SetConfigurationValue(SECTION, "IPAddress", DefaultIP);
|
||||
config.SetConfigurationValue(SECTION, "Port", DefaultPort);
|
||||
config.SetConfigurationValue(SECTION, "MediaType", DefaultMedia);
|
||||
config.SetConfigurationValue(SECTION, "SerializerType", DefaultSerializer);
|
||||
}
|
||||
|
||||
_logger.Trace("Consumer Instrument Manager is creating Ums Client");
|
||||
|
||||
if (null == UmsClientFactory || null == UmsFactory)
|
||||
{
|
||||
var ex = new ArgumentNullException(string.Format("Ums components are null, please check MEF plugin location: {0}", _partsLocation));
|
||||
_logger.ErrorException(ex, ex.Message);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
string name = config.GetConfigurationValue(SECTION, "Name", DefaultName);
|
||||
string ipAddress = config.GetConfigurationValue(SECTION, "IPAddress", DefaultIP);
|
||||
string hostPort = config.GetConfigurationValue(SECTION, "Port", DefaultPort);
|
||||
string mediaType = config.GetConfigurationValue(SECTION, "MediaType", DefaultMedia);
|
||||
string serializerType = config.GetConfigurationValue(SECTION, "SerializerType", DefaultSerializer);
|
||||
|
||||
//we already checked for null above!
|
||||
_umsHost = UmsFactory.GetInstance(name, ipAddress, hostPort, UmsInstanceType.Client, mediaType, serializerType);
|
||||
|
||||
//open a client for the instrument manager
|
||||
_instrumentManager = UmsClientFactory.GetClient<IInstrumentManager>(_umsHost);
|
||||
_instrumentManager.Open();
|
||||
|
||||
//open a client for the host server
|
||||
_rpcInstrumentManagerHost = UmsClientFactory.GetClient<IRpcInstrumentManagerHost>(_umsHost);
|
||||
_rpcInstrumentManagerHost.Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// will initialize factories for instuments managed under RINSS
|
||||
/// </summary>
|
||||
private void InitializeFactories()
|
||||
{
|
||||
_logger.Debug($"InitializeFactories ProxyFactories count = {ProxyFactories.Count()}");
|
||||
|
||||
foreach (var fact in ProxyFactories)
|
||||
{
|
||||
_logger.Debug("InitializeFactories fact=" + fact.Value);
|
||||
//initialize each factory so it can create the clients
|
||||
fact.Value.Initialize(_umsHost, UmsClientFactory);
|
||||
|
||||
//map out the factories with their interface names
|
||||
var availableInterfaces = fact.Value.GetSupportedInterfaces();
|
||||
_logger.Debug($"InitializeFactories availableInterfaces count = {availableInterfaces.Count}");
|
||||
|
||||
foreach (var face in availableInterfaces)
|
||||
{
|
||||
_logger.Debug($"InitializeFactories Interface = {face}");
|
||||
_factoryMap.Add(face.ToLower(), fact.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// will configure instruments when not managed by Service
|
||||
/// </summary>
|
||||
/// <exception cref="ConfigurationException"></exception>
|
||||
private void ConfigureInstruments()
|
||||
{
|
||||
_logger.Info("Configuring Instruments");
|
||||
IConfiguration config = ConfigManager.GetConfiguration("Instruments");
|
||||
|
||||
if (null == config)
|
||||
{
|
||||
throw new ConfigurationException("could not find configuration file");
|
||||
}
|
||||
|
||||
string rawConfig = config.GetXmlConfiguration("Instruments");
|
||||
if (string.IsNullOrWhiteSpace(rawConfig))
|
||||
{
|
||||
_logger.Warn("No RPC configuration found, creating default 'Instruments'");
|
||||
config.SetXmlConfiguration("Instruments", new XElement("Instrument",
|
||||
new XElement("Name", "Sample"),
|
||||
new XElement("Factory", "Sample")).ToString());
|
||||
rawConfig = config.GetXmlConfiguration("Instruments");
|
||||
}
|
||||
|
||||
_instrumentTypes.Add(typeof(IInstrument));
|
||||
if (0 == InstrumentFactories.Count())
|
||||
{
|
||||
_logger.Warn($"There are no instrument factories registered using the following path: {Path.GetFullPath(_partsLocation)}");
|
||||
}
|
||||
|
||||
XElement xmlConfig = XElement.Parse(rawConfig);
|
||||
if (null == xmlConfig)
|
||||
{
|
||||
throw new ConfigurationException("could not parse configuration file");
|
||||
}
|
||||
|
||||
var decendants = xmlConfig.Descendants("Instrument");
|
||||
if (null != decendants)
|
||||
{
|
||||
foreach (var instrument in decendants)
|
||||
{
|
||||
var instName = instrument.Element("Name").Value;
|
||||
var instFactory = instrument.Element("Factory").Value;
|
||||
_logger.Trace($"In ConfigureInstruments before factory call with XML name: {instName} and XML factory: {instFactory}");
|
||||
var factory = (from f in InstrumentFactories
|
||||
where !string.IsNullOrWhiteSpace(f.Metadata.ModelNumber) && f.Metadata.ModelNumber.Equals(instFactory, StringComparison.OrdinalIgnoreCase)
|
||||
select f).FirstOrDefault();
|
||||
|
||||
if (factory != null)
|
||||
{
|
||||
object inst = null;
|
||||
try
|
||||
{
|
||||
// instantiate the applicable instrument
|
||||
inst = factory.Value.GetInstrument(instName, !_isThereHardware);
|
||||
_logger.Info($"Creating instrument '{instName}'");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.WarnException(ex, ex.Message);
|
||||
inst = null;
|
||||
}
|
||||
|
||||
if (null == inst)
|
||||
{
|
||||
_logger.Warn($"Could not create the instrument: {instName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
var supported = factory.Value.GetSupportedInterfaces();
|
||||
if (null != supported)
|
||||
{
|
||||
//add the instrument
|
||||
string txt = $"Adding instrument: Name - {instName}, Type - {inst.GetType()}";
|
||||
_instruments.Add(instName.ToLower(), inst);
|
||||
foreach (var supportedInterface in supported)
|
||||
{
|
||||
_instrumentTypes.Add(supportedInterface);
|
||||
_logger.Info($"{txt}, Interface - {supportedInterface}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn($"Did not see any supported interfaces for: {instName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn($"{instName} did not have a matching factory with supported type {instFactory}");
|
||||
|
||||
if (InstrumentFactories.Count() > 0)
|
||||
{
|
||||
var factories = new StringBuilder();
|
||||
factories.Append("Available Factory types loaded: ");
|
||||
foreach (var kvp in InstrumentFactories)
|
||||
{
|
||||
factories.AppendLine();
|
||||
factories.AppendFormat(" {0}", kvp.Metadata.ModelNumber);
|
||||
}
|
||||
_logger.Info(factories.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("could not find instrument section of configuration");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// checks if instrument is available
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
private bool InstrumentIsAvailable(string name)
|
||||
{
|
||||
//check if our host has a instrument by this name available to us
|
||||
if (!_availableInstruments.Any(t => 0 == string.Compare(t.InstrumentName, name, true)))
|
||||
{
|
||||
_logger.Warn($"{name} instrument not available");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// checks if instrument factory is available
|
||||
/// </summary>
|
||||
/// <param name="interfaceName"></param>
|
||||
/// <returns></returns>
|
||||
private bool FactoryIsAvailable(string interfaceName)
|
||||
{
|
||||
bool bReturn = false;
|
||||
|
||||
if (typeof(IInstrument).FullName == interfaceName)
|
||||
{
|
||||
_logger.Debug($"In GeneralInstrumentManager in method FactoryIsAvailable with typeof(IInstrument).FullName == interfaceName : {interfaceName}");
|
||||
bReturn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//check if we have a factory that supports this interface
|
||||
var sb = new StringBuilder();
|
||||
foreach (KeyValuePair<string, IInstrumentProxyFactory> x in _factoryMap)
|
||||
{
|
||||
sb.Append("FactoryMap IInstrumentProxyFactory: key = ");
|
||||
sb.Append(x.Key);
|
||||
sb.Append(" value = ");
|
||||
sb.Append(x.Value);
|
||||
sb.Append(" supportedInterfaces = ");
|
||||
sb.Append(x.Value.GetSupportedInterfaces());
|
||||
sb.Append(Environment.NewLine);
|
||||
}
|
||||
|
||||
_logger.Debug(sb.ToString());
|
||||
|
||||
var kvp = _factoryMap.Where((t) => 0 == string.Compare(t.Key, interfaceName, true))
|
||||
.Select(t => new { t.Key, t.Value })
|
||||
.FirstOrDefault();
|
||||
|
||||
if (null == kvp)
|
||||
{
|
||||
_logger.Warn($"{interfaceName} interface proxy factory not found");
|
||||
}
|
||||
bReturn = kvp != null;
|
||||
}
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(SolutionDir)Program.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<AssemblyName>Raytheon.Instruments.InstrumentManager.GeneralInstrumentManager</AssemblyName>
|
||||
<RootNamespace>Raytheon.Instruments</RootNamespace>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<Company>Raytheon Technologies</Company>
|
||||
<Product>General Instrument Manager</Product>
|
||||
<Authors>TEEC</Authors>
|
||||
<Copyright>Copyright © Raytheon Technologies $([System.DateTime]::get_now().ToString("yyyy"))</Copyright>
|
||||
<Description>Instrument Manager that works with RINSS or without RINSS</Description>
|
||||
|
||||
<Version>1.4.1</Version>
|
||||
<Configurations>Debug;Release;Deploy</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Raytheon.Composition" Version="1.0.0.14" />
|
||||
<PackageReference Include="Raytheon.Configuration.Contracts" Version="2.3.0" />
|
||||
<PackageReference Include="Raytheon.Configuration" Version="2.6.1" />
|
||||
<PackageReference Include="Raytheon.Instruments.RpcInstrumentManager.Contracts" Version="1.1.1.0" />
|
||||
<PackageReference Include="Raytheon.Logging.Contracts" Version="1.3.0.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.Contracts" Version="1.5.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.InstrumentManager.Contracts" Version="1.7.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.ServiceProcess" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(SolutionDir)Program.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<AssemblyName>Raytheon.Instruments.PowerSupplies.Keysight67XX</AssemblyName>
|
||||
<RootNamespace>Raytheon.Instruments</RootNamespace>
|
||||
<Product>Keysight 67XX Series Power Supply</Product>
|
||||
<Description>Keysight 67XX Series Power Supply</Description>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<Company>Raytheon Technologies</Company>
|
||||
<Authors>TEEC</Authors>
|
||||
<Copyright>Copyright © Raytheon Technologies $(Year)</Copyright>
|
||||
|
||||
<!-- Dynamic Versioning (Suitable for Release) -->
|
||||
<!-- <Version>$(Version)$(Suffix)</Version> -->
|
||||
|
||||
<!-- Static Versioning (Suitable for Development) -->
|
||||
<Version>1.0.0</Version>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
<PackageReference Include="Raytheon.Configuration" Version="2.6.1" />
|
||||
<PackageReference Include="Raytheon.Configuration.Contracts" Version="2.3.0" />
|
||||
|
||||
<!--
|
||||
<PackageReference Include="Raytheon.Instruments.PowerSupply.Contracts" Version="1.1.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.PowerSupplies.Simulation" Version="1.0.0" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Interfaces\PowerSupply\PowerSupply.Contracts.csproj" />
|
||||
<ProjectReference Include="..\..\EthernetSockets\CommDeviceTcpClient\TcpClient.csproj" />
|
||||
<ProjectReference Include="..\PowerSupplySim\PowerSupplySim.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,117 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// 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 NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "PowerSupplyKeysightN67xxFactory")]
|
||||
public class KeysightN67xxPowerFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private static ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
public KeysightN67xxPowerFactory(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 KeysightN67xxPowerFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
if (NLog.LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(PowerSupply));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public object GetInstrument(string name, bool simulateHw)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (simulateHw)
|
||||
return new PowerSupplySim(name, _configurationManager, _logger);
|
||||
else
|
||||
return new KeysightN67xxPowerSupply(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"Unable to construct {name} instrument instance");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets supported interfaces
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns confiuration 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,663 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// 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 NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to simulate any power supply module
|
||||
/// </summary>
|
||||
class KeysightN67xxPowerModule : PowerSupplyModule
|
||||
{
|
||||
private List<string> _groupedModules;
|
||||
private List<string> _coupledModules;
|
||||
private string _powerSupplySystemName;
|
||||
private EthernetSockets.TcpClient _tcpClient;
|
||||
IConfigurationFile _config;
|
||||
|
||||
private ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public KeysightN67xxPowerModule(string iniFilePath, string powerSupplySystemName)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_powerSupplySystemName = powerSupplySystemName;
|
||||
|
||||
_config = new ConfigurationFile(iniFilePath);
|
||||
|
||||
string ipAddress = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.ETHERNET_ADDRESS.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
int port = 0;
|
||||
Int32.TryParse(_config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.ETHERNET_PORT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out port);
|
||||
string moduleDef = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.MODULE_DEFINITION.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
string coupledModules = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.COUPLED_MODULES.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
string groupedModules = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.GROUPED_MODULES.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
|
||||
List<string> powerModules = moduleDef.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
_coupledModules = coupledModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
_groupedModules = groupedModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
|
||||
_tcpClient = new EthernetSockets.TcpClient(ipAddress, port);
|
||||
_tcpClient.Initialize();
|
||||
_tcpClient.Connect();
|
||||
|
||||
ResetPowerSupplySystem();
|
||||
|
||||
bool systemRebooted = false;
|
||||
if (_groupedModules.Count() > 1)
|
||||
GroupModules(_groupedModules, out systemRebooted);
|
||||
else if (_coupledModules.Count() > 1)
|
||||
CoupleModules(_coupledModules);
|
||||
|
||||
if (systemRebooted)
|
||||
{
|
||||
_tcpClient.Disconnect();
|
||||
_tcpClient.Connect();
|
||||
}
|
||||
|
||||
if (_groupedModules.Count() > 1)
|
||||
{
|
||||
powerModules.Clear();
|
||||
// since modules are grouped, we pick the first module as the representative module
|
||||
powerModules.Add(_groupedModules[0]);
|
||||
}
|
||||
|
||||
// build the power module map
|
||||
string moduleIndex = "";
|
||||
double ovp = 0.0;
|
||||
double ocp = 0.0;
|
||||
double voltageSetPoint = 0.0;
|
||||
double voltageSlewRate = -1.0;
|
||||
|
||||
double minVoltage = 0.0;
|
||||
double maxVoltage = 0.0;
|
||||
double minCurrent = 0.0;
|
||||
double maxCurrent = 0.0;
|
||||
|
||||
for (int i = 0; i < powerModules.Count(); i++)
|
||||
{
|
||||
string moduleName = powerModules[i];
|
||||
|
||||
moduleIndex = _config.ReadValue(moduleName, PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.OCP.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out ocp);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.OVP.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out ovp);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SETPOINT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out voltageSetPoint);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SLEW_RATE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out voltageSlewRate);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_VOLTAGE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out minVoltage);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_VOLTAGE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out maxVoltage);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_CURRENT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out minCurrent);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_CURRENT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out maxCurrent);
|
||||
|
||||
PowerModuleInfoDict[moduleName] = new Raytheon.Instruments.PowerSupplies.PowerSupplyModuleInfo(moduleIndex, ocp, ovp, voltageSetPoint, voltageSlewRate, minVoltage, maxVoltage, minCurrent, maxCurrent);
|
||||
|
||||
ActivePowerModule = moduleName;
|
||||
SetConstantVoltageMode();
|
||||
SetAndConfirmOvp();
|
||||
SetAndConfirmOcp();
|
||||
SetAndConfirmVoltageSetpoint();
|
||||
SetAndConfirmVoltageSlewRate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable Front Panel
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override bool DisplayEnabled
|
||||
{
|
||||
set
|
||||
{
|
||||
SemObj?.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable Front Panel
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override bool FrontPanelEnabled
|
||||
{
|
||||
get { SemObj?.Release(); throw new NotImplementedException(); }
|
||||
set
|
||||
{
|
||||
string command;
|
||||
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
if (value)
|
||||
command = KeysightPowerSupplyScpiCommands.SET_FRONTPANEL_ENABLE_CMD + "\n";
|
||||
else
|
||||
command = KeysightPowerSupplyScpiCommands.SET_FRONTPANEL_DISABLE_CMD + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turn on power module's output
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override void On()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
CheckActivePowerModuleValidity();
|
||||
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_OUTPUT_ENABLE_CMD + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turn off power module's output
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override void Off()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
CheckActivePowerModuleValidity();
|
||||
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_OUTPUT_DISABLE_CMD + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform self test
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override SelfTestResult PerformSelfTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SELFTEST_CMD + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
string[] stringVec = rsp.Split(',');
|
||||
|
||||
int status = -1;
|
||||
Int32.TryParse(stringVec[0], out status);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
SelfTestResult = SelfTestResult.Fail;
|
||||
throw new Exception($"{_powerSupplySystemName}'s self-test failed with error code: {status}");
|
||||
}
|
||||
else
|
||||
SelfTestResult = SelfTestResult.Pass;
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); }
|
||||
|
||||
return SelfTestResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set constant voltage mode
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetConstantVoltageMode()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_CONSTANT_VOLTAGE_CMD + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set and Confirm OVP
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetAndConfirmOvp()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_OVP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
command = KeysightPowerSupplyScpiCommands.READ_OVP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
double ovp = 0.0;
|
||||
|
||||
Double.TryParse(rsp, out ovp);
|
||||
|
||||
if (ovp != PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_)
|
||||
throw new Exception($"Unable to set OVP. Expected OVP: {PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_}. Actual: {ovp}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set and Confirm OCP
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetAndConfirmOcp()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_OCP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
command = KeysightPowerSupplyScpiCommands.READ_OCP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
double ocp = 0.0;
|
||||
|
||||
Double.TryParse(rsp, out ocp);
|
||||
|
||||
if (ocp != PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_)
|
||||
throw new Exception($"Unable to set OCP. Expected OCP: {PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_}. Actual: {ocp}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set and Confirm Voltage Setpoint
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetAndConfirmVoltageSetpoint()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_VOLTAGE_SETPOINT_CMD + " " + PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
command = KeysightPowerSupplyScpiCommands.READ_VOLTAGE_SETPOINT_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
double voltage = 0.0;
|
||||
|
||||
Double.TryParse(rsp, out voltage);
|
||||
|
||||
if (voltage != PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_)
|
||||
throw new Exception($"Unable to set Voltage Setpoint. Expected Voltage Setpoint: {PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_}. Actual: {voltage}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set and Confirm Slew Rate
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetAndConfirmVoltageSlewRate()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
if (PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_ > 0.0)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_VOLTAGE_SLEW_RATE_CMD + " " + PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
command = KeysightPowerSupplyScpiCommands.READ_VOLTAGE_SLEW_RATE_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
double voltageSlewRate = 0.0;
|
||||
|
||||
Double.TryParse(rsp, out voltageSlewRate);
|
||||
|
||||
if (voltageSlewRate != PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_)
|
||||
throw new Exception($"Unable to set Voltage Slew Rate. Expected Voltage Slew Rate: {PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_}. Actual: {voltageSlewRate}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get error code
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
protected override string GetErrorCode(out int errorCode)
|
||||
{
|
||||
errorCode = 0;
|
||||
string rtn = "";
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_ERROR_CODE_CMD + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
string[] stringVec = rsp.Split(',');
|
||||
|
||||
Int32.TryParse(stringVec[0], out errorCode);
|
||||
|
||||
if (stringVec.Length > 1)
|
||||
{
|
||||
rtn = stringVec[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read voltage
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override double ReadVoltage()
|
||||
{
|
||||
double val = 0.0;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_VOLTAGE_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
Double.TryParse(rsp, out val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read current
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override double ReadCurrent()
|
||||
{
|
||||
double val = 0.0;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_CURRENT_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
Double.TryParse(rsp, out val);
|
||||
}
|
||||
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read protection status
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override int ReadProtectionStatus()
|
||||
{
|
||||
int val = -1;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_PROTECTION_STATUS_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
Int32.TryParse(rsp, out val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if module's output is on
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override bool IsOutputOn()
|
||||
{
|
||||
bool isOn = false;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_OUTPUT_STATUS_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
int status = -1;
|
||||
|
||||
Int32.TryParse(rsp, out status);
|
||||
|
||||
if (status == 1)
|
||||
{
|
||||
isOn = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isOn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When modules are grouped, they act as one module
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void GroupModules(List<string> moduleList, out bool systemRebooted)
|
||||
{
|
||||
// 1. Group the channels
|
||||
string groupListToDefine = "(@";
|
||||
string groupListToQuery = "";
|
||||
string moduleNumber = "";
|
||||
|
||||
systemRebooted = false;
|
||||
|
||||
for (int i = 0; i < moduleList.Count; i++)
|
||||
{
|
||||
moduleNumber = _config.ReadValue(moduleList[i], PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
|
||||
groupListToDefine += moduleNumber;
|
||||
groupListToQuery += moduleNumber;
|
||||
|
||||
// add a ',' if this is not the final element in the list
|
||||
if (i < moduleList.Count() - 1)
|
||||
{
|
||||
groupListToDefine += ",";
|
||||
groupListToQuery += ",";
|
||||
}
|
||||
else
|
||||
{
|
||||
groupListToDefine += ")";
|
||||
}
|
||||
}
|
||||
|
||||
groupListToQuery = "\"" + groupListToQuery + "\"\n";
|
||||
|
||||
// see if channels are grouped
|
||||
string queryGroupCommand = KeysightPowerSupplyScpiCommands.QUERY_GROUP_CHANNELS + "\n";
|
||||
|
||||
for (int i = 1; i <= 2; i++)
|
||||
{
|
||||
string respStr = SendCommandAndGetResponse(queryGroupCommand);
|
||||
|
||||
// if modules are not grouped
|
||||
if (respStr != groupListToQuery)
|
||||
{
|
||||
groupListToDefine += "\n";
|
||||
|
||||
string groupCommand = KeysightPowerSupplyScpiCommands.SET_GROUP_DEFINE_CMD + " " + groupListToDefine;
|
||||
|
||||
SendCommand(groupCommand);
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.REBOOT_CMD + "\n";
|
||||
// after grouping the modules, need to reboot system for it to take effect
|
||||
SendCommand(command);
|
||||
|
||||
// wait 20 seconds for reboot
|
||||
Thread.Sleep(20000);
|
||||
|
||||
systemRebooted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When modules are coupled, they turned on and off in unison
|
||||
/// i.e turn on/off one module, all other coupled modules will automatically turn on/off
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void CoupleModules(List<string> moduleList)
|
||||
{
|
||||
string coupleListToDefine = "";
|
||||
string moduleNumber = "";
|
||||
|
||||
for (int i = 0; i < moduleList.Count(); i++)
|
||||
{
|
||||
moduleNumber = _config.ReadValue(moduleList[i], PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
|
||||
coupleListToDefine += moduleNumber;
|
||||
|
||||
// add a ',' if this is not the final element in the list
|
||||
if (i < moduleList.Count() - 1)
|
||||
{
|
||||
coupleListToDefine += ",";
|
||||
}
|
||||
}
|
||||
|
||||
coupleListToDefine += "\n";
|
||||
|
||||
// see if channels are grouped
|
||||
string queryCoupleChannelCommand = KeysightPowerSupplyScpiCommands.QUERY_COUPLE_CHANNELS + "\n";
|
||||
|
||||
for (int i = 1; i <= 2; i++)
|
||||
{
|
||||
string respStr = SendCommandAndGetResponse(queryCoupleChannelCommand);
|
||||
|
||||
string queryCoupleStateCommand = KeysightPowerSupplyScpiCommands.QUERY_COUPLE_STATE + "\n";
|
||||
string respStr2 = SendCommandAndGetResponse(queryCoupleStateCommand);
|
||||
|
||||
if (coupleListToDefine != respStr || respStr2 == "0\n")
|
||||
{
|
||||
// send command to couple modules
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_COUPLE_CHANNELS_CMD + " " + coupleListToDefine;
|
||||
SendCommand(command);
|
||||
|
||||
// turn coupling on
|
||||
command = KeysightPowerSupplyScpiCommands.SET_COUPLE_ON_CMD + "\n";
|
||||
SendCommand(command);
|
||||
|
||||
// output protection on
|
||||
command = KeysightPowerSupplyScpiCommands.SET_COUPLE_OUTPUT_PROTECT_ON_CMD + "\n";
|
||||
SendCommand(command);
|
||||
}
|
||||
else if (i == 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset Power Supply System
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void ResetPowerSupplySystem()
|
||||
{
|
||||
// send the command
|
||||
string command = KeysightPowerSupplyScpiCommands.RESET_CMD + "\n";
|
||||
SendCommand(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send command
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SendCommand(string command)
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
byte[] msg = Encoding.ASCII.GetBytes(command);
|
||||
|
||||
_tcpClient.Write(msg, (uint)msg.Length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send command and get response
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private string SendCommandAndGetResponse(string command)
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
byte[] readBuf = new byte[100];
|
||||
_tcpClient.SetReadTimeout(2000);
|
||||
|
||||
int bytesRec = 0;
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
try
|
||||
{
|
||||
bytesRec = (int)_tcpClient.Read(ref readBuf);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
throw new Exception("SocketException Error Code: " + ex.ErrorCode + $" ({((SocketError)ex.ErrorCode).ToString()})");
|
||||
}
|
||||
|
||||
return Encoding.ASCII.GetString(readBuf, 0, bytesRec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
// 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 NLog;
|
||||
using Raytheon.Common;
|
||||
using Raytheon.Instruments.EthernetSockets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for controlling a Keysightt N6700 Series Power Supply System
|
||||
/// </summary>
|
||||
public class KeysightN67xxPowerSupply : PowerSupply
|
||||
{
|
||||
private string _iniFilePath;
|
||||
|
||||
private static ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public KeysightN67xxPowerSupply(string deviceInstanceName, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
Name = deviceInstanceName;
|
||||
_logger = logger;
|
||||
_configurationManager = configurationManager;
|
||||
|
||||
// configuration obtained from [deviceInstanceName].xml file
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
_iniFilePath = Path.Combine(assemblyFolder, _configuration.GetConfigurationValue(deviceInstanceName, PowerSupplyConfigXml.INI_FILE_PATH.ToString(), $".\\{Raytheon.Common.GeneralConstants.InstrumentConfigFolder}\\{deviceInstanceName}.ini"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform shutdown
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override void Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform reset
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override void Reset()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear errors
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override bool ClearErrors()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement Indexer in order to access a specific power module
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override PowerSupplyModule this[object powerDeviceId]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!(powerDeviceId == null || powerDeviceId.GetType().IsEnum))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(powerDeviceId)} must be an enumerated type or null");
|
||||
}
|
||||
|
||||
_powerSupplyModule.GetSemphamore().WaitOne();
|
||||
|
||||
if (powerDeviceId != null)
|
||||
_powerSupplyModule.SetActivePowerModule(powerDeviceId.ToString());
|
||||
|
||||
return _powerSupplyModule;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Group or couple modules as specified in config file
|
||||
/// Gather information for each power module from config file
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override void Initialize()
|
||||
{
|
||||
_powerSupplyModule = new KeysightN67xxPowerModule(_iniFilePath, Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// UNCLASSIFIED
|
||||
/*-------------------------------------------------------------------------
|
||||
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||
COMPANY.
|
||||
|
||||
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||
GOVERNMENT.
|
||||
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
public static class KeysightPowerSupplyScpiCommands
|
||||
{
|
||||
public static string CLEAR_CMD = "*CLS";
|
||||
public static string RESET_CMD = "*RST";
|
||||
public static string SELFTEST_CMD = "*TST?";
|
||||
public static string READ_ERROR_CODE_CMD = "SYST:ERR?";
|
||||
public static string REBOOT_CMD = "SYST:REB";
|
||||
|
||||
// panel disable/enable commands
|
||||
public static string SET_FRONTPANEL_DISABLE_CMD = "SYST:COMM:RLST RWL";
|
||||
public static string SET_FRONTPANEL_ENABLE_CMD = "SYST:COMM:RLST REM";
|
||||
|
||||
// watchdog commands
|
||||
public static string SET_WATCHDOGDELAY_CMD = "OUTP:PROT:WDOG:DEL";
|
||||
public static string SET_WATCHDOGON_CMD = "OUTP:PROT:WDOG ON";
|
||||
public static string SET_WATCHDOGOFF_CMD = "OUTP:PROT:WDOG OFF";
|
||||
|
||||
// coupling commands
|
||||
public static string SET_COUPLE_CHANNELS_CMD = "OUTP:COUP:CHAN";
|
||||
public static string SET_COUPLE_ON_CMD = "OUTP:COUP ON";
|
||||
public static string SET_COUPLE_OUTPUT_PROTECT_ON_CMD = "OUTP:PROT:COUP ON";
|
||||
public static string QUERY_COUPLE_CHANNELS = "OUTP:COUP:CHAN?";
|
||||
public static string QUERY_COUPLE_STATE = "OUTP:COUP?";
|
||||
|
||||
// Grouping Commands
|
||||
public static string SET_GROUP_DEFINE_CMD = "SYST:GRO:DEF";
|
||||
public static string UNGROUP_ALL_CHANNELS_CMD = "SYST:GRO:DEL:ALL";
|
||||
public static string QUERY_GROUP_CHANNELS = "SYST:GRO:CAT?";
|
||||
|
||||
// current commands
|
||||
public static string SET_OCP_CMD = "CURR:LEV";
|
||||
public static string SET_OCP_ON_CMD = "CURR:PROT:STAT ON";
|
||||
public static string READ_CURRENT_CMD = "MEAS:CURR?";
|
||||
public static string READ_OCP_CMD = "CURR:LEV?";
|
||||
|
||||
// voltage commands
|
||||
public static string SET_OVP_CMD = "VOLT:PROT";
|
||||
public static string SET_VOLTAGE_SLEW_RATE_CMD = "VOLT:SLEW";
|
||||
public static string SET_VOLTAGE_SETPOINT_CMD = "VOLT:LEV";
|
||||
public static string SET_CONSTANT_VOLTAGE_CMD = "STAT:OPER:ENAB 1";
|
||||
public static string READ_VOLTAGE_CMD = "MEAS:VOLT?";
|
||||
public static string READ_VOLTAGE_SETPOINT_CMD = "VOLT?";
|
||||
public static string READ_OVP_CMD = "VOLT:PROT?";
|
||||
public static string READ_VOLTAGE_SLEW_RATE_CMD = "VOLT:SLEW?";
|
||||
|
||||
// set output commands
|
||||
public static string SET_OUTPUT_DISABLE_CMD = "OUTP OFF";
|
||||
public static string SET_OUTPUT_ENABLE_CMD = "OUTP ON";
|
||||
|
||||
//query status
|
||||
public static string READ_OUTPUT_STATUS_CMD = "OUTP?";
|
||||
public static string READ_ERROR_STATUS_CMD = "SYST:ERR?";
|
||||
public static string READ_PROTECTION_STATUS_CMD = "STAT:QUES:COND?";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// 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 NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to simulate any power supply module
|
||||
/// </summary>
|
||||
class PowerSupplyModuleSim : PowerSupplyModule
|
||||
{
|
||||
private List<string> _groupedModules;
|
||||
private List<string> _coupledModules;
|
||||
private string _powerSupplySystemName;
|
||||
private bool _frontPanelEnabled = true;
|
||||
|
||||
private ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public PowerSupplyModuleSim(string iniFilePath, string powerSupplySystemName)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_powerSupplySystemName = powerSupplySystemName;
|
||||
|
||||
IConfigurationFile config = new ConfigurationFile(iniFilePath);
|
||||
|
||||
string moduleDef = config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.MODULE_DEFINITION.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
string coupledModules = config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.COUPLED_MODULES.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
string groupedModules = config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.GROUPED_MODULES.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
|
||||
List<string> powerModules = moduleDef.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
_coupledModules = coupledModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
_groupedModules = groupedModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
|
||||
if (_groupedModules.Count() > 1)
|
||||
{
|
||||
powerModules.Clear();
|
||||
// since modules are grouped, we pick the first module as the representative module
|
||||
powerModules.Add(_groupedModules[0]);
|
||||
}
|
||||
|
||||
// build the power module map
|
||||
string moduleIndex = "";
|
||||
double ovp = 0.0;
|
||||
double ocp = 0.0;
|
||||
double voltageSetPoint = 0.0;
|
||||
double voltageSlewRate = 0.0;
|
||||
|
||||
double minVoltage = 0.0;
|
||||
double maxVoltage = 0.0;
|
||||
double minCurrent = 0.0;
|
||||
double maxCurrent = 0.0;
|
||||
|
||||
for (int i = 0; i < powerModules.Count(); i++)
|
||||
{
|
||||
string moduleName = powerModules[i];
|
||||
|
||||
moduleIndex = config.ReadValue(moduleName, PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.OCP.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out ocp);
|
||||
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.OVP.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out ovp);
|
||||
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SETPOINT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out voltageSetPoint);
|
||||
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SLEW_RATE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out voltageSlewRate);
|
||||
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_VOLTAGE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out minVoltage);
|
||||
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_VOLTAGE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out maxVoltage);
|
||||
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_CURRENT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out minCurrent);
|
||||
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_CURRENT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out maxCurrent);
|
||||
|
||||
PowerModuleInfoDict[moduleName] = new Raytheon.Instruments.PowerSupplies.PowerSupplyModuleInfo(moduleIndex, ocp, ovp, voltageSetPoint, voltageSlewRate, minVoltage, maxVoltage, minCurrent, maxCurrent);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable Front Panel
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override bool DisplayEnabled
|
||||
{
|
||||
set { SemObj?.Release(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable Front Panel
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override bool FrontPanelEnabled
|
||||
{
|
||||
get { SemObj?.Release(); throw new NotImplementedException(); }
|
||||
set { _frontPanelEnabled = value; SemObj?.Release(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turn on power module's output
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override void On()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
CheckActivePowerModuleValidity();
|
||||
|
||||
if (_coupledModules.Contains(ActivePowerModule))
|
||||
{
|
||||
foreach (string module in _coupledModules)
|
||||
{
|
||||
PowerModuleInfoDict[module].isOn_ = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
PowerModuleInfoDict[ActivePowerModule].isOn_ = true;
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turn off power module's output
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override void Off()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
CheckActivePowerModuleValidity();
|
||||
|
||||
if (_coupledModules.Contains(ActivePowerModule))
|
||||
{
|
||||
foreach (string module in _coupledModules)
|
||||
{
|
||||
PowerModuleInfoDict[module].isOn_ = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
PowerModuleInfoDict[ActivePowerModule].isOn_ = false;
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform self test
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override SelfTestResult PerformSelfTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
SelfTestResult = SelfTestResult.Pass;
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); };
|
||||
|
||||
return SelfTestResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read voltage
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override double ReadVoltage()
|
||||
{
|
||||
double val = 0.0;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
if (PowerModuleInfoDict[ActivePowerModule].isOn_)
|
||||
val = PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read current
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override double ReadCurrent()
|
||||
{
|
||||
double val = 0.0;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
if (PowerModuleInfoDict[ActivePowerModule].isOn_)
|
||||
val = (PowerModuleInfoDict[ActivePowerModule].lowerCurrentLimit_ + PowerModuleInfoDict[ActivePowerModule].upperCurrentLimit_) / 2.0;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read protection status
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override int ReadProtectionStatus()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get error code
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
protected override string GetErrorCode(out int errorCode)
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
errorCode = 0;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// 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 NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to simulate any power supply system
|
||||
/// </summary>
|
||||
public class PowerSupplySim : PowerSupply
|
||||
{
|
||||
private string _iniFilePath;
|
||||
|
||||
private static ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public PowerSupplySim(string deviceInstanceName, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
Name = deviceInstanceName;
|
||||
_logger = logger;
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
_iniFilePath = Path.Combine(assemblyFolder,_configuration.GetConfigurationValue(deviceInstanceName, "IniFilePath", $".\\{Raytheon.Common.GeneralConstants.InstrumentConfigFolder}\\{deviceInstanceName}.ini"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform shutdown
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override void Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform reset
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override void Reset()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear errors
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override bool ClearErrors()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Group or couple modules as specified in config file
|
||||
/// Gather information for each power module from config file
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override void Initialize()
|
||||
{
|
||||
_powerSupplyModule = new PowerSupplyModuleSim(_iniFilePath, Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement Indexer to obtain a power module
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override PowerSupplyModule this[object powerDeviceId]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!(powerDeviceId == null || powerDeviceId.GetType().IsEnum))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(powerDeviceId)} must be an enumerated type or null");
|
||||
}
|
||||
|
||||
_powerSupplyModule.GetSemphamore().WaitOne();
|
||||
|
||||
if (powerDeviceId != null)
|
||||
_powerSupplyModule.SetActivePowerModule(powerDeviceId.ToString());
|
||||
|
||||
return _powerSupplyModule;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(SolutionDir)Program.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<AssemblyName>Raytheon.Instruments.PowerSupplies.Simulation</AssemblyName>
|
||||
<RootNamespace>Raytheon.Instruments</RootNamespace>
|
||||
<Product>Power Supply Simulation</Product>
|
||||
<Description>Power Supply Simulation</Description>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<Company>Raytheon Technologies</Company>
|
||||
<Authors>TEEC</Authors>
|
||||
<Copyright>Copyright © Raytheon Technologies $([System.DateTime]::get_now().ToString("yyyy"))</Copyright>
|
||||
|
||||
<!-- Dynamic Versioning (Suitable for Release) -->
|
||||
<!-- <Version>$(Version)$(Suffix)</Version> -->
|
||||
|
||||
<!-- Static Versioning (Suitable for Development) -->
|
||||
<Version>1.0.0</Version>
|
||||
<Configurations>Debug;Release;Deploy</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
<PackageReference Include="Raytheon.Configuration" Version="2.6.1" />
|
||||
<PackageReference Include="Raytheon.Configuration.Contracts" Version="2.3.0" />
|
||||
|
||||
<!--
|
||||
<PackageReference Include="Raytheon.Instruments.PowerSupply.Contracts" Version="1.1.0" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Interfaces\PowerSupply\PowerSupply.Contracts.csproj" />
|
||||
<ProjectReference Include="..\..\..\Raytheon.Common\Raytheon.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,114 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// 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 NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "PowerSupplySimulationFactory")]
|
||||
public class PowerSupplySimulationFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private static ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
public PowerSupplySimulationFactory(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 PowerSupplySimulationFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
if (NLog.LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(PowerSupply));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public object GetInstrument(string name, bool simulateHw)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new PowerSupplySim(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"Unable to construct {name} instrument instance");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets supported interfaces
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns confiuration 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user