Big changes

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

View File

@@ -0,0 +1,767 @@
// 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 NationalInstruments.NI4882;
using System;
using System.IO.Ports;
using NLog;
using Raytheon.Common;
using Raytheon.Units;
namespace Raytheon.Instruments
{
/// <summary>
/// A class that provides an interface for controlling Eloads.
/// </summary>
public class ELoadScpiKeysight : IEload
{
#region PrivateClassMembers
// General Commands
private const string _CHAN = "CHAN ";
private const string _INPUTON = "INP ON";
private const string _INPUTOFF = "INP OFF";
// Resistance Commands
private const string _RESISTANCE = "RESistance ";
private const string _RESISTANCE_MODE = "MODE RESistance";
private const string _RESISTANCE_MODE_FIXED = "RESistance:MODE FIXED ";
private const string _RESISTANCE_RANGE = "RESistance:RANGe ";
// Current Commands
private const string _CURRENT = "CURRent ";
private const string _CURRENT_MODE = "MODE CURRent ";
private const string _CURRENT_MODE_FIXED = "CURRent:MODE FIXED ";
private const string _CURRENT_PROTECTION = "CURR:PROTection ";
private const string _CURRENT_PROTECTION_ENABLE = "CURRent:PROTection:STATe ON";
private const string _CURRENT_RANGE = "CURRent:RANGe ";
//voltage commands
private const string _VOLTAGE_PROTECTION = "VOLT:PROTection ";
private const string _VOLTAGE_PROTECTION_ENABLE = "VOLT:PROTection:STATe ON";
// read commands
private const string _CURRENT_SETPOINT_QUERY = "CURR?";
private const string _CURRENT_QUERY = "MEAS:CURR?";
private const string _READVOLTAGEQUERY = "MEAS:VOLT?";
private const string _MODE_QUERY = "MODE? ";
private const string _INPUTONQUERY = "INP?";
private const string _READRESISTANCEQUERY = "RESistance?";
private const string _ERRORCODE_QUERY = "SYST:ERR?";
private const string _CURRENT_PROTECTION_QUERY = "CURR:PROTection?";
private const string _VOLTAGE_PROTECTION_QUERY = "VOLT:PROTection?";
private const string _PROTECTION_STATUS_QUERY = "STATus:CHANnel:CONDition?";
private readonly int _channelNumber;
private EloadModuleMode _mode;
private EloadModuleMode _ini_mode;
private double _setpointVal;
private double _ini_setpointVal;
private double _overCurrentProtection;
private double _overVoltageProtection;
private SerialPort _serialPort;
private Device _gpibDevice;
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
public string DetailedStatus { get; protected set; }
public bool DisplayEnabled { get; set; }
public bool FrontPanelEnabled { get; set; }
public InstrumentMetadata Info { get; set; }
public string Name { get; protected set; }
public SelfTestResult SelfTestResult => PerformSelfTest();
public State Status { get; set; }
#endregion
#region PrivateFuctions
/// <summary>
/// Dispose of this object's resources.
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
Disable();
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
/// <summary>
/// Querys the Eload module for an error code.
/// </summary>
/// <returns>The error code.</returns>
private string GetErrorCode(out int errorCode)
{
// not calling IOQuery() here so IOQuery() can call GetErrorCode() after each query
SetChannel();
string rsp = "";
if (_serialPort != null)
{
_serialPort.WriteLine(_ERRORCODE_QUERY);
rsp = _serialPort.ReadLine();
}
else
{
_gpibDevice.Write(_ERRORCODE_QUERY);
rsp = _gpibDevice.ReadString();
}
rsp = rsp.Replace("\r", "");
string[] tokens = rsp.Split(',');
errorCode = Util.ConvertStringToInt32(tokens[0]);
// it should always be 2
if (tokens.Length >= 2)
{
return tokens[1];
}
else
{
return "";
}
}
/// <summary>
/// Send the set channel command to the Eload module.
/// </summary>
private void SetChannel()
{
// not calling IOWrite so IOWrite can call this function each time
// no need to check for errors here since they are checked in IOWrite()/IOQuery()
string channelCommand = _CHAN + _channelNumber.ToString();
if (_serialPort != null)
{
_serialPort.WriteLine(channelCommand);
}
else
{
_gpibDevice.Write(channelCommand);
}
}
/// <summary>
/// Set the overcurrent protection value and verifies setting.
/// </summary>
/// <param name="overCurrentProtection">The overcurrent value.</param>
private void SetAndConfirmOverCurrentProtection(double overCurrentProtection)
{
string currentProtectionCommand = _CURRENT_PROTECTION + _overCurrentProtection.ToString();
IOWrite(currentProtectionCommand);
string currentProtectionEnableCommand = _CURRENT_PROTECTION_ENABLE;
IOWrite(currentProtectionEnableCommand);
var programmedOcp = ReadOverCurrentProtection().Amps;
if (programmedOcp != overCurrentProtection)
{
throw new Exception("Tried to set OCP to: " + overCurrentProtection.ToString() + ", but eload reports: " + programmedOcp.ToString());
}
}
/// <summary>
/// Set the overvoltage protection value and verifies setting.
/// </summary>
/// <param name="overVoltageProtection">The overvoltage value.</param>
private void SetAndConfirmOverVoltageProtection(double overVoltageProtection)
{
string voltageProtectionCommand = _VOLTAGE_PROTECTION + overVoltageProtection.ToString();
IOWrite(voltageProtectionCommand);
string voltageProtectionEnableCommand = _VOLTAGE_PROTECTION_ENABLE;
IOWrite(voltageProtectionEnableCommand);
var programmedOvp = ReadOverVoltageProtection().Volts;
if (programmedOvp != overVoltageProtection)
{
throw new Exception("Tried to set OVP to: " + overVoltageProtection.ToString() + ", but eload reports: " + programmedOvp.ToString());
}
}
#endregion
#region PublicFuctions
/// <summary>
/// ELoadScpiKeysight factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public ELoadScpiKeysight(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
_gpibDevice = null;
_serialPort = _configuration.GetConfigurationValue("ELoadScpiKeysight", "SerialPort", new SerialPort());
_channelNumber = _configuration.GetConfigurationValue("ELoadScpiKeysight", "ChannelNumber", 0);
_mode = _configuration.GetConfigurationValue("ELoadScpiKeysight", "Mode", EloadModuleMode.CURRENT);
_ini_mode = _configuration.GetConfigurationValue("ELoadScpiKeysight", "IniMode", EloadModuleMode.CURRENT);
_setpointVal = _configuration.GetConfigurationValue("ELoadScpiKeysight", "SetpointVal", 0.0);
_ini_setpointVal = _configuration.GetConfigurationValue("ELoadScpiKeysight", "IniSetpointVal", 0.0);
_overCurrentProtection = _configuration.GetConfigurationValue("ELoadScpiKeysight", "OverCurrentProtection", 0.0);
_overVoltageProtection = _configuration.GetConfigurationValue("ELoadScpiKeysight", "OverVoltageProtection", 0.0);
// make sure it is off
Disable();
// set mode
SetMode(_mode);
// set the setpoint
SetSetpoint(_setpointVal, _mode);
//set OCP
SetAndConfirmOverCurrentProtection(_overCurrentProtection);
}
/// <summary>
/// The constructor for an Eload.
/// </summary>
/// <param name="serialPort">The interface to the Eload instrument.</param>
/// <param name="channelNumber">The channel number for the Eload module.</param>
/// <param name="mode">The operating mode of this Eload module.</param>
/// <param name="setpointVal">The setpoint value of the Eload module. Depends on operation mode.</param>
/// <param name="overCurrentProtection">The overcurrent protection value.</param>
public ELoadScpiKeysight(SerialPort serialPort, int channelNumber, EloadModuleMode mode, double setpointVal, double overCurrentProtection, double overVoltageProtection)
{
_gpibDevice = null;
_serialPort = serialPort;
_channelNumber = channelNumber;
_mode = mode;
_ini_mode = mode;
_setpointVal = setpointVal;
_ini_setpointVal = setpointVal;
_overCurrentProtection = overCurrentProtection;
_overVoltageProtection = overVoltageProtection;
_logger = LogManager.GetCurrentClassLogger();
// make sure it is off
Disable();
// set mode
SetMode(mode);
// set the setpoint
SetSetpoint(setpointVal, mode);
//set OCP
SetAndConfirmOverCurrentProtection(_overCurrentProtection);
}
/// <summary>
///
/// </summary>
/// <param name="gpibDevice"></param>
/// <param name="channelNumber"></param>
/// <param name="mode"></param>
/// <param name="setpointVal"></param>
/// <param name="overCurrentProtection"></param>
/// <param name="overVoltageProtection"></param>
public ELoadScpiKeysight(Device gpibDevice, int channelNumber, EloadModuleMode mode, double setpointVal, double overCurrentProtection, double overVoltageProtection)
{
_serialPort = null;
_gpibDevice = gpibDevice;
_channelNumber = channelNumber;
_mode = mode;
_ini_mode = mode;
_setpointVal = setpointVal;
_ini_setpointVal = setpointVal;
_overCurrentProtection = overCurrentProtection;
_overVoltageProtection = overVoltageProtection;
// make sure it is off
Disable();
// set mode
SetMode(mode);
// set the setpoint
SetSetpoint(setpointVal, mode);
//set OCP
SetAndConfirmOverCurrentProtection(_overCurrentProtection);
}
/// <summary>
/// The finalizer.
/// </summary>
~ELoadScpiKeysight()
{
Dispose(false);
}
/// <summary>
/// Dispose of this object's resources.
/// </summary>
public void Dispose()
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
/// <summary>
/// Query if the Eload module input is on.
/// </summary>
/// <returns>Status of Eload. True = On, False = Off.</returns>
public bool IsInputOn()
{
string readCommand = _INPUTONQUERY;
string rsp = IOQuery(readCommand);
if (rsp == "0")
{
return false;
}
else
{
return true;
}
}
/// <summary>
/// Send a SCPI Command to the instrument and get a response.
/// </summary>
/// <param name="commandString">The command to send.</param>
/// <returns>THe instrument response.</returns>
public string IOQuery(string commandString)
{
// not calling IOWrite() so IOWrite() can check for errors after each write
SetChannel();
string rsp = "";
if (_serialPort != null)
{
_serialPort.WriteLine(commandString);
rsp = _serialPort.ReadLine();
}
else
{
_gpibDevice.Write(commandString);
rsp = _gpibDevice.ReadString();
}
rsp = rsp.Replace("\r", "");
// check for errors
int err = 0;
string errorMsg = GetErrorCode(out err);
if (err != 0)
{
throw new Exception(errorMsg);
}
return rsp;
}
/// <summary>
/// Send a SCPI Command to the instrument.
/// </summary>
/// <param name="commandString">The command to be send.</param>
public void IOWrite(string commandString)
{
SetChannel();
if (_serialPort != null)
{
_serialPort.WriteLine(commandString);
}
else
{
_gpibDevice.Write(commandString);
}
// check for errors
int err = 0;
string errorMsg = GetErrorCode(out err);
if (err != 0)
{
throw new Exception(errorMsg);
}
}
/// <summary>
/// Turn off the Eload module.
/// </summary>
public void Disable()
{
IOWrite(_INPUTOFF);
}
/// <summary>
/// Turn on the Eload module.
/// </summary>
public void Enable()
{
IOWrite(_INPUTON);
}
/// <summary>
/// Reads the current of the Eload module.
/// </summary>
/// <returns>The current (Amps)</returns>
public Current ReadCurrent()
{
string readCommand = _CURRENT_QUERY;
string rsp = IOQuery(readCommand);
double ret = Util.ConvertStringToDouble(rsp);
return Current.FromAmps(ret);
}
/// <summary>
/// Reads the mode of the Eload module.
/// </summary>
/// <returns>The mode.</returns>
public EloadModuleMode ReadMode()
{
string readCommand = _MODE_QUERY;
string ret = Convert.ToString(IOQuery(readCommand));
var mode = EloadModuleMode.RESISTANCE;
// will ger RES, CURR, or VOLT(tbd)
if (EloadModuleMode.CURRENT.ToString().Contains(ret) == true)
{
mode = EloadModuleMode.CURRENT;
}
else if (EloadModuleMode.RESISTANCE.ToString().Contains(ret) == true)
{
mode = EloadModuleMode.RESISTANCE;
}
else if (EloadModuleMode.VOLTAGE.ToString().Contains(ret) == true)
{
mode = EloadModuleMode.VOLTAGE;
}
else
{
throw new Exception("Unknown return from load: " + ret);
}
return mode;
}
/// <summary>
/// Reads the overcurrent setting from an Eload module.
/// </summary>
/// <returns>The current (Amps).</returns>
public Current ReadOverCurrentProtection()
{
string currentProtectionCommand = _CURRENT_PROTECTION_QUERY;
string rsp = IOQuery(currentProtectionCommand);
double ret = Util.ConvertStringToDouble(rsp);
return Current.FromAmps(ret);
}
/// <summary>
/// Reads the overvoltage setting from an Eload module.
/// </summary>
/// <returns>The voltage (Volts).</returns>
public Voltage ReadOverVoltageProtection()
{
string voltageProtectionCommand = _VOLTAGE_PROTECTION_QUERY;
string rsp = IOQuery(voltageProtectionCommand);
double ret = Util.ConvertStringToDouble(rsp);
return Voltage.FromVolts(ret);
}
/// <summary>
/// Query the Eload module for the resistance.
/// </summary>
/// <returns>The resistance (Ohms).</returns>
public Resistance ReadResistance()
{
string readCommand = _READRESISTANCEQUERY;
string rsp = IOQuery(readCommand);
double ret = Util.ConvertStringToDouble(rsp);
return Resistance.FromOhms(ret);
}
/// <summary>
/// Queries the Eload module for the setpoint value. Depends on operation mode.
/// </summary>
/// <returns>The setpoint value.</returns>
public double ReadSetpoint()
{
string readCommand = "";
if (_mode == EloadModuleMode.CURRENT)
{
readCommand = _CURRENT_SETPOINT_QUERY;
}
else if (_mode == EloadModuleMode.RESISTANCE)
{
readCommand = _READRESISTANCEQUERY;
}
else if (_mode == EloadModuleMode.VOLTAGE)
{
throw new Exception("voltage mode not supported");
}
else
{
throw new Exception("Unknown mode: " + _mode.ToString());
}
string rsp = IOQuery(readCommand);
double ret = Util.ConvertStringToDouble(rsp);
return ret;
}
/// <summary>
/// Query the Eload module for the voltage.
/// </summary>
/// <returns>The voltage (Volts).</returns>
public Voltage ReadVoltage()
{
string readCommand = _READVOLTAGEQUERY;
string rsp = IOQuery(readCommand);
double ret = Util.ConvertStringToDouble(rsp);
return Voltage.FromVolts(ret);
}
/// <summary>
/// Reads the overvoltage setting from an Eload module.
/// </summary>
/// <returns>The voltage (Volts).</returns>
public ushort ReadProtectionStatus()
{
string ProtectionStatusCommand = _PROTECTION_STATUS_QUERY;
string rsp = IOQuery(ProtectionStatusCommand);
ushort ret = Util.ConvertStringToUInt16(rsp);
return ret;
}
/// <summary>
/// Resets the eload setpoint and mode to config file values
/// </summary>
public void SetInitialSetting()
{
SetMode(_ini_mode);
SetSetpoint(_ini_setpointVal, _ini_mode);
}
/// <summary>
/// Change the mode for the Eload module.
/// </summary>
/// <param name="mode">The desired Eload module mode.</param>
public void SetMode(EloadModuleMode mode)
{
//make sure it is off
Disable();
string command = "";
string fixedCommand = "";
if (mode == EloadModuleMode.CURRENT)
{
command = _CURRENT_MODE;
fixedCommand = _CURRENT_MODE_FIXED;
}
else if (mode == EloadModuleMode.RESISTANCE)
{
command = _RESISTANCE_MODE;
fixedCommand = _RESISTANCE_MODE_FIXED;
}
else if (mode == EloadModuleMode.VOLTAGE)
{
throw new Exception("Voltage mode is not yet supported");
}
else
{
throw new Exception("unsupported mode: " + mode.ToString());
}
IOWrite(command);
IOWrite(fixedCommand);
_mode = mode;
}
/// <summary>
/// Change the setpoint and operation mode of the Eload module.
/// </summary>
/// <param name="newSetpoint">The new setpoint.</param>
/// <param name="mode">The new mode.</param>
public void SetSetpoint(double newSetpoint, EloadModuleMode mode)
{
if (mode != _mode)
{
throw new Exception("the current mode and the specified mode do not match. Current Mode: " + _mode.ToString() + ", specified mode: " + mode.ToString());
}
string rangeCommand = "";
string command = "";
if (_mode == EloadModuleMode.CURRENT)
{
if (newSetpoint > _overCurrentProtection)
{
throw new Exception("the setpoint " + newSetpoint + "is outside the limit");
}
rangeCommand = _CURRENT_RANGE + newSetpoint.ToString();
command = _CURRENT + newSetpoint.ToString();
}
else if (_mode == EloadModuleMode.RESISTANCE)
{
if (newSetpoint <= 0)
{
throw new Exception("Invalid resistance: " + newSetpoint.ToString());
}
//i = v/r
double tempVoltage = ReadVoltage().Volts;
// if voltage is not 0, we will confirm that resulting current is within range.
// Having Abs() to ensure to cover both +/- voltage cases if there is any.
if (Math.Abs(tempVoltage) > 1)
{
//calculate the resulting current
double tempCurrent = Math.Abs(tempVoltage) / newSetpoint;
if (tempCurrent > _overCurrentProtection)
{
throw new Exception("the setpoint " + newSetpoint + "is outside the limit");
}
}
rangeCommand = _RESISTANCE_RANGE + newSetpoint.ToString();
command = _RESISTANCE + newSetpoint.ToString();
}
else if (_mode == EloadModuleMode.VOLTAGE)
{
throw new Exception("voltage mode not supported");
}
else
{
throw new Exception("Unknown mode: " + _mode.ToString());
}
IOWrite(rangeCommand);
IOWrite(command);
// update our member now that everything checks out
_setpointVal = newSetpoint;
}
public bool ClearErrors()
{
return true;
}
public void Initialize()
{
}
public SelfTestResult PerformSelfTest()
{
throw new NotImplementedException();
}
public void Reset()
{
Disable();
Enable();
}
public void Shutdown()
{
Dispose();
}
#endregion
}
}

View File

@@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.ELoadScpiKeysight</AssemblyName>
<Product>ELoad Scpi Keysight implementation</Product>
<Description>ELoad Scpi Keysight implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Instruments.ELoad.Contracts" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ELoadSim\ELoadSim.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="NationalInstruments.NI4882">
<HintPath>..\..\Common\COTS\NI\NationalInstruments.NI4882.dll</HintPath>
</Reference>
</ItemGroup>
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
<Target Name="CopyFiles" AfterTargets="AfterBuild">
<ItemGroup>
<FILES_1 Include="$(OutDir)*.dll" />
<FILES_2 Include="$(OutDir)*.pdb" />
</ItemGroup>
<Copy SourceFiles="@(FILES_1)" DestinationFolder="$(HalTempFolder)" />
<Copy SourceFiles="@(FILES_2)" DestinationFolder="$(HalTempFolder)" />
</Target>
</Project>

View File

@@ -0,0 +1,139 @@
// **********************************************************************************************************
// ELoadScpiKeysightFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "ELoadScpiKeysightFactory")]
public class ELoadScpiKeysightFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public ELoadScpiKeysightFactory(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 ELoadScpiKeysightFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IEload));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new ELoadScpiKeysight(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new EloadSim(name, _configurationManager, _logger);
else
return new ELoadScpiKeysight(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,388 @@
// 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.Threading;
using NLog;
using Raytheon.Common;
using Raytheon.Units;
namespace Raytheon.Instruments
{
/// <summary>
/// A simulated eload
/// </summary>
public class EloadSim : IEload
{
#region PrivateClassMembers
private readonly double _overCurrentProtection;
private readonly double _overVoltageProtection;
private double _setpointVal;
private double _ini_setpointval;
private double _voltage;
private readonly int _channelNumber;
private bool _isOn;
private EloadModuleMode _mode;
private EloadModuleMode _originalMode;
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
public string DetailedStatus { get; protected set; }
public bool DisplayEnabled { get; set; }
public bool FrontPanelEnabled { get; set; }
public InstrumentMetadata Info { get; set; }
public string Name { get; protected set; }
public SelfTestResult SelfTestResult => PerformSelfTest();
public State Status { get; set; }
#endregion
#region PublicFuctions
/// <summary>
/// FlowMeterOmegaDPF20 factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public EloadSim(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
const double SETPOINT_VOLTAGE = 28.0;
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
_channelNumber = _configuration.GetConfigurationValue("EloadSim", "ChannelNumber", 0);
_mode = _configuration.GetConfigurationValue("EloadSim", "Mode", EloadModuleMode.CURRENT);
_setpointVal = _configuration.GetConfigurationValue("EloadSim", "SetpointVal", 0.0);
_ini_setpointval = _configuration.GetConfigurationValue("EloadSim", "IniSetpointVal", 0.0);
_overCurrentProtection = _configuration.GetConfigurationValue("EloadSim", "OverCurrentProtection", 0.0);
_overVoltageProtection = _configuration.GetConfigurationValue("EloadSim", "OverVoltageProtection", 0.0);
_voltage = SETPOINT_VOLTAGE;
_originalMode = _mode;
// make sure it is off
Disable();
}
/// <summary>
/// The constructor for an Eload (Simulation).
/// </summary>
/// <param name="channelNumber">The channel number for the Eload.</param>
/// <param name="mode">The operation mode of the channel. Modes: Resistance, Voltage, Current.</param>
/// <param name="setpointVal">The operation point of the load. This can be a voltage, current, or resistance.</param>
/// <param name="overCurrentProtection">Overcurrent setpoint that will turn off the channel if exceeded.</param>
/// <param name="overVoltageProtection">Overvoltage setpoint that will turn off channel if exceeded (double check).</param>
public EloadSim(int channelNumber, EloadModuleMode mode, double setpointVal, double overCurrentProtection, double overVoltageProtection)
{
const double SETPOINT_VOLTAGE = 28.0;
_logger = LogManager.GetCurrentClassLogger();
_channelNumber = channelNumber;
_setpointVal = setpointVal;
_ini_setpointval = setpointVal;
_overCurrentProtection = overCurrentProtection;
_overVoltageProtection = overVoltageProtection;
_voltage = SETPOINT_VOLTAGE;
_mode = mode;
_originalMode = mode;
Disable();
}
/// <summary>
/// The finalizer.
/// </summary>
~EloadSim()
{
Dispose(false);
}
/// <summary>
/// Dispose of this object's resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Send a SCPI Command to the instrument and get a response.
/// </summary>
/// <param name="commandString">The command to send.</param>
/// <returns>THe instrument response.</returns>
public string IOQuery(string commandString)
{
// just to provide a small delay 10ms for the sim
Thread.Sleep(10);
return "IOQuery Sim Response";
}
/// <summary>
/// Send a SCPI Command to the instrument.
/// </summary>
/// <param name="commandString">The command to be send.</param>
public void IOWrite(string commandString)
{
// just to provide a small delay 10ms for the sim
Thread.Sleep(10);
}
/// <summary>
/// Query if the Eload input is on (simulated).
/// </summary>
/// <returns>Status of Eload (simulated). True = On, False = Off.</returns>
public bool IsInputOn()
{
return _isOn;
}
/// <summary>
/// Turns the Eload off (simulated).
/// </summary>
public void Enable()
{
_isOn = false;
}
/// <summary>
/// Turns the Eload on (simulated).
/// </summary>
public void Disable()
{
_isOn = true;
}
/// <summary>
/// Reads the current of the Eload.
/// </summary>
/// <returns>The current (simulated).</returns>
public Current ReadCurrent()
{
const double MIN_CURRENT = 1.0;
// just to provide a small delay 10ms for the sim
Thread.Sleep(10);
double currentToReturn = 0.0;
if (_isOn)
{
double maxCurrent = _overCurrentProtection;
Random rnd = new Random();
double seed = rnd.NextDouble();
currentToReturn = (seed * (maxCurrent - MIN_CURRENT)) + MIN_CURRENT;
}
return Current.FromAmps(currentToReturn);
}
/// <summary>
/// Reads the mode of the Eload.
/// </summary>
/// <returns>The mode (simulated).</returns>
public EloadModuleMode ReadMode()
{
return _mode;
}
/// <summary>
/// Reads the overcurrent setting from an Eload.
/// </summary>
/// <returns>Overcurrent setting (simulated).</returns>
public Current ReadOverCurrentProtection()
{
// just to provide a small delay 10ms for the sim
Thread.Sleep(10);
return Current.FromAmps(_overCurrentProtection);
}
/// <summary>
/// Reads the overvoltage setting from an Eload.
/// </summary>
/// <returns>Overvoltage setting (simulated).</returns>
public Voltage ReadOverVoltageProtection()
{
// just to provide a small delay 10ms for the sim
Thread.Sleep(10);
return Voltage.FromVolts(_overVoltageProtection);
}
/// <summary>
/// Reads the resistance of the Eload.
/// </summary>
/// <returns>The resistance (simulated).</returns>
public Resistance ReadResistance()
{
// just to provide a small delay 10ms for the sim
Thread.Sleep(10);
double resistanceToReturn = 0.0;
if (_isOn)
{
double maxCurrent = _setpointVal + 1;
double minCurrent = _setpointVal - 1;
Random rnd = new Random();
double seed = rnd.NextDouble();
resistanceToReturn = (seed * (maxCurrent - minCurrent)) + minCurrent;
}
return Resistance.FromOhms(resistanceToReturn);
}
/// <summary>
/// Reads the setpoint of the Eload.
/// </summary>
/// <returns>The setpoint (simulated).</returns>
public double ReadSetpoint()
{
return _setpointVal;
}
/// <summary>
/// Reads the voltage of the Eload.
/// </summary>
/// <returns>The voltage (simulated).</returns>
public Voltage ReadVoltage()
{
// just to provide a small delay 10ms for the sim
Thread.Sleep(10);
double voltageToReturn = 0.0;
if (_isOn)
{
double maxVoltage = _voltage + 1;
double minVoltage = _voltage - 1;
Random rnd = new Random();
double seed = rnd.NextDouble();
voltageToReturn = (seed * (maxVoltage - minVoltage)) + minVoltage;
}
return Voltage.FromVolts(voltageToReturn);
}
/// <summary>
/// Reads the protection status from an Eload.
/// </summary>
/// <returns>Protection status (simulated).</returns>
public ushort ReadProtectionStatus()
{
// just to provide a small delay 10ms for the sim
Thread.Sleep(10);
// The sim never triggers the protection status
return 0;
}
/// <summary>
/// Sets Initial Settings
/// </summary>
public void SetInitialSetting()
{
_mode = _originalMode;
_setpointVal = _ini_setpointval;
}
/// <summary>
/// Change the operation mode of the Eload.
/// </summary>
/// <param name="mode">The desired Eload mode.</param>
public void SetMode(EloadModuleMode mode)
{
_mode = mode;
}
/// <summary>
/// Change the setpoint of the Eload.
/// </summary>
/// <param name="newSetpoint">The desired setpoint of the Eload.</param>
public void SetSetpoint(double newSetpoint, EloadModuleMode mode)
{
if (mode != _mode)
{
throw new Exception("the current mode and the specified mode do not match. Current Mode: " + _mode.ToString() + ", specified mode: " + mode.ToString());
}
_setpointVal = newSetpoint;
}
/// <summary>
/// Dispose of this object's resources.
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
}
public bool ClearErrors()
{
return true;
}
public void Initialize()
{
SetInitialSetting();
}
public SelfTestResult PerformSelfTest()
{
throw new NotImplementedException();
}
public void Reset()
{
Disable();
Enable();
}
public void Shutdown()
{
Dispose();
}
#endregion
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.ELoadSim</AssemblyName>
<Product>ELoad Sim implementation</Product>
<Description>ELoad Sim implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
<PackageReference Include="Raytheon.Instruments.ELoad.Contracts" Version="1.1.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,136 @@
// **********************************************************************************************************
// ELoadSimFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "ELoadSimFactory")]
public class ELoadSimFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public ELoadSimFactory(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 ELoadSimFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IEload));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new EloadSim(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
return new EloadSim(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,973 @@
// 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 NationalInstruments.NI4882;
using NLog;
using Raytheon.Common;
using Raytheon.Units;
using System;
using System.Collections.Generic;
using System.IO.Ports;
namespace Raytheon.Instruments
{
/// <summary>
/// This class interfaces to a Keysight N3300 Eload system
/// </summary>
public class EloadSystemScpiKeysight : IELoadSystem
{
#region PrivateClassMembers
private enum ControlInterface
{
COM_PORT,
GPIB
}
// system commands
private const string _CLEAREVENTREG = "*CLS";
private const string _CLEARSERVICEREQUEST = "*SRE 0";
private const string _CLEAREVENTSTATUSENABLEREGISTER = "*ESE 0";
private const string _ERRORCODE = "SYST:ERR?";
private const string _RESET = "*RST";
private const string _SELFTEST = "*TST?";
private string _systemName;
private SerialPort _serialPort;
private Device _gpibDevice;
private ControlInterface _interface;
private readonly SortedDictionary<string, IEload> _eloadChannelMap;
private readonly bool _isThereHardware;
private static object _syncObj = new Object();
// default the timeout for responses to 5 seconds
private const int _READ_TIMEOUT = 5000;
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
public string DetailedStatus { get; protected set; }
public bool DisplayEnabled { get; set; }
public bool FrontPanelEnabled { get; set; }
public InstrumentMetadata Info { get; set; }
public string Name { get; protected set; }
public SelfTestResult SelfTestResult => PerformSelfTest();
public State Status { get; set; }
#endregion
#region PrivateFuctions
/// <summary>
/// Send a SCPI Command to the instrument and get a response.
/// </summary>
/// <param name="commandString">The command to send.</param>
/// <returns>The instrument response.</returns>
private string IOQuery(string commandString)
{
// not calling IOWrite() so IOWrite() can check for errors after each write
string rsp = "";
if (_interface == ControlInterface.COM_PORT)
{
_serialPort.WriteLine(commandString);
rsp = _serialPort.ReadLine();
}
else if (_interface == ControlInterface.GPIB)
{
_gpibDevice.Write(commandString);
rsp = _gpibDevice.ReadString();
}
else
{
throw new Exception("unknown interface type: " + _interface.ToString());
}
rsp = rsp.Replace("\r", "");
// check for errors
int err = 0;
string errorMsg = GetErrorCode(out err);
if (err != 0)
{
throw new Exception(errorMsg);
}
return rsp;
}
/// <summary>
/// Sends a SCPI Command to the instrument.
/// </summary>
/// <param name="commandString">The command to send.</param>
private void IOWrite(string commandString)
{
if (_interface == ControlInterface.COM_PORT)
{
_serialPort.WriteLine(commandString);
}
else if (_interface == ControlInterface.GPIB)
{
_gpibDevice.Write(commandString);
}
else
{
throw new Exception("unknown interface type: " + _interface.ToString());
}
int err = 0;
string errorMsg = GetErrorCode(out err);
if (err != 0)
{
throw new Exception(errorMsg);
}
}
/// <summary>
/// Resets the instrument and clears event registers, error queue,
/// service request enable register, and event status enable register.
/// </summary>
private void Reset()
{
IOWrite(_RESET);
IOWrite(_CLEAREVENTREG);
IOWrite(_CLEARSERVICEREQUEST);
IOWrite(_CLEAREVENTSTATUSENABLEREGISTER);
}
#endregion
#region PublicFuctions
/// <summary>
/// FlowMeterOmegaDPF20 factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public EloadSystemScpiKeysight(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
_gpibDevice = null;
_serialPort = _configuration.GetConfigurationValue("ELoadScpiKeysight", "SerialPort", new SerialPort());
var flowControl = _configuration.GetConfigurationValue("ELoadScpiKeysight", "FlowControl", Handshake.None);
try
{
_interface = ControlInterface.COM_PORT;
_systemName = Name;
_serialPort.Open();
_serialPort.ReadTimeout = _READ_TIMEOUT;
_serialPort.Handshake = flowControl;
Reset();
_eloadChannelMap = new SortedDictionary<string, IEload>(StringComparer.InvariantCultureIgnoreCase);
}
catch (Exception)
{
if (_serialPort.IsOpen == true)
{
_serialPort.Close();
}
throw;
}
}
/// <summary>
/// The constructor for com port interface which open up the comm port, resets the system and waits for additional commands
/// </summary>
/// <param name="comPortName">The COM port name as it exists in windows device manager.</param>
/// <param name="baudRate">The bit rate of the host computer COM port.</param>
/// <param name="parity">The parity setting of the host computer. 0 = None, 1 = Odd, 2 = Even, 3 = Mark, 4 = Space.</param>
/// <param name="dataBits">The number of bits of data sent per transfer.</param>
/// <param name="stopBits">The number of stop bits used by host computer.</param>
/// <param name ="flowControl">Handshake method. 0 = None, 1 = XonXoff, 2 = RTS, 3 = RTSXonXoff.</param>
/// <param name="isThereHardware">Software operation mode. True = Hardware available, False = Simulation Only.</param>
public EloadSystemScpiKeysight(string systemName, string comPortName, int baudRate, Parity parity, int dataBits, StopBits stopBits, Handshake flowControl, bool isThereHardware)
{
try
{
_logger = LogManager.GetCurrentClassLogger();
_interface = ControlInterface.COM_PORT;
_systemName = systemName;
_isThereHardware = isThereHardware;
_serialPort = null;
_gpibDevice = null;
if (_isThereHardware == true)
{
_serialPort = new SerialPort(comPortName, baudRate, parity, dataBits, stopBits);
_serialPort.Open();
_serialPort.ReadTimeout = _READ_TIMEOUT;
_serialPort.Handshake = flowControl;
Reset();
}
_eloadChannelMap = new SortedDictionary<string, IEload>(StringComparer.InvariantCultureIgnoreCase);
}
catch (Exception ex)
{
if (_serialPort.IsOpen == true)
{
_serialPort.Close();
}
_logger.Error(ex.Message);
throw;
}
}
/// <summary>
/// The constructor for gpib interface which open up the comm port, resets the system and waits for additional commands
/// </summary>
/// <param name="systemName"></param>
/// <param name="boardNumber"></param>
/// <param name="primaryAddress"></param>
/// <param name="isThereHardware"></param>
public EloadSystemScpiKeysight(string systemName, int boardNumber, byte primaryAddress, bool isThereHardware)
{
try
{
_interface = ControlInterface.GPIB;
_systemName = systemName;
_isThereHardware = isThereHardware;
_serialPort = null;
_gpibDevice = null;
if (_isThereHardware == true)
{
_gpibDevice = new Device(boardNumber, primaryAddress);
//@@@ TBD if this make the newline go out after each write
_gpibDevice.EndOfStringCharacter = 0xa;
_gpibDevice.IOTimeout = TimeoutValue.T3s;
Reset();
}
_eloadChannelMap = new SortedDictionary<string, IEload>(StringComparer.InvariantCultureIgnoreCase);
}
catch (Exception)
{
if (_gpibDevice != null)
{
_gpibDevice.Dispose();
_gpibDevice = null;
}
throw;
}
}
/// <summary>
/// The finalizer
/// </summary>
~EloadSystemScpiKeysight()
{
Dispose(false);
}
/// <summary>
/// Add an Eload to the system.
/// </summary>
/// <param name="name">The name of the channel (module) for reference.</param>
/// <param name="channelNumber">The channel number for the Eload..</param>
/// <param name="mode">The operation mode of the channel. Modes: Resistance, Voltage, Current.</param>
/// <param name="setpoint">The operation point of the load. This can be a voltage, current, or resistance</param>
/// <param name="overCurrentProtection">Overcurrent setpoint that will turn off the channel if exceeded.</param>
/// <param name="overVoltageProtection">Overvoltage setpoint that will turn off channel if exceeded (double check).</param>
public void AddEloadChannel(string name, int channelNumber, EloadModuleMode mode, double setpoint, Current overCurrentProtection, Voltage overVoltageProtection)
{
try
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(name.ToUpper()) == true)
{
throw new Exception("system already contains a module named: " + name.ToUpper());
}
IEload eload;
if (_isThereHardware)
{
if (_interface == ControlInterface.COM_PORT)
{
eload = new ELoadScpiKeysight(_serialPort, channelNumber, mode, setpoint, overCurrentProtection.Amps, overVoltageProtection.Volts);
}
else if (_interface == ControlInterface.GPIB)
{
eload = new ELoadScpiKeysight(_gpibDevice, channelNumber, mode, setpoint, overCurrentProtection.Amps, overVoltageProtection.Volts);
}
else
{
throw new Exception("unknown interface: " + _interface.ToString());
}
}
else
{
eload = new EloadSim(channelNumber, mode, setpoint, overCurrentProtection.Amps, overVoltageProtection.Volts);
}
_eloadChannelMap.Add(name.ToUpper(), eload);
}
}
catch (Exception)
{
if (_interface == ControlInterface.COM_PORT)
{
_serialPort.Close();
}
else if (_interface == ControlInterface.GPIB)
{
_gpibDevice.Dispose();
_gpibDevice = null;
}
throw;
}
}
/// <summary>
/// Dispose of this object's resources.
/// </summary>
public void Dispose()
{
try
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
/// <summary>
/// Get the error code.
/// </summary>
/// <returns>The error code.</returns>
public string GetErrorCode(out int errorCode)
{
lock (_syncObj)
{
if (_isThereHardware == true)
{
// not calling IOQuery() here so IOQuery() can call GetErrorCode() after each query
string rsp = "";
if (_interface == ControlInterface.COM_PORT)
{
_serialPort.WriteLine(_ERRORCODE);
rsp = _serialPort.ReadLine();
}
else if (_interface == ControlInterface.GPIB)
{
_gpibDevice.Write(_ERRORCODE);
rsp = _gpibDevice.ReadString();
}
else
{
throw new Exception("unknown interface type: " + _interface.ToString());
}
rsp = rsp.Replace("\r", "");
string[] tokens = rsp.Split(',');
errorCode = Util.ConvertStringToInt32(tokens[0]);
// it should always be 2
if (tokens.Length >= 2)
{
return tokens[1];
}
else
{
return "";
}
}
else
{
errorCode = 0;
return "";
}
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<string> GetModuleNames()
{
lock (_syncObj)
{
List<string> moduleNames = new List<string>();
foreach (KeyValuePair<string, IEload> modules in _eloadChannelMap)
{
moduleNames.Add(modules.Key);
}
return moduleNames;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public string GetSystemName()
{
lock (_syncObj)
{
return _systemName;
}
}
/// <summary>
/// Query if the Eload input is on.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <returns>Status of Eload. True = On, False = Off.</returns>
public bool IsInputOn(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
bool status = _eloadChannelMap[channelName.ToUpper()].IsInputOn();
return status;
}
}
/// <summary>
/// Turn off the Eload input.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
public void Disable(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
_eloadChannelMap[channelName.ToUpper()].Disable();
}
}
/// <summary>
/// Turn on the Eload input.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
public void Enable(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
_eloadChannelMap[channelName.ToUpper()].Enable();
}
}
/// <summary>
///
/// </summary>
/// <param name="channelName"></param>
/// <param name="command"></param>
/// <returns></returns>
public string IOQuery(string channelName, string command)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
return _eloadChannelMap[channelName.ToUpper()].IOQuery(command);
}
}
/// <summary>
///
/// </summary>
/// <param name="channelName"></param>
/// <param name="command"></param>
public void IOWrite(string channelName, string command)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
_eloadChannelMap[channelName.ToUpper()].IOWrite(command);
}
}
/// <summary>
/// Reads the current of the Eload.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <returns>Measured current (Amps).</returns>
public Current ReadCurrent(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
var value = _eloadChannelMap[channelName.ToUpper()].ReadCurrent();
return value;
}
}
/// <summary>
/// Reads all Eload data (voltage, current, resistance, setpoint, input state, mode).
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <param name="voltage">The measured voltage (Volts).</param>
/// <param name="current">The measured current (Amps).</param>
/// <param name="resistance">The measured resistance (Ohms).</param>
/// <param name="setpoint">The setpoint of the Eload. Depends on mode of operation.</param>
/// <param name="isInputOn">The state of the Eload.</param>
/// <param name="mode">The mode of the Eload.</param>
public void ReadData(string channelName, out Voltage voltage, out Current current, out Resistance resistance, out double setpoint, out bool isInputOn, out EloadModuleMode mode, out ushort status)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
voltage = _eloadChannelMap[channelName.ToUpper()].ReadVoltage();
current = _eloadChannelMap[channelName.ToUpper()].ReadCurrent();
resistance = _eloadChannelMap[channelName.ToUpper()].ReadResistance();
setpoint = _eloadChannelMap[channelName.ToUpper()].ReadSetpoint();
isInputOn = _eloadChannelMap[channelName.ToUpper()].IsInputOn();
mode = _eloadChannelMap[channelName.ToUpper()].ReadMode();
status = _eloadChannelMap[channelName.ToUpper()].ReadProtectionStatus();
}
}
/// <summary>
/// Reads the mode of the Eload
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <returns>The mode</returns>
public EloadModuleMode ReadMode(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
EloadModuleMode value = _eloadChannelMap[channelName.ToUpper()].ReadMode();
return value;
}
}
/// <summary>
/// Reads the overcurrent setting from an Eload.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <returns>Overcurrent setting (Amps).</returns>
public Current ReadOverCurrentProtection(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
var value = _eloadChannelMap[channelName.ToUpper()].ReadOverCurrentProtection();
return value;
}
}
/// <summary>
/// Reads the overvoltage setting from an Eload.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <returns>Overvoltage setting (Volts).</returns>
public Voltage ReadOverVoltageProtection(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
var value = _eloadChannelMap[channelName.ToUpper()].ReadOverVoltageProtection();
return value;
}
}
/// <summary>
/// Read the resistance.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <returns>The resistance (Ohms).</returns>
public Resistance ReadResistance(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
var value = _eloadChannelMap[channelName.ToUpper()].ReadResistance();
return value;
}
}
/// <summary>
/// Reads the setpoint of the Eload.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <returns>The setpoint. Depends on mode.</returns>
public double ReadSetpoint(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
return _eloadChannelMap[channelName.ToUpper()].ReadSetpoint();
}
}
/// <summary>
/// Reads the voltage of the Eload.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <returns>The voltage (Volts)</returns>
public Voltage ReadVoltage(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
var value = _eloadChannelMap[channelName.ToUpper()].ReadVoltage();
return value;
}
}
/// <summary>
/// Reads the protection status from an Eload.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <returns>Protection status register.</returns>
public ushort ReadProtectionStatus(string channelName)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
ushort value = _eloadChannelMap[channelName.ToUpper()].ReadProtectionStatus();
return value;
}
}
/// <summary>
/// Run a self-test.
/// </summary>
public void Selftest()
{
try
{
// change the timeout to account for the long self test to 30 seconds
if (_interface == ControlInterface.COM_PORT)
{
//@@@ is this the right time?
_serialPort.ReadTimeout = 30000;
}
else if (_interface == ControlInterface.GPIB)
{
//@@@ TBD
}
else
{
throw new Exception("unknown interface type: " + _interface.ToString());
}
// send the command
string rspStr = IOQuery(_SELFTEST);
// parse the response
string[] tokens = rspStr.Split('\n');
int rsp = Util.ConvertStringToInt32(tokens[0]);
if (rsp != 0)
{
string errorMsg = "returned an error: " + rsp.ToString();
throw new Exception(errorMsg);
}
}
catch (Exception)
{
throw;
}
finally
{
// restore the timeout
if (_interface == ControlInterface.COM_PORT)
{
_serialPort.ReadTimeout = _READ_TIMEOUT;
}
else if (_interface == ControlInterface.GPIB)
{
//@@@ TBD
}
else
{
throw new Exception("unknown interface type: " + _interface.ToString());
}
}
}
/// <summary>
/// Resets all channels to config file values
/// </summary>
public void SetInitialSetting(string module)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(module.ToUpper()) == false)
{
throw new Exception("could not find load: " + module.ToUpper());
}
_eloadChannelMap[module.ToUpper()].SetInitialSetting();
}
}
/// <summary>
/// Resets all channels to config file values
/// </summary>
public void SetInitialSettingAll()
{
lock (_syncObj)
{
foreach (KeyValuePair<String, IEload> eload in _eloadChannelMap)
{
_eloadChannelMap[eload.Key].SetInitialSetting();
}
}
}
/// <summary>
/// Change the operation mode of the Eload.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <param name="mode">The desired Eload mode.</param>
public void SetMode(string channelName, EloadModuleMode mode)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
_eloadChannelMap[channelName.ToUpper()].SetMode(mode);
}
}
/// <summary>
/// Change the setpoint and operation mode of the Eload.
/// </summary>
/// <param name="channelName">The name of the Eload.</param>
/// <param name="newSetpoint">The desired setpoint of the Eload.</param>
/// <param name="mode">The desired Eload mode.</param>
public void SetSetpoint(string channelName, double newSetpoint, EloadModuleMode mode)
{
lock (_syncObj)
{
if (_eloadChannelMap.ContainsKey(channelName.ToUpper()) == false)
{
throw new Exception("could not find module: " + channelName.ToUpper());
}
_eloadChannelMap[channelName.ToUpper()].SetSetpoint(newSetpoint, mode);
}
}
/// <summary>
/// Dispose of this objects resources
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
try
{
lock (_syncObj)
{
if (disposing)
{
foreach (KeyValuePair<string, IEload> entry in _eloadChannelMap)
{
entry.Value.Shutdown();
}
if (_serialPort != null)
{
Reset();
_serialPort.Dispose();
_serialPort = null;
}
if (_gpibDevice != null)
{
Reset();
_gpibDevice.Dispose();
_gpibDevice = null;
}
}
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
public bool ClearErrors()
{
throw new NotImplementedException();
}
public void Initialize()
{
throw new NotImplementedException();
}
public SelfTestResult PerformSelfTest()
{
throw new NotImplementedException();
}
void IInstrument.Reset()
{
throw new NotImplementedException();
}
public void Shutdown()
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)Solution.props" />
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.EloadSystemScpiKeysight</AssemblyName>
<Product>Eload System Scpi Keysight implementation</Product>
<Description>Eload System Scpi Keysight implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->
<!-- Disable the line below for dynamic versioning -->
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0" />
<PackageReference Include="Raytheon.Instruments.ELoadSystem.Contracts" Version="1.1.0" />
<PackageReference Include="Raytheon.Instruments.ELoad.Contracts" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ELoadScpiKeysight\ELoadScpiKeysight.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="NationalInstruments.NI4882">
<HintPath>..\..\Common\COTS\NI\NationalInstruments.NI4882.dll</HintPath>
</Reference>
</ItemGroup>
<!-- Copy all *.dlls and *.pdb in the output folder to a temp folder -->
<Target Name="CopyFiles" AfterTargets="AfterBuild">
<ItemGroup>
<FILES_1 Include="$(OutDir)*.dll" />
<FILES_2 Include="$(OutDir)*.pdb" />
</ItemGroup>
<Copy SourceFiles="@(FILES_1)" DestinationFolder="$(HalTempFolder)" />
<Copy SourceFiles="@(FILES_2)" DestinationFolder="$(HalTempFolder)" />
</Target>
</Project>

View File

@@ -0,0 +1,277 @@
// **********************************************************************************************************
// EloadSystemScpiKeysightFactory.cs
// 2/20/2023
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using Raytheon.Units;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.IO.Ports;
using System.Reflection;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "EloadSystemScpiKeysightFactory")]
public class EloadSystemScpiKeysightFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
public EloadSystemScpiKeysightFactory(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 EloadSystemScpiKeysightFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IEload));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new EloadSystemScpiKeysight(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetInstrument(string name, bool simulateHw)
{
try
{
_logger = LogManager.GetLogger(name);
return new EloadSystemScpiKeysight(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets supported interfaces
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
#region PrivateFuctions
/// <summary>
/// Parses the power controller ini file.
/// This ini file defines the number of power systems/modules that this controller will manage.
/// Upon parsing the file, this function populates this class members with the ini file information
/// </summary>
private static IELoadSystem CreateEloadSystemInstrument(string instrumentDefFile, string iniSectionName, bool isThereHardware)
{
const char COMMA_DELIM = ',';
// interface types
const string GPIB = "GPIB";
const string RS232 = "232";
// system
const string BOARD_NUMBER_KEY = "BOARD_NUMBER";
const string INTERFACE_KEY = "INTERFACE";
const string ADDRESS_KEY = "ADDRESS";
const string BAUD_RATE = "BAUD_RATE";
const string PARITY = "PARITY";
const string DATA_BITS = "DATA_BITS";
const string STOP_BITS = "STOP_BITS";
const string FLOW_CONTROL = "FLOW_CONTROL";
const string MODULE_DEFINITION_KEY = "MODULE_DEFINITION";
// modules
const string MODE = "MODE";
const string CHANNEL_NUM = "CHANNEL_NUM";
const string SETPOINT_VALUE = "SETPOINT_VALUE";
const string OCP = "OVER_CURRENT_PROTECTION";
const string OVP = "OVER_VOLTAGE_PROTECTION";
IniFile iniReader = new IniFile(instrumentDefFile);
// pull out the address and the list of definitions
string interfaceType = iniReader.ReadValue(iniSectionName, INTERFACE_KEY);
string[] moduleDefinitionList = null;
IELoadSystem loadSystem = null;
if (interfaceType.ToUpper() == GPIB)
{
int gpibBoardNumber = Convert.ToInt32(iniReader.ReadValue(iniSectionName, BOARD_NUMBER_KEY));
byte gpibAddress = Convert.ToByte(iniReader.ReadValue(iniSectionName, ADDRESS_KEY));
string moduleDefinitionSections = iniReader.ReadValue(iniSectionName, MODULE_DEFINITION_KEY);
moduleDefinitionList = moduleDefinitionSections.Split(COMMA_DELIM);
loadSystem = new EloadSystemScpiKeysight(iniSectionName, gpibBoardNumber, gpibAddress, isThereHardware);
}
else if (interfaceType.ToUpper() == RS232)
{
string eloadSystemComAddress = iniReader.ReadValue(iniSectionName, ADDRESS_KEY);
int eloadSystemComBaudRate = Convert.ToInt32(iniReader.ReadValue(iniSectionName, BAUD_RATE));
Parity eloadSystemComParity = (Parity)Enum.Parse(typeof(Parity), iniReader.ReadValue(iniSectionName, PARITY));
int eloadSystemComDataBits = Convert.ToInt32(iniReader.ReadValue(iniSectionName, DATA_BITS));
Handshake flowControl = (Handshake)Enum.Parse(typeof(Handshake), iniReader.ReadValue(iniSectionName, FLOW_CONTROL));
StopBits eloadSystemComStopBits = (StopBits)Enum.Parse(typeof(StopBits), iniReader.ReadValue(iniSectionName, STOP_BITS));
string moduleDefinitionSections = iniReader.ReadValue(iniSectionName, MODULE_DEFINITION_KEY);
moduleDefinitionList = moduleDefinitionSections.Split(COMMA_DELIM);
loadSystem = new EloadSystemScpiKeysight(iniSectionName, eloadSystemComAddress, eloadSystemComBaudRate, eloadSystemComParity, eloadSystemComDataBits, eloadSystemComStopBits, flowControl, isThereHardware);
}
else
{
throw new Exception("EloadMeasurementInstruments::CreateEloadSystemInstrument() - Invalid Interface type in ini file. Ini file contained: " + interfaceType + ", supported types are: " + GPIB + "," + RS232);
}
foreach (string module in moduleDefinitionList)
{
string trimmedModuleName = module.TrimStart(' ');
trimmedModuleName = trimmedModuleName.TrimEnd(' ');
int modeTemp = Convert.ToInt32(iniReader.ReadValue(trimmedModuleName, MODE));
int channelNumber = Convert.ToInt32(iniReader.ReadValue(trimmedModuleName, CHANNEL_NUM));
double setpoint = Convert.ToDouble(iniReader.ReadValue(trimmedModuleName, SETPOINT_VALUE));
double ocp = Convert.ToDouble(iniReader.ReadValue(trimmedModuleName, OCP));
double ovp = Convert.ToDouble(iniReader.ReadValue(trimmedModuleName, OVP));
EloadModuleMode mode;
if (modeTemp == 0)
{
mode = EloadModuleMode.RESISTANCE;
}
else if (modeTemp == 1)
{
mode = EloadModuleMode.VOLTAGE;
}
else if (modeTemp == 2)
{
mode = EloadModuleMode.CURRENT;
}
else
{
throw new Exception("EloadMeasurementInstruments::CreateEloadSystemInstrument() - Invalid mode input: " + modeTemp.ToString());
}
loadSystem.AddEloadChannel(trimmedModuleName.ToUpper(), channelNumber, mode, setpoint, Current.FromAmps(ocp), Voltage.FromVolts(ovp));
}
return loadSystem;
}
#endregion
#region PublicFuctions
public static List<IELoadSystem> CreateEloadSystemInstrument(string instrumentDefFile, bool isThereHardware)
{
const string KEYSIGHT_ELOAD_SCPI = "KEYSIGHT_SCPI_ELOAD_SYSTEM";
List<IELoadSystem> loadSystemsToReturn = new List<IELoadSystem>();
IniFile iniReader = new IniFile(instrumentDefFile);
List<string> loadSystemsToCreateKeys = iniReader.ReadAllKeys("ELOAD_SYSTEMS_TO_CREATE");
foreach (string loadSystemName in loadSystemsToCreateKeys)
{
string loadSystemType = iniReader.ReadValue("ELOAD_SYSTEMS_TO_CREATE", loadSystemName);
if (loadSystemType.ToUpper() == KEYSIGHT_ELOAD_SCPI.ToUpper())
{
IELoadSystem loadSystem = CreateEloadSystemInstrument(instrumentDefFile, loadSystemName, isThereHardware);
loadSystemsToReturn.Add(loadSystem);
}
else
{
string errorMsg = "EloadMeasurementInstruments::CreateEloadSystemInstrument() - Unsupported ELoad instrument: " + loadSystemName + "\n";
errorMsg += "Supported instrument are: " + KEYSIGHT_ELOAD_SCPI;
throw new Exception(errorMsg);
}
}
return loadSystemsToReturn;
}
#endregion
}
}