Big changes
This commit is contained in:
@@ -0,0 +1,780 @@
|
||||
// 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.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// Ignore Spelling: Selftest ovp ocp
|
||||
|
||||
using NLog;
|
||||
using Raytheon.Instruments;
|
||||
using Raytheon.Instruments.PowerSupply;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace MeasurementManagerLib
|
||||
{
|
||||
/// <summary>
|
||||
/// The entry point for the library that controls power supplies.
|
||||
/// This class parses out the definition of all power supplies in a system and provides control to the host.
|
||||
/// In simple cases, the host only needs to fill in the ini file and use the OutputDisable() and OutputEnable() functions.
|
||||
/// A variety of other capability is exposed for more complex applications.
|
||||
/// </summary>
|
||||
public class PowerSupplyMeasurementManager : IDisposable
|
||||
{
|
||||
#region PublicClassMembers
|
||||
/// <summary>
|
||||
/// A callback definition for the power monitor.
|
||||
/// The host may pass in this delegate to PowerLogStart() to receive callbacks from the monitor thread.
|
||||
/// </summary>
|
||||
/// <param name="retData">The callback returns a comma delimited string of the format: "System, Module, voltage, voltage setpoint, current, output status, fault status";</param>
|
||||
/// <param name="errorCode">If an exception is thrown in the monitor thread, this value will be set to -1, else it will be 0;</param>
|
||||
public delegate void PowerMonitorDelegate(List<PowerMonitorCallbackData> retData, int errorCode);
|
||||
|
||||
#endregion
|
||||
|
||||
#region PrivateClassMembers
|
||||
// power system name to power system object
|
||||
private SortedDictionary<string, IPowerSupplySystem> _powerSystemNameToObjectMap;
|
||||
|
||||
// power module name to power system object
|
||||
private SortedDictionary<string, IPowerSupplySystem> _powerModuleNameToObjectMap;
|
||||
private PowerSupplyDataLogWorker _dataLogWorker;
|
||||
private Thread _dataLogThread;
|
||||
|
||||
// these are used to remember the logging thread params if the host is loading new power def files
|
||||
string _prevPowerLogFileName;
|
||||
int _prevPowerLogRestTime;
|
||||
PowerMonitorDelegate _prevPowerLogCallback;
|
||||
|
||||
private static NLog.ILogger _logger;
|
||||
private IInstrumentManager _instrumentManager;
|
||||
|
||||
private string _powerSystemWithFailedSelfTest = String.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PublicFuctions
|
||||
|
||||
/// <summary>
|
||||
/// will create an array of power systems with power supplies
|
||||
/// </summary>
|
||||
/// <param name="instrumentManager"></param>
|
||||
/// <param name="powerSupplySystems"></param>
|
||||
public PowerSupplyMeasurementManager(IInstrumentManager instrumentManager)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_instrumentManager = instrumentManager;
|
||||
|
||||
_powerSystemNameToObjectMap = new SortedDictionary<string, IPowerSupplySystem>();
|
||||
|
||||
// create some maps to support the functions the MAL input
|
||||
_powerSystemNameToObjectMap = new SortedDictionary<string, IPowerSupplySystem>(StringComparer.InvariantCultureIgnoreCase);
|
||||
_powerModuleNameToObjectMap = new SortedDictionary<string, IPowerSupplySystem>(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
ICollection<object> powerSystemList = _instrumentManager.GetInstruments(typeof(IPowerSupplySystem));
|
||||
// populate the maps
|
||||
foreach (IPowerSupplySystem powerSystem in powerSystemList)
|
||||
{
|
||||
powerSystem.Initialize();
|
||||
_powerSystemNameToObjectMap[powerSystem.Name.ToUpper()] = powerSystem;
|
||||
|
||||
List<string> moduleNames = powerSystem.GetModuleNames();
|
||||
|
||||
foreach (string moduleName in moduleNames)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()))
|
||||
{
|
||||
throw new Exception("There is more than 1 power system that have the same module name: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()] = powerSystem;
|
||||
}
|
||||
}
|
||||
|
||||
PerformPowerSupplySelfTests();
|
||||
|
||||
if (_powerSystemWithFailedSelfTest != String.Empty)
|
||||
{
|
||||
throw new Exception($"{_powerSystemWithFailedSelfTest}'s self-test failed.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform self test on power supply system
|
||||
/// Self test for each power system takes a while, so we don't want to run self test every time we initialize the power system
|
||||
/// So we only want to run self test under 2 conditions:
|
||||
/// 1. Certain time has elapsed since last power off
|
||||
/// 2. Certain time has elapsed since last self test run ( in the absence of power off time)
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
private void PerformPowerSupplySelfTests()
|
||||
{
|
||||
_logger.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
|
||||
|
||||
string errorMsg = String.Empty;
|
||||
|
||||
ICollection<object> powerSystemList = _instrumentManager.GetInstruments(typeof(IPowerSupplySystem));
|
||||
|
||||
Task[] taskArray = new Task[powerSystemList.Count];
|
||||
|
||||
int index = 0;
|
||||
foreach (IPowerSupplySystem powerSystem in powerSystemList)
|
||||
{
|
||||
// perform self test on power system
|
||||
Task task = Task.Factory.StartNew(() => PerformPowerSupplySelfTestTask(powerSystem));
|
||||
taskArray.SetValue(task,index++);
|
||||
}
|
||||
|
||||
Task.WaitAll(taskArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform self test on power supply system
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
private void PerformPowerSupplySelfTestTask(IPowerSupplySystem powerSystem)
|
||||
{
|
||||
SelfTestResult result = SelfTestResult.Pass;
|
||||
|
||||
_logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() for {powerSystem.Name} is running...");
|
||||
|
||||
try
|
||||
{
|
||||
result = powerSystem.PerformSelfTest();
|
||||
|
||||
if (result == SelfTestResult.Fail && String.IsNullOrEmpty(_powerSystemWithFailedSelfTest))
|
||||
{
|
||||
_powerSystemWithFailedSelfTest = powerSystem.Name;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.Error(ex.Message + "\n" + ex.StackTrace);
|
||||
}
|
||||
|
||||
_logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() for {powerSystem.Name} is exiting...");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable the power supply display interface.
|
||||
/// </summary>
|
||||
/// <param name="powerSystem">The name of the system to disable, as defined in the config file</param>
|
||||
public void DisplayDisable(string powerSystem)
|
||||
{
|
||||
if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find power system: " + powerSystem);
|
||||
}
|
||||
|
||||
_powerSystemNameToObjectMap[powerSystem.ToUpper()].DisplayEnabled = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable the power supply display interface.
|
||||
/// </summary>
|
||||
/// <param name="powerSystem">The name of the system to disable, as defined in the config file</param>
|
||||
public void DisplayEnable(string powerSystem)
|
||||
{
|
||||
if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find power system: " + powerSystem);
|
||||
}
|
||||
|
||||
_powerSystemNameToObjectMap[powerSystem.ToUpper()].DisplayEnabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this object.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
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 all of the power module names
|
||||
/// </summary>
|
||||
/// <returns>Array of the system/module names.</returns>
|
||||
public List<string> GetPowerModuleList()
|
||||
{
|
||||
List<string> powerModules = new List<string>();
|
||||
|
||||
foreach (KeyValuePair<string, IPowerSupplySystem> item in _powerModuleNameToObjectMap)
|
||||
{
|
||||
powerModules.Add(item.Key);
|
||||
}
|
||||
|
||||
return powerModules;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the power module names for a given system
|
||||
/// </summary>
|
||||
/// <returns>Array of the system/module names.</returns>
|
||||
public List<string> GetPowerSupplyList(string powerSystem)
|
||||
{
|
||||
if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Unknown power system: " + powerSystem);
|
||||
}
|
||||
|
||||
return _powerSystemNameToObjectMap[powerSystem.ToUpper()].GetModuleNames();
|
||||
}//GetPowerSupplyModuleInfoDict
|
||||
|
||||
/// <summary>
|
||||
/// Get the dictionary that contains configuration information for each module
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Dictionary<string, PowerSupplyModuleInfo> GetPowerSupplyModuleInfoDict(string powerSystem)
|
||||
{
|
||||
if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Unknown power system: " + powerSystem);
|
||||
}
|
||||
|
||||
return _powerSystemNameToObjectMap[powerSystem.ToUpper()].GetPowerSupplyModuleInfoDict(powerSystem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Power System names.
|
||||
/// </summary>
|
||||
/// <returns>Array of power system names, as defined in the config file</returns>
|
||||
public List<string> GetPowerSupplySystemList()
|
||||
{
|
||||
List<string> powerSystems = new List<string>();
|
||||
|
||||
foreach (KeyValuePair<string, IPowerSupplySystem> item in _powerSystemNameToObjectMap)
|
||||
{
|
||||
powerSystems.Add(item.Key);
|
||||
}
|
||||
|
||||
return powerSystems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the supply and returns the programed OCP. Should match what was in the definition file.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the power supply.</param>
|
||||
/// <returns>The programmed overcurrent protection value</returns>
|
||||
public double GetOverCurrentProtection(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].GetOverCurrentSetting(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the supply and returns the programed OVP. Should match what was in the definition file.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the power supply.</param>
|
||||
/// <returns>The programmed overvoltage protection value.</returns>
|
||||
public double GetOverVoltageProtection(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].GetOverVoltageSetting(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the supply and returns the programed slew rate
|
||||
/// </summary>
|
||||
/// <param name="moduleName"></param>
|
||||
/// <returns>The programmed slew rate</returns>
|
||||
public double GetSlewRate(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].GetSlewRate(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the system that contains the passed in module and returns the system error code.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The module to query.</param>
|
||||
/// <param name="errorCode">The error code.</param>
|
||||
/// <returns>The string form of the error code. Will be empty string if there is no error.</returns>
|
||||
public string GetSystemErrorCode(string moduleName, out int errorCode)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].GetErrorCode(out errorCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the supply and returns the programmed voltage setpoint.
|
||||
/// After construction, this should match what was in the definition file.
|
||||
/// The host may override the value by calling SetVoltageSetpoint().
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the power supply.</param>
|
||||
/// <returns>The programmed voltage setpoint.</returns>
|
||||
public double GetVoltageSetpoint(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].GetVoltageSetting(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the supply and returns true if output is enabled.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the power supply.</param>
|
||||
/// <returns>True if output is enabled, false if it is not enabled.</returns>
|
||||
public bool IsPowerSupplyOn(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].IsOutputOn(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a SCPI command to the power system and reads the response
|
||||
/// </summary>
|
||||
/// <param name="powerSystem">The name of the power system.</param>
|
||||
/// <param name="command">The SCPI command to send</param>
|
||||
/// <returns></returns>
|
||||
public string IOQuery(string powerSystem, string command)
|
||||
{
|
||||
if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find power system: " + powerSystem);
|
||||
}
|
||||
|
||||
return _powerSystemNameToObjectMap[powerSystem.ToUpper()].IOQuery(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a SCPI command to the power system
|
||||
/// </summary>
|
||||
/// <param name="powerSystem">The name of the power system.</param>
|
||||
/// <param name="command">The SCPI command to send</param>
|
||||
public void IOWrite(string powerSystem, string command)
|
||||
{
|
||||
if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find power system: " + powerSystem);
|
||||
}
|
||||
|
||||
_powerSystemNameToObjectMap[powerSystem.ToUpper()].IOWrite(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the current of a module.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The module to read.</param>
|
||||
/// <returns>The current (Amps).</returns>
|
||||
public double MeasureCurrent(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].MeasureCurrent(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the supply for its voltage.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The module to read.</param>
|
||||
/// <returns>The voltage (Volts).</returns>
|
||||
public double MeasureVoltage(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].MeasureVoltage(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable the output of the power supply.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the power supply module.</param>
|
||||
public void OutputDisable(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()].Off(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable the output of the power supply.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the module to enable.</param>
|
||||
public void OutputEnable(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()].On(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// start logging of power supply data.
|
||||
/// Queries the list of all power modules.
|
||||
/// Logs data to the define path.
|
||||
/// Returns data to defined callback function.
|
||||
/// </summary>
|
||||
/// <param name="fileName">Path to create the log file.</param>
|
||||
/// <param name="threadRestTimeMs">The time to wait between queries.</param>
|
||||
/// <param name="callback">Function to call. Null can be passed in in which case no hot callback will be issued</param>
|
||||
public void PowerLogStart(string fileName, int threadRestTimeMs, PowerMonitorDelegate callback)
|
||||
{
|
||||
// if we have been running before, stop just in case the host did not
|
||||
if (_dataLogWorker != null)
|
||||
{
|
||||
PowerLogStop();
|
||||
|
||||
_dataLogWorker.Dispose();
|
||||
}
|
||||
|
||||
_dataLogWorker = new PowerSupplyDataLogWorker(this, fileName, threadRestTimeMs, callback);
|
||||
|
||||
_dataLogThread = new Thread(_dataLogWorker.DoWork);
|
||||
|
||||
// start the thread back up
|
||||
_dataLogThread.Start();
|
||||
|
||||
_prevPowerLogFileName = fileName;
|
||||
_prevPowerLogRestTime = threadRestTimeMs;
|
||||
_prevPowerLogCallback = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// stops logging data and closes the file.
|
||||
/// </summary>
|
||||
public void PowerLogStop()
|
||||
{
|
||||
// Wait up to 5 seconds for the thread to quit
|
||||
const int THREAD_QUIT_TIMEOUT_MS = 5000;
|
||||
|
||||
string functionName = $"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}()";
|
||||
|
||||
if (_dataLogWorker != null)
|
||||
{
|
||||
_dataLogWorker.QuitWork();
|
||||
|
||||
if ((_dataLogThread != null) && _dataLogThread.IsAlive)
|
||||
{
|
||||
bool didThreadQuit = _dataLogThread.Join(THREAD_QUIT_TIMEOUT_MS);
|
||||
|
||||
if (didThreadQuit == false)
|
||||
{
|
||||
_logger.Error($"{functionName} - Logging Thread did not quit as expected, aborting it");
|
||||
_dataLogThread.Abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("{functionName} - Logging Thread quit successfully after join");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("{functionName} - Logging Thread quit successfully");
|
||||
}
|
||||
}
|
||||
|
||||
_prevPowerLogFileName = null;
|
||||
_prevPowerLogRestTime = 0;
|
||||
_prevPowerLogCallback = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Control the power supply internal mechanical relay state
|
||||
/// </summary>
|
||||
/// <param name="shallWeConnect">True to connect, false to disconnect</param>
|
||||
public void MechanicalRelayOutputControl(string moduleName, bool shallWeConnect)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()].MechanicalRelayOutputControl(moduleName, shallWeConnect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query all power supply data in a single call.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the module to query.</param>
|
||||
/// <param name="voltage">The voltage that was read.</param>
|
||||
/// <param name="voltageSetpoint">The voltage setpoint that was read.</param>
|
||||
/// <param name="current">The current that was read.</param>
|
||||
/// <param name="outputStatus">The output status. True if output is enabled, false if output is disabled.</param>
|
||||
/// <param name="faultStatus">The value of the fault status register. See power supply docs for meaning (0 means no fault).</param>
|
||||
/*public void ReadPowerData(string moduleName, out double voltage, out double voltageSetpoint, out double current, out bool outputStatus, out int faultStatus)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("PowerSupplyManager::ReadPowerData() - could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()].ReadPowerData(moduleName, out voltage, out voltageSetpoint, out current, out outputStatus, out faultStatus);
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Query all power supply data in a single call.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the module to query.</param>
|
||||
public PowerData ReadPowerData(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].ReadPowerData(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="moduleName"></param>
|
||||
/// <returns></returns>
|
||||
public int ReadProtectionStatus(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
return _powerModuleNameToObjectMap[moduleName.ToUpper()].ReadProtectionStatus(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the setpoint voltage to the value contained in the ini file
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The module to reset</param>
|
||||
public void SetInitialVoltage(string moduleName)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()].SetInitialVoltage(moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Every power supply gets its voltage set to what was in the ini file
|
||||
/// </summary>
|
||||
public void SetInitialVoltageAll()
|
||||
{
|
||||
List<string> powerModules = GetPowerModuleList();
|
||||
foreach (string powerModule in powerModules)
|
||||
{
|
||||
SetInitialVoltage(powerModule);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the slew rate in volts per second
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the power module</param>
|
||||
/// <param name="slewRate">slew in volts per second</param>
|
||||
/*public void SetSlewRate(string moduleName, double slewRate)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("PowerSupplyManager::SetSlewRate() - could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()].SetSlewRate(moduleName, slewRate);
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="moduleName"></param>
|
||||
/// <param name="ocpValue"></param>
|
||||
public void SetOverCurrentProtection(string moduleName, double ocpValue)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()].SetOverCurrentProtection(moduleName, ocpValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="moduleName"></param>
|
||||
/// <param name="ovpValue"></param>
|
||||
public void SetOverVoltageProtection(string moduleName, double ovpValue)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()].SetOverVoltageProtection(moduleName, ovpValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the setpoint voltage of a module.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The module to set.</param>
|
||||
/// <param name="setpointVoltage">The setpoint voltage.</param>
|
||||
public void SetVoltageSetpoint(string moduleName, double setpointVoltage)
|
||||
{
|
||||
if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find module: " + moduleName);
|
||||
}
|
||||
|
||||
_powerModuleNameToObjectMap[moduleName.ToUpper()].SetVoltageSetpoint(moduleName, setpointVoltage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable the power system watchdog.
|
||||
/// </summary>
|
||||
/// <param name="powerSystem">The power system to act on.</param>
|
||||
public void WatchdogDisable(string powerSystem)
|
||||
{
|
||||
if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find power system: " + powerSystem);
|
||||
}
|
||||
|
||||
_powerSystemNameToObjectMap[powerSystem.ToUpper()].WatchdogDisable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable the power system watchdog.
|
||||
/// </summary>
|
||||
/// <param name="powerSystem">The system to act on.</param>
|
||||
/// <param name="timeInSeconds">The number of seconds for the watchdog.</param>
|
||||
public void WatchdogEnable(string powerSystem, uint timeInSeconds)
|
||||
{
|
||||
if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false)
|
||||
{
|
||||
throw new Exception("Could not find power system: " + powerSystem);
|
||||
}
|
||||
|
||||
_powerSystemNameToObjectMap[powerSystem.ToUpper()].WatchdogEnable(timeInSeconds);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PrivateClassFunctions
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~PowerSupplyMeasurementManager()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this object.
|
||||
/// </summary>
|
||||
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_logger.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");
|
||||
|
||||
// stop the logging if it is still running
|
||||
try
|
||||
{
|
||||
PowerLogStop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex.Message + "\r\n" + ex.StackTrace);
|
||||
}
|
||||
|
||||
// dispose the thread
|
||||
try
|
||||
{
|
||||
if (_dataLogWorker != null)
|
||||
{
|
||||
_dataLogWorker.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex.Message + "\r\n" + ex.StackTrace);
|
||||
}
|
||||
|
||||
// dispose of the other resources
|
||||
foreach (KeyValuePair<string, IPowerSupplySystem> entry in _powerSystemNameToObjectMap)
|
||||
{
|
||||
try
|
||||
{
|
||||
entry.Value.Shutdown();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex.Message + "\r\n" + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(SolutionDir)Solution.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AssemblyName>PowerSupplyMeasurementManager</AssemblyName>
|
||||
<Product>Composable Test Software Library</Product>
|
||||
<Description>Power Supply Measurement Manager</Description>
|
||||
<OutputType>Library</OutputType>
|
||||
|
||||
<!-- Static versioning (Suitable for Development) -->
|
||||
<!-- Disable the line below for dynamic versioning -->
|
||||
<Version>1.1.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.InstrumentManager.Contracts" Version="1.8.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.PowerSupplySystem.Contracts" Version="1.3.0" />
|
||||
<PackageReference Include="Raytheon.Common" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,246 @@
|
||||
// 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.Threading;
|
||||
using Raytheon.Common;
|
||||
using System.IO;
|
||||
using Raytheon.Instruments;
|
||||
using Raytheon.Instruments.PowerSupply;
|
||||
|
||||
namespace MeasurementManagerLib
|
||||
{
|
||||
/// <summary>
|
||||
/// A worker for iterating through each supply in the system, querying its' data, logging it out, and issuing callbacks to the host
|
||||
/// </summary>
|
||||
internal class PowerSupplyDataLogWorker : IWorkerInterface
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
|
||||
private bool _threadQuitControl;
|
||||
private AutoResetEvent _quitEvent;
|
||||
private StreamWriter _fileWriter;
|
||||
private readonly string _logFilePath;
|
||||
private readonly int _threadRestTimeMs;
|
||||
private readonly PowerSupplyMeasurementManager.PowerMonitorDelegate _callback;
|
||||
private readonly PowerSupplyMeasurementManager _controller;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PrivateFunctions
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~PowerSupplyDataLogWorker()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release of resources
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_fileWriter.Dispose();
|
||||
|
||||
_quitEvent.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PublicFuctions
|
||||
|
||||
/// <summary>
|
||||
/// The constructor
|
||||
/// </summary>
|
||||
/// <param name="controller">The controller for the power supplies</param>
|
||||
/// <param name="fileName">The file name to log the data to</param>
|
||||
/// <param name="threadRestTimeMs">The number os ms to rest after each iteration through the loop</param>
|
||||
/// <param name="callback">The host callback function. If null, no callback is issued</param>
|
||||
public PowerSupplyDataLogWorker(PowerSupplyMeasurementManager controller, string fileName, int threadRestTimeMs, PowerSupplyMeasurementManager.PowerMonitorDelegate callback)
|
||||
{
|
||||
_controller = controller;
|
||||
|
||||
// these gets set in SetControlParams
|
||||
_logFilePath = fileName;
|
||||
_callback = callback;
|
||||
_threadRestTimeMs = threadRestTimeMs;
|
||||
|
||||
_fileWriter = new StreamWriter(_logFilePath, true);
|
||||
|
||||
_threadQuitControl = false;
|
||||
_quitEvent = new AutoResetEvent(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this object. Needed for releasing thread/comm resources
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
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>
|
||||
/// Loops thorugh each supply in the system, queries the status, logs it out and calls the host callback
|
||||
/// </summary>
|
||||
public void DoWork()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Used to handle the labels at the top of the CSV log file generated
|
||||
const string LOG_PREFIX = "DateTime,Module,Voltage,VoltageSetpoint,Current,IsOutputOn,fault status";
|
||||
|
||||
// callback error codes
|
||||
const int NO_ERROR = 0;
|
||||
const int ERROR = -1;
|
||||
|
||||
List<string> powerModules = _controller.GetPowerModuleList();
|
||||
|
||||
_fileWriter.WriteLine(LOG_PREFIX);
|
||||
|
||||
while (_threadQuitControl == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_quitEvent.WaitOne(_threadRestTimeMs))
|
||||
{
|
||||
_threadQuitControl = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//string callbackData = CALLBACK_PREFIX;
|
||||
List<PowerMonitorCallbackData> callBackDataList = new List<PowerMonitorCallbackData>();
|
||||
|
||||
//get data from each supply
|
||||
foreach (string powerModule in powerModules)
|
||||
{
|
||||
// check for quit event and exit if needed
|
||||
if (_quitEvent.WaitOne(1) == true)
|
||||
{
|
||||
_threadQuitControl = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
PowerData data = _controller.ReadPowerData(powerModule);
|
||||
|
||||
PowerMonitorCallbackData callbackData;
|
||||
callbackData.powerModule = powerModule;
|
||||
callbackData.voltage = data.Voltage;
|
||||
callbackData.voltageSetpoint = data.VoltageSetpoint;
|
||||
callbackData.current = data.Current;
|
||||
callbackData.outputStatus = data.OutputStatus;
|
||||
callbackData.ovpocpStatus = data.FaultStatus;
|
||||
callbackData.overVoltageProtectionValue = data.OverVoltageProtection;
|
||||
callbackData.overCurrentProtectionValue = data.OverCurrentProtection;
|
||||
|
||||
callBackDataList.Add(callbackData);
|
||||
|
||||
string log = Util.GetTimeString() + "," + powerModule + "," + Convert.ToString(data.Voltage) + "," + Convert.ToString(data.VoltageSetpoint) + "," + Convert.ToString(data.Current) + "," + Convert.ToString(data.OutputStatus) + "," + Convert.ToString(data.FaultStatus);
|
||||
|
||||
// log out the data
|
||||
_fileWriter.WriteLine(log);
|
||||
_fileWriter.Flush();
|
||||
|
||||
// check for quit event and exit if needed
|
||||
if (_quitEvent.WaitOne(1) == true)
|
||||
{
|
||||
_threadQuitControl = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point our return and log strings are both built, so return back the data string on the callback
|
||||
if (_callback != null && _threadQuitControl == false && callBackDataList.Count != 0)
|
||||
{
|
||||
_callback(callBackDataList, NO_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string msg = e.Message;
|
||||
|
||||
ErrorLogger.Instance().Write(msg + "\r\n" + e.StackTrace, ErrorLogger.LogLevel.ERROR);
|
||||
|
||||
_fileWriter.WriteLine(Util.GetTimeString() + ", " + msg);
|
||||
|
||||
// if callbacks are enabled, alert the host to the error
|
||||
if (_callback != null && _threadQuitControl == false)
|
||||
{
|
||||
_callback(null, ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ErrorLogger.Instance().Write("PowerSupplyDataLogWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the thread, closes the datalogger and calls move file
|
||||
/// </summary>
|
||||
public void QuitWork()
|
||||
{
|
||||
_threadQuitControl = true;
|
||||
|
||||
_quitEvent.Set();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user