My improved version of PowerSupply and TcpClient implementation
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="$(SolutionDir)Solution.props" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AssemblyName>Raytheon.Instruments.PowerSupplies.Keysight67XX</AssemblyName>
|
||||||
|
<Product>Keysight 67XX Series Power Supply</Product>
|
||||||
|
<Description>Keysight 67XX Series Power Supply</Description>
|
||||||
|
|
||||||
|
<!-- 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" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\TcpClient\TcpClient.csproj" />
|
||||||
|
<ProjectReference Include="..\PowerSupplySim\PowerSupplySim.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
// UNCLASSIFIED
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||||
|
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||||
|
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||||
|
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||||
|
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||||
|
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||||
|
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||||
|
COMPANY.
|
||||||
|
|
||||||
|
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||||
|
GOVERNMENT.
|
||||||
|
|
||||||
|
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
using NLog;
|
||||||
|
using Raytheon.Common;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.Composition;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Raytheon.Instruments.PowerSupplies
|
||||||
|
{
|
||||||
|
[ExportInstrumentFactory(ModelNumber = "PowerSupplyKeysightN67xxFactory")]
|
||||||
|
public class KeysightN67xxPowerFactory : IInstrumentFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The supported interfaces
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||||
|
private static ILogger _logger;
|
||||||
|
private readonly IConfigurationManager _configurationManager;
|
||||||
|
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||||
|
private static string DefaultPath;
|
||||||
|
|
||||||
|
public KeysightN67xxPowerFactory(string defaultConfigPath = DefaultConfigPath)
|
||||||
|
: this(null, defaultConfigPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// COECommDeviceInstrumentFactory injection constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="configManager"></param>
|
||||||
|
/// <param name="simEngine"></param>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
[ImportingConstructor]
|
||||||
|
public KeysightN67xxPowerFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||||
|
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||||
|
{
|
||||||
|
DefaultPath = defaultConfigPath;
|
||||||
|
_logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
if (NLog.LogManager.Configuration == null)
|
||||||
|
{
|
||||||
|
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||||
|
NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||||
|
}
|
||||||
|
|
||||||
|
_configurationManager = configManager ?? GetConfigurationManager();
|
||||||
|
_supportedInterfaces.Add(typeof(PowerSupply));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the instrument
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IInstrument GetInstrument(string name)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the instrument
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public object GetInstrument(string name, bool simulateHw)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (simulateHw)
|
||||||
|
return new PowerSupplySim(name, _configurationManager, _logger);
|
||||||
|
else
|
||||||
|
return new KeysightN67xxPowerSupply(name, _configurationManager, _logger);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, $"Unable to construct {name} instrument instance");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets supported interfaces
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ICollection<Type> GetSupportedInterfaces()
|
||||||
|
{
|
||||||
|
return _supportedInterfaces.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// returns confiuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static IConfigurationManager GetConfigurationManager()
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,662 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
// 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());
|
||||||
|
int port = 0;
|
||||||
|
Int32.TryParse(_config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.ETHERNET_PORT.ToString()), out port);
|
||||||
|
string moduleDef = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.MODULE_DEFINITION.ToString());
|
||||||
|
string coupledModules = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.COUPLED_MODULES.ToString());
|
||||||
|
string groupedModules = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.GROUPED_MODULES.ToString());
|
||||||
|
|
||||||
|
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());
|
||||||
|
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.OCP.ToString()), out ocp);
|
||||||
|
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.OVP.ToString()), out ovp);
|
||||||
|
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SETPOINT.ToString()), out voltageSetPoint);
|
||||||
|
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SLEW_RATE.ToString()), out voltageSlewRate);
|
||||||
|
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_VOLTAGE.ToString()), out minVoltage);
|
||||||
|
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_VOLTAGE.ToString()), out maxVoltage);
|
||||||
|
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_CURRENT.ToString()), out minCurrent);
|
||||||
|
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_CURRENT.ToString()), 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
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
coupleListToDefine += moduleNumber;
|
||||||
|
|
||||||
|
// add a ',' if this is not the final element in the list
|
||||||
|
if (i < moduleList.Count() - 1)
|
||||||
|
{
|
||||||
|
coupleListToDefine += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coupleListToDefine += "\n";
|
||||||
|
|
||||||
|
// see if channels are grouped
|
||||||
|
string queryCoupleChannelCommand = KeysightPowerSupplyScpiCommands.QUERY_COUPLE_CHANNELS + "\n";
|
||||||
|
|
||||||
|
for (int i = 1; i <= 2; i++)
|
||||||
|
{
|
||||||
|
string respStr = SendCommandAndGetResponse(queryCoupleChannelCommand);
|
||||||
|
|
||||||
|
string queryCoupleStateCommand = KeysightPowerSupplyScpiCommands.QUERY_COUPLE_STATE + "\n";
|
||||||
|
string respStr2 = SendCommandAndGetResponse(queryCoupleStateCommand);
|
||||||
|
|
||||||
|
if (coupleListToDefine != respStr || respStr2 == "0\n")
|
||||||
|
{
|
||||||
|
// send command to couple modules
|
||||||
|
string command = KeysightPowerSupplyScpiCommands.SET_COUPLE_CHANNELS_CMD + " " + coupleListToDefine;
|
||||||
|
SendCommand(command);
|
||||||
|
|
||||||
|
// turn coupling on
|
||||||
|
command = KeysightPowerSupplyScpiCommands.SET_COUPLE_ON_CMD + "\n";
|
||||||
|
SendCommand(command);
|
||||||
|
|
||||||
|
// output protection on
|
||||||
|
command = KeysightPowerSupplyScpiCommands.SET_COUPLE_OUTPUT_PROTECT_ON_CMD + "\n";
|
||||||
|
SendCommand(command);
|
||||||
|
}
|
||||||
|
else if (i == 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset Power Supply System
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private void ResetPowerSupplySystem()
|
||||||
|
{
|
||||||
|
// send the command
|
||||||
|
string command = KeysightPowerSupplyScpiCommands.RESET_CMD + "\n";
|
||||||
|
SendCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send command
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private void SendCommand(string command)
|
||||||
|
{
|
||||||
|
lock (SyncObj)
|
||||||
|
{
|
||||||
|
byte[] msg = Encoding.ASCII.GetBytes(command);
|
||||||
|
|
||||||
|
_tcpClient.Write(msg, (uint)msg.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send command and get response
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string SendCommandAndGetResponse(string command)
|
||||||
|
{
|
||||||
|
lock (SyncObj)
|
||||||
|
{
|
||||||
|
byte[] readBuf = new byte[100];
|
||||||
|
_tcpClient.SetReadTimeout(2000);
|
||||||
|
|
||||||
|
int bytesRec = 0;
|
||||||
|
|
||||||
|
SendCommand(command);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bytesRec = (int)_tcpClient.Read(ref readBuf);
|
||||||
|
}
|
||||||
|
catch (SocketException ex)
|
||||||
|
{
|
||||||
|
throw new Exception("SocketException Error Code: " + ex.ErrorCode + $" ({((SocketError)ex.ErrorCode).ToString()})");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Encoding.ASCII.GetString(readBuf, 0, bytesRec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
// 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.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using NLog;
|
||||||
|
using Raytheon.Common;
|
||||||
|
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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
|
||||||
|
{
|
||||||
|
string powerDeviceName = String.Empty;
|
||||||
|
|
||||||
|
if (powerDeviceId != null && (powerDeviceId.GetType().IsEnum || powerDeviceId is string))
|
||||||
|
{
|
||||||
|
powerDeviceName = powerDeviceId.ToString();
|
||||||
|
}
|
||||||
|
else if (powerDeviceId != null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"{nameof(powerDeviceId)} must be null or enumerated or string type");
|
||||||
|
}
|
||||||
|
|
||||||
|
_powerSupplyModule.GetSemphamore().WaitOne();
|
||||||
|
|
||||||
|
if (powerDeviceId != null)
|
||||||
|
_powerSupplyModule.SetActivePowerModule(powerDeviceName);
|
||||||
|
|
||||||
|
return _powerSupplyModule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Group or couple modules as specified in config file
|
||||||
|
/// Gather information for each power module from config file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
_powerSupplyModule = new KeysightN67xxPowerModule(_iniFilePath, Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
// UNCLASSIFIED
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||||
|
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||||
|
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||||
|
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||||
|
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||||
|
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||||
|
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||||
|
COMPANY.
|
||||||
|
|
||||||
|
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||||
|
GOVERNMENT.
|
||||||
|
|
||||||
|
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Raytheon.Instruments.PowerSupplies
|
||||||
|
{
|
||||||
|
public static class KeysightPowerSupplyScpiCommands
|
||||||
|
{
|
||||||
|
public static string CLEAR_CMD = "*CLS";
|
||||||
|
public static string RESET_CMD = "*RST";
|
||||||
|
public static string SELFTEST_CMD = "*TST?";
|
||||||
|
public static string READ_ERROR_CODE_CMD = "SYST:ERR?";
|
||||||
|
public static string REBOOT_CMD = "SYST:REB";
|
||||||
|
|
||||||
|
// panel disable/enable commands
|
||||||
|
public static string SET_FRONTPANEL_DISABLE_CMD = "SYST:COMM:RLST RWL";
|
||||||
|
public static string SET_FRONTPANEL_ENABLE_CMD = "SYST:COMM:RLST REM";
|
||||||
|
|
||||||
|
// watchdog commands
|
||||||
|
public static string SET_WATCHDOGDELAY_CMD = "OUTP:PROT:WDOG:DEL";
|
||||||
|
public static string SET_WATCHDOGON_CMD = "OUTP:PROT:WDOG ON";
|
||||||
|
public static string SET_WATCHDOGOFF_CMD = "OUTP:PROT:WDOG OFF";
|
||||||
|
|
||||||
|
// coupling commands
|
||||||
|
public static string SET_COUPLE_CHANNELS_CMD = "OUTP:COUP:CHAN";
|
||||||
|
public static string SET_COUPLE_ON_CMD = "OUTP:COUP ON";
|
||||||
|
public static string SET_COUPLE_OUTPUT_PROTECT_ON_CMD = "OUTP:PROT:COUP ON";
|
||||||
|
public static string QUERY_COUPLE_CHANNELS = "OUTP:COUP:CHAN?";
|
||||||
|
public static string QUERY_COUPLE_STATE = "OUTP:COUP?";
|
||||||
|
|
||||||
|
// Grouping Commands
|
||||||
|
public static string SET_GROUP_DEFINE_CMD = "SYST:GRO:DEF";
|
||||||
|
public static string UNGROUP_ALL_CHANNELS_CMD = "SYST:GRO:DEL:ALL";
|
||||||
|
public static string QUERY_GROUP_CHANNELS = "SYST:GRO:CAT?";
|
||||||
|
|
||||||
|
// current commands
|
||||||
|
public static string SET_OCP_CMD = "CURR:LEV";
|
||||||
|
public static string SET_OCP_ON_CMD = "CURR:PROT:STAT ON";
|
||||||
|
public static string READ_CURRENT_CMD = "MEAS:CURR?";
|
||||||
|
public static string READ_OCP_CMD = "CURR:LEV?";
|
||||||
|
|
||||||
|
// voltage commands
|
||||||
|
public static string SET_OVP_CMD = "VOLT:PROT";
|
||||||
|
public static string SET_VOLTAGE_SLEW_RATE_CMD = "VOLT:SLEW";
|
||||||
|
public static string SET_VOLTAGE_SETPOINT_CMD = "VOLT:LEV";
|
||||||
|
public static string SET_CONSTANT_VOLTAGE_CMD = "STAT:OPER:ENAB 1";
|
||||||
|
public static string READ_VOLTAGE_CMD = "MEAS:VOLT?";
|
||||||
|
public static string READ_VOLTAGE_SETPOINT_CMD = "VOLT?";
|
||||||
|
public static string READ_OVP_CMD = "VOLT:PROT?";
|
||||||
|
public static string READ_VOLTAGE_SLEW_RATE_CMD = "VOLT:SLEW?";
|
||||||
|
|
||||||
|
// set output commands
|
||||||
|
public static string SET_OUTPUT_DISABLE_CMD = "OUTP OFF";
|
||||||
|
public static string SET_OUTPUT_ENABLE_CMD = "OUTP ON";
|
||||||
|
|
||||||
|
//query status
|
||||||
|
public static string READ_OUTPUT_STATUS_CMD = "OUTP?";
|
||||||
|
public static string READ_ERROR_STATUS_CMD = "SYST:ERR?";
|
||||||
|
public static string READ_PROTECTION_STATUS_CMD = "STAT:QUES:COND?";
|
||||||
|
}
|
||||||
|
}
|
||||||
63
Source/DucLib/PowerSupplies/PowerSupplyBasic/PowerSupply.cs
Normal file
63
Source/DucLib/PowerSupplies/PowerSupplyBasic/PowerSupply.cs
Normal 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get power supply module names
|
||||||
|
/// </summary>
|
||||||
|
/// <param></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<string> GetPowerSupplyModuleNames()
|
||||||
|
{
|
||||||
|
return _powerSupplyModule.PowerModules;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<Import Project="$(SolutionDir)Solution.props" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AssemblyName>Raytheon.Instruments.PowerSupplyBasic</AssemblyName>
|
||||||
|
<Description>PowerSupply Basic</Description>
|
||||||
|
<Product>PowerSupply Basic</Product>
|
||||||
|
|
||||||
|
<Version>1.1.0.0</Version>
|
||||||
|
</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.6.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
// 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 List<string> PowerModules { get; protected set; }
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
private 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
voltageLowerLimit_ = -1.0;
|
||||||
|
voltageUpperLimit_ = -1.0;
|
||||||
|
currentLowerLimit_ = -1.0;
|
||||||
|
currentUpperLimit_ = -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;
|
||||||
|
voltageLowerLimit_ = minVoltage;
|
||||||
|
voltageUpperLimit_ = maxVoltage;
|
||||||
|
currentLowerLimit_ = minCurrent;
|
||||||
|
currentUpperLimit_ = maxCurrent;
|
||||||
|
isOn_ = false;
|
||||||
|
faultStatus = -1;
|
||||||
|
|
||||||
|
moduleNameFormat = "(@" + moduleIndex + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string moduleNameFormat;
|
||||||
|
public double overCurrentProtection_;
|
||||||
|
public double overVoltageProtection_;
|
||||||
|
public double voltageLowerLimit_;
|
||||||
|
public double voltageUpperLimit_;
|
||||||
|
public double currentLowerLimit_;
|
||||||
|
public double currentUpperLimit_;
|
||||||
|
public double voltageSetpoint_;
|
||||||
|
public double voltageSlewRate_;
|
||||||
|
public bool isOn_;
|
||||||
|
public int faultStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
// 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 NLog;
|
||||||
|
using Raytheon.Common;
|
||||||
|
|
||||||
|
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());
|
||||||
|
string coupledModules = config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.COUPLED_MODULES.ToString());
|
||||||
|
string groupedModules = config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.GROUPED_MODULES.ToString());
|
||||||
|
|
||||||
|
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());
|
||||||
|
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.OCP.ToString()), out ocp);
|
||||||
|
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.OVP.ToString()), out ovp);
|
||||||
|
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SETPOINT.ToString()), out voltageSetPoint);
|
||||||
|
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SLEW_RATE.ToString()), out voltageSlewRate);
|
||||||
|
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_VOLTAGE.ToString()), out minVoltage);
|
||||||
|
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_VOLTAGE.ToString()), out maxVoltage);
|
||||||
|
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_CURRENT.ToString()), out minCurrent);
|
||||||
|
Double.TryParse(config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_CURRENT.ToString()), 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
|
||||||
|
{
|
||||||
|
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].currentLowerLimit_ + PowerModuleInfoDict[ActivePowerModule].currentUpperLimit_) / 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 "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
119
Source/DucLib/PowerSupplies/PowerSupplySim/PowerSupplySim.cs
Normal file
119
Source/DucLib/PowerSupplies/PowerSupplySim/PowerSupplySim.cs
Normal 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 System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using NLog;
|
||||||
|
using Raytheon.Common;
|
||||||
|
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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
|
||||||
|
{
|
||||||
|
string powerDeviceName = String.Empty;
|
||||||
|
|
||||||
|
if (powerDeviceId != null && (powerDeviceId.GetType().IsEnum || powerDeviceId is string))
|
||||||
|
{
|
||||||
|
powerDeviceName = powerDeviceId.ToString();
|
||||||
|
}
|
||||||
|
else if (powerDeviceId != null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"{nameof(powerDeviceId)} must be null or enumerated or string type");
|
||||||
|
}
|
||||||
|
|
||||||
|
_powerSupplyModule.GetSemphamore().WaitOne();
|
||||||
|
|
||||||
|
if (powerDeviceId != null)
|
||||||
|
_powerSupplyModule.SetActivePowerModule(powerDeviceName);
|
||||||
|
|
||||||
|
return _powerSupplyModule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="$(SolutionDir)Solution.props" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AssemblyName>Raytheon.Instruments.PowerSupplies.Simulation</AssemblyName>
|
||||||
|
<Product>Power Supply Simulation</Product>
|
||||||
|
<Description>Power Supply Simulation</Description>
|
||||||
|
|
||||||
|
<!-- 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.Common" Version="1.0.0" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<PackageReference Include="Raytheon.Instruments.PowerSupply.Contracts" Version="1.1.0" />
|
||||||
|
-->
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PowerSupplyBasic\PowerSupplyBasic.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
// UNCLASSIFIED
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||||
|
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||||
|
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||||
|
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||||
|
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||||
|
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||||
|
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||||
|
COMPANY.
|
||||||
|
|
||||||
|
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||||
|
GOVERNMENT.
|
||||||
|
|
||||||
|
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
using NLog;
|
||||||
|
using Raytheon.Common;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.Composition;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Raytheon.Instruments.PowerSupplies
|
||||||
|
{
|
||||||
|
[ExportInstrumentFactory(ModelNumber = "PowerSupplySimulationFactory")]
|
||||||
|
public class PowerSupplySimulationFactory : IInstrumentFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The supported interfaces
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||||
|
private static ILogger _logger;
|
||||||
|
private readonly IConfigurationManager _configurationManager;
|
||||||
|
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||||
|
private static string DefaultPath;
|
||||||
|
|
||||||
|
public PowerSupplySimulationFactory(string defaultConfigPath = DefaultConfigPath)
|
||||||
|
: this(null, defaultConfigPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// COECommDeviceInstrumentFactory injection constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="configManager"></param>
|
||||||
|
/// <param name="simEngine"></param>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
[ImportingConstructor]
|
||||||
|
public PowerSupplySimulationFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||||
|
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||||
|
{
|
||||||
|
DefaultPath = defaultConfigPath;
|
||||||
|
_logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
if (NLog.LogManager.Configuration == null)
|
||||||
|
{
|
||||||
|
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||||
|
NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||||
|
}
|
||||||
|
|
||||||
|
_configurationManager = configManager ?? GetConfigurationManager();
|
||||||
|
_supportedInterfaces.Add(typeof(PowerSupply));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the instrument
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IInstrument GetInstrument(string name)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the instrument
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public object GetInstrument(string name, bool simulateHw)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new PowerSupplySim(name, _configurationManager, _logger);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, $"Unable to construct {name} instrument instance");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets supported interfaces
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ICollection<Type> GetSupportedInterfaces()
|
||||||
|
{
|
||||||
|
return _supportedInterfaces.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// returns confiuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static IConfigurationManager GetConfigurationManager()
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
226
Source/DucLib/TcpClient/TcpClient.cs
Normal file
226
Source/DucLib/TcpClient/TcpClient.cs
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
// 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.Net;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Raytheon.Instruments.EthernetSockets
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class for controlling a TCP client communication device
|
||||||
|
/// </summary>
|
||||||
|
public class TcpClient
|
||||||
|
{
|
||||||
|
#region PrivateClassMembers
|
||||||
|
|
||||||
|
private Socket _sock;
|
||||||
|
private string _remoteAddress;
|
||||||
|
private int _remotePort;
|
||||||
|
private IPEndPoint _remoteEP = null;
|
||||||
|
private IPAddress _ipAddress = null;
|
||||||
|
private object _syncObj = new object();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Functions
|
||||||
|
|
||||||
|
/// <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
|
||||||
|
}
|
||||||
|
}
|
||||||
21
Source/DucLib/TcpClient/TcpClient.csproj
Normal file
21
Source/DucLib/TcpClient/TcpClient.csproj
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="$(SolutionDir)Solution.props" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AssemblyName>TcpClient</AssemblyName>
|
||||||
|
<Product>TCP Client implementation</Product>
|
||||||
|
<Description>TCP Client implementation</Description>
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||||
|
|
||||||
|
<!-- 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>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -362,6 +362,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerSupplyMeasurementManag
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Program", "Program\Program.csproj", "{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Program", "Program\Program.csproj", "{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DucLib", "DucLib", "{F20B097A-6283-426E-A9B5-D71E498E4A78}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpClient", "DucLib\TcpClient\TcpClient.csproj", "{4D2E2A24-9FD4-49C9-8448-F7006ED790B8}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeysightN67XX", "DucLib\PowerSupplies\Keysight67XX\KeysightN67XX.csproj", "{CCD1C6AA-2C4E-40E1-8233-20875B5833D3}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerSupplySim", "DucLib\PowerSupplies\PowerSupplySim\PowerSupplySim.csproj", "{059FF15F-D78A-4727-BA84-16836EB9F2DF}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerSupplyBasic", "DucLib\PowerSupplies\PowerSupplyBasic\PowerSupplyBasic.csproj", "{675101BD-867F-4268-838B-F1E673B9007A}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PowerSupplies", "PowerSupplies", "{C2277D2F-C982-420A-AD8D-82452A83793B}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -1071,6 +1083,30 @@ Global
|
|||||||
{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
|
{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
|
||||||
{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4D2E2A24-9FD4-49C9-8448-F7006ED790B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4D2E2A24-9FD4-49C9-8448-F7006ED790B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4D2E2A24-9FD4-49C9-8448-F7006ED790B8}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
|
||||||
|
{4D2E2A24-9FD4-49C9-8448-F7006ED790B8}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
|
||||||
|
{4D2E2A24-9FD4-49C9-8448-F7006ED790B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4D2E2A24-9FD4-49C9-8448-F7006ED790B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{CCD1C6AA-2C4E-40E1-8233-20875B5833D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{CCD1C6AA-2C4E-40E1-8233-20875B5833D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{CCD1C6AA-2C4E-40E1-8233-20875B5833D3}.Deploy|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{CCD1C6AA-2C4E-40E1-8233-20875B5833D3}.Deploy|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{CCD1C6AA-2C4E-40E1-8233-20875B5833D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{CCD1C6AA-2C4E-40E1-8233-20875B5833D3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{059FF15F-D78A-4727-BA84-16836EB9F2DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{059FF15F-D78A-4727-BA84-16836EB9F2DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{059FF15F-D78A-4727-BA84-16836EB9F2DF}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
|
||||||
|
{059FF15F-D78A-4727-BA84-16836EB9F2DF}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
|
||||||
|
{059FF15F-D78A-4727-BA84-16836EB9F2DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{059FF15F-D78A-4727-BA84-16836EB9F2DF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{675101BD-867F-4268-838B-F1E673B9007A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{675101BD-867F-4268-838B-F1E673B9007A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{675101BD-867F-4268-838B-F1E673B9007A}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
|
||||||
|
{675101BD-867F-4268-838B-F1E673B9007A}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
|
||||||
|
{675101BD-867F-4268-838B-F1E673B9007A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{675101BD-867F-4268-838B-F1E673B9007A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -1223,6 +1259,11 @@ Global
|
|||||||
{9BE7316F-AA0D-46C5-9AC4-1038697884A0} = {22A60CBA-5ADA-47C6-95B4-EAEC014EC878}
|
{9BE7316F-AA0D-46C5-9AC4-1038697884A0} = {22A60CBA-5ADA-47C6-95B4-EAEC014EC878}
|
||||||
{C402EA41-F756-4270-946C-D3DC4E1BAEB5} = {CE2D75B9-FC4A-41C6-84B8-AD838A70C1FF}
|
{C402EA41-F756-4270-946C-D3DC4E1BAEB5} = {CE2D75B9-FC4A-41C6-84B8-AD838A70C1FF}
|
||||||
{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A} = {4D2003A8-CBCB-498C-9186-355650A84D41}
|
{FAFB2DB1-AF3A-4F78-8BBB-124C51C4D62A} = {4D2003A8-CBCB-498C-9186-355650A84D41}
|
||||||
|
{4D2E2A24-9FD4-49C9-8448-F7006ED790B8} = {F20B097A-6283-426E-A9B5-D71E498E4A78}
|
||||||
|
{CCD1C6AA-2C4E-40E1-8233-20875B5833D3} = {C2277D2F-C982-420A-AD8D-82452A83793B}
|
||||||
|
{059FF15F-D78A-4727-BA84-16836EB9F2DF} = {C2277D2F-C982-420A-AD8D-82452A83793B}
|
||||||
|
{675101BD-867F-4268-838B-F1E673B9007A} = {C2277D2F-C982-420A-AD8D-82452A83793B}
|
||||||
|
{C2277D2F-C982-420A-AD8D-82452A83793B} = {F20B097A-6283-426E-A9B5-D71E498E4A78}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {CA9C7EC5-FDF7-444C-99C8-7BDBE8AF4EDB}
|
SolutionGuid = {CA9C7EC5-FDF7-444C-99C8-7BDBE8AF4EDB}
|
||||||
|
|||||||
Reference in New Issue
Block a user