// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using NLog;
using Raytheon.Common;
using Raytheon.Instruments;
using Raytheon.Instruments.Dmm;
using Raytheon.Units;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace MeasurementManagerLib
{
///
/// The interface to the instruments contained in the vsu test station.
/// This class reads in test station configuration ini file that contains:
/// - DMM measurement definitions
/// The host of this class can invoke those measurements by commanding the this class with the ini file string names
/// which insulates the caller from having to know the details of that measurement
///
public class SwitchMeasurementManager : IDisposable
{
#region PublicMembers
///
/// Type of DMM Resistance Measurements
///
public enum DMMResistanceType
{
TWO,
FOUR,
};
public enum DMMVoltageType
{
DC,
AC,
};
public delegate void SwitchMeasurementDelegate();
///
/// Struct for holding on to DMM measurement definitions
///
public struct DMMFrequencyMeasurementFields
{
public readonly double _range;
public readonly double _resolution;
public readonly double _scaleFactor;
public readonly int _delay;
public List _relays;
public readonly double _voltRange;
public readonly double _numReads;
public DMMFrequencyMeasurementFields(double range, double resolution, int delay, double scaleFactor, List relays, double voltRange, double numReads)
{
_range = range;
_resolution = resolution;
_delay = delay;
_scaleFactor = scaleFactor;
_relays = relays;
_voltRange = voltRange;
_numReads = numReads;
}
}
///
/// Struct for holding on to DMM measurement definitions
///
public struct DMMVoltageMeasurementFields
{
public readonly double _range;
public readonly double _resolution;
public readonly double _scaleFactor;
public readonly int _delay;
public List _relays;
public DMMVoltageType _voltageType;
public DMMVoltageMeasurementFields(double range, double resolution, int delay, double scaleFactor, List relays, DMMVoltageType voltageType)
{
_range = range;
_resolution = resolution;
_delay = delay;
_scaleFactor = scaleFactor;
_relays = relays;
_voltageType = voltageType;
}
}
///
/// Struct for holding on to DMM measurement definitions
///
public struct DMMResistanceMeasurementFields
{
public readonly string _pcode;
public readonly double _range;
public readonly double _resolution;
public readonly double _scaleFactor;
public readonly int _delay;
public List _relays;
public DMMResistanceType _dmmResistanceType;
public readonly string _cableAndPinId;
public readonly double _lowerLimit;
public readonly double _upperLimit;
public DMMResistanceMeasurementFields(string pcode, double range, double resolution, int delay, double scaleFactor, List relays, DMMResistanceType type, string cableAndPinId, double lowerLimit, double upperLimit)
{
_pcode = pcode;
_range = range;
_resolution = resolution;
_delay = delay;
_scaleFactor = scaleFactor;
_relays = relays;
_dmmResistanceType = type;
_cableAndPinId = cableAndPinId;
_lowerLimit = lowerLimit;
_upperLimit = upperLimit;
}
}
public struct SwitchMeasurementFields
{
public List _relays;
public SwitchMeasurementFields(List relays)
{
_relays = relays;
}
}
///
/// State for a trigger edge.
///
public enum ScopeEdge
{
FALLING = 0,
RISING,
HOLDING
};
public readonly struct ScopePulseWidthMeasurementFields
{
public readonly List _relays;
public readonly int _channelNumber;
public readonly ScopeEdge _edge;
public readonly double _timePerDivision;
public readonly double _timeOffset;
public readonly double _triggerLevel;
public readonly double _voltageOffset;
public readonly double _voltageScale;
public readonly string _inputImpedance;
//public readonly double m_measurementTime;
public readonly int _delay;
public readonly bool _shallWeSaveImage;
public readonly int _maxTriggerWaitTime;
public ScopePulseWidthMeasurementFields(List relays, int channelNumber, ScopeEdge edge, double timePerDivision, double timeOffset, double triggerLevel, double voltageOffset, double voltageScale, string inputImpedance, int delay, bool shallWeSaveImage, int maxTriggerWaitTime)
{
_relays = relays;
_channelNumber = channelNumber;
_edge = edge;
_inputImpedance = inputImpedance;
_timePerDivision = timePerDivision;
_timeOffset = timeOffset;
_triggerLevel = triggerLevel;
_voltageOffset = voltageOffset;
_voltageScale = voltageScale;
_delay = delay;
_shallWeSaveImage = shallWeSaveImage;
_maxTriggerWaitTime = maxTriggerWaitTime;
}
}
public readonly struct ScopeFrequencyMeasurementFields
{
public readonly List _relays;
public readonly int _channelNumber;
public readonly ScopeEdge _edge;
public readonly double _timePerDivision;
public readonly double _timeOffset;
public readonly double _triggerLevel;
public readonly double _voltageOffset;
public readonly double _voltageScale;
public readonly string _inputImpedance;
//public readonly double m_measurementTime;
public readonly int _delay;
public readonly bool _shallWeSaveImage;
public readonly int _maxTriggerWaitTime;
public ScopeFrequencyMeasurementFields(List relays, int channelNumber, ScopeEdge edge, double timePerDivision, double timeOffset, double triggerLevel, double voltageOffset, double voltageScale, string inputImpedance, int delay, bool shallWeSaveImage, int maxTriggerWaitTime)
{
_relays = relays;
_channelNumber = channelNumber;
_edge = edge;
_inputImpedance = inputImpedance;
_timePerDivision = timePerDivision;
_timeOffset = timeOffset;
_triggerLevel = triggerLevel;
_voltageOffset = voltageOffset;
_voltageScale = voltageScale;
_delay = delay;
_shallWeSaveImage = shallWeSaveImage;
_maxTriggerWaitTime = maxTriggerWaitTime;
}
}
//public Dictionary _dmmFrequencyMeasurements = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
public Dictionary DmmFrequencyMeasurements
{
get { return _dmmFrequencyMeasurements; }
set { _dmmFrequencyMeasurements = value; CheckForDmmFrequencyConfigValidity(); }
}
public Dictionary DmmResistanceMeasurements
{
get { return _dmmResistanceMeasurements; }
set { _dmmResistanceMeasurements = value; CheckForDmmResistanceConfigValidity(); }
}
public Dictionary DmmVoltageMeasurements
{
get { return _dmmVoltageMeasurements; }
set { _dmmVoltageMeasurements = value; CheckForDmmVoltageConfigValidity(); }
}
public Dictionary SwitchMeasurements { get; set; }
public Dictionary ScopeFreqMeasurements
{
get { return _scopeFreqMeasurements; }
set { _scopeFreqMeasurements = value; CheckForScopeFrequencyConfigValidity(); }
}
public Dictionary ScopePulseWidthMeasurements
{
get { return _scopePulseWidthMeasurements; }
set { _scopePulseWidthMeasurements = value; CheckForScopePulseWidthConfigValidity(); }
}
public List RelayExclusionList { get; set; }
#endregion
#region PrivateClassMembers
///
/// private class members
///
private readonly IDmm _dmm;
private readonly IOscilloScope _scope;
private readonly Dictionary _switchCards;
private static readonly object _syncObj = new Object();
private static NLog.ILogger _logger;
private Dictionary _dmmResistanceMeasurements;
private Dictionary _dmmFrequencyMeasurements;
private Dictionary _dmmVoltageMeasurements;
private Dictionary _scopeFreqMeasurements;
private Dictionary _scopePulseWidthMeasurements;
#endregion
#region PrivateFunctions
///
/// The Finalizer
///
~SwitchMeasurementManager()
{
Dispose(false);
}
///
/// Check configuration information is correct
///
private void CheckForDmmResistanceConfigValidity()
{
foreach (KeyValuePair entry in DmmResistanceMeasurements)
{
List relays = entry.Value._relays;
foreach (string relayDef in relays)
{
string[] relayInfo = relayDef.Split('-');
if (relayInfo.Length != 2)
{
throw new Exception("Dmm resistance measurement relay format is not correct: " + relayDef);
}
if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false)
{
throw new Exception("Dmm resistance measurement relay card field does not exist: " + relayInfo[0]);
}
}
}
}
///
/// Check configuration information is correct
///
private void CheckForDmmFrequencyConfigValidity()
{
foreach (KeyValuePair entry in DmmFrequencyMeasurements)
{
List relays = entry.Value._relays;
foreach (string relayDef in relays)
{
string[] relayInfo = relayDef.Split('-');
if (relayInfo.Length != 2)
{
throw new Exception("Dmm frequency measurement relay format is not correct: " + relayDef);
}
if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false)
{
throw new Exception("Dmm frequency measurement relay card field does not exist: " + relayInfo[0]);
}
}
}
}
///
/// Check configuration information is correct
///
private void CheckForDmmVoltageConfigValidity()
{
foreach (KeyValuePair entry in DmmVoltageMeasurements)
{
List relays = entry.Value._relays;
foreach (string relayDef in relays)
{
string[] relayInfo = relayDef.Split('-');
if (relayInfo.Length != 2)
{
throw new Exception("Dmm voltage measurement relay format is not correct: " + relayDef);
}
if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false)
{
throw new Exception("Dmm voltage measurement relay card field does not exist: " + relayInfo[0]);
}
}
}
}
///
/// Check configuration information is correct
///
private void CheckForScopeFrequencyConfigValidity()
{
foreach (KeyValuePair entry in ScopeFreqMeasurements)
{
List relays = entry.Value._relays;
foreach (string relayDef in relays)
{
string[] relayInfo = relayDef.Split('-');
if (relayInfo.Length != 2)
{
throw new Exception("Scope frequency measurement relay format is not correct: " + relayDef);
}
if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false)
{
throw new Exception("Scope frequency measurement relay card field does not exist: " + relayInfo[0]);
}
}
}
}
///
/// Check configuration information is correct
///
private void CheckForScopePulseWidthConfigValidity()
{
foreach (KeyValuePair entry in ScopePulseWidthMeasurements)
{
List relays = entry.Value._relays;
foreach (string relayDef in relays)
{
string[] relayInfo = relayDef.Split('-');
if (relayInfo.Length != 2)
{
throw new Exception("Scope pulse width measurement relay format is not correct: " + relayDef);
}
if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false)
{
throw new Exception("Scope pulse width measurement relay card field does not exist: " + relayInfo[0]);
}
}
}
}
///
/// Check a list of relays against a list of not allowed relays
///
///
/// True if everything is good and checks out, false if relaysToCheck contains a relay on the not allowed list
private bool CheckRelayVerificationList(List relaysToCheck)
{
for (int i = 0; i < relaysToCheck.Count; i++)
{
string relayToCheck = relaysToCheck[i];
for (int j = 0; j < RelayExclusionList.Count; j++)
{
string notAllowedRelay = RelayExclusionList[j];
if (relayToCheck.ToUpper() == notAllowedRelay.ToUpper())
{
return false;
}
}
}
return true;
}
///
///
///
///
///
///
///
///
private void ConfigureDmmSettingsAndCloseAnyRelays(string measurementName, out List measurementRelays, out DMMResistanceMeasurementFields measurement, out MeasurementFunction type, bool delayAfterClosingRelay = true)
{
if (DmmResistanceMeasurements.ContainsKey(measurementName.ToUpper()) == false)
{
throw new Exception("could not find measurement: " + measurementName);
}
measurement = DmmResistanceMeasurements[measurementName.ToUpper()];
measurementRelays = measurement._relays;
byte desiredMeasurementType = (byte)measurement._dmmResistanceType;
SwitchRelayClose(measurementRelays);
if (delayAfterClosingRelay)
{
Thread.Sleep(measurement._delay);
}
type = Raytheon.Instruments.Dmm.MeasurementFunction.TwoWireResistance;
if (measurement._dmmResistanceType == DMMResistanceType.TWO)
{
type = Raytheon.Instruments.Dmm.MeasurementFunction.TwoWireResistance;
}
else if (measurement._dmmResistanceType == DMMResistanceType.FOUR)
{
type = Raytheon.Instruments.Dmm.MeasurementFunction.FourWireResistance;
}
else
{
throw new Exception("unknown resistance type: " + measurement._dmmResistanceType.ToString());
}
}
///
/// Dispose of this objects resources
///
///
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_dmm != null)
{
try
{
_dmm.Shutdown();
}
catch (Exception err)
{
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
}
}
if (_switchCards != null)
{
foreach (KeyValuePair switchCard in _switchCards)
{
try
{
if (_switchCards[switchCard.Key] != null)
{
_switchCards[switchCard.Key].Shutdown();
}
}
catch (Exception err)
{
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
}
}
}
if (_scope != null)
{
try
{
_scope.Shutdown();
}
catch (Exception err)
{
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
}
}
try
{
ErrorLogger.Instance().Dispose();
}
catch (Exception)
{
// nothing to do
}
}
}
///
/// Will command the switch cards close a specified list of relays
///
///
private void SwitchRelayClose(List relayList)
{
// open all relays on the switch. Just extra layer of protection so we don't short out the relays
SwitchRelayOpenAll();
Thread.Sleep(10);
// verify none of the relays are on the exclusion list
bool areRelaysOk = CheckRelayVerificationList(relayList);
if (areRelaysOk == false)
{
throw new Exception("Commanded relay is not allowed");
}
foreach (string combo in relayList)
{
//break out the card and relay
string[] cardRelay = combo.Split('-');
string cardObject = cardRelay[0].Trim();
string relay = cardRelay[1].Trim();
//close the relays
_switchCards[cardObject.ToUpper()].Connect(relay);
}
}
///
/// Will command the switch card open all relays or the specified list of relays
///
/// Optional list of relays to open
private void SwitchRelayOpen(List relayList)
{
foreach (string combo in relayList)
{
//break out the card and relay
string[] cardRelay = combo.Split('-');
string cardObject = cardRelay[0].Trim();
string relay = cardRelay[1].Trim();
//open the relays
_switchCards[cardObject.ToUpper()].Disconnect(relay);
}
}
///
/// Opens all relays on all switch cards
///
private void SwitchRelayOpenAll()
{
foreach (KeyValuePair switchCard in _switchCards)
{
_switchCards[switchCard.Key].DisconnectAll();
}
}
#endregion
#region PublicFunctions
///
/// constructor that uses instrument manager for creating an instrument
///
///
///
///
///
///
public SwitchMeasurementManager(IInstrumentManager instrumentManager)
{
_logger = LogManager.GetCurrentClassLogger();
_switchCards = new Dictionary();
ICollection