Initial check-in

This commit is contained in:
Duc
2025-01-03 09:50:39 -07:00
parent 45596e360d
commit 1d8f6e4c96
143 changed files with 9835 additions and 0 deletions

63
.gitattributes vendored Normal file
View File

@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

369
.gitignore vendored Normal file
View File

@@ -0,0 +1,369 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
Source/TestStand/Reports
Source/Nuget/cache/
Source/Nuget/SolutionPackages
Thumbs.db
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
#*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

View File

@@ -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
}
}

View File

@@ -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>

View File

@@ -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
}
}

View File

@@ -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);
}
}
}

View File

@@ -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
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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?";
}
}

View File

@@ -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 "";
}
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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>

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Program.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>Raytheon.Instruments.CommDevice.Contracts</AssemblyName>
<RootNamespace>Raytheon.Instruments</RootNamespace>
<Description>ICommDevice interface definition</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Company>Raytheon Technologies</Company>
<Product>HAL</Product>
<Authors>TEEC</Authors>
<Copyright>Copyright © Raytheon Technologies $([System.DateTime]::get_now().ToString("yyyy"))</Copyright>
<Version>1.0.0</Version>
<Configurations>Debug;Release;Deploy</Configurations>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Raytheon.Communication.Rpc.Contracts" Version="1.*" />
<PackageReference Include="Raytheon.Communication.Ums.Core.Contracts" Version="1.*" />
<PackageReference Include="Raytheon.Communication.Ums.Rpc.Attributes" Version="1.*" />
<PackageReference Include="Raytheon.Instruments.Contracts" Version="1.5.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,63 @@
/*-------------------------------------------------------------------------
// 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 Raytheon.Communication;
namespace Raytheon.Instruments
{
/// <summary>
/// An interface to any device that you can write and read to/from
/// </summary>
public interface ICommDevice : IInstrument
{
/// <summary>
/// Close the communication interface
/// </summary>
[UmsCommand("ICommDevice.Close")]
void Close();
/// <summary>
/// Open the communication interface
/// </summary>
[UmsCommand("ICommDevice.Open")]
void Open();
/// <summary>
/// Reads data from a communication device
/// </summary>
/// <param name="dataRead"></param>
/// <returns>number of bytes read</returns>
[UmsCommand("ICommDevice.Read")]
uint Read(ref byte[] dataRead);
/// <summary>
/// Set the timeout on a read
/// </summary>
/// <param name="timeout"></param>
[UmsCommand("ICommDevice.SetReadTimeout")]
void SetReadTimeout(uint timeout);
/// <summary>
/// Writes data to a communication device
/// </summary>
/// <param name="data"></param>
/// <param name="numBytesToWrite"></param>
/// <returns>the number of bytes written</returns>
[UmsCommand("ICommDevice.Write")]
uint Write(byte[] data, uint numBytesToWrite);
}
}

View File

@@ -0,0 +1,18 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
//
// To add a suppression to this file, right-click the message in the
// Error List, point to "Suppress Message(s)", and click
// "In Project Suppression File".
// You do not need to add suppressions to this file manually.
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
[assembly: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "RINSS")]
[assembly: SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Scope = "member", Target = "Raytheon.Instruments.IInstrumentProxyFactory.#GetSupportedInterfaces()")]
[assembly: SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Scope = "member", Target = "Raytheon.Instruments.IInstrumentFactory.#GetSupportedInterfaces()")]
[assembly: SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable", Scope = "type", Target = "Raytheon.Instruments.InstrumentException")]

View File

@@ -0,0 +1,151 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using Raytheon.Communication;
namespace Raytheon.Instruments
{
/// <summary>
/// IInstrument - RINSS generic instrument interface, that all instruments MUST implement
/// </summary>
public interface IInstrument
{
/// <summary>
/// ClearErrors - clear existing errors but leave options in current state
/// </summary>
/// <returns>returns true if errors are successfully cleared</returns>
[UmsCommand("RINSS.IInstrument.ClearErrors")]
bool ClearErrors();
/// <summary>
/// DetailedStatus - will contain detailed information about the current state of the instrument
/// </summary>
String DetailedStatus
{
[UmsCommand("RINSS.IInstrument.GetDetailedStatus")]
get;
}
/// <summary>
/// DisplayEnabled - some instruments will be no-op, but likely needed on all
/// will shut down any display on the hardware to hide any
/// classified information if visible
/// </summary>
bool DisplayEnabled
{
[UmsCommand("RINSS.IInstrument.GetDisplayEnabled")]
get;
[UmsCommand("RINSS.IInstrument.SetDisplayEnabled")]
set;
}
/// <summary>
/// FrontPanelEnabled - some instruments will be no-op, but likely needed on all
/// has the ability to disable any panel buttons, so that
/// the hardware may not be changed by human touch
/// </summary>
bool FrontPanelEnabled
{
[UmsCommand("RINSS.IInstrument.GetFrontPanelEnabled")]
get;
[UmsCommand("RINSS.IInstrument.SetFrontPanelEnabled")]
set;
}
/// <summary>
/// Info - extra instrument information, currently only model number information
/// </summary>
InstrumentMetadata Info
{
[UmsCommand("RINSS.IInstrument.GetInfo")]
get;
}
/// <summary>
/// Initialize - remove any state knowledge from the hardware and call any
/// initialize methods needed. this may take time and differs only
/// from reset by the fact it may power cycle or do something more than
/// settings to the instrument
/// </summary>
[UmsCommand("RINSS.IInstrument.Initialize")]
void Initialize();
/// <summary>
/// Name - unique identifier for the instrument
/// </summary>
string Name
{
[UmsCommand("RINSS.IInstrument.GetName")]
get;
}
/// <summary>
/// PerformSelfTest - do a hardware self test
/// </summary>
/// <returns>result of the self test</returns>
[UmsCommand("RINSS.IInstrument.PerformSelfTest")]
SelfTestResult PerformSelfTest();
/// <summary>
/// Reset - put state of the unit back to startup state
/// </summary>
[UmsCommand("RINSS.IInstrument.Reset")]
void Reset();
/// <summary>
/// SelfTestResult - end result of the hardware self test performed
/// </summary>
SelfTestResult SelfTestResult
{
[UmsCommand("RINSS.IInstrument.GetSelfTestResult")]
get;
}
/// <summary>
/// Shutdown - could potentially turn off the instrument
/// </summary>
[UmsCommand("RINSS.IInstrument.Shutdown")]
void Shutdown();
/// <summary>
/// Status - current state infromation
/// </summary>
State Status
{
[UmsCommand("RINSS.IInstrument.GetStatus")]
get;
}
}
}

View File

@@ -0,0 +1,65 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Raytheon.Communication;
namespace Raytheon.Instruments
{
/// <summary>
/// IInstrumentFactory - interface for RINSS's factory pattern, each of these should create
/// instruments of the types they support
/// </summary>
public interface IInstrumentFactory
{
/// <summary>
/// GetInstrument - main call to a factory to get an instrument it can create
/// </summary>
/// <remarks>do not pass IInstrument objects via RPC, it is a copy of the object</remarks>
/// <param name="name">unique name of the instrument</param>
/// <returns>null if instrument cannot be found, otherwise the instrument implementation</returns>
IInstrument GetInstrument(string name);
object GetInstrument(string name, bool simulateHw);
/// <summary>
/// GetSupportedInterfaces - used to get all the types of instruments a factory could be used
/// to create.
/// </summary>
/// <returns>collection of specific instrument types it can create</returns>
[UmsCommand("RINSS.IInstrumentFactory.GetSupportedInterfaces")]
ICollection<Type> GetSupportedInterfaces();
}
}

View File

@@ -0,0 +1,50 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Raytheon.Instruments
{
/// <summary>
/// IInstrumentFactoryInfo - interface for meta data about the instrument factory
/// </summary>
public interface IInstrumentFactoryInfo
{
/// <summary>
/// ModelNumber - a unique identifier for the instrument factory
/// </summary>
string ModelNumber { get; }
}
}

View File

@@ -0,0 +1,70 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Raytheon.Communication;
using Raytheon.Communication.Rpc;
namespace Raytheon.Instruments
{
/// <summary>
/// IInstrumentProxyFactory - interface to a proxy instrument factory, used to identify
/// the ums piece that will do the proxy'ing
/// </summary>
public interface IInstrumentProxyFactory
{
/// <summary>
/// Initialize - sets up the factory with the ums components it needs to distribute
/// the proxy instruments
/// </summary>
/// <param name="umsHost">the port used to proxy</param>
/// <param name="umsClientFactory">the factory associated with port to create the clients</param>
void Initialize(IUms umsHost, IUmsClientFactory umsClientFactory);
/// <summary>
/// GetInstrument - get a proxy'd instrument
/// </summary>
/// <param name="name">unique name of the instrument</param>
/// <returns>null if the instrument does not exist and the instrument implementation if it does</returns>
IInstrument GetInstrument(string name);
/// <summary>
/// GetSupportedInterfaces - discovery about the factory to find out which instruments
/// it provides proxies to
/// </summary>
/// <returns>collection of supported interface names</returns>
ICollection<string> GetSupportedInterfaces();
}
}

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
<Class Name="Raytheon.Instruments.InstrumentProxyFactory&lt;T&gt;">
<Position X="7" Y="0.5" Width="4.5" />
<TypeIdentifier>
<HashCode>AAgAABAGAAAAAQCAAAAAAAgAQAAAAAAAQAAAAAAAAAA=</HashCode>
<FileName>InstrumentProxyFactory.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Interface Name="Raytheon.Instruments.IInstrument">
<Position X="0.5" Y="0.5" Width="2.75" />
<TypeIdentifier>
<HashCode>AAAAAAAEAAAABQAAIAAAAQYEAAAAAAAQAAAAAEAAiAA=</HashCode>
<FileName>IInstrument.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="Raytheon.Instruments.IInstrumentFactory">
<Position X="3.5" Y="0.5" Width="3.25" />
<TypeIdentifier>
<HashCode>AAgAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>IInstrumentFactory.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="Raytheon.Instruments.IInstrumentProxyFactory">
<Position X="7" Y="3.75" Width="4.5" />
<TypeIdentifier>
<HashCode>AAgAAAAAAAAAAQAAAAAAAAgAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>IInstrumentProxyFactory.cs</FileName>
</TypeIdentifier>
</Interface>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,104 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using Raytheon.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Raytheon.Instruments
{
public abstract class Instrument
{
/// <summary>
/// DetailedStatus - will contain detailed information about the current state of the instrument
/// </summary>
public string DetailedStatus
{
get;
set;
}
/// <summary>
/// Info - extra instrument information, currently only model number information
/// </summary>
public InstrumentMetadata Info
{
get;
set;
}
/// <summary>
/// Name - unique identifier for the instrument
/// </summary>
public string Name
{
get;
set;
}
/// <summary>
/// Status - current state infromation
/// </summary>
public State Status
{
get;
set;
}
/// <summary>
/// ClearErrors - clear existing errors but leave options in current state
/// </summary>
/// <returns>returns true if errors are successfully cleared</returns>
public abstract bool ClearErrors();
/// <summary>
/// Initialize - remove any state knowledge from the hardware and call any
/// initialize methods needed. this may take time and differs only
/// from reset by the fact it may power cycle or do something more than
/// settings to the instrument
/// </summary>
public abstract void Initialize();
/// <summary>
/// Reset - put state of the unit back to startup state
/// </summary>
public abstract void Reset();
/// <summary>
/// Shutdown - could potentially turn off the instrument
/// </summary>
public abstract void Shutdown();
}
}

View File

@@ -0,0 +1,146 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace Raytheon.Instruments
{
/// <summary>
/// InstrumentException - an exception that can be thrown by all instruments
/// while processing any instruction
/// <remarks>can be used as a base class</remarks>
/// </summary>
[DataContract]
public class InstrumentException : Exception
{
[DataMember]
private string _message = string.Empty;
[DataMember]
private int _errorCode = 0;
/// <summary>
/// Message - readable information associated with the exception
/// </summary>
public override string Message
{
get
{
return _message;
}
}
/// <summary>
/// ErrorCode - code associated with error involved with this exception
/// </summary>
public int ErrorCode
{
get { return _errorCode; }
set { _errorCode = value; }
}
/// <summary>
/// InstrumentException - default constructor
/// </summary>
public InstrumentException()
: base()
{
}
/// <summary>
/// InstrumentException - constructor with a message as parameter
/// </summary>
/// <param name="message">message about the exception</param>
public InstrumentException(string message)
: base()
{
_message = message;
}
/// <summary>
/// InstrumentException - constructor that takes an error code
/// </summary>
/// <param name="errorCode">the error code</param>
public InstrumentException(int errorCode)
: base()
{
_errorCode = errorCode;
}
/// <summary>
/// InstrumentException - constructor that takes an error code and message
/// </summary>
/// <param name="errorCode">the error code</param>
/// <param name="message">the message</param>
public InstrumentException(int errorCode, string message)
: base()
{
_message = message;
_errorCode = errorCode;
}
/// <summary>
/// InstrumentException - constructor that takes an error message and inner exception
/// </summary>
/// <param name="message">the message</param>
/// <param name="innerException">an inner exception</param>
public InstrumentException(string message, Exception innerException)
: base(message, innerException)
{
_message = message;
}
/// <summary>
/// InstrumentException - protected constructor
/// </summary>
/// <param name="info">serialization info</param>
/// <param name="context">context</param>
protected InstrumentException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
/// <summary>
/// GetObjectData - override for serialization
/// </summary>
/// <param name="info">how to serialize</param>
/// <param name="context">context</param>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
}
}
}

View File

@@ -0,0 +1,65 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
namespace Raytheon.Instruments
{
/// <summary>
/// ExportInstrumentFactoryAttribute - attribute to allow MEF to figure all the factories out
/// </summary>
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class ExportInstrumentFactoryAttribute : ExportAttribute, IInstrumentFactoryInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="ExportInstrumentFactoryAttribute"/> class.
/// </summary>
public ExportInstrumentFactoryAttribute()
: base(typeof(IInstrumentFactory))
{
}
/// <summary>
/// Gets or sets the model number.
/// </summary>
/// <value>
/// The model number.
/// </value>
public string ModelNumber { get; set; }
}
}

View File

@@ -0,0 +1,55 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.Diagnostics.CodeAnalysis;
namespace Raytheon.Instruments
{
/// <summary>
/// InstrumentMetadata - any instrument information not needed for running
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class InstrumentMetadata : ExportAttribute
{
/// <summary>
/// ModelNumber - the model number for the instrument
/// </summary>
public string ModelNumber { get; set; }
}
}

View File

@@ -0,0 +1,161 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Raytheon.Communication;
using Raytheon.Communication.Rpc;
using System.Globalization;
namespace Raytheon.Instruments
{
/// <summary>
/// Generic (and abstract) proxy factory for helping to do all of the work that needs to
/// be done in proxy factories. All that needs implementation is the GetSupportedInterfaces
/// method, this will be up to the impl
///
/// What shall be done is a proxy factory for every interface should be declared in
/// a dll. Then a consumer would import via MEF all the factories and use them appropriately
/// </summary>
public abstract class InstrumentProxyFactory<T> : IInstrumentProxyFactory
where T : class
{
#region Private Fields
//as of right now these do not appear to need access to the implementing class
private IUms _UmsHost;
private IUmsClientFactory _UmsClientFactory;
//Added a GetProxy method for access to a specific proxy
private Dictionary<string, IUmsClient<T>> _Proxies;
#endregion
#region IInstrumentProxyFactory Members
/// <summary>
/// This must be called to initialize a factory with a media port to create the client
/// </summary>
/// <param name="umsHost">host for the client factory to use to create the proxy</param>
/// <param name="umsClientFactory">client factory to use to create proxies</param>
public virtual void Initialize(IUms umsHost, IUmsClientFactory umsClientFactory)
{
_Proxies = new Dictionary<string, IUmsClient<T>>();
_UmsClientFactory = umsClientFactory;
_UmsHost = umsHost;
}
/// <summary>
/// This is the call any client rpc instrument manager would use to get the proxy
/// it will return the specific instrument proxy which can be cast to a generic
/// IInstrument if needed, the only way to cast to a derived type is to return one
/// in the first place since they are proxies
/// </summary>
/// <param name="name">instrument name</param>
/// <returns>the Type proxy (not the IInstrument)</returns>
public virtual IInstrument GetInstrument(string name)
{
return GetSpecificInstrument(name) as IInstrument;
}
/// <summary>
/// Implementing class must provide the interfaces it supports
/// Since this is purely an interface driven proxy the acutal implementation
/// under the hood of the Interfaces matters not
/// </summary>
/// <returns>collection of interfaces it can create proxies to</returns>
public abstract ICollection<string> GetSupportedInterfaces();
#endregion
#region Protected Methods
/// <summary>
/// returns the specific instruments proxy, this is a generic operation so put into abstract class
/// </summary>
/// <param name="name">instrument name</param>
/// <returns>the specific instruments proxy</returns>
protected virtual T GetSpecificInstrument(string name)
{
if (null == _Proxies)
{
string message = typeof(T).FullName + " Factory not initialized, proxy container not created";
throw new InstrumentException(message);
}
if (!_Proxies.ContainsKey(name))
{
var proxy = CreateProxy(name);
_Proxies.Add(name, proxy);
}
return _Proxies[name].Contract;
}
/// <summary>
/// added to allow an implementing class to get access to proxies so that it may add properties or
/// whatever else needs to be done to the objects
/// </summary>
/// <param name="proxyName">instrument name</param>
/// <returns>the proxy to that specific instrument</returns>
protected IUmsClient<T> GetProxy(string proxyName)
{
IUmsClient<T> proxy = null;
_Proxies.TryGetValue(proxyName, out proxy);
return proxy;
}
/// <summary>
/// creates the proxy, this is a generic operation, so put into the abstract class
/// </summary>
/// <param name="proxyName">instrument name</param>
/// <returns>the proxy to the given instrument</returns>
protected virtual IUmsClient<T> CreateProxy(string proxyName)
{
if (null == _UmsClientFactory || null == _UmsHost)
{
string message = typeof(T).FullName + " Factory not initialized, ums information is null";
throw new InstrumentException(message);
}
IUmsClient<T> proxy = _UmsClientFactory.GetClient<T>(_UmsHost);
proxy.AddProperty("instName", proxyName);
proxy.Open();
return proxy;
}
#endregion
}
}

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Program.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>Raytheon.Instruments.Contracts</AssemblyName>
<RootNamespace>Raytheon.Instruments</RootNamespace>
<Company>Raytheon Technologies</Company>
<Product>Raytheon Configuration</Product>
<Description>Base Instrument interface and export attribute</Description>
<Authors>TEEC</Authors>
<Copyright>Copyright © Raytheon Technologies $([System.DateTime]::get_now().ToString("yyyy"))</Copyright>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>1.5.0.0</Version>
<Configurations>Debug;Release;Deploy</Configurations>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Raytheon.Communication.Rpc.Contracts" Version="1.*" />
<PackageReference Include="Raytheon.Communication.Ums.Core.Contracts" Version="1.*" />
<PackageReference Include="Raytheon.Communication.Ums.Rpc.Attributes" Version="1.*" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,63 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System.Runtime.Serialization;
namespace Raytheon.Instruments
{
/// <summary>
/// SelfTestResult - an enumeration for passing, failing or unknown state
/// of a self test.
/// </summary>
[DataContract]
public enum SelfTestResult
{
/// <summary>
/// SelfTestResult.Unknown - this indicates it is unknown what the self test result
/// is currently.
/// </summary>
[EnumMember]
Unknown,
/// <summary>
/// SelfTestResult.Pass - last time the self test was run, it passed.
/// </summary>
[EnumMember]
Pass,
/// <summary>
/// SelfTestResult.Fail - last time teh self test was run, it failed.
/// </summary>
[EnumMember]
Fail,
}
}

View File

@@ -0,0 +1,88 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace Raytheon.Instruments
{
/// <summary>
/// State - enumeration for the states a instrument could be in
/// </summary>
[DataContract]
public enum State
{
/// <summary>
/// State.Ready - the up and running waiting on instructions
/// </summary>
[EnumMember]
Ready,
/// <summary>
/// State.Busy - the instrument cannot be tasked it is already processing
/// some command or instruction that cannot be interrupted
/// </summary>
[EnumMember]
Busy,
/// <summary>
/// State.CommunicationFailure - the instrument is in error right now and the
/// software component has lost connection with
/// the instrument
/// </summary>
[EnumMember]
CommunicationFailure,
/// <summary>
/// State.HardwareFailure - the hardware has failed and cannot recover from some
/// error
/// </summary>
[EnumMember]
HardwareFailure,
/// <summary>
/// State.InternalError - driver error internal to the software
/// </summary>
[EnumMember]
InternalError,
/// <summary>
/// State.Uninitialized - an unknown state as the instrument must be initialized to
/// understand it's current state.
/// </summary>
[EnumMember]
Uninitialized,
}
}

View File

@@ -0,0 +1,11 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
//
// To add a suppression to this file, right-click the message in the
// Error List, point to "Suppress Message(s)", and click
// "In Project Suppression File".
// You do not need to add suppressions to this file manually.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant")]

View File

@@ -0,0 +1,158 @@
// ******************************************************************************************
// ** **
// ** RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION **
// ** PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS **
// ** AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.DISCLOSURE TO **
// ** UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO **
// ** RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS **
// ** CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS **
// ** OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON **
// ** COMPANY. **
// ** **
// ** THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. **
// ** GOVERNMENT. **
// ** **
// ** UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. **
// ** **
// ** WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE **
// ** EXPORT OR DISCLOSURE TO NON-U.S.PERSONS, WHEREVER LOCATED, IS RESTRICTED **
// ** BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R.SECTION **
// ** 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS(EAR) (15 C.F.R.SECTION **
// ** 730-774). THIS DOCUMENT CANNOT BE EXPORTED(E.G., PROVIDED TO A SUPPLIER **
// ** OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S.PERSON, WHEREVER **
// ** LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS **
// ** BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S.GOVERNMENT **
// ** APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL **
// ** PENALTIES. **
// ** **
// ** CAPITAL EQUIPMENT/SOFTWARE: THIS TECHNICAL DATA WAS DEVELOPED OR ACQUIRED **
// ** EXCLUSIVELY AT CONTRACTOR EXPENSE AND IS INTENDED FOR USE ON MULTIPLE **
// ** PROJECTS/PROGRAMS. **
// ** **
// *******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Raytheon.Communication;
using System.Diagnostics.CodeAnalysis;
namespace Raytheon.Instruments
{
/// <summary>
/// Instrument manager interface.
/// </summary>
/// <remarks>
/// An instrument manager is responsible for loading all of the instrument plugins and providing an interface for retrieving those instruments.
/// </remarks>
[UmsContract]
public interface IInstrumentManager
{
/// <summary>
/// Gets an instrument by name.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>The instrument</returns>
/// <remarks>This function cannot be named the same as the Generic method GetInstrument/<T/>
/// because certain test executives do not support generics, and will throw an AmbiguousMatchException.</remarks>
IInstrument GetGenericInstrument(string name);
/// <summary>
/// Gets an instrument by name.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>The instrument</returns>
T GetInstrument<T>(string name) where T : class;
/// <summary>
/// Gets all instruments currently loaded.
/// </summary>
/// <returns>collection of all known instruments</returns>
ICollection<object> GetInstruments();
/// <summary>
/// Gets all instruments currently loaded.
/// </summary>
/// <returns>array of all known instruments</returns>
[UmsCommand("IInstrumentManager.GetInstrumentsArray")]
object[] GetInstrumentsArray();
/// <summary>
/// Gets the instruments of the given type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>all known instruments of a certain type</returns>
ICollection<object> GetInstruments(Type type);
/// <summary>
/// Gets the instruments of the given type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>array of instruments of the specified type</returns>
object[] GetInstrumentsArray(Type type);
/// <summary>
/// Initializes the instrument manager
/// </summary>
[UmsCommand("IInstrumentManager.Initialize")]
void Initialize();
/// <summary>
/// Sets/Gets the part location
/// Added Dec 2013 to better clarify where the part locations are loading from
/// and to be able to set it before initialization
/// </summary>
string _partsLocation
{
get;
set;
}
/// <summary>
/// Closes the instrument manager
/// </summary>
void Shutdown();
/// <summary>
/// Returns a collection of instrument names loaded.
/// </summary>
/// <returns>all the known instrument's unique name</returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[UmsCommand("IInstrumentManager.GetInstrumentNames")]
ICollection<string> GetInstrumentNames();
/// <summary>
/// Returns a collection of instrument names loaded.
/// </summary>
/// <returns>all the known instrument names in array form</returns>
[UmsCommand("IInstrumentManager.GetInstrumentNamesArray")]
string[] GetInstrumentNamesArray();
/// <summary>
/// Initializes all of the instruments.
/// </summary>
[UmsCommand("IInstrumentManager.InitializeInstruments")]
void InitializeInstruments();
/// <summary>
/// Initializes the instrument.
/// </summary>
/// <param name="instName">Name of the inst.</param>
[UmsCommand("IInstrumentManager.InitializeInstrument")]
void InitializeInstrument(string instName);
/// <summary>
/// Shuts down all of the instruments.
/// </summary>
[UmsCommand("IInstrumentManager.ShutdownInstruments")]
void ShutdownInstruments();
/// <summary>
/// Shutdowns the instrument.
/// </summary>
/// <param name="instName">Name of the inst.</param>
[UmsCommand("IInstrumentManager.ShutdownInstrument")]
void ShutdownInstrument(string instName);
}
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Program.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>Raytheon.Instruments.InstrumentManager.Contracts</AssemblyName>
<RootNamespace>Raytheon.Instruments</RootNamespace>
<Company>Raytheon Technologies</Company>
<Product>Raytheon Configuration</Product>
<Description>Instrument Manager Interface</Description>
<Authors>TEEC</Authors>
<Copyright>Copyright © Raytheon Technologies $([System.DateTime]::get_now().ToString("yyyy"))</Copyright>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>1.7.1.0</Version>
<Configurations>Debug;Release;Deploy</Configurations>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Raytheon.Communication.Rpc.Contracts" Version="1.*" />
<PackageReference Include="Raytheon.Communication.Ums.Core.Contracts" Version="1.*" />
<PackageReference Include="Raytheon.Communication.Ums.Rpc.Attributes" Version="1.*" />
<PackageReference Include="Raytheon.Instruments.Contracts" Version="1.5.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Program.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>Raytheon.Instruments.PowerSupply.Contracts</AssemblyName>
<RootNamespace>Raytheon.Instruments</RootNamespace>
<Description>PowerSupply Interface</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Company>Raytheon Technologies</Company>
<Product>HAL</Product>
<Authors>TEEC</Authors>
<Copyright>Copyright © Raytheon Technologies $([System.DateTime]::get_now().ToString("yyyy"))</Copyright>
<Version>1.1.0.0</Version>
<Configurations>Debug;Release;Deploy</Configurations>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Raytheon.Communication.Rpc.Contracts" Version="1.*" />
<PackageReference Include="Raytheon.Communication.Ums.Core.Contracts" Version="1.*" />
<PackageReference Include="Raytheon.Communication.Ums.Rpc.Attributes" Version="1.*" />
<PackageReference Include="Raytheon.Instruments.Contracts" Version="1.5.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,53 @@
/*-------------------------------------------------------------------------
// 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
{
/// <summary>
/// Base class that defines interface for power supply systems
/// </summary>
public abstract class PowerSupply : Instrument
{
protected PowerSupplyModule _powerSupplyModule;
/// <summary>
/// Implement Indexer in order to access a specific power module
/// </summary>
/// <param></param>
/// <returns></returns>
public virtual PowerSupplyModule this[object i]
{
get { return null; }
}
/// <summary>
/// Get power supply module info dictionary
/// </summary>
/// <param></param>
/// <returns></returns>
public Dictionary<string, PowerSupplies.PowerSupplyModuleInfo> GetPowerSupplyModuleInfoDict()
{
return _powerSupplyModule.PowerModuleInfoDict;
}
}
}

View File

@@ -0,0 +1,47 @@
/*-------------------------------------------------------------------------
// 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 enum PowerSupplyConfigIni
{
// list all the sections here
GENERAL,
// list all the keys here
ETHERNET_ADDRESS,
ETHERNET_PORT,
MODULE_DEFINITION,
COUPLED_MODULES,
GROUPED_MODULES,
INDEX,
OCP,
OVP,
VOLTAGE_SETPOINT,
VOLTAGE_SLEW_RATE,
MIN_VOLTAGE,
MAX_VOLTAGE,
MIN_CURRENT,
MAX_CURRENT
}
}

View File

@@ -0,0 +1,31 @@
/*-------------------------------------------------------------------------
// 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 enum PowerSupplyConfigXml
{
// list all the keys here
INI_FILE_PATH
}
}

View File

@@ -0,0 +1,205 @@
/*-------------------------------------------------------------------------
// 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 Raytheon.Instruments.PowerSupplies;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Raytheon.Instruments
{
/// <summary>
/// Base class that defines interface for power supply modules
/// </summary>
public abstract class PowerSupplyModule
{
protected Semaphore SemObj = new System.Threading.Semaphore(initialCount: 1, maximumCount: 1);
protected object SyncObj = new object();
protected string ActivePowerModule;
public Dictionary<string, PowerSupplyModuleInfo> PowerModuleInfoDict { get; protected set; }
/// <summary>
/// Constructor
/// </summary>
public PowerSupplyModule()
{
PowerModuleInfoDict = new Dictionary<string, PowerSupplyModuleInfo>();
}
/// <summary>
/// DisplayEnabled - some instruments will be no-op, but likely needed on all
/// will shut down any display on the hardware to hide any
/// classified information if visible
/// </summary>
public virtual bool DisplayEnabled
{
get;
set;
}
/// <summary>
/// FrontPanelEnabled - some instruments will be no-op, but likely needed on all
/// has the ability to disable any panel buttons, so that
/// the hardware may not be changed by human touch
/// </summary>
public virtual bool FrontPanelEnabled
{
get;
set;
}
/// <summary>
/// SelfTestResult - end result of the hardware self test performed
/// </summary>
public SelfTestResult SelfTestResult
{
get;
set;
}
/// <summary>
/// PerformSelfTest - do a hardware self test
/// </summary>
/// <returns>result of the self test</returns>
public abstract SelfTestResult PerformSelfTest();
/// <summary>
/// Set active module
/// </summary>
/// <param></param>
/// <returns></returns>
public void SetActivePowerModule(string activePowerModule)
{
ActivePowerModule = activePowerModule;
}
/// <summary>
/// Check if active module is valid
/// </summary>
/// <param></param>
/// <returns></returns>
protected void CheckActivePowerModuleValidity()
{
if (ActivePowerModule == null || ActivePowerModule.Length == 0)
throw new Exception($"{nameof(ActivePowerModule)} is not set");
if (!PowerModuleInfoDict.ContainsKey(ActivePowerModule))
throw new Exception($"Invalid power module: {ActivePowerModule}");
}
/// <summary>
/// Return semaphore
/// </summary>
/// <param></param>
/// <returns></returns>
public Semaphore GetSemphamore() { return SemObj; }
/// <summary>
/// Turn on power module's output
/// </summary>
/// <param></param>
/// <returns></returns>
public abstract void On();
/// <summary>
/// Turn off power module's output
/// </summary>
/// <param></param>
/// <returns></returns>
public abstract void Off();
/// <summary>
/// Determine if module's output is on
/// </summary>
/// <param></param>
/// <returns></returns>
protected virtual bool IsOutputOn()
{
bool isOn = false;
lock (SyncObj)
{
CheckActivePowerModuleValidity();
isOn = PowerModuleInfoDict[ActivePowerModule].isOn_;
}
return isOn;
}
/// <summary>
/// Read power supply module's data all at once
/// </summary>
/// <param></param>
/// <returns></returns>
public virtual void ReadPowerSupplyData(out double volts, out double current, out double voltSetpoint, out bool isOn, out int faultStatus)
{
volts = 0.0;
current = 0.0;
voltSetpoint = 0.0;
isOn = false;
faultStatus = 0;
try
{
lock (SyncObj)
{
CheckActivePowerModuleValidity();
volts = ReadVoltage();
current = ReadCurrent();
voltSetpoint = PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_;
isOn = IsOutputOn();
faultStatus = ReadProtectionStatus();
}
}
finally { SemObj?.Release(); };
}
/// <summary>
/// Read voltage
/// </summary>
/// <param></param>
/// <returns></returns>
protected abstract double ReadVoltage();
/// <summary>
/// Read current
/// </summary>
/// <param></param>
/// <returns></returns>
protected abstract double ReadCurrent();
/// <summary>
/// Read protection status
/// </summary>
/// <param></param>
/// <returns></returns>
protected abstract int ReadProtectionStatus();
/// <summary>
/// Get error code
/// </summary>
/// <param></param>
/// <returns></returns>
protected abstract string GetErrorCode(out int errorCode);
}
}

View File

@@ -0,0 +1,70 @@
/*-------------------------------------------------------------------------
// 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 class PowerSupplyModuleInfo
{
public PowerSupplyModuleInfo()
{
overCurrentProtection_ = -1.0;
overVoltageProtection_ = -1.0;
voltageSetpoint_ = -1.0;
voltageSlewRate_ = -1.0;
lowerVoltageLimit_ = -1.0;
upperVoltageLimit_ = -1.0;
lowerCurrentLimit_ = -1.0;
upperCurrentLimit_ = -1.0;
isOn_ = false;
faultStatus = -1;
}
public PowerSupplyModuleInfo(string moduleIndex, double overCurrentProtection, double overVoltageProtection, double voltageSetpoint, double voltageSlewRate, double minVoltage, double maxVoltage, double minCurrent, double maxCurrent)
{
overCurrentProtection_ = overCurrentProtection;
overVoltageProtection_ = overVoltageProtection;
voltageSetpoint_ = voltageSetpoint;
voltageSlewRate_ = voltageSlewRate;
lowerVoltageLimit_ = minVoltage;
upperVoltageLimit_ = maxVoltage;
lowerCurrentLimit_ = minCurrent;
upperCurrentLimit_ = maxCurrent;
isOn_ = false;
faultStatus = -1;
moduleNameFormat = "(@" + moduleIndex + ")";
}
public string moduleNameFormat;
public double overCurrentProtection_;
public double overVoltageProtection_;
public double lowerVoltageLimit_;
public double upperVoltageLimit_;
public double lowerCurrentLimit_;
public double upperCurrentLimit_;
public double voltageSetpoint_;
public double voltageSlewRate_;
public bool isOn_;
public int faultStatus;
}
}

View File

@@ -0,0 +1,139 @@
/*-------------------------------------------------------------------------
// 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;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
namespace Raytheon
{
/// <summary>
/// Class for controlling all power supplies
/// </summary>
public class PowerModuleMeasurementManager
{
#region PrivateClassMembers
/// <summary>
/// NLog logger
/// </summary>
private static NLog.ILogger _logger;
private PowerSupply _powerSupply;
private IConfigurationFile _powerOffAndSelfTestConfig;
#endregion
public bool FrontPanelEnabled
{
get
{
if (_powerSupply != null)
{
return _powerSupply[null].FrontPanelEnabled;
}
else
return true;
}
set
{
if (_powerSupply != null)
{
_powerSupply[null].FrontPanelEnabled = value;
}
}
}
/// <summary>
/// constructor
/// </summary>
/// <param name="stePowerSupplyInstanceName">the name specified in the Instruments.xml file</param>
public PowerModuleMeasurementManager(PowerSupply powerSupply, IConfigurationFile powerOffAndSelfTestConfig)
{
_logger = LogManager.GetCurrentClassLogger();
_powerSupply = powerSupply;
_powerOffAndSelfTestConfig = powerOffAndSelfTestConfig;
}
/// <summary>
/// The Finalizer
/// </summary>
~PowerModuleMeasurementManager()
{
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() ...");
}
/// <summary>
/// Initialize the instrument(s)
/// </summary>
public void Initialize()
{
_logger.Trace($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
}
/// <summary>
/// Shuts down manager, clears resources
/// </summary>
public void Shutdown()
{
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
_powerSupply.Shutdown();
}
/// <summary>
/// Read various power supply data
/// </summary>
public void ReadPowerSupplyData(object module, out double voltage, out double current, out double voltageSetPoint, out bool isOn, out int faultStatus)
{
_powerSupply[module].ReadPowerSupplyData(out voltage, out current, out voltageSetPoint, out isOn, out faultStatus);
}
/// <summary>
/// Enable the output of the power supply.
/// </summary>
/// <param name="moduleName">The name of the module to enable.</param>
public void OutputEnable(object module)
{
_powerSupply[module].On();
}
/// <summary>
/// Disable the output of the power supply.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public void OutputDisable(object module)
{
_powerSupply[module].ReadPowerSupplyData(out double voltage, out double current, out double voltageSetPoint, out bool isOn, out int faultStatus);
if (isOn)
{
_powerSupply[module].Off();
// save the time of this power off to file
MeasurementManager.PowerSupply.Util.SaveTime(_powerSupply.Name, DateTime.Now.ToString(), null, _powerOffAndSelfTestConfig);
}
}
}
}

View File

@@ -0,0 +1,218 @@
/*-------------------------------------------------------------------------
// 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;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Raytheon
{
/// <summary>
/// Class for controlling all power supplies
/// </summary>
public class PowerSupplyMeasurementManager
{
#region PrivateClassMembers
/// <summary>
/// NLog logger
/// </summary>
private static NLog.ILogger _logger;
private IConfigurationFile _powerOffAndSelfTestConfig;
private IInstrumentManager _instrumentManager;
private Dictionary<string, PowerModuleMeasurementManager> _powerSystemNameToPowerModuleMeasurementManagerDict = new Dictionary<string, PowerModuleMeasurementManager>();
string _powerSystemWithFailedSelfTest = String.Empty;
#endregion
/// <summary>
/// constructor
/// </summary>
/// <param name="stePowerSupplyInstanceName">the name specified in the Instruments.xml file</param>
public PowerSupplyMeasurementManager(IInstrumentManager instrumentManager, string powerSupplySelfTestLogFile)
{
_logger = LogManager.GetCurrentClassLogger();
_powerOffAndSelfTestConfig = new ConfigurationFile(powerSupplySelfTestLogFile);
_instrumentManager = instrumentManager;
}
/// <summary>
/// The Finalizer
/// </summary>
~PowerSupplyMeasurementManager()
{
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() ...");
}
/// <summary>
/// Implement Indexer to obtain a powermodulemeasurementmanager
/// </summary>
/// <param name=""></param>
/// <returns></returns>
public PowerModuleMeasurementManager this[object powerSystemId]
{
get
{
if (!powerSystemId.GetType().IsEnum)
{
throw new ArgumentException($"{nameof(powerSystemId)} must be an enumerated type");
}
if (!_powerSystemNameToPowerModuleMeasurementManagerDict.ContainsKey(powerSystemId.ToString()))
{
throw new Exception($"Invalid power supply system: {powerSystemId.ToString()}");
}
return _powerSystemNameToPowerModuleMeasurementManagerDict[powerSystemId.ToString()];
}
}
/// <summary>
/// Initialize the instrument(s)
/// </summary>
public void Initialize()
{
_logger.Trace($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
PerformSelfTest();
if (_powerSystemWithFailedSelfTest != String.Empty)
{
throw new Exception($"{_powerSystemWithFailedSelfTest}'s self-test failed.");
}
}
/// <summary>
/// Perform self test on power supply system
/// Self test for each power system takes a while, so we don't want to run self test every time we initialize the power system
/// So we only want to run self test under 2 conditions:
/// 1. Certain time has elapsed since last power off
/// 2. Certain time has elapsed since last self test run ( in the absence of power off time)
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private async void PerformSelfTest()
{
_logger.Trace($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
string errorMsg = String.Empty;
Dictionary<string, Task<SelfTestResult>> powerSystemToSelfTestTaskDict = new Dictionary<string, Task<SelfTestResult>>();
bool allSelfTestsPassed = true;
ICollection<object> psList = _instrumentManager.GetInstruments(typeof(PowerSupply));
foreach (PowerSupply ps in psList)
{
ps.Initialize();
// perform self test on power system
Task<SelfTestResult> task = PerformSelfTestTask(ps);
powerSystemToSelfTestTaskDict[ps.Name] = task;
}
foreach (var item in powerSystemToSelfTestTaskDict)
{
// wait for self test on power system to finish
SelfTestResult result = await item.Value;
if (result == SelfTestResult.Fail && String.IsNullOrEmpty(_powerSystemWithFailedSelfTest))
{
allSelfTestsPassed = false;
_powerSystemWithFailedSelfTest = item.Key;
}
}
if (allSelfTestsPassed)
{
foreach (PowerSupply ps in psList)
{
_powerSystemNameToPowerModuleMeasurementManagerDict[ps.Name] = new PowerModuleMeasurementManager(ps, _powerOffAndSelfTestConfig);
}
}
}
/// <summary>
/// Perform self test on power supply system
/// Self test for each power system takes a while, so we don't want to run self test every time we initialize the power system
/// So we only want to run self test under 2 conditions:
/// 1. Certain time has elapsed since last power off
/// 2. Certain time has elapsed since last self test run ( in the absence of power off time)
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private Task<SelfTestResult> PerformSelfTestTask(PowerSupply ps)
{
SelfTestResult result = SelfTestResult.Pass;
_logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() for {ps.Name} is running...");
try
{
bool performSelfTest = false;
const int HOURS_ELAPSED = 2;
string lastSaveTime = MeasurementManager.PowerSupply.Util.GetLastSavedTime(ps.Name, _powerOffAndSelfTestConfig);
if (DateTime.TryParse(lastSaveTime, out DateTime dt))
{
// if this power supply system has been turn off for a certain number of hours, then we want to perform self test on it
if (DateTime.Now.Subtract(dt).TotalHours >= HOURS_ELAPSED)
{
performSelfTest = true;
}
}
else { performSelfTest = true; }
if (performSelfTest)
{
_logger?.Info($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() executing self-test for {ps.Name}...");
result = ps[null].PerformSelfTest();
if (result == SelfTestResult.Pass)
{
// save the time of this self test to file
MeasurementManager.PowerSupply.Util.SaveTime(ps.Name, null, DateTime.Now.ToString(), _powerOffAndSelfTestConfig);
}
}
else
_logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() skipping self-test for {ps.Name}...");
}
catch (Exception ex)
{
_logger?.Error(ex.Message + "\n" + ex.StackTrace);
}
_logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() for {ps.Name} is exiting...");
return Task.FromResult(result);
}
}
}

View File

@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Program.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>Raytheon.InstrumentManagers.PowerSupplyManager</AssemblyName>
<RootNamespace>Raytheon.InstrumentManagers</RootNamespace>
<Product>Power Supply Manager Implementation</Product>
<Description>Provide access to the actual power supplies</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.InstrumentManager.GeneralInstrumentManager" Version="1.4.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Interfaces\PowerSupply\PowerSupply.Contracts.csproj" />
<ProjectReference Include="..\..\Raytheon.Common\Raytheon.Common.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,64 @@
/*-------------------------------------------------------------------------
// 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;
using System.IO;
using System.Xml.Serialization;
namespace Raytheon
{
/// <summary>
/// Serialiable class to store self test and power off time to XML
/// and restore info from XML to this class
/// </summary>
[Serializable]
public class PowerSupplySelfTestTime
{
[XmlAttribute("power_system")]
public string _powerSystem { get; set; }
// date and time of last power off of a power module
[XmlAttribute("power_off_time")]
public string _powerOffTime { get; set; }
// date and time of last successful self test
[XmlAttribute("self_test_time")]
public string _selfTestTime { get; set; }
/// <summary>
/// constructor
/// </summary>
public PowerSupplySelfTestTime()
{
_powerOffTime = Raytheon.Common.GeneralConstants.DefaultConfigValue;
_powerSystem = Raytheon.Common.GeneralConstants.DefaultConfigValue;
_selfTestTime = Raytheon.Common.GeneralConstants.DefaultConfigValue;
}
/// <summary>
/// constructor
/// </summary>
public PowerSupplySelfTestTime(string powerSystem, string powerOffTime, string selfTestTime)
{
_powerOffTime = powerOffTime;
_powerSystem = powerSystem;
_selfTestTime = selfTestTime;
}
}
}

View File

@@ -0,0 +1,115 @@
/*-------------------------------------------------------------------------
// 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 Raytheon.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Raytheon.MeasurementManager.PowerSupply
{
/// <summary>
/// Define non-specific constants
/// </summary>
internal static class Util
{
/// <summary>
/// Read from the XML file the time for this power system
/// If time of power off is available, we return this time
/// If time of last self test run is available, we return this time
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static string GetLastSavedTime(string powerSystem, IConfigurationFile powerOffAndSelfTestConfig)
{
string savedTime = "";
string powerOffTime = "";
string selfTestTime = "";
List<PowerSupplySelfTestTime> powerOffEntryListTemp = new List<PowerSupplySelfTestTime>();
List<PowerSupplySelfTestTime> powerOffEntryList = powerOffAndSelfTestConfig.ReadList<PowerSupplySelfTestTime>(nameof(PowerSupplySelfTestTime), nameof(PowerSupplySelfTestTime), powerOffEntryListTemp);
foreach (var powerOffEntry in powerOffEntryList)
{
if (powerOffEntry._powerSystem == powerSystem)
{
if (DateTime.TryParse(powerOffEntry._powerOffTime, out DateTime dt))
powerOffTime = powerOffEntry._powerOffTime;
if (DateTime.TryParse(powerOffEntry._selfTestTime, out dt))
selfTestTime = powerOffEntry._selfTestTime;
}
}
if (String.IsNullOrEmpty(powerOffTime))
savedTime = selfTestTime;
else if (String.IsNullOrEmpty(selfTestTime))
savedTime = powerOffTime;
else if (!String.IsNullOrEmpty(powerOffTime) && !String.IsNullOrEmpty(selfTestTime))
{
if (DateTime.TryParse(powerOffTime, out DateTime powerOffDt) && DateTime.TryParse(selfTestTime, out DateTime selfTestDt))
{
if (DateTime.Compare(powerOffDt, selfTestDt) == 1)
savedTime = powerOffTime;
else
savedTime = selfTestTime;
}
}
return savedTime;
}
/// <summary>
/// Save time of power off or self test event
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static void SaveTime(string powerSystem, string powerOffTime, string selfTestTime, IConfigurationFile powerOffAndSelfTestConfig)
{
List<PowerSupplySelfTestTime> powerOffEntryListTemp = new List<PowerSupplySelfTestTime>();
List<PowerSupplySelfTestTime> powerOffEntryList = powerOffAndSelfTestConfig.ReadList<PowerSupplySelfTestTime>(nameof(PowerSupplySelfTestTime), nameof(PowerSupplySelfTestTime), powerOffEntryListTemp);
var entry = powerOffEntryList.Find(b => b._powerSystem == powerSystem);
if (entry != null)
{
if (!string.IsNullOrEmpty(powerOffTime))
entry._powerOffTime = powerOffTime;
if (!string.IsNullOrEmpty(selfTestTime))
entry._selfTestTime = selfTestTime;
}
else
{
PowerSupplySelfTestTime data = new PowerSupplySelfTestTime(powerSystem, powerOffTime, selfTestTime);
if (string.IsNullOrEmpty(powerOffTime))
data._powerOffTime = Raytheon.Common.GeneralConstants.DefaultConfigValue;
if (string.IsNullOrEmpty(selfTestTime))
data._selfTestTime = Raytheon.Common.GeneralConstants.DefaultConfigValue;
powerOffEntryList.Add(data);
}
powerOffAndSelfTestConfig.WriteList(nameof(PowerSupplySelfTestTime), nameof(PowerSupplySelfTestTime), powerOffEntryList);
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

31
Source/Program.props Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Year>$([System.DateTime]::get_now().ToString("yyyy"))</Year>
<Major>$(Year)</Major>
<Minor>$([System.DateTime]::get_now().ToString("MM"))</Minor>
<Build>$([System.DateTime]::get_now().ToString("dd"))</Build>
<Revision>$([MSBuild]::Divide($([System.DateTime]::get_Now().get_TimeOfDay().get_TotalMinutes()), 2).ToString('F0'))</Revision>
<Version>$(Major).$(Minor).$(Build).$(Revision)</Version>
<Suffix></Suffix>
</PropertyGroup>
<Target Name="DeleteStaleFiles" BeforeTargets="Build">
<ItemGroup>
<StaleFiles Include="$(OutDir)..*.nupkg" />
</ItemGroup>
<Message Text="Deleting Stale Files: @(StaleFiles, '%0A')" Condition="'@(StaleFiles-&gt;Count())' &gt; 0" />
<Delete Files="@(StaleFiles)" />
</Target>
<Target Name="PostBuild" AfterTargets="Pack">
<MakeDir Directories="$(SolutionDir)Nuget\SolutionPackages" Condition="!Exists('$(SolutionDir)\Nuget\SolutionPackages')" />
<Exec Command="dotnet nuget push --source &quot;SolutionLocalSource&quot; $(OutDir)..\*.nupkg" />
</Target>
</Project>

151
Source/Program.sln Normal file
View File

@@ -0,0 +1,151 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34408.163
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Program", "Program\Program.csproj", "{00896DC5-536A-4036-85A9-B9E7F9FB712E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "UnitTests\UnitTests.csproj", "{9425542E-2602-4043-8583-1378BD959589}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Program", "_Program", "{4D2003A8-CBCB-498C-9186-355650A84D41}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interfaces", "Interfaces", "{B966EB5E-29AF-4641-A4EF-EB77444FE06A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Instruments.Contracts", "Interfaces\IInstrument\Instruments.Contracts.csproj", "{CDC73C19-53A6-47B3-9B53-54D99C551EC2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Instruments.InstrumentManager.Contracts", "Interfaces\IInstrumentManager\Instruments.InstrumentManager.Contracts.csproj", "{481E843F-3E5F-45E6-8CC9-2FE5D750038A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Instruments", "Instruments", "{2075F72F-BBE8-48A2-B7CA-4401FEDA5457}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneralIntsrumentManager", "Instruments\GeneralIntsrumentManager\GeneralIntsrumentManager.csproj", "{3484D84A-5374-422D-B087-D16F9911749B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PowerSupplies", "PowerSupplies", "{69413672-FD51-480A-B8D5-3E1C7B720929}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EthernetSockets", "EthernetSockets", "{2CF1CAF6-8241-46A0-BC97-CF69F2F14C90}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TcpClient", "Instruments\EthernetSockets\CommDeviceTcpClient\TcpClient.csproj", "{4B168939-2EC4-4710-B7C9-E41F6E4C6A23}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommDevice.Contracts", "Interfaces\ICommDevice\CommDevice.Contracts.csproj", "{372502DE-CB7B-4DBB-A669-0639BDAB0CFC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerSupply.Contracts", "Interfaces\PowerSupply\PowerSupply.Contracts.csproj", "{2E6A9882-5CCD-4737-8170-2DF0943E5F3E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerSupplySim", "Instruments\PowerSupplies\PowerSupplySim\PowerSupplySim.csproj", "{E43692A0-43F8-40EB-A5F4-0F5F15FC1055}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KeysightN67XX", "Instruments\PowerSupplies\Keysight67XX\KeysightN67XX.csproj", "{4FDBF1AB-19BE-419D-B2E6-B9D236F40914}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MeasurementManagers", "MeasurementManagers", "{C440909C-8430-4BFC-ADAD-2144BFFA050F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerSupplyMeasurementManager", "MeasurementManagers\PowerSupplyMeasurementManager\PowerSupplyMeasurementManager.csproj", "{143332EA-D6A2-456E-991D-7710B911F2D5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProgramGui", "ProgramGUI\ProgramGui.csproj", "{44C9E245-6152-4EC9-ACE4-577FE366FCBD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Raytheon.Common", "Raytheon.Common\Raytheon.Common.csproj", "{E51671D2-86BE-4BCC-B7AF-2749CEDB19F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Deploy|Any CPU = Deploy|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{00896DC5-536A-4036-85A9-B9E7F9FB712E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{00896DC5-536A-4036-85A9-B9E7F9FB712E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00896DC5-536A-4036-85A9-B9E7F9FB712E}.Deploy|Any CPU.ActiveCfg = Debug|Any CPU
{00896DC5-536A-4036-85A9-B9E7F9FB712E}.Deploy|Any CPU.Build.0 = Debug|Any CPU
{00896DC5-536A-4036-85A9-B9E7F9FB712E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00896DC5-536A-4036-85A9-B9E7F9FB712E}.Release|Any CPU.Build.0 = Release|Any CPU
{9425542E-2602-4043-8583-1378BD959589}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9425542E-2602-4043-8583-1378BD959589}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9425542E-2602-4043-8583-1378BD959589}.Deploy|Any CPU.ActiveCfg = Debug|Any CPU
{9425542E-2602-4043-8583-1378BD959589}.Deploy|Any CPU.Build.0 = Debug|Any CPU
{9425542E-2602-4043-8583-1378BD959589}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9425542E-2602-4043-8583-1378BD959589}.Release|Any CPU.Build.0 = Release|Any CPU
{CDC73C19-53A6-47B3-9B53-54D99C551EC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CDC73C19-53A6-47B3-9B53-54D99C551EC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CDC73C19-53A6-47B3-9B53-54D99C551EC2}.Deploy|Any CPU.ActiveCfg = Debug|Any CPU
{CDC73C19-53A6-47B3-9B53-54D99C551EC2}.Deploy|Any CPU.Build.0 = Debug|Any CPU
{CDC73C19-53A6-47B3-9B53-54D99C551EC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CDC73C19-53A6-47B3-9B53-54D99C551EC2}.Release|Any CPU.Build.0 = Release|Any CPU
{481E843F-3E5F-45E6-8CC9-2FE5D750038A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{481E843F-3E5F-45E6-8CC9-2FE5D750038A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{481E843F-3E5F-45E6-8CC9-2FE5D750038A}.Deploy|Any CPU.ActiveCfg = Debug|Any CPU
{481E843F-3E5F-45E6-8CC9-2FE5D750038A}.Deploy|Any CPU.Build.0 = Debug|Any CPU
{481E843F-3E5F-45E6-8CC9-2FE5D750038A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{481E843F-3E5F-45E6-8CC9-2FE5D750038A}.Release|Any CPU.Build.0 = Release|Any CPU
{3484D84A-5374-422D-B087-D16F9911749B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3484D84A-5374-422D-B087-D16F9911749B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3484D84A-5374-422D-B087-D16F9911749B}.Deploy|Any CPU.ActiveCfg = Debug|Any CPU
{3484D84A-5374-422D-B087-D16F9911749B}.Deploy|Any CPU.Build.0 = Debug|Any CPU
{3484D84A-5374-422D-B087-D16F9911749B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3484D84A-5374-422D-B087-D16F9911749B}.Release|Any CPU.Build.0 = Release|Any CPU
{4B168939-2EC4-4710-B7C9-E41F6E4C6A23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B168939-2EC4-4710-B7C9-E41F6E4C6A23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B168939-2EC4-4710-B7C9-E41F6E4C6A23}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
{4B168939-2EC4-4710-B7C9-E41F6E4C6A23}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
{4B168939-2EC4-4710-B7C9-E41F6E4C6A23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B168939-2EC4-4710-B7C9-E41F6E4C6A23}.Release|Any CPU.Build.0 = Release|Any CPU
{372502DE-CB7B-4DBB-A669-0639BDAB0CFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{372502DE-CB7B-4DBB-A669-0639BDAB0CFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{372502DE-CB7B-4DBB-A669-0639BDAB0CFC}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
{372502DE-CB7B-4DBB-A669-0639BDAB0CFC}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
{372502DE-CB7B-4DBB-A669-0639BDAB0CFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{372502DE-CB7B-4DBB-A669-0639BDAB0CFC}.Release|Any CPU.Build.0 = Release|Any CPU
{2E6A9882-5CCD-4737-8170-2DF0943E5F3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2E6A9882-5CCD-4737-8170-2DF0943E5F3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2E6A9882-5CCD-4737-8170-2DF0943E5F3E}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
{2E6A9882-5CCD-4737-8170-2DF0943E5F3E}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
{2E6A9882-5CCD-4737-8170-2DF0943E5F3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2E6A9882-5CCD-4737-8170-2DF0943E5F3E}.Release|Any CPU.Build.0 = Release|Any CPU
{E43692A0-43F8-40EB-A5F4-0F5F15FC1055}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E43692A0-43F8-40EB-A5F4-0F5F15FC1055}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E43692A0-43F8-40EB-A5F4-0F5F15FC1055}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
{E43692A0-43F8-40EB-A5F4-0F5F15FC1055}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
{E43692A0-43F8-40EB-A5F4-0F5F15FC1055}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E43692A0-43F8-40EB-A5F4-0F5F15FC1055}.Release|Any CPU.Build.0 = Release|Any CPU
{4FDBF1AB-19BE-419D-B2E6-B9D236F40914}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FDBF1AB-19BE-419D-B2E6-B9D236F40914}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FDBF1AB-19BE-419D-B2E6-B9D236F40914}.Deploy|Any CPU.ActiveCfg = Debug|Any CPU
{4FDBF1AB-19BE-419D-B2E6-B9D236F40914}.Deploy|Any CPU.Build.0 = Debug|Any CPU
{4FDBF1AB-19BE-419D-B2E6-B9D236F40914}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FDBF1AB-19BE-419D-B2E6-B9D236F40914}.Release|Any CPU.Build.0 = Release|Any CPU
{143332EA-D6A2-456E-991D-7710B911F2D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{143332EA-D6A2-456E-991D-7710B911F2D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{143332EA-D6A2-456E-991D-7710B911F2D5}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
{143332EA-D6A2-456E-991D-7710B911F2D5}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
{143332EA-D6A2-456E-991D-7710B911F2D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{143332EA-D6A2-456E-991D-7710B911F2D5}.Release|Any CPU.Build.0 = Release|Any CPU
{44C9E245-6152-4EC9-ACE4-577FE366FCBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44C9E245-6152-4EC9-ACE4-577FE366FCBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44C9E245-6152-4EC9-ACE4-577FE366FCBD}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
{44C9E245-6152-4EC9-ACE4-577FE366FCBD}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
{44C9E245-6152-4EC9-ACE4-577FE366FCBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44C9E245-6152-4EC9-ACE4-577FE366FCBD}.Release|Any CPU.Build.0 = Release|Any CPU
{E51671D2-86BE-4BCC-B7AF-2749CEDB19F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E51671D2-86BE-4BCC-B7AF-2749CEDB19F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E51671D2-86BE-4BCC-B7AF-2749CEDB19F2}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
{E51671D2-86BE-4BCC-B7AF-2749CEDB19F2}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
{E51671D2-86BE-4BCC-B7AF-2749CEDB19F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E51671D2-86BE-4BCC-B7AF-2749CEDB19F2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{00896DC5-536A-4036-85A9-B9E7F9FB712E} = {4D2003A8-CBCB-498C-9186-355650A84D41}
{CDC73C19-53A6-47B3-9B53-54D99C551EC2} = {B966EB5E-29AF-4641-A4EF-EB77444FE06A}
{481E843F-3E5F-45E6-8CC9-2FE5D750038A} = {B966EB5E-29AF-4641-A4EF-EB77444FE06A}
{3484D84A-5374-422D-B087-D16F9911749B} = {2075F72F-BBE8-48A2-B7CA-4401FEDA5457}
{69413672-FD51-480A-B8D5-3E1C7B720929} = {2075F72F-BBE8-48A2-B7CA-4401FEDA5457}
{2CF1CAF6-8241-46A0-BC97-CF69F2F14C90} = {2075F72F-BBE8-48A2-B7CA-4401FEDA5457}
{4B168939-2EC4-4710-B7C9-E41F6E4C6A23} = {2CF1CAF6-8241-46A0-BC97-CF69F2F14C90}
{372502DE-CB7B-4DBB-A669-0639BDAB0CFC} = {B966EB5E-29AF-4641-A4EF-EB77444FE06A}
{2E6A9882-5CCD-4737-8170-2DF0943E5F3E} = {B966EB5E-29AF-4641-A4EF-EB77444FE06A}
{E43692A0-43F8-40EB-A5F4-0F5F15FC1055} = {69413672-FD51-480A-B8D5-3E1C7B720929}
{4FDBF1AB-19BE-419D-B2E6-B9D236F40914} = {69413672-FD51-480A-B8D5-3E1C7B720929}
{143332EA-D6A2-456E-991D-7710B911F2D5} = {C440909C-8430-4BFC-ADAD-2144BFFA050F}
{44C9E245-6152-4EC9-ACE4-577FE366FCBD} = {4D2003A8-CBCB-498C-9186-355650A84D41}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CA9C7EC5-FDF7-444C-99C8-7BDBE8AF4EDB}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,220 @@
/*-------------------------------------------------------------------------
// 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 ProgramLib;
using NLog;
using Raytheon.Common;
using Raytheon.Instruments;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ProgramGui;
using ProgramGui.Model;
using ProgramGui.View;
using ProgramGui.ViewModel;
using System.Windows;
using Raytheon;
namespace ProgramLib
{
internal class UutPowerAction
{
#region PrivateClassMembers
private static NLog.ILogger _logger;
private static object powerSyncObj = new object();
private bool _sttoSuccess = true;
private string fatalErrorMsg;
#endregion
public UutPowerAction()
{
_logger = LogManager.GetCurrentClassLogger();
}
~UutPowerAction()
{
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() ...");
}
/// <summary>
/// Power off UUT
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public void UutPowerOff()
{
try
{
lock (powerSyncObj)
{
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
Program.Instance().GetPowerSupplyMeasurementManager()[PowerSupplyConstants.POWER_DEVICE.STE_POWER_SUPPLY_SYSTEM].OutputDisable(ProgramLib.PowerSupplyConstants.POWER_DEVICE.STE_PVM_5V);
// enable front panel
Program.Instance().GetPowerSupplyMeasurementManager()[PowerSupplyConstants.POWER_DEVICE.STE_POWER_SUPPLY_SYSTEM].FrontPanelEnabled = true;
// signal to PowerSupplyReadThread to stop monitoring power
Program.Instance()._eventManager[EventManager.Events.UUT_POWER_OFF].Set();
ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.MAIN].Dispatcher.Invoke((Action)delegate
{
ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.MAIN].Hide();
});
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Power on UUT
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public void UutPowerOn()
{
try
{
lock (powerSyncObj)
{
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
Program.Instance().GetPowerSupplyMeasurementManager()[PowerSupplyConstants.POWER_DEVICE.STE_POWER_SUPPLY_SYSTEM].ReadPowerSupplyData(ProgramLib.PowerSupplyConstants.POWER_DEVICE.STE_PVM_5V, out double voltage, out double current, out double voltageSetPoint, out bool isOn, out int faultStatus);
if (!isOn)
{
Task.Factory.StartNew(() => PerformSttoTask());
ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK].Dispatcher.Invoke((Action)delegate
{
ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.MAIN].Hide();
ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK].ShowDialog();
});
if (_sttoSuccess)
{
ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK].Dispatcher.Invoke((Action)delegate
{
ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.MAIN].Show();
});
Program.Instance().GetPowerSupplyMeasurementManager()[PowerSupplyConstants.POWER_DEVICE.STE_POWER_SUPPLY_SYSTEM].OutputEnable(ProgramLib.PowerSupplyConstants.POWER_DEVICE.STE_PVM_5V);
// disable front panel
Program.Instance().GetPowerSupplyMeasurementManager()[PowerSupplyConstants.POWER_DEVICE.STE_POWER_SUPPLY_SYSTEM].FrontPanelEnabled = false;
// signal to PowerSupplyReadThread to start monitoring power
Program.Instance()._eventManager[EventManager.Events.UUT_POWER_ON].Set();
}
else
{
throw new Exception(fatalErrorMsg);
}
}
}
}
catch (Exception)
{
throw;
}
}
private async void PerformSttoTask()
{
ImpedanceDataModel impedanceDataModel;
ImpedanceCheckWindow impedanceCheckWindow = (ImpedanceCheckWindow)ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK];
try
{
_logger?.Debug($"{this.GetType().Name}::PerformSttoTask() running...");
bool forceFail = false;
string measurementStatus = "PASSED";
ImpedanceCheckWindowViewModel.Images passFailImage = ImpedanceCheckWindowViewModel.Images.PASS_CHECK;
impedanceCheckWindow._viewModel.ClearData();
int MAX_ITERATION = 15;
int cableNum = 17;
int cablePin1 = 5;
int cablePin2 = 7;
int measurement = 5;
string measurementName;
for (int i = 1; i <= MAX_ITERATION; i++)
{
measurementName = $"P{cableNum}_P{cablePin1++}_P{cableNum++}_P{cablePin2++}";
impedanceDataModel = new ImpedanceDataModel();
if (i == MAX_ITERATION / 2 && forceFail)
{
passFailImage = ImpedanceCheckWindowViewModel.Images.FAIL_CHECK;
measurementStatus = "FAILED";
_sttoSuccess = false;
}
impedanceDataModel.PassFailImagePath = impedanceCheckWindow._viewModel._imageToResourcePathDict[passFailImage];
impedanceDataModel.Description = $"{measurementName} Measured {measurement} Range [0,50]";
if (Program.Instance()._testStandSeqContext != null)
{
Program.Instance()._testStandSeqContext.Step.AdditionalResults.CustomResults.Insert($"\"{measurementName}\"", $"\"Measured: {measurement++} Range [0,50] - {measurementStatus}\"");
}
impedanceCheckWindow._viewModel.AddData(impedanceDataModel);
if (!_sttoSuccess)
{
fatalErrorMsg = impedanceDataModel.Description;
throw new Exception(fatalErrorMsg);
}
await Task.Delay(300);
}
}
catch (Exception ex)
{
_logger.Error(ex.Message + "\n" + ex.StackTrace);
}
finally
{
if (!_sttoSuccess)
{
impedanceCheckWindow.Dispatcher.Invoke((Action)delegate
{
impedanceCheckWindow.btnClose.Visibility = Visibility.Visible;
});
}
else
{
impedanceCheckWindow.Dispatcher.Invoke((Action)delegate
{
impedanceCheckWindow.Hide();
});
}
_logger?.Debug($"{this.GetType().Name}::PerformSttoTask() exiting...");
}
}
}
}

View File

@@ -0,0 +1,74 @@
/*-------------------------------------------------------------------------
// 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;
using System.Threading.Tasks;
namespace ProgramLib
{
/// <summary>
/// Abstract base class for all threads
/// </summary>
internal abstract class BasicThread
{
protected Thread _thread;
/// <summary>
/// Spawn thread and start it
/// </summary>
/// <param name=""></param>
/// <returns></returns>
public void Start()
{
_thread = new Thread(new ThreadStart(DoWork));
_thread.Start();
}
/// <summary>
/// Method that executes on the thread.
/// Child class must implement this method
/// </summary>
/// <param name=""></param>
/// <returns></returns>
protected abstract void DoWork();
/// <summary>
/// Tells thread to quit
/// </summary>
/// <param name=""></param>
/// <returns></returns>
public virtual void Quit() { }
/// <summary>
/// Wait for thread to exit
/// </summary>
/// <param name=""></param>
/// <returns></returns>
public virtual void WaitForExit()
{
if (_thread != null)
{
// wait for thread to terminate
_thread.Join();
}
}
}
}

View File

@@ -0,0 +1,34 @@
/*-------------------------------------------------------------------------
// 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 ProgramLib
{
/// <summary>
/// Define non-specific constants
/// </summary>
internal static class GeneralConstants
{
public const string ProgramConfigFilename = "config.ini";
public const string DefaultConfigValue = "NOTSET";
}
}

View File

@@ -0,0 +1,42 @@
/*-------------------------------------------------------------------------
// 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 ProgramLib
{
/// <summary>
/// Power supply constants
/// </summary>
internal static class PowerSupplyConstants
{
public enum POWER_DEVICE
{
STE_POWER_SUPPLY_SYSTEM,
// Power modules
UUT_REF_3_3V,
STE_PVM_5V,
STE_GU_INTERFACE_RELAYS_25V,
STE_GU_INTERFACE_RF_INTERFACE_5V,
}
}
}

View File

@@ -0,0 +1,41 @@
/*-------------------------------------------------------------------------
// 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 ProgramLib
{
/// <summary>
/// Define all the sections and keys that exists in the INI file
/// </summary>
internal enum ProgramConfigIni
{
// list all the sections here
GENERAL,
// list all the keys here
DATA_BASE_PATH,
DATA_TEMP_PATH,
APP_BASE_PATH,
POWER_SUPPLY_SELF_TEST_DATETIME,
POWER_SUPPLY_READ_RATE
}
}

View File

@@ -0,0 +1,69 @@
/*-------------------------------------------------------------------------
// 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;
namespace ProgramLib
{
/// <summary>
/// Store UUT information
/// </summary>
internal class UutInfo
{
#region PublicMembers
#endregion
#region PrivateClassMembers
// class variables
private readonly string _partNumber;
private readonly string _serialNumber;
#endregion
#region PrivateFuctions
/// <summary>
/// The constructor
/// </summary>
public UutInfo(string partNumber, string serialNumber)
{
_partNumber = partNumber;
_serialNumber = serialNumber;
}
#endregion
#region PublicFuctions
/// <summary>
///
/// </summary>
/// <returns></returns>
internal string GetPartNumber()
{
return _partNumber;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
internal string GetSerialNumber()
{
return _serialNumber;
}
#endregion
}
}

View File

@@ -0,0 +1,154 @@
/*-------------------------------------------------------------------------
// 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;
using System.Threading.Tasks;
namespace ProgramLib
{
/// <summary>
/// Class that maps event array index to any event enumeration and wraps the WaitHandle.WaitAny() function
/// Use case:
/// When calling WaitHandle.WaitAny(EventArray), it only returns the index of the event in the array that is being signalled.
/// Refering to an index of the array to know which event it is is not ideal. We want to be able to refer to an enumeration instead
/// Usage:
/// In class that uses this class, must define a enumeration
/// public enum Events
/// {
/// EVENT1,
/// EVENT2,
/// EVENT3,
/// EVENTN
///
/// // DO NOT change the name
/// // This must be the last member in the enum
/// EVENT_TIMED_OUT
/// }
/// Dictionary<Events, EventWaitHandle> dict = new Dictionary<Events, EventWaitHandle>();
/// dict[Events.EVENT1] = new ManualResetEvent(false);
/// dict[Events.EVENT2] = new AutoResetEvent(false);
/// dict[Events.EVENT3] = new ManualResetEvent(false);
/// dict[Events.EVENTN] = new AutoResetEvent(false);
/// dict[Events.EVENT_TIMED_OUT] = null;
///
/// EventGroup<Events, EventWaitHandle> eventGroup = new EventGroup<Events, EventWaitHandle>(dict);
///
/// Events id = eventGroup.WaitAny([Optional_timeout]);
///
/// if (id == Events.EVENT_TIMED_OUT){} // only if timeout was specified
/// if (id == Events.EVENT1){}
///
/// </summary>
internal class EventGroup<T1,T2>
{
Dictionary<T1, T2> _eventDict = null;
T2[] _eventArray = null;
/// <summary>
/// Constructor
/// </summary>
private EventGroup()
{
}
/// <summary>
/// Constructor
/// The event enum passed in must be defined in the following format:
/// public enum Events
/// {
/// EVENT1,
/// EVENT2,
/// EVENT3,
/// EVENTN
///
/// // DO NOT change the name
/// // This must be the last member in the enum
/// EVENT_TIMED_OUT
/// }
/// </summary>
/// <param name="eventDict">A dictionary that contains event enum that is associated to an event object</param>
public EventGroup(Dictionary<T1, T2> eventDict)
{
if (eventDict == null)
throw new Exception($"{nameof(eventDict)} cannot be null");
if (!eventDict.First().Key.GetType().IsEnum)
{
throw new Exception($"{nameof(eventDict)}'s key must be an enumerated type");
}
// get the last element in the dictionary
var element = eventDict.ElementAt(eventDict.Count - 1);
// check if the name of the last enum member is what we expect
string actualNameOfLastEnumMember = ((Enum)Convert.ChangeType(element.Key, typeof(Enum))).ToString();
string expectedNameOfLastEnumMember = "EVENT_TIMED_OUT";
if (actualNameOfLastEnumMember != expectedNameOfLastEnumMember)
{
throw new Exception($"Enum {element.Key.GetType().Name} must have {expectedNameOfLastEnumMember} as its last member. {nameof(eventDict)} must have {expectedNameOfLastEnumMember} as the last key in the dictionary");
}
if (eventDict.First().Value.GetType().BaseType != typeof(EventWaitHandle))
{
throw new Exception($"{nameof(eventDict)}'s value must be ManualResetEvent or AutoResetEvent type");
}
_eventDict = eventDict;
_eventArray = new T2[_eventDict.Count - 1];
int index = 0;
foreach (KeyValuePair<T1, T2> entry in _eventDict)
{
if (index < _eventDict.Count - 1)
_eventArray[index++] = entry.Value;
}
}
/// <summary>
/// Return the enumerated event based on the index of the event in the event array that is being signalled
/// </summary>
/// <param name="timeoutMilliseconds">time out in milliseconds</param>
public T1 WaitAny(int? timeoutMilliseconds = null)
{
int index = 0;
T1 eventId = default;
if (timeoutMilliseconds == null)
index = WaitHandle.WaitAny((EventWaitHandle[])Convert.ChangeType(_eventArray, typeof(EventWaitHandle[])));
else
index = WaitHandle.WaitAny((EventWaitHandle[])Convert.ChangeType(_eventArray, typeof(EventWaitHandle[])), (int)timeoutMilliseconds);
if (index == WaitHandle.WaitTimeout)
{
var element = _eventDict.ElementAt(_eventDict.Count - 1);
eventId = element.Key;
}
else
{
var element = _eventDict.ElementAt(index);
eventId = element.Key;
}
return eventId;
}
}
}

View File

@@ -0,0 +1,39 @@
/*-------------------------------------------------------------------------
// 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 ProgramLib
{
/// <summary>
/// Partial class... defines all the types that this class needs
/// </summary>
internal partial class EventManager
{
public enum Events
{
GLOBAL_QUIT,
UUT_POWER_ON,
UUT_POWER_OFF,
FATAL_FAILURE
}
}
}

View File

@@ -0,0 +1,70 @@
/*-------------------------------------------------------------------------
// 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;
using System.Threading.Tasks;
namespace ProgramLib
{
/// <summary>
/// Stores global events that any thread can use to monitor
/// </summary>
internal partial class EventManager
{
private EventWaitHandle[] _events = new EventWaitHandle[Enum.GetValues(typeof(Events)).Cast<int>().Max() + 1];
// specify which event should have to be manually reset
List<Events> _manualEventList = new List<Events>
{
Events.GLOBAL_QUIT,
Events.FATAL_FAILURE
};
/// <summary>
/// The private constructor
/// </summary>
public EventManager()
{
for (int i = 0; i < _events.Count(); i++)
{
if (_manualEventList.Contains((Events)i))
{
_events[i] = new ManualResetEvent(false);
}
else
_events[i] = new AutoResetEvent(false);
}
}
/// <summary>
/// Implement Indexer to obtain an event object
/// </summary>
/// <param name=""></param>
/// <returns></returns>
public EventWaitHandle this[Events eventId]
{
get
{
return _events[(int)eventId];
}
}
}
}

View File

@@ -0,0 +1,46 @@
/*-------------------------------------------------------------------------
// 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 ProgramLib
{
/// <summary>
/// Partial class... defines all the types that this class needs
/// </summary>
internal partial class FileAndFolderManager
{
public enum Folders
{
// List data folder + its subfolders
DATA,
DATA_TEMP,
// List app folder + its folders
APP
}
public enum Files
{
POWER_SUPPLY_SELF_TEST_DATETIME
}
}
}

View File

@@ -0,0 +1,120 @@
/*-------------------------------------------------------------------------
// 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.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Raytheon.Common;
namespace ProgramLib
{
/// <summary>
/// Partial class... this is the main class responsible for parsing config.ini in order
/// to construct file paths and folder paths
/// </summary>
internal partial class FileAndFolderManager
{
private Dictionary<Folders, string> foldersDict = new Dictionary<Folders, string>();
private Dictionary<Files, string> filesDict = new Dictionary<Files, string>();
private IConfigurationFile _programConfig;
/// <summary>
/// The private constructor
/// </summary>
/// <param name="programConfig">the UUT part number</param>
public FileAndFolderManager(IConfigurationFile programConfig)
{
_programConfig = programConfig;
buildFolders();
createFolders();
buildFiles();
}
/// <summary>
/// Build folder paths so we can acccess them later
/// </summary>
/// <param name="iniObj"></param>
/// <returns></returns>
private void buildFolders()
{
string dataBasePath = _programConfig.ReadValue(ProgramConfigIni.GENERAL.ToString(), ProgramConfigIni.DATA_BASE_PATH.ToString(), "NOT SET");
foldersDict[Folders.DATA] = dataBasePath;
string val = _programConfig.ReadValue(ProgramConfigIni.GENERAL.ToString(), ProgramConfigIni.DATA_TEMP_PATH.ToString(), "NOT SET");
foldersDict[Folders.DATA_TEMP] = Path.Combine(dataBasePath, val);
string appBasePath = _programConfig.ReadValue(ProgramConfigIni.GENERAL.ToString(), ProgramConfigIni.APP_BASE_PATH.ToString(), "NOT SET");
foldersDict[Folders.APP] = dataBasePath;
}
/// <summary>
/// We create all the necessary folders
/// </summary>
/// <param name="iniObj"></param>
/// <returns></returns>
private void createFolders()
{
Directory.CreateDirectory(foldersDict[Folders.DATA_TEMP]);
}
/// <summary>
/// Build file paths so we can acccess them later
/// </summary>
/// <param name="iniObj"></param>
/// <returns></returns>
private void buildFiles()
{
string val = _programConfig.ReadValue(ProgramConfigIni.GENERAL.ToString(), ProgramConfigIni.POWER_SUPPLY_SELF_TEST_DATETIME.ToString(), "NOT SET");
filesDict[Files.POWER_SUPPLY_SELF_TEST_DATETIME] = Path.Combine(foldersDict[Folders.DATA_TEMP], val);
}
/// <summary>
/// Return the full folder path
/// </summary>
/// <param name="folder"></param>
/// <returns></returns>
public string getFolder(Folders folder)
{
if (foldersDict.ContainsKey(folder))
{
return foldersDict[folder];
}
else
throw new Exception($"{folder.ToString()} is invalid");
}
/// <summary>
/// Return the full file path
/// </summary>
/// <param name="iniObj"></param>
/// <returns></returns>
public string getFile(Files file)
{
if (filesDict.ContainsKey(file))
{
return filesDict[file];
}
else
throw new Exception($"{file.ToString()} is invalid");
}
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Configurations>
<IniConfiguration>
<section name="Parts">
<key name="Location" value="C:\Program Files (x86)\Raytheon\RINSS\Parts" />
</section>
</IniConfiguration>
<XmlConfigurations>
<XmlConfiguration name="Instruments">
<Instrument>
<Name>TCP_CLIENT_1</Name>
<Factory>EthernetSocketsTcpClientFactory</Factory>
</Instrument>
<Instrument>
<Name>STE_POWER_SUPPLY_SYSTEM</Name>
<Factory>PowerSupplyKeysightN67xxFactory</Factory>
</Instrument>
</XmlConfiguration>
</XmlConfigurations>
</Configurations>

View File

@@ -0,0 +1,59 @@
[GENERAL]
ETHERNET_ADDRESS = localhost
ETHERNET_PORT = 5025
MODULE_DEFINITION = UUT_REF_3_3V, STE_PVM_5V, STE_GU_INTERFACE_RELAYS_25V, STE_GU_INTERFACE_RF_INTERFACE_5V
; 0 means no coupled modules.
; couple means turning on/off any one of the module, turns on/off the others
COUPLED_MODULES = STE_PVM_5V, STE_GU_INTERFACE_RELAYS_25V, STE_GU_INTERFACE_RF_INTERFACE_5V
; 0 means no grouped modules.
; group means turning combining 2 or more modules thus acting as one module
GROUPED_MODULES = 0
INTERFACE = ETHERNET
; GU | KW | KWSIM | SELFTEST | ZERO VOLTAGE
[UUT_REF_3_3V]
INDEX = 1
OCP = 2.0
OVP = 4.0
VOLTAGE_SETPOINT = 3.3
MIN_VOLTAGE = 3.0
MAX_VOLTAGE = 3.75
MAX_CURRENT = 2.0
MIN_CURRENT = -0.25
[STE_PVM_5V]
INDEX = 2
OCP = 2.0
OVP = 8.0
VOLTAGE_SETPOINT = 5.0
; STE Power (PVM and peripherals) supply settings
MIN_VOLTAGE = 4.0
MAX_VOLTAGE = 5.5
MAX_CURRENT = 1.5
MIN_CURRENT = -.25
[STE_GU_INTERFACE_RELAYS_25V]
INDEX = 3
OCP = 3.0
OVP = 34.0
VOLTAGE_SETPOINT = 25.0
; STE Power (GU interface and Relays) Supply settings
MIN_VOLTAGE = 22.0
MAX_VOLTAGE = 30.0
MAX_CURRENT = 3.0
MIN_CURRENT = -0.25
[STE_GU_INTERFACE_RF_INTERFACE_5V]
INDEX = 4
OCP = 5.0
OVP = 6.5
VOLTAGE_SETPOINT = 5.0
; STE Power (PVM and peripherals) supply settings
MIN_VOLTAGE = 4.0
MAX_VOLTAGE = 6.3
MAX_CURRENT = 4.5
MIN_CURRENT = -.25

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Configurations>
<IniConfiguration>
<section name="STE_POWER_SUPPLY_SYSTEM">
<key name="INI_FILE_PATH" value=".\InstrumentConfig\STE_POWER_SUPPLY_SYSTEM.ini" />
</section>
</IniConfiguration>
<XmlConfigurations />
</Configurations>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true">
<!--
See http://nlog-project.org/wiki/Configuration_file
for information on customizing logging rules and outputs.
-->
<!-- add your targets here -->
<targets>
<default-wrapper xsi:type="AsyncWrapper" batchSize="1000" overflowAction="Grow" timeToSleepBetweenBatches="1"/>
<target type="FallbackGroup" name="FusionLogging" returnToFirstOnSuccess="true">
<target type="File" name="FileBackup" fileName="${specialFolder:CommonApplicationData}/Raytheon/logs/${shortdate}/${logger}.log" layout="${longdate} | ${logger} | ${message} ${exception}"/>
<target type="File" name="LocalFileBackup" fileName="${basedir}/logs/${shortdate}/${logger}.log" layout="${longdate} | ${logger} | ${message} ${exception}"/>
</target>
<target name="logDashboard" type="Chainsaw" address="udp://127.0.0.1:7777" />
<target xsi:type="File" name="logFiles" fileName="${specialfolder:folder=CommonApplicationData}/Raytheon/logs/${shortdate}/${logger:fsNormalize=true}.log" layout="${log4jxmlevent}" />
<target xsi:type="File" name="RunFile" filename="${specialfolder:folder=CommonApplicationData}/Raytheon/logs/${shortdate}/_All.log" layout="${log4jxmlevent}" />
<target name="console" type="ColoredConsole" layout="${longdate} | ${logger} | ${message} ${exception}"/>
<target name="blackHole" xsi:type="Null" />
</targets>
<!-- add your logging rules here
Log level (lowest to highest):
1. TRACE
2. DEBUG
3. INFO
4. WARN
5. ERROR
6. FATAL
-->
<rules>
<!-- Enable/Disable log level here
To Disable a log level, set "enable" attribute to true
To Enable a log level, set "enable" attribute to false -->
<logger levels="Trace" name="*" writeTo="blackHole" final="true" enabled="false" />
<logger levels="Info" name="*" writeTo="blackHole" final="true" enabled="false" />
<logger levels="Debug" name="*" writeTo="blackHole" final="true" enabled="false" />
<!-- ======================================= -->
<logger name="*" minlevel="Trace" writeTo="RunFile,console,LogDashboard" />
</rules>
</nlog>

View File

@@ -0,0 +1,73 @@
/*-------------------------------------------------------------------------
// 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 ProgramGui;
using Raytheon.Instruments;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ProgramLib
{
public partial class Program
{
public void UutPowerOn()
{
try
{
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
UutPowerAction uutPowerAction = new UutPowerAction();
uutPowerAction.UutPowerOn();
}
catch (Exception ex)
{
_logger.Error(ex.Message + "\n" + ex.StackTrace);
// DO NOT THROW in this block
// this function will handle the error accordingly since we could be calling this from third-party test executive like TestStand
TerminateTestOnMainThreadError(ex);
}
}
public void UutPowerOff()
{
try
{
_logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
UutPowerAction uutPowerAction = new UutPowerAction();
uutPowerAction.UutPowerOff();
}
catch (Exception ex)
{
_logger.Error(ex.Message + "\n" + ex.StackTrace);
// DO NOT THROW in this block
// this function will handle the error accordingly since we could be calling this from third-party test executive like TestStand
TerminateTestOnMainThreadError(ex);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More