Major upgrade

This commit is contained in:
Duc
2025-10-24 15:18:11 -07:00
parent fd85735c93
commit ce583d1664
478 changed files with 237518 additions and 47610 deletions

View File

@@ -16,30 +16,30 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Automation.BDaq;
using NLog;
using Raytheon.Common;
using System.IO;
using System.Reflection;
using Raytheon.Instruments.GeneralIO;
namespace Raytheon.Instruments
{
/// <summary>
/// A class that implements a Context DIO card
/// </summary>
public class DIOAdvantech : IGeneralIO, IDisposable
{
#region PrivateClassMembers
private InstantDiCtrl _inputCtrl;
private InstantDoCtrl _outputCtrl;
private string _name;
private readonly int _deviceNum;
private readonly SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
private ErrorCode errorCode = ErrorCode.Success;
/// <summary>
/// A class that implements a Context DIO card
/// </summary>
public class DIOAdvantech : IGeneralIO, IDisposable
{
#region PrivateClassMembers
private InstantDiCtrl _inputCtrl;
private InstantDoCtrl _outputCtrl;
private string _name;
private readonly int _deviceNum;
private readonly SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
private ErrorCode errorCode = ErrorCode.Success;
private int _numChannelPerPort = 8;
private int _channelStartIndex = 0;
@@ -47,60 +47,41 @@ namespace Raytheon.Instruments
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelInfoMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#region PrivateClassFunctions
~DIOAdvantech()
{
Dispose(false);
}
#endregion
private static bool BioFailed(ErrorCode err)
{
return err < ErrorCode.Success && err >= ErrorCode.ErrorHandleNotValid;
}
/// <summary>
/// Dispose the object's resources
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
if (_state == State.Ready)
{
Shutdown();
#region PrivateClassFunctions
~DIOAdvantech()
{
Dispose(false);
}
_state = State.Uninitialized;
}
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
private static bool BioFailed(ErrorCode err)
{
return err < ErrorCode.Success && err >= ErrorCode.ErrorHandleNotValid;
}
/// <summary>
/// Dispose the object's resources
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_state == State.Ready)
{
Shutdown();
_state = State.Uninitialized;
}
}
}
/// <summary>
/// Because the user has to define each channel number in the config file, some people will use 0 or 1 start their starting channel number
@@ -111,65 +92,65 @@ namespace Raytheon.Instruments
/// <param name="bitIndex">bitIndex will range from 0..M</param>
/// </summary>
private void GetPortIndexAndBitIndex(string signalName, out int portIndex, out int bitIndex)
{
portIndex = (int)(Math.Ceiling((double)((int)_signalNameToChannelMap[signalName].channelNumber + Math.Abs(_channelStartIndex - 1)) / (double)_numChannelPerPort) - 1.0);
{
portIndex = (int)(Math.Ceiling((double)((int)_signalNameToChannelInfoMap[signalName].channelNumber + Math.Abs(_channelStartIndex - 1)) / (double)_numChannelPerPort) - 1.0);
int multiplier = ((int)_signalNameToChannelMap[signalName].channelNumber + _numChannelPerPort) / _numChannelPerPort;
bitIndex = (((int)_signalNameToChannelMap[signalName].channelNumber + _numChannelPerPort) - (_numChannelPerPort * multiplier)) - _channelStartIndex;
int multiplier = ((int)_signalNameToChannelInfoMap[signalName].channelNumber + _numChannelPerPort) / _numChannelPerPort;
bitIndex = (((int)_signalNameToChannelInfoMap[signalName].channelNumber + _numChannelPerPort) - (_numChannelPerPort * multiplier)) - _channelStartIndex;
if (bitIndex < 0)
{
bitIndex = _numChannelPerPort - 1;
}
}
/// <summary>
/// Invert Contec DIO bits.
/// </summary>
private byte InvertBit(byte bitValue)
{
if (bitValue == 0)
{
return 1;
}
else if (bitValue == 1)
{
return 0;
}
else
{
throw new Exception("Unexpected input value: " + bitValue.ToString());
}
}
private void ReadBit(int port, int bitNum, out byte data)
{
_inputCtrl.ReadBit(port, bitNum, out data);
}
private void WriteBit(int port, int bitNum, byte bitState)
{
errorCode = _outputCtrl.WriteBit(port, bitNum, bitState);
/// <summary>
/// Invert Contec DIO bits.
/// </summary>
private byte InvertBit(byte bitValue)
{
if (bitValue == 0)
{
return 1;
}
else if (bitValue == 1)
{
return 0;
}
else
{
throw new Exception("Unexpected input value: " + bitValue.ToString());
}
}
private void ReadBit(int port, int bitNum, out byte data)
{
_inputCtrl.ReadBit(port, bitNum, out data);
}
private void WriteBit(int port, int bitNum, byte bitState)
{
errorCode = _outputCtrl.WriteBit(port, bitNum, bitState);
if (BioFailed(errorCode))
{
throw new Exception("call to WriteBit returned error: " + errorCode.ToString() + " on card: " + _name); ;
}
}
#endregion
if (BioFailed(errorCode))
{
throw new Exception("call to WriteBit returned error: " + errorCode.ToString() + " on card: " + _name); ;
}
}
#endregion
#region PublicClassFunctions
#region PublicClassFunctions
/// <summary>
/// DIOAdvantech factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOAdvantech(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
/// <summary>
/// DIOAdvantech factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOAdvantech(string deviceName, IConfigurationManager configurationManager)
{
Name = deviceName;
_logger = logger;
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
@@ -189,10 +170,10 @@ namespace Raytheon.Instruments
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_CHANNELS_PER_PORT.ToString()), out _numChannelPerPort);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.CHANNEL_START_INDEX.ToString()), out _channelStartIndex);
if (!(_channelStartIndex == 0 || _channelStartIndex == 1))
{
throw new Exception($"The value for key {ConfigIni.CHANNEL_START_INDEX.ToString()} in section {Name} must be 0 or 1 in {dioModuleDefPath}");
}
if (!(_channelStartIndex == 0 || _channelStartIndex == 1))
{
throw new Exception($"The value for key {ConfigIni.CHANNEL_START_INDEX.ToString()} in section {Name} must be 0 or 1 in {dioModuleDefPath}");
}
List<string> outputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
@@ -200,7 +181,7 @@ namespace Raytheon.Instruments
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
@@ -211,115 +192,103 @@ namespace Raytheon.Instruments
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.ioType = IODatatypes.IOType.DigitalOutput;
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.ioType = IODatatypes.IOType.DigitalInput;
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
}
_selfTestResult = SelfTestResult.Unknown;
}
/// <summary>
///
/// </summary>
public DIOAdvantech(string deviceName, int deviceNum)
{
_deviceNum = deviceNum;
_name = deviceName;
/// <summary>
///
/// </summary>
public DIOAdvantech(string deviceName, int deviceNum)
{
_deviceNum = deviceNum;
_name = deviceName;
_logger = LogManager.GetCurrentClassLogger();
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
}
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
}
public bool ClearErrors()
{
throw new NotImplementedException();
}
public bool ClearErrors()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
//_outputCtrl.SelectedDevice; Need to see what the card returns for this
return "This is a Advantech DIO Card " + _name;
}
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
//_outputCtrl.SelectedDevice; Need to see what the card returns for this
return "This is a Advantech DIO Card " + _name;
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
GC.SuppressFinalize(this);
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
@@ -327,50 +296,50 @@ namespace Raytheon.Instruments
/// <param name="signalName"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
{
lock (_syncObj)
{
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels+_channelStartIndex} on card " + _name);
throw new Exception($"The input channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
GetPortIndexAndBitIndex(signalName, out int portIndex, out int bitIndex);
ReadBit(portIndex, bitIndex, out byte data);
ReadBit(portIndex, bitIndex, out byte data);
return (IODatatypes.BitState)(data);
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
//@@@ do we need both of these? DO can read and write. Read may be for internal read back
_inputCtrl = new InstantDiCtrl();
_outputCtrl = new InstantDoCtrl();
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
//@@@ do we need both of these? DO can read and write. Read may be for internal read back
_inputCtrl = new InstantDiCtrl();
_outputCtrl = new InstantDoCtrl();
_inputCtrl.SelectedDevice = new DeviceInformation(_deviceNum);
_outputCtrl.SelectedDevice = new DeviceInformation(_deviceNum);
_inputCtrl.SelectedDevice = new DeviceInformation(_deviceNum);
_outputCtrl.SelectedDevice = new DeviceInformation(_deviceNum);
if (_shallWeInitializeOutput)
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelMap)
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelInfoMap)
{
if (item.Value.initialValue != -1)
{
@@ -380,73 +349,73 @@ namespace Raytheon.Instruments
}
_state = State.Ready;
}
else
{
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
}
else
{
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
/// Return list of signal names
/// Return map of all signals
/// </summary>
public List<string> GetSignalNames()
public Dictionary<string, IODatatypes.DIOChannelInfo> GetAllSignals()
{
return new List<string>(_signalNameToChannelMap.Keys);
return _signalNameToChannelInfoMap;
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
// card does not support self test
//throw new NotImplementedException("card does not support self test" + " on card " + _name);
throw new NotImplementedException();
}
}
public void Reset()
{
lock (_syncObj)
{
Shutdown();
Initialize();
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
// card does not support self test
//throw new NotImplementedException("card does not support self test" + " on card " + _name);
throw new NotImplementedException();
}
}
public void Reset()
{
lock (_syncObj)
{
Shutdown();
Initialize();
}
}
/// <summary>
///
@@ -455,58 +424,58 @@ namespace Raytheon.Instruments
/// <param name="state"> high(open) or low(closed) </param>
///
public void SetBit(string signalName, IODatatypes.BitState state)
{
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
{
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels +_channelStartIndex} on card " + _name);
throw new Exception($"The output channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
GetPortIndexAndBitIndex(signalName, out int portIndex, out int bitIndex);
GetPortIndexAndBitIndex(signalName, out int portIndex, out int bitIndex);
WriteBit(portIndex, bitIndex, (byte)state);
}
}
public void SetTristate(string signalName)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
public void Shutdown()
{
lock (_syncObj)
{
if (_state == State.Ready)
{
_outputCtrl.Dispose();
_inputCtrl.Dispose();
_state = State.Uninitialized;
}
}
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
#endregion
}
}
}
public void SetTristate(string signalName)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
public void Shutdown()
{
lock (_syncObj)
{
if (_state == State.Ready)
{
_outputCtrl.Dispose();
_inputCtrl.Dispose();
_state = State.Uninitialized;
}
}
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
#endregion
}
}

View File

@@ -30,71 +30,65 @@
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOAdvantechFactory")]
public class DIOAdvantechFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
[ExportInstrumentFactory(ModelNumber = "DIOAdvantechFactory")]
public class DIOAdvantechFactory : IInstrumentFactory
{
private readonly List<Type> _supportedInterfaces = new List<Type>();
public DIOAdvantechFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOAdvantechFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
public DIOAdvantechFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
/// <summary>
/// DIOAdvantechFactory injection constructor
/// </summary>
[ImportingConstructor]
public DIOAdvantechFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOAdvantech(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
return new DIOAdvantech(name, _configurationManager);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
@@ -105,12 +99,10 @@ namespace Raytheon.Instruments
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
return new DIOSim(name, _configurationManager);
else
return new DIOAdvantech(name, _configurationManager, _logger);
return new DIOAdvantech(name, _configurationManager);
}
catch (Exception)
{
@@ -123,17 +115,17 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -16,14 +16,13 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using CdioCs;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using NLog;
using Raytheon.Common;
using System.ComponentModel.Composition.Primitives;
using System.IO;
using System.Reflection;
using CdioCs;
using NLog;
using Raytheon.Common;
using Raytheon.Instruments.GeneralIO;
namespace Raytheon.Instruments
{
@@ -47,15 +46,10 @@ namespace Raytheon.Instruments
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelInfoMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
@@ -69,29 +63,15 @@ namespace Raytheon.Instruments
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
try
if (disposing)
{
if (disposing)
if (_state == State.Ready)
{
if (_state == State.Ready)
{
Reset();
Reset();
_dio.Exit(_id);
_dio.Exit(_id);
_state = State.Uninitialized;
}
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
_state = State.Uninitialized;
}
}
}
@@ -124,11 +104,11 @@ namespace Raytheon.Instruments
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOContec(string deviceName, IConfigurationManager configurationManager, ILogger logger)
public DIOContec(string deviceName, IConfigurationManager configurationManager)
{
Name = deviceName;
_logger = logger;
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
@@ -164,7 +144,7 @@ namespace Raytheon.Instruments
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
@@ -175,22 +155,24 @@ namespace Raytheon.Instruments
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.ioType = IODatatypes.IOType.DigitalOutput;
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.ioType = IODatatypes.IOType.DigitalInput;
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
_selfTestResult = SelfTestResult.Unknown;
@@ -207,13 +189,13 @@ namespace Raytheon.Instruments
/// Note that all signals on the Contec DIO card are inverted.
/// This class masks the inversion so that the caller does not have to deal with it.
/// </summary>
public DIOContec(string name, string address, List<uint> inputPins, List<uint> outputPins)
public DIOContec(string deviceName, string address, List<uint> inputPins, List<uint> outputPins)
{
_name = name;
_name = deviceName;
_address = address;
_logger = LogManager.GetCurrentClassLogger();
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
_selfTestResult = SelfTestResult.Unknown;
@@ -275,23 +257,9 @@ namespace Raytheon.Instruments
{
lock (_syncObj)
{
try
{
Dispose(true);
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
GC.SuppressFinalize(this);
}
}
@@ -320,15 +288,15 @@ namespace Raytheon.Instruments
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
throw new Exception($"The input channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int bitIndex = (int)_signalNameToChannelInfoMap[signalName].channelNumber - _channelStartIndex;
byte dioData = 0;
@@ -417,7 +385,7 @@ namespace Raytheon.Instruments
if (_shallWeInitializeOutput)
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelMap)
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelInfoMap)
{
if (item.Value.initialValue != -1)
{
@@ -436,11 +404,11 @@ namespace Raytheon.Instruments
}
/// <summary>
/// Return list of signal names
/// Return map of all signals
/// </summary>
public List<string> GetSignalNames()
public Dictionary<string, IODatatypes.DIOChannelInfo> GetAllSignals()
{
return new List<string>(_signalNameToChannelMap.Keys);
return _signalNameToChannelInfoMap;
}
/// <summary>
@@ -525,15 +493,15 @@ namespace Raytheon.Instruments
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
throw new Exception($"The output channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int bitIndex = (int)_signalNameToChannelInfoMap[signalName].channelNumber - _channelStartIndex;
int ret = _dio.OutBit(_id, (short)bitIndex, InvertBit((byte)state));

View File

@@ -32,71 +32,64 @@
// **********************************************************************************************************
// Ignore Spelling: Contec
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOContecFactory")]
public class DIOContecFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
[ExportInstrumentFactory(ModelNumber = "DIOContecFactory")]
public class DIOContecFactory : IInstrumentFactory
{
private readonly List<Type> _supportedInterfaces = new List<Type>();
public DIOContecFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOContecFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
public DIOContecFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
/// <summary>
/// DIOContecFactory injection constructor
/// </summary>
[ImportingConstructor]
public DIOContecFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOContec(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
return new DIOContec(name, _configurationManager);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
@@ -107,12 +100,10 @@ namespace Raytheon.Instruments
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
return new DIOSim(name, _configurationManager);
else
return new DIOContec(name, _configurationManager, _logger);
return new DIOContec(name, _configurationManager);
}
catch (Exception)
{
@@ -125,17 +116,17 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1,66 @@
// ******************************************************************************//
// 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.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// ****************************************************************************//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Raytheon.Instruments
{
internal enum BitDirection
{
Input,
Output
}
internal struct PortDirections
{
public BitDirection _PortOne;
public BitDirection _PortTwo;
public BitDirection _PortThree;
public BitDirection _PortFour;
public BitDirection _PortFive;
public PortDirections( BitDirection PortOne, BitDirection PortTwo, BitDirection PortThree,
BitDirection PortFour, BitDirection PortFive )
{
_PortOne = PortOne;
_PortTwo = PortTwo;
_PortThree = PortThree;
_PortFour = PortFour;
_PortFive = PortFive;
}
}
}

View File

@@ -0,0 +1,635 @@
// 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.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using NLog;
using Raytheon.Common;
using Raytheon.Instruments.GeneralIO;
namespace Raytheon.Instruments
{
/// <summary>
/// A class that implements a Pickering DIO card
/// </summary>
public class DIOIcs8003 : IGeneralIO
{
#region PrivateClassMembers
private string _name;
private string _ipAddress;
private int _ipPort;
private SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
private int _numChannelPerPort = 8;
private int _channelStartIndex = 0;
private int _numInputChannels;
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private NetworkStream _dioStream;
private PortDirections _portDirections;
private const int _READ_BUFFER_SIZE = 128;
private const int _READ_TIMEOUT = 5000;
private const int _BUFFER_OFFSET = 0;
private byte[] _dataBuffer;
// Carriage return for string
private const string _CARRIAGE_RETURN = "\n";
// Reset Device
private const String _RestDevice = "*RST";
// Execute Self-Test
private const String _CommandSelfTest = "*TST?";
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelInfoMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
private readonly ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
#region PublicClassFunctions
/// <summary>
/// DIOIcs8003 factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOIcs8003(string deviceName, IConfigurationManager configurationManager)
{
Name = deviceName;
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
_dataBuffer = new byte[_READ_BUFFER_SIZE];
_portDirections = new PortDirections(BitDirection.Input, BitDirection.Input, BitDirection.Input, BitDirection.Input, BitDirection.Input);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(_configurationManager.ConfigurationStoragePath, dioModuleDefPath));
IConfigurationFile dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
_ipAddress = dioModuleConfig.ReadValue(Name, ConfigIni.DIO_ADDRESS.ToString());
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.DIO_PORT.ToString()), out _ipPort);
Boolean.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.SHALL_WE_DRIVE_OUTPUT_UPON_INITIALIZATION.ToString()), out _shallWeInitializeOutput);
List<string> outputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_CHANNELS_PER_PORT.ToString()), out _numChannelPerPort);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_OUTPUT_CHANNELS.ToString()), out _numOutputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.NUM_INPUT_CHANNELS.ToString()), out _numInputChannels);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.CHANNEL_START_INDEX.ToString()), out _channelStartIndex);
if (!(_channelStartIndex == 0 || _channelStartIndex == 1))
{
throw new Exception($"The value for key {ConfigIni.CHANNEL_START_INDEX.ToString()} in section {Name} must be 0 or 1 in {dioModuleDefPath}");
}
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.ioType = IODatatypes.IOType.DigitalOutput;
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelInfoMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.ioType = IODatatypes.IOType.DigitalInput;
info.initialValue = -1;
_signalNameToChannelInfoMap[signalName] = info;
}
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
}
~DIOIcs8003()
{
}
/// <summary>
/// Initialize the card
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
//Create and open a socket to the dio card
TcpClient dioSocket = new TcpClient(_ipAddress, _ipPort);
_dioStream = dioSocket.GetStream();
// Set the timeout (read)
_dioStream.ReadTimeout = _READ_TIMEOUT;
Thread.Sleep(1000);
// Flush the buffer
if (_dioStream.DataAvailable)
{
Thread.Sleep(1000);
Read();
}
// Send command to reset device
Write(_RestDevice);
_state = State.Ready;
}
else
{
throw new Exception("Expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
/// Return map of all signals
/// </summary>
public Dictionary<string, IODatatypes.DIOChannelInfo> GetAllSignals()
{
return _signalNameToChannelInfoMap;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a ICS8003 DIO Card " + _name;
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <param name="state"></param>
public void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
uint bit = _signalNameToChannelInfoMap[signalName].channelNumber;
String msg;
if (state == IODatatypes.BitState.High)
{
msg = "Route:Close ";
}
else
{
msg = "Route:Open ";
}
uint conversion = ConvertChannelToBit(bit);
// Byte 1
if (bit <= 8)
{
if (_portDirections._PortOne == BitDirection.Input)
{
InitializeOutputsLow(1);
_portDirections._PortOne = BitDirection.Output;
}
msg = msg + "1,";
}
// Byte 2
else if (bit > 8 && bit <= 16)
{
if (_portDirections._PortTwo == BitDirection.Input)
{
InitializeOutputsLow(2);
_portDirections._PortTwo = BitDirection.Output;
}
msg = msg + "2,";
}
// Byte 3
else if (bit > 16 && bit <= 24)
{
if (_portDirections._PortThree == BitDirection.Input)
{
InitializeOutputsLow(3);
_portDirections._PortThree = BitDirection.Output;
}
msg = msg + "3,";
}
// Byte 4
else if (bit > 24 && bit <= 32)
{
if (_portDirections._PortFour == BitDirection.Input)
{
InitializeOutputsLow(4);
_portDirections._PortFour = BitDirection.Output;
}
msg = msg + "4,";
}
// Byte 5
else if (bit > 32 && bit <= 40)
{
if (_portDirections._PortFive == BitDirection.Input)
{
InitializeOutputsLow(5);
_portDirections._PortFive = BitDirection.Output;
}
msg = msg + "5,";
}
// Set the bit
msg = msg + conversion.ToString();
// Send msg
Write(msg);
}
}
/// <summary>
///
/// </summary>
/// <param name="signalName"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
uint bit = _signalNameToChannelInfoMap[signalName].channelNumber;
uint conversion = ConvertChannelToBit(bit);
String msg = "Sense:Bit? ";
// Byte 1
if (bit <= 8)
{
msg = msg + "1,";
}
// Byte 2
else if (bit > 8 && bit <= 16)
{
msg = msg + "2,";
}
// Byte 3
else if (bit > 16 && bit <= 24)
{
msg = msg + "3,";
}
// Byte 4
else if (bit > 24 && bit <= 32)
{
msg = msg + "4,";
}
// Byte 5
else if (bit > 32 && bit <= 40)
{
msg = msg + "5,";
}
msg = msg + conversion.ToString();
String result = Query(msg);
if (result == "1")
{
return IODatatypes.BitState.High;
}
else
{
return IODatatypes.BitState.Low;
}
}
}
private uint ConvertChannelToBit(uint bit)
{
uint conversion = (bit % 8);
if (conversion == 0)
{
conversion = 7;
}
else
{
conversion -= 1;
}
return conversion;
}
private String Query(String msg)
{
lock (_syncObj)
{
// Send message
Write(msg);
// Wait
Thread.Sleep(100);
// Get response (and parse)
String rsp = Parse(Read());
return rsp;
}
}
private String Read()
{
lock (_syncObj)
{
String rsp = "";
// Flush
FlushReadBuffer(ref _dataBuffer);
// Get response
_dioStream.Read(_dataBuffer, _BUFFER_OFFSET, _dataBuffer.Length);
rsp = Encoding.ASCII.GetString(_dataBuffer);
return rsp;
}
}
private void Write(String msg)
{
lock (_syncObj)
{
// Check for connect
string commandString = msg + _CARRIAGE_RETURN;
byte[] commandBuffer = Encoding.ASCII.GetBytes(commandString);
// Send message
_dioStream.Write(commandBuffer, _BUFFER_OFFSET, commandBuffer.Length);
}
}
private void FlushReadBuffer(ref byte[] buffer)
{
// Clear the buffer
Array.Clear(buffer, _BUFFER_OFFSET, buffer.Length);
}
// Initialize a port to be an output in a known (low) state
private void InitializeOutputsLow(int port)
{
// Initialize port as an output (initialize to low)
String msg = "Source:Data:Port" + port.ToString() + " 0";
Write(msg);
}
private String Parse(String msg)
{
String Result = "";
// Parse the message by line endings (\n)
String[] Temp = msg.Split('\n');
// Result in first line
Result = Temp[0];
return Result;
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
// Send command to perform self-test (might be empty string)
String results = Query(_CommandSelfTest);
if (results == "0")
{
_selfTestResult = SelfTestResult.Pass;
}
else
{
_selfTestResult = SelfTestResult.Fail;
}
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
Shutdown();
Initialize();
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
if (_dioStream != null)
{
_dioStream.Close();
}
_state = State.Uninitialized;
}
}
#endregion
}
}

View File

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

View File

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

View File

@@ -16,115 +16,73 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using Raytheon.Common;
using NLog;
using Pickering.Lxi.Communication;
using Pickering.Lxi.Piplx;
using Pickering.Lxi;
using System.IO;
using System.Reflection;
using NLog;
using Pickering.Lxi.Piplx;
using Raytheon.Common;
using Raytheon.Instruments.GeneralIO;
namespace Raytheon.Instruments
{
/// <summary>
/// A class that implements a Pickering DIO card
/// </summary>
public class DIOPickering40x : IGeneralIO, IDisposable
public class DIOPickering40x : IGeneralIO
{
#region PrivateClassMembers
private string _name;
private readonly int _pxiCardSlotIndex;
private SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
private PiplxCard _dioCard;
private string _lxiIpAddress;
private int _deviceNum;
private int _busNum;
private SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
private PiplxCard _dioCard;
private int _numChannelPerPort = 8;
private int _channelStartIndex = 0;
private int _numInputChannels;
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private bool _shallWeInitializeOutput = false;
PiplxManager _piplxManager;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelInfoMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
private readonly ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
#endregion
#region PublicClassFunctions
/// <summary>
/// NLog logger
/// DIOPickering40x factory constructor
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOPickering40x(string deviceName, IConfigurationManager configurationManager)
{
Name = deviceName;
#endregion
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
#region PrivateClassFunctions
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
/// <summary>
/// The finalizer.
/// </summary>
~DIOPickering40x()
{
Dispose(false);
}
/// <summary>
/// Dispose of this object.
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
// nothing to do here
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
#endregion
#region PublicClassFunctions
/// <summary>
/// DIOPickering40x factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOPickering40x(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
_logger = logger;
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(assemblyFolder, dioModuleDefPath));
dioModuleDefPath = Path.GetFullPath(Path.Combine(_configurationManager.ConfigurationStoragePath, dioModuleDefPath));
IConfigurationFile dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.PXI_CARD_SLOT_INDEX.ToString()), out _pxiCardSlotIndex);
_lxiIpAddress = dioModuleConfig.ReadValue(Name, ConfigIni.LXI_IP_ADDRESS.ToString());
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.BUS_NUMBER.ToString()), out _busNum);
Int32.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.DEVICE_NUMBER.ToString()), out _deviceNum);
Boolean.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.SHALL_WE_DRIVE_OUTPUT_UPON_INITIALIZATION.ToString()), out _shallWeInitializeOutput);
Boolean.TryParse(dioModuleConfig.ReadValue(Name, ConfigIni.SHALL_WE_DRIVE_OUTPUT_UPON_INITIALIZATION.ToString()), out _shallWeInitializeOutput);
List<string> outputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.OUTPUT_SIGNALS}");
List<string> intputSignalNames = dioModuleConfig.ReadAllKeys($"{Name}.{ConfigIni.INPUT_SIGNALS}");
@@ -139,39 +97,50 @@ namespace Raytheon.Instruments
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
{
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
string[] infoTokens = iniLine.Split('|');
if (infoTokens.Length != 2)
{
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} does not contain 2 tokens");
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.ioType = IODatatypes.IOType.DigitalOutput;
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.initialValue = -1;
info.ioType = IODatatypes.IOType.DigitalInput;
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
}
_state = State.Uninitialized;
}
~DIOPickering40x()
{
if (_dioCard != null)
{
_dioCard.Close();
_piplxManager.Disconnect();
}
}
/// <summary>
/// Initialize the card
@@ -182,27 +151,39 @@ namespace Raytheon.Instruments
{
if (_state == State.Uninitialized)
{
PiplxManager manager = new PiplxManager("");
_piplxManager = new PiplxManager(_lxiIpAddress);
_dioCard = (PiplxCard)manager.Cards[_pxiCardSlotIndex];
foreach (PiplxCard card in _piplxManager.Cards)
{
PiplxCardInfo info = (PiplxCardInfo)card.Info;
PiplxCardInfo info = (PiplxCardInfo)_dioCard.Info;
if (info.Device == _deviceNum && info.Bus == _busNum)
{
_dioCard = card;
_numInputChannels = info.InputSubunitsCount * _numChannelPerPort;
_numOutputChannels = info.OutputSubunitsCount * _numChannelPerPort;
_numInputChannels = info.InputSubunitsCount * _numChannelPerPort;
_numOutputChannels = info.OutputSubunitsCount * _numChannelPerPort;
_dioCard.Open();
_dioCard.Open();
break;
}
}
if (_shallWeInitializeOutput)
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelMap)
{
if (item.Value.initialValue != -1)
{
SetBit(item.Key, (IODatatypes.BitState)item.Value.initialValue);
}
}
}
if (_dioCard == null)
{
throw new Exception($"No DIO card exists in LXI chassis with DEVICE_NUMBER={_deviceNum} and BUS_NUMBER={_busNum}");
}
if (_shallWeInitializeOutput)
{
foreach (KeyValuePair<string, IODatatypes.DIOChannelInfo> item in _signalNameToChannelInfoMap)
{
if (item.Value.initialValue != -1)
{
SetBit(item.Key, (IODatatypes.BitState)item.Value.initialValue);
}
}
}
_state = State.Ready;
}
@@ -214,11 +195,11 @@ namespace Raytheon.Instruments
}
/// <summary>
/// Return list of signal names
/// Return map of all signals
/// </summary>
public List<string> GetSignalNames()
{
return new List<string>(_signalNameToChannelMap.Keys);
public Dictionary<string, IODatatypes.DIOChannelInfo> GetAllSignals()
{
return _signalNameToChannelInfoMap;
}
/// <summary>
@@ -226,79 +207,52 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
throw new NotImplementedException();
}
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a Pickering DIO Card " + _name;
}
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a Pickering DIO Card " + _name;
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
@@ -309,19 +263,19 @@ namespace Raytheon.Instruments
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels +_channelStartIndex} on card " + _name);
throw new Exception($"The output channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
GetPortIndexAndBitIndex(signalName, out int portIndex, out int bitIndex);
DigitalInputOutputSubunit subunit = (DigitalInputOutputSubunit)_dioCard.OutputSubunits[portIndex];
subunit[bitIndex+1] = state != 0;
subunit[bitIndex + 1] = state != 0;
}
}
@@ -331,24 +285,24 @@ namespace Raytheon.Instruments
/// <param name="signalName"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
{
lock (_syncObj)
{
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels+_channelStartIndex} on card " + _name);
throw new Exception($"The input channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
GetPortIndexAndBitIndex(signalName, out int portIndex, out int bitIndex);
DigitalInputOutputSubunit subunit = (DigitalInputOutputSubunit)_dioCard.InputSubunits[portIndex];
return (IODatatypes.BitState)(subunit[bitIndex+1] ? 1:0);
return (IODatatypes.BitState)(subunit[bitIndex + 1] ? 1 : 0);
}
}
}
/// <summary>
/// Because the user has to define each channel number in the config file, some people will use 0 or 1 start their starting channel number
@@ -360,10 +314,10 @@ namespace Raytheon.Instruments
/// </summary>
private void GetPortIndexAndBitIndex(string signalName, out int portIndex, out int bitIndex)
{
portIndex = (int)(Math.Ceiling((double)((int)_signalNameToChannelMap[signalName].channelNumber + Math.Abs(_channelStartIndex - 1)) / (double)_numChannelPerPort) - 1.0);
portIndex = (int)(Math.Ceiling((double)((int)_signalNameToChannelInfoMap[signalName].channelNumber + Math.Abs(_channelStartIndex - 1)) / (double)_numChannelPerPort) - 1.0);
int multiplier = ((int)_signalNameToChannelMap[signalName].channelNumber + _numChannelPerPort) / _numChannelPerPort;
bitIndex = (((int)_signalNameToChannelMap[signalName].channelNumber + _numChannelPerPort) - (_numChannelPerPort * multiplier)) - _channelStartIndex;
int multiplier = ((int)_signalNameToChannelInfoMap[signalName].channelNumber + _numChannelPerPort) / _numChannelPerPort;
bitIndex = (((int)_signalNameToChannelInfoMap[signalName].channelNumber + _numChannelPerPort) - (_numChannelPerPort * multiplier)) - _channelStartIndex;
if (bitIndex < 0)
{
bitIndex = _numChannelPerPort - 1;
@@ -374,109 +328,109 @@ namespace Raytheon.Instruments
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
{
get
{
throw new NotImplementedException();
}
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
Shutdown();
Initialize();
}
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
_state = State.Uninitialized;
}
}
#endregion
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
_state = State.Uninitialized;
}
}
#endregion
}
}

View File

@@ -4,8 +4,8 @@
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>Raytheon.Instruments.DIOPickering40x</AssemblyName>
<Product>DIO Sim implementation</Product>
<Description>DIO Sim implementation</Description>
<Product>DIO Pickering 40x implementation</Product>
<Description>DIO Pickering 40x implementation</Description>
<OutputType>Library</OutputType>
<!-- Static versioning (Suitable for Development) -->

View File

@@ -30,71 +30,64 @@
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOPickering40xFactory")]
public class DIOPickering40xFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
[ExportInstrumentFactory(ModelNumber = "DIOPickering40xFactory")]
public class DIOPickering40xFactory : IInstrumentFactory
{
private readonly List<Type> _supportedInterfaces = new List<Type>();
public DIOPickering40xFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOPickering40xFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
public DIOPickering40xFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
/// <summary>
/// DIOPickering40xFactory injection constructor
/// </summary>
[ImportingConstructor]
public DIOPickering40xFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOPickering40x(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
return new DIOPickering40x(name, _configurationManager);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
@@ -105,12 +98,10 @@ namespace Raytheon.Instruments
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
return new DIOSim(name, _configurationManager);
else
return new DIOPickering40x(name, _configurationManager, _logger);
return new DIOPickering40x(name, _configurationManager);
}
catch (Exception)
{
@@ -123,17 +114,17 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -0,0 +1 @@
Pickering 40-419-003

View File

@@ -30,71 +30,64 @@
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOSiCp210xFactory")]
public class DIOSiCp210xFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
[ExportInstrumentFactory(ModelNumber = "DIOSiCp210xFactory")]
public class DIOSiCp210xFactory : IInstrumentFactory
{
private readonly List<Type> _supportedInterfaces = new List<Type>();
public DIOSiCp210xFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOSiCp210xFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
public DIOSiCp210xFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
/// <summary>
/// DIOSiCp210xFactory injection constructor
/// </summary>
[ImportingConstructor]
public DIOSiCp210xFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOSiCp210x(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
return new DIOSiCp210x(name, _configurationManager);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
@@ -105,12 +98,10 @@ namespace Raytheon.Instruments
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
return new DIOSim(name, _configurationManager);
else
return new DIOSiCp210x(name, _configurationManager, _logger);
return new DIOSiCp210x(name, _configurationManager);
}
catch (Exception)
{
@@ -123,17 +114,17 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -1,134 +1,132 @@
using System;
using System.Collections.Generic;
using Win_API;
using Raytheon.Instruments.GeneralIO;
using CP210xRuntime_DLL;
using NLog;
using Raytheon.Common;
using Raytheon.Instruments.GeneralIO;
using Win_API;
namespace Raytheon.Instruments
{
/// <summary>
///
/// </summary>
public class ECPDIOSiCp210x : DIOSiCp210x
{
private string _comPort = string.Empty;
/// <summary>
///
/// </summary>
public class ECPDIOSiCp210x : DIOSiCp210x
{
private string _comPort = string.Empty;
/// <summary>
/// ECPDIOSiCp210x factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public ECPDIOSiCp210x(string deviceName, IConfigurationManager configurationManager, ILogger logger)
: base(deviceName, configurationManager, logger)
{
_comPort = _dioModuleConfig.ReadValue(Name, ConfigIni.COM_PORT.ToString());
}
/// <summary>
/// ECPDIOSiCp210x factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public ECPDIOSiCp210x(string deviceName, IConfigurationManager configurationManager)
: base(deviceName, configurationManager)
{
_comPort = _dioModuleConfig.ReadValue(Name, ConfigIni.COM_PORT.ToString());
}
/// <summary>
///
/// </summary>
/// <param name="deviceName"></param>
/// <param name="deviceNum"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public ECPDIOSiCp210x(string deviceName, uint deviceNum)
: base(deviceName, deviceNum)
{ }
/// <summary>
///
/// </summary>
/// <param name="deviceName"></param>
/// <param name="deviceNum"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public ECPDIOSiCp210x(string deviceName, uint deviceNum)
: base(deviceName, deviceNum)
{ }
/// <summary>
///
/// </summary>
/// <param name="deviceName"></param>
/// <param name="comPort"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public ECPDIOSiCp210x(string deviceName, string comPort)
: base(deviceName, 0)
{
_comPort = comPort;
}
/// <summary>
///
/// </summary>
/// <param name="deviceName"></param>
/// <param name="comPort"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public ECPDIOSiCp210x(string deviceName, string comPort)
: base(deviceName, 0)
{
_comPort = comPort;
}
/// <summary>
///
/// </summary>
/// <param name="comPort"></param>
public void SetComPort(string comPort)
{
_comPort = comPort;
}
/// <summary>
///
/// </summary>
/// <param name="comPort"></param>
public void SetComPort(string comPort)
{
_comPort = comPort;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private IntPtr GetHandle()
{
var comString = $"\\\\.\\{_comPort}";
var securityAttbs = NativeMethods.InitWithDefaultAttributes();
/// <summary>
///
/// </summary>
/// <returns></returns>
private IntPtr GetHandle()
{
var comString = $"\\\\.\\{_comPort}";
var securityAttbs = NativeMethods.InitWithDefaultAttributes();
//Open a handle the device specified
IntPtr hDevice = NativeMethods.CreateFileA(comString,
//Open a handle the device specified
IntPtr hDevice = NativeMethods.CreateFileA(comString,
NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE,
0,
ref securityAttbs,
3,
NativeMethods.FILE_ATTRIBUTE_NORMAL | NativeMethods.FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
0,
ref securityAttbs,
3,
NativeMethods.FILE_ATTRIBUTE_NORMAL | NativeMethods.FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
if (hDevice != NativeMethods.INVALID_HANDLE_VALUE)
{
return hDevice;
}
else
{
throw new Exception($"Unable to get a valid handle using COM port {_comPort}");
}
}
if (hDevice != NativeMethods.INVALID_HANDLE_VALUE)
{
return hDevice;
}
else
{
throw new Exception($"Unable to get a valid handle using COM port {_comPort}");
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public ushort ReadLatch()
{
var handle = GetHandle();
ushort latch = 0;
/// <summary>
///
/// </summary>
/// <returns></returns>
public ushort ReadLatch()
{
var handle = GetHandle();
ushort latch = 0;
var errCode = CP210xRuntime.CP210xRT_ReadLatch(handle, ref latch);
var errCode = CP210xRuntime.CP210xRT_ReadLatch(handle, ref latch);
NativeMethods.CloseHandle(handle);
if (errCode == SI_SUCCESS)
{
return latch;
}
else
{
throw new Exception($"Error when reading CP210X latch. Error code returned: {errCode}");
}
}
if (errCode == SI_SUCCESS)
{
return latch;
}
else
{
throw new Exception($"Error when reading CP210X latch. Error code returned: {errCode}");
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <returns></returns>
public override IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <returns></returns>
public override IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
throw new Exception($"The input channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int bitIndex = (int)_signalNameToChannelInfoMap[signalName].channelNumber - _channelStartIndex;
ushort mask = (ushort)(0x1 << (int)bitIndex);
@@ -136,59 +134,59 @@ namespace Raytheon.Instruments
return (IODatatypes.BitState)(latch & mask);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <param name="state"></param>
public override void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <param name="state"></param>
public override void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
throw new Exception($"The output channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int bitIndex = (int)_signalNameToChannelInfoMap[signalName].channelNumber - _channelStartIndex;
ushort mask = (ushort)(0x1 << (int)bitIndex);
if (state == IODatatypes.BitState.High)
{
WriteLatch(mask, mask);
}
else
{
WriteLatch(mask, 0);
}
}
}
if (state == IODatatypes.BitState.High)
{
WriteLatch(mask, mask);
}
else
{
WriteLatch(mask, 0);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="mask"></param>
/// <param name="latch"></param>
/// <returns></returns>
protected override void WriteLatch(ushort mask, ushort latch)
{
var handle = GetHandle();
/// <summary>
///
/// </summary>
/// <param name="mask"></param>
/// <param name="latch"></param>
/// <returns></returns>
protected override void WriteLatch(ushort mask, ushort latch)
{
var handle = GetHandle();
int ret = CP210xRuntime.CP210xRT_WriteLatch(handle, mask, latch);
int ret = CP210xRuntime.CP210xRT_WriteLatch(handle, mask, latch);
NativeMethods.CloseHandle(handle);
NativeMethods.CloseHandle(handle);
if (ret != SI_SUCCESS)
{
throw new Exception("call to write latch returned error: " + ret.ToString() + " on card: " + _name);
}
}
if (ret != SI_SUCCESS)
{
throw new Exception("call to write latch returned error: " + ret.ToString() + " on card: " + _name);
}
}
}
}
}

View File

@@ -30,71 +30,64 @@
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "ECPDIOSiCp210xFactory")]
public class ECPDIOSiCp210xFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
[ExportInstrumentFactory(ModelNumber = "ECPDIOSiCp210xFactory")]
public class ECPDIOSiCp210xFactory : IInstrumentFactory
{
private readonly List<Type> _supportedInterfaces = new List<Type>();
public ECPDIOSiCp210xFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public ECPDIOSiCp210xFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
public ECPDIOSiCp210xFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
/// <summary>
/// ECPDIOSiCp210xFactory injection constructor
/// </summary>
[ImportingConstructor]
public ECPDIOSiCp210xFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new ECPDIOSiCp210x(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
return new ECPDIOSiCp210x(name, _configurationManager);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
@@ -105,12 +98,10 @@ namespace Raytheon.Instruments
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
return new DIOSim(name, _configurationManager);
else
return new ECPDIOSiCp210x(name, _configurationManager, _logger);
return new ECPDIOSiCp210x(name, _configurationManager);
}
catch (Exception)
{
@@ -123,17 +114,17 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -16,14 +16,14 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using SIUSBXP_DLL;
using System.Collections.Specialized;
using NLog;
using Raytheon.Common;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;
using Raytheon.Instruments.GeneralIO;
using SIUSBXP_DLL;
namespace Raytheon.Instruments
{
@@ -49,15 +49,10 @@ namespace Raytheon.Instruments
private int _numOutputChannels;
private bool _shallWeInitializeOutput = false;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelInfoMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
@@ -149,27 +144,13 @@ namespace Raytheon.Instruments
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
try
if (disposing)
{
if (disposing)
if (_state == State.Ready)
{
if (_state == State.Ready)
{
Close();
Close();
_state = State.Uninitialized;
}
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
_state = State.Uninitialized;
}
}
}
@@ -523,11 +504,11 @@ namespace Raytheon.Instruments
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOSiUSBXp(string deviceName, IConfigurationManager configurationManager, ILogger logger)
public DIOSiUSBXp(string deviceName, IConfigurationManager configurationManager)
{
Name = deviceName;
_logger = logger;
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
@@ -561,7 +542,7 @@ namespace Raytheon.Instruments
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
@@ -572,22 +553,24 @@ namespace Raytheon.Instruments
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.ioType = IODatatypes.IOType.DigitalOutput;
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.ioType = IODatatypes.IOType.DigitalInput;
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
_handle = IntPtr.Zero;
@@ -609,7 +592,7 @@ namespace Raytheon.Instruments
_handle = IntPtr.Zero;
_state = State.Uninitialized;
_selfTestResult = SelfTestResult.Unknown;
_logger = LogManager.GetCurrentClassLogger();
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
//@@@ Do we need to pass in more args to configure the DIO (Baud?)
}
@@ -661,23 +644,9 @@ namespace Raytheon.Instruments
{
lock (_syncObj)
{
try
{
Dispose(true);
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
GC.SuppressFinalize(this);
}
}
@@ -706,15 +675,15 @@ namespace Raytheon.Instruments
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
throw new Exception($"The output channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int bitIndex = (int)_signalNameToChannelInfoMap[signalName].channelNumber - _channelStartIndex;
byte latchValue = 0;
@@ -758,11 +727,11 @@ namespace Raytheon.Instruments
}
/// <summary>
/// Return list of signal names
/// Return map of all signals
/// </summary>
public List<string> GetSignalNames()
public Dictionary<string, IODatatypes.DIOChannelInfo> GetAllSignals()
{
return new List<string>(_signalNameToChannelMap.Keys);
return _signalNameToChannelInfoMap;
}
/// <summary>
@@ -843,15 +812,15 @@ namespace Raytheon.Instruments
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The output channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
throw new Exception($"The output channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels + _channelStartIndex} on card " + _name);
}
int bitIndex = (int)_signalNameToChannelMap[signalName].channelNumber - _channelStartIndex;
int bitIndex = (int)_signalNameToChannelInfoMap[signalName].channelNumber - _channelStartIndex;
byte mask = (byte)bitIndex;

View File

@@ -30,71 +30,64 @@
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOSiUSBXpFactory")]
public class DIOSiUSBXpFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
[ExportInstrumentFactory(ModelNumber = "DIOSiUSBXpFactory")]
public class DIOSiUSBXpFactory : IInstrumentFactory
{
private readonly List<Type> _supportedInterfaces = new List<Type>();
public DIOSiUSBXpFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOSiUSBXpFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
public DIOSiUSBXpFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
/// <summary>
/// DIOSiUSBXpFactory injection constructor
/// </summary>
[ImportingConstructor]
public DIOSiUSBXpFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOSiUSBXp(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
return new DIOSiUSBXp(name, _configurationManager);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
@@ -105,12 +98,10 @@ namespace Raytheon.Instruments
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
return new DIOSim(name, _configurationManager);
else
return new DIOSiUSBXp(name, _configurationManager, _logger);
return new DIOSiUSBXp(name, _configurationManager);
}
catch (Exception)
{
@@ -123,17 +114,17 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -16,41 +16,39 @@ UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using Raytheon.Instruments.GeneralIO;
using System.Collections.Generic;
using Raytheon.Common;
using NLog;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting;
using NLog;
using Raytheon.Common;
using Raytheon.Instruments.GeneralIO;
namespace Raytheon.Instruments
{
/// <summary>
/// A Simulated DIO class
/// </summary>
public class DIOSim : IGeneralIO
{
#region PrivateClassMembers
private string _name;
private SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
/// <summary>
/// A Simulated DIO class
/// </summary>
public class DIOSim : IGeneralIO
{
#region PrivateClassMembers
private string _name;
private SelfTestResult _selfTestResult;
private State _state;
private object _syncObj = new Object();
/// <summary>
/// NLog logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Raytheon configuration
/// </summary>
private readonly IConfigurationManager _configurationManager;
private readonly IConfiguration _configuration;
private const int _channelStartIndex = 0;
private int _numInputChannels;
private int _numOutputChannels;
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
private Dictionary<string, IODatatypes.DIOChannelInfo> _signalNameToChannelInfoMap = new Dictionary<string, IODatatypes.DIOChannelInfo>();
#endregion
@@ -60,59 +58,40 @@ namespace Raytheon.Instruments
/// The finalizer.
/// </summary>
~DIOSim()
{
Dispose(false);
}
{
Dispose(false);
}
/// <summary>
/// Dispose of this object.
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
// nothing to do here
}
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected
}
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
/// <param name="disposing">True = currently disposing, False = not disposing.</param>
protected virtual void Dispose(bool disposing)
{
}
#endregion
#endregion
#region PublicClassFunctions
#region PublicClassFunctions
/// <summary>
/// DIOSim factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOSim(string deviceName, IConfigurationManager configurationManager, ILogger logger)
{
Name = deviceName;
/// <summary>
/// DIOSim factory constructor
/// </summary>
/// <param name="deviceName"></param>
/// <param name="configurationManager"></param>
public DIOSim(string deviceName, IConfigurationManager configurationManager)
{
Name = deviceName;
_logger = logger;
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
_configurationManager = configurationManager;
_configuration = _configurationManager.GetConfiguration(Name);
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string dioModuleDefPath = _configuration.GetConfigurationValue(deviceName, ConfigXml.DIO_MODULE_DEF_FILEPATH.ToString());
if (!Path.IsPathRooted(dioModuleDefPath))
dioModuleDefPath = Path.GetFullPath(Path.Combine(assemblyFolder, dioModuleDefPath));
dioModuleDefPath = Path.GetFullPath(Path.Combine(_configurationManager.ConfigurationStoragePath, dioModuleDefPath));
IConfigurationFile dioModuleConfig = new ConfigurationFile(dioModuleDefPath);
@@ -125,7 +104,7 @@ namespace Raytheon.Instruments
IODatatypes.DIOChannelInfo info;
foreach (string signalName in outputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.OUTPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.OUTPUT_SIGNALS}", signalName);
@@ -136,48 +115,50 @@ namespace Raytheon.Instruments
}
info.channelNumber = Convert.ToUInt32(infoTokens[0]);
info.ioType = IODatatypes.IOType.DigitalOutput;
info.initialValue = Convert.ToInt32(infoTokens[1]);
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
foreach (string signalName in intputSignalNames)
{
if (_signalNameToChannelMap.ContainsKey(signalName))
if (_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Key {signalName} in section {Name}.{ConfigIni.INPUT_SIGNALS} conflicts with the same key defined in another section.");
string iniLine = dioModuleConfig.ReadValue($"{Name}.{ConfigIni.INPUT_SIGNALS}", signalName);
info.channelNumber = Convert.ToUInt32(iniLine);
info.ioType = IODatatypes.IOType.DigitalInput;
info.initialValue = -1;
_signalNameToChannelMap[signalName] = info;
_signalNameToChannelInfoMap[signalName] = info;
}
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
}
/// <summary>
/// Constructor for DIO simulation.
/// </summary>
/// <param name="name"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public DIOSim(string name)
{
_name = name;
_logger = LogManager.GetCurrentClassLogger();
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
}
_state = State.Uninitialized;
}
/// <summary>
/// Return list of signal names
/// Constructor for DIO simulation.
/// </summary>
public List<string> GetSignalNames()
/// <param name="deviceName"></param>
/// <param name="inputPins"></param>
/// <param name="outputPins"></param>
public DIOSim(string deviceName)
{
return new List<string>(_signalNameToChannelMap.Keys);
_name = deviceName;
_logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
_selfTestResult = SelfTestResult.Unknown;
_state = State.Uninitialized;
}
/// <summary>
/// Return map of all signals
/// </summary>
public Dictionary<string, IODatatypes.DIOChannelInfo> GetAllSignals()
{
return _signalNameToChannelInfoMap;
}
/// <summary>
@@ -185,194 +166,180 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public bool ClearErrors()
{
throw new NotImplementedException();
}
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a DIO Sim called " + _name;
}
}
/// <summary>
///
/// </summary>
public string DetailedStatus
{
get
{
return "This is a DIO Sim called " + _name;
}
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public bool DisplayEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
try
{
Dispose(true);
/// <summary>
/// Dispose of this object.
/// </summary>
public void Dispose()
{
lock (_syncObj)
{
Dispose(true);
GC.SuppressFinalize(this);
}
catch (Exception)
{
try
{
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
}
catch (Exception)
{
//Do not rethrow. Exception from error logger that has already been garbage collected.
}
}
}
}
GC.SuppressFinalize(this);
}
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
public bool FrontPanelEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
/// <returns></returns>
public IODatatypes.BitState GetBitState(string signalName)
{
lock (_syncObj)
{
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numInputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels} on card " + _name);
throw new Exception($"The input channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numInputChannels} on card " + _name);
}
return IODatatypes.BitState.Low;
}
}
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public InstrumentMetadata Info
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
_state = State.Ready;
}
else
{
throw new Exception("DIOSim::Initialize() - expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
///
/// </summary>
public void Initialize()
{
lock (_syncObj)
{
if (_state == State.Uninitialized)
{
_state = State.Ready;
}
else
{
throw new Exception("DIOSim::Initialize() - expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
}
}
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfInputBits
{
get
{
return (uint)_numInputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
public uint NumberOfOutputBits
{
get
{
return (uint)_numOutputChannels;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
_selfTestResult = SelfTestResult.Pass;
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SelfTestResult PerformSelfTest()
{
lock (_syncObj)
{
_selfTestResult = SelfTestResult.Pass;
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
}
}
/// <summary>
///
/// </summary>
public void Reset()
{
lock (_syncObj)
{
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
/// </summary>
public SelfTestResult SelfTestResult
{
get
{
return _selfTestResult;
}
}
/// <summary>
///
@@ -380,49 +347,49 @@ namespace Raytheon.Instruments
/// <param name="channelNum"></param>
/// <param name="state"></param>
public void SetBit(string signalName, IODatatypes.BitState state)
{
lock (_syncObj)
{
if (!_signalNameToChannelMap.ContainsKey(signalName))
{
lock (_syncObj)
{
if (!_signalNameToChannelInfoMap.ContainsKey(signalName))
throw new Exception($"Signal name {signalName} doesn't exist for card: " + _name);
if (_signalNameToChannelMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelMap[signalName].channelNumber < _channelStartIndex)
if (_signalNameToChannelInfoMap[signalName].channelNumber >= _numOutputChannels || _signalNameToChannelInfoMap[signalName].channelNumber < _channelStartIndex)
{
throw new Exception($"The input channel number {_signalNameToChannelMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels} on card " + _name);
throw new Exception($"The input channel number {_signalNameToChannelInfoMap[signalName].channelNumber} specified must be >= {_channelStartIndex} and < {_numOutputChannels} on card " + _name);
}
}
}
}
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
/// <summary>
///
/// </summary>
/// <param name="bit"></param>
public void SetTristate(string signalName)
{
}
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
public State Status
{
get
{
return _state;
}
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
_state = State.Uninitialized;
}
}
#endregion
}
/// <summary>
///
/// </summary>
public void Shutdown()
{
lock (_syncObj)
{
_state = State.Uninitialized;
}
}
#endregion
}
}

View File

@@ -30,71 +30,67 @@
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOSimFactory")]
public class DIOSimFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
[ExportInstrumentFactory(ModelNumber = "DIOSimFactory")]
public class DIOSimFactory : IInstrumentFactory
{
private readonly List<Type> _supportedInterfaces = new List<Type>();
public DIOSimFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOSimFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
public DIOSimFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
/// <summary>
/// DIOSimFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOSimFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOSim(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
return new DIOSim(name, _configurationManager);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
@@ -105,8 +101,7 @@ namespace Raytheon.Instruments
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOSim(name, _configurationManager, _logger);
return new DIOSim(name, _configurationManager);
}
catch (Exception)
{
@@ -119,17 +114,17 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}

View File

@@ -30,71 +30,64 @@
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using NLog;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;
namespace Raytheon.Instruments
{
[ExportInstrumentFactory(ModelNumber = "DIOTeradyneEDigital6020AFactory")]
public class DIOTeradyneEDigital6020AFactory : IInstrumentFactory
{
/// <summary>
/// The supported interfaces
/// </summary>
private readonly List<Type> _supportedInterfaces = new List<Type>();
private ILogger _logger;
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
[ExportInstrumentFactory(ModelNumber = "DIOTeradyneEDigital6020AFactory")]
public class DIOTeradyneEDigital6020AFactory : IInstrumentFactory
{
private readonly List<Type> _supportedInterfaces = new List<Type>();
public DIOTeradyneEDigital6020AFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
private readonly IConfigurationManager _configurationManager;
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
private static string DefaultPath;
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
/// <param name="configManager"></param>
/// <param name="simEngine"></param>
/// <param name="logger"></param>
[ImportingConstructor]
public DIOTeradyneEDigital6020AFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
public DIOTeradyneEDigital6020AFactory(string defaultConfigPath = DefaultConfigPath)
: this(null, defaultConfigPath)
{
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
/// <summary>
/// COECommDeviceInstrumentFactory injection constructor
/// </summary>
[ImportingConstructor]
public DIOTeradyneEDigital6020AFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
[Import(AllowDefault = true)] string defaultConfigPath = null)
{
DefaultPath = defaultConfigPath;
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
_logger = LogManager.GetLogger(name);
return new DIOTeradyneEDigital6020A(name, _configurationManager, _logger);
}
catch (Exception)
{
throw;
}
}
if (LogManager.Configuration == null)
{
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
}
_configurationManager = configManager ?? GetConfigurationManager();
_supportedInterfaces.Add(typeof(IGeneralIO));
}
/// <summary>
/// Gets the instrument
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IInstrument GetInstrument(string name)
{
try
{
return new DIOTeradyneEDigital6020A(name, _configurationManager);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Gets the instrument
@@ -105,12 +98,10 @@ namespace Raytheon.Instruments
{
try
{
_logger = LogManager.GetLogger(name);
if (simulateHw)
return new DIOSim(name, _configurationManager, _logger);
return new DIOSim(name, _configurationManager);
else
return new DIOTeradyneEDigital6020A(name, _configurationManager, _logger);
return new DIOTeradyneEDigital6020A(name, _configurationManager);
}
catch (Exception)
{
@@ -123,17 +114,17 @@ namespace Raytheon.Instruments
/// </summary>
/// <returns></returns>
public ICollection<Type> GetSupportedInterfaces()
{
return _supportedInterfaces.ToArray();
}
{
return _supportedInterfaces.ToArray();
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
/// <summary>
/// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
/// </summary>
/// <returns></returns>
private static IConfigurationManager GetConfigurationManager()
{
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
}
}
}