879 lines
27 KiB
C#
879 lines
27 KiB
C#
/*-------------------------------------------------------------------------
|
|
// 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
|
|
|
|
}
|
|
}
|