// 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 System; using System.Collections.Generic; using System.Threading.Tasks; using NLog; using Raytheon.Instruments; using Raytheon.Instruments.PowerSupply; namespace MeasurementManagerLib { /// /// 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. /// public class PowerSupplyMeasurementManager : IDisposable { #region PublicClassMembers private Exception _exceptionFromSuportThread; private object _powerSupplySelfTestSyncOjb = new object(); #endregion #region PrivateClassMembers // power system name to power system object private SortedDictionary _powerSystemNameToObjectMap; // power module name to power system object private SortedDictionary _powerModuleNameToObjectMap; private static NLog.ILogger _logger; private IInstrumentManager _instrumentManager; private string _powerSystemWithFailedSelfTest = String.Empty; #endregion #region PublicFuctions /// /// will create an array of power systems with power supplies /// /// /// public PowerSupplyMeasurementManager(IInstrumentManager instrumentManager) { _logger = LogManager.GetCurrentClassLogger(); _instrumentManager = instrumentManager; _powerSystemNameToObjectMap = new SortedDictionary(); // create some maps to support the functions the MAL input _powerSystemNameToObjectMap = new SortedDictionary(StringComparer.InvariantCultureIgnoreCase); _powerModuleNameToObjectMap = new SortedDictionary(StringComparer.InvariantCultureIgnoreCase); PerformPowerSupplySelfTests(); if (_powerSystemWithFailedSelfTest != String.Empty) { throw new Exception($"{_powerSystemWithFailedSelfTest}'s self-test failed."); } else if (_exceptionFromSuportThread != null) { throw new Exception("Check inner exception", _exceptionFromSuportThread); } ICollection powerSystemList = _instrumentManager.GetInstruments(typeof(IPowerSupplySystem)); // populate the maps foreach (IPowerSupplySystem powerSystem in powerSystemList) { powerSystem.Initialize(); _powerSystemNameToObjectMap[powerSystem.Name.ToUpper()] = powerSystem; List 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; } } } /// /// 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) /// /// /// private void PerformPowerSupplySelfTests() { _logger.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method..."); string errorMsg = String.Empty; ICollection 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); } /// /// Perform self test on power supply system /// /// /// private void PerformPowerSupplySelfTestTask(IPowerSupplySystem powerSystem) { SelfTestResult result = SelfTestResult.Pass; Exception exception = null; string powerSystemWithFailedSelfTest = String.Empty; _logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() for {powerSystem.Name} is running..."); try { result = powerSystem.PerformSelfTest(); if (result == SelfTestResult.Fail) { powerSystemWithFailedSelfTest = powerSystem.Name; } } catch (Exception ex) { exception = ex; } lock (_powerSupplySelfTestSyncOjb) { if (String.IsNullOrEmpty(_powerSystemWithFailedSelfTest) && _exceptionFromSuportThread == null) { if (!String.IsNullOrEmpty(powerSystemWithFailedSelfTest)) _powerSystemWithFailedSelfTest = powerSystemWithFailedSelfTest; else if (exception != null) { _exceptionFromSuportThread = exception; } } } _logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() for {powerSystem.Name} is exiting..."); } /// /// Disable the power supply display interface. /// /// The name of the system to disable, as defined in the config file 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; } /// /// Enable the power supply display interface. /// /// The name of the system to disable, as defined in the config file 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; } /// /// Dispose of this object. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Get all of the power module names /// /// Array of the system/module names. public List GetPowerModuleList() { List powerModules = new List(); foreach (KeyValuePair item in _powerModuleNameToObjectMap) { powerModules.Add(item.Key); } return powerModules; } /// /// Get the power module names for a given system /// /// Array of the system/module names. public List GetPowerSupplyList(string powerSystem) { if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false) { throw new Exception("Unknown power system: " + powerSystem); } return _powerSystemNameToObjectMap[powerSystem.ToUpper()].GetModuleNames(); }//GetPowerSupplyModuleInfoDict /// /// Get the dictionary that contains configuration information for each module /// /// public Dictionary GetPowerSupplyModuleInfoDict(string powerSystem) { if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false) { throw new Exception("Unknown power system: " + powerSystem); } return _powerSystemNameToObjectMap[powerSystem.ToUpper()].GetPowerSupplyModuleInfoDict(powerSystem); } /// /// Gets the Power System names. /// /// Array of power system names, as defined in the config file public List GetPowerSupplySystemList() { List powerSystems = new List(); foreach (KeyValuePair item in _powerSystemNameToObjectMap) { powerSystems.Add(item.Key); } return powerSystems; } /// /// Query the supply and returns the programed OCP. Should match what was in the definition file. /// /// The name of the power supply. /// The programmed overcurrent protection value 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); } /// /// Query the supply and returns the programed OVP. Should match what was in the definition file. /// /// The name of the power supply. /// The programmed overvoltage protection value. 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); } /// /// Query the supply and returns the programed slew rate /// /// /// The programmed slew rate 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); } /// /// Query the system that contains the passed in module and returns the system error code. /// /// The module to query. /// The error code. /// The string form of the error code. Will be empty string if there is no error. 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); } /// /// 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(). /// /// The name of the power supply. /// The programmed voltage setpoint. 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); } /// /// Query the supply and returns true if output is enabled. /// /// The name of the power supply. /// True if output is enabled, false if it is not enabled. 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); } /// /// Sends a SCPI command to the power system and reads the response /// /// The name of the power system. /// The SCPI command to send /// 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); } /// /// Sends a SCPI command to the power system /// /// The name of the power system. /// The SCPI command to send 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); } /// /// Read the current of a module. /// /// The module to read. /// The current (Amps). 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); } /// /// Query the supply for its voltage. /// /// The module to read. /// The voltage (Volts). 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); } /// /// Disable the output of the power supply. /// /// The name of the power supply module. public void OutputDisable(string moduleName) { if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false) { throw new Exception("Could not find module: " + moduleName); } _powerModuleNameToObjectMap[moduleName.ToUpper()].Off(moduleName); } /// /// Enable the output of the power supply. /// /// The name of the module to enable. public void OutputEnable(string moduleName) { if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false) { throw new Exception("Could not find module: " + moduleName); } _powerModuleNameToObjectMap[moduleName.ToUpper()].On(moduleName); } /// /// Control the power supply internal mechanical relay state /// /// True to connect, false to disconnect 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); } /// /// Query all power supply data in a single call. /// /// The name of the module to query. /// The voltage that was read. /// The voltage setpoint that was read. /// The current that was read. /// The output status. True if output is enabled, false if output is disabled. /// The value of the fault status register. See power supply docs for meaning (0 means no fault). /*public void ReadPowerData(string moduleName, out double voltage, out double voltageSetpoint, out double current, out bool isOutputOn, 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 isOutputOn, out faultStatus); }*/ /// /// Query all power supply data in a single call. /// /// The name of the module to query. 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); } /// /// /// /// /// 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); } /// /// Resets the setpoint voltage to the value contained in the ini file /// /// The module to reset public void SetInitialVoltage(string moduleName) { if (_powerModuleNameToObjectMap.ContainsKey(moduleName.ToUpper()) == false) { throw new Exception("Could not find module: " + moduleName); } _powerModuleNameToObjectMap[moduleName.ToUpper()].SetInitialVoltage(moduleName); } /// /// Every power supply gets its voltage set to what was in the ini file /// public void SetInitialVoltageAll() { List powerModules = GetPowerModuleList(); foreach (string powerModule in powerModules) { SetInitialVoltage(powerModule); } } /// /// Sets the slew rate in volts per second /// /// The name of the power module /// slew in volts per second /*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); }*/ /// /// /// /// /// 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); } /// /// /// /// /// 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); } /// /// Set the setpoint voltage of a module. /// /// The module to set. /// The setpoint voltage. 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); } /// /// Disable the power system watchdog. /// /// The power system to act on. public void WatchdogDisable(string powerSystem) { if (_powerSystemNameToObjectMap.ContainsKey(powerSystem.ToUpper()) == false) { throw new Exception("Could not find power system: " + powerSystem); } _powerSystemNameToObjectMap[powerSystem.ToUpper()].WatchdogDisable(); } /// /// Enable the power system watchdog. /// /// The system to act on. /// The number of seconds for the watchdog. 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 /// /// The Finalizer /// ~PowerSupplyMeasurementManager() { Dispose(false); } /// /// Dispose of this object. /// /// True = currently disposing, False = not disposing. protected virtual void Dispose(bool disposing) { if (disposing) { _logger.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method..."); // dispose of the other resources foreach (KeyValuePair entry in _powerSystemNameToObjectMap) { try { entry.Value.Shutdown(); } catch (Exception ex) { _logger.Error(ex.Message + "\r\n" + ex.StackTrace); } } } } #endregion } }