Big changes
This commit is contained in:
@@ -0,0 +1,875 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// 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)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
throw new Exception($"{instName} did not have a matching factory with supported type {instFactory}");
|
||||
}
|
||||
}
|
||||
}
|
||||
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,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(SolutionDir)Solution.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<AssemblyName>Raytheon.Instruments.InstrumentManager.GeneralInstrumentManager</AssemblyName>
|
||||
<Product>General Instrument Manager</Product>
|
||||
|
||||
<!-- Static versioning (Suitable for Development) -->
|
||||
<!-- Disable the line below for dynamic versioning -->
|
||||
<Version>1.5.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Raytheon.Composition" Version="1.0.0.14" />
|
||||
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
|
||||
<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.6.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.InstrumentManager.Contracts" Version="1.8.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.ServiceProcess" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user