//>>*************************************************************************** // UNCLASSIFIED // // COPYRIGHT 2017 RAYTHEON MISSILE SYSTEMS // ALL RIGHTS RESERVED // This data was developed pursuant to Contract Number HQ0147-12-C-0004/1088370 // with the US Government. The US Government's rights in and to this // copyrighted data are as specified in DFAR 252.227-7013 // which was made part of the above contract. // // Distribution Statement: D -Distribution authorized to the DoD and DoD // contractors only based on Critical Technology Requirements, May 2001. // Other requests shall be referred to PEO THEATER AIR DEFENSE (PMS 422). // Warning: - This document contains technical data whose export is restricted // by the Arms Export Control Act (Title 22, U.S.C.) or Export // Administration Act of 1979, as amended (Title 50, U.S.C.). Violations // of these laws are subject to severe criminal penalties. Disseminate in // accordance with provisions of DoD 5230.25. // Destruction Notice: - For unclassified, limited distribution information, // destroy by any method that will prevent disclosure of contents or // reconstruction of the document. Classified information, destroy in // accordance with DoD-5220.22-M or OPNAVINST 5510.1h. //>>*************************************************************************** using System; using System.Net.Sockets; using System.Text; using NLog; using Raytheon.Common; namespace Raytheon.Instruments { /// /// This is a class for controlling a VTI EX1200-3001, 5002, 4264 switch card. /// It only supports individual relay mode at this time. /// public class SwitchKeysightScpi : ISwitch { #region PrivateMemberVariables private const string READ_ERROR_STATUS_CMD = "SYST:ERR?"; private const string _SELFTESTCMD = "*TST?"; private const string _RESETCMD = "*RST"; //@@@ add scpi commands here private int _PORT = 5025; private const int _READ_TIMEOUT = 5000; private byte[] _readBuffer; private NetworkStream _tcpStream; private string _name; private readonly ILogger _logger; private readonly IConfigurationManager _configurationManager; private readonly IConfiguration _configuration; #endregion #region PrivateFunctions /// /// Dispose of this object's resources. /// /// True = currently disposing, False = not disposing. protected virtual void Dispose(bool disposing) { } /// /// Convert scpi data to string /// /// /// private string ConvertToString(ref byte[] data) { string rsp = System.Text.Encoding.ASCII.GetString(data); return rsp; } /// /// Get the error code. /// /// The error code (number). private int GetErrorCode() { // not calling IOQuery() here so IOQuery() can call GetErrorCode() after each query string command = READ_ERROR_STATUS_CMD + "\n"; // convert to a byte array byte[] commandBuffer = Encoding.ASCII.GetBytes(command); // send the data out _tcpStream.Write(commandBuffer, 0, commandBuffer.Length); // clear our buffer Array.Clear(_readBuffer, 0, _readBuffer.Length); // read the response int numBytesRead = _tcpStream.Read(_readBuffer, 0, _readBuffer.Length); // convert to a string string rspStr = ConvertToString(ref _readBuffer); // parse the response string[] tokens = rspStr.Split(','); int ret = Util.ConvertStringToInt32(tokens[0]); return ret; } /// /// Send a command to the DMM and get the response /// /// The command to send /// The DMM response private string IOQuery(string commandString) { // send the command IOWrite(commandString); // clear our buffer Array.Clear(_readBuffer, 0, _readBuffer.Length); // read from the response int numBytesRead = _tcpStream.Read(_readBuffer, 0, _readBuffer.Length); // convert response to a string string rspStr = ConvertToString(ref _readBuffer); // check for errors int err = GetErrorCode(); if (err != 0) { throw new Exception("SwitchKeysightScpi:IOQuery() - returned error code: " + err.ToString()); } return rspStr; } /// /// Sends a SCPI Command to the instrument. /// /// The SCPI Command to be sent to the instrument. private void IOWrite(string commandString) { // convert to a byte array byte[] commandBuffer = Encoding.ASCII.GetBytes(commandString); // send the data out _tcpStream.Write(commandBuffer, 0, commandBuffer.Length); // check for errors int err = GetErrorCode(); if (err != 0) { throw new Exception("SwitchKeysightScpi:IOQuery() - returned error code: " + err.ToString()); } } /// /// Perform self-test. /// private void SelfTest() { try { // change the timeout to account for the long self test _tcpStream.ReadTimeout = 30000; // send the command and get the response string command = _SELFTESTCMD + "\n"; string rspStr = IOQuery(command); // parse the response string[] tokens = rspStr.Split('\n'); int rsp = Util.ConvertStringToInt32(tokens[0]); if (rsp != 0) { string errorMsg = "returned an error: " + rsp.ToString() + "," + rspStr; throw new Exception(errorMsg); } } catch (Exception) { throw; } finally { // restore the timeout _tcpStream.ReadTimeout = _READ_TIMEOUT; } } #endregion #region PublicFunctions /// /// SwitchKeysightScpi factory constructor /// /// /// public SwitchKeysightScpi(string deviceName, IConfigurationManager configurationManager) { Name = deviceName; _logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}"); _configurationManager = configurationManager; _configuration = _configurationManager.GetConfiguration(Name); var address = _configuration.GetConfigurationValue("SwitchKeysightScpi", "Address", "127.0.0.1"); _PORT = _configuration.GetConfigurationValue("SwitchKeysightScpi", "Port", 5025); const int READ_BUFFER_SIZE = 512; _readBuffer = new byte[READ_BUFFER_SIZE]; TcpClient dmmSocketConn = new TcpClient(address, _PORT); _tcpStream = dmmSocketConn.GetStream(); _tcpStream.ReadTimeout = _READ_TIMEOUT; SelfTest(); } /// /// Constructor for RelaySwitch card. /// /// The address of the RelaySwitch. /// The options used for setting up the instrument. public SwitchKeysightScpi(string deviceName, string address) { const int READ_BUFFER_SIZE = 512; _name = deviceName; _logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}"); _readBuffer = new byte[READ_BUFFER_SIZE]; TcpClient dmmSocketConn = new TcpClient(address, _PORT); _tcpStream = dmmSocketConn.GetStream(); _tcpStream.ReadTimeout = _READ_TIMEOUT; SelfTest(); } /// /// Finalizer. /// ~SwitchKeysightScpi() { Dispose(false); } /// /// /// /// public bool ClearErrors() { throw new NotImplementedException(); } /// /// Close a single relay. /// /// The relay to close. public void Connect(string path) { // send the command //IOWrite(command); //read back to verify state of relay? //"ROUT:CLOS (@3923)" } /// /// Open a single relay. /// /// The relay to open. public void Disconnect(string path) { // send the command //IOWrite(command); //read back to verify state of relay? //"ROUT:OPEN (@3923)") } /// /// /// public void DisconnectAll() { } /// /// Dispose of resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// /// public string DetailedStatus { get { return "This is a Keysight 34980A switch"; } } /// /// /// public bool DisplayEnabled { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } } /// /// /// public bool FrontPanelEnabled { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } } /// /// /// public InstrumentMetadata Info { get { throw new NotSupportedException(); } } /// /// /// public void Initialize() { throw new NotSupportedException(); } /// /// /// public bool IsDebounced { get { throw new NotSupportedException(); } } /// /// /// public string Name { get { return _name; } set { _name = value; } } /// /// /// public SelfTestResult SelfTestResult { get { throw new NotSupportedException(); } } /// /// /// public State Status { get { throw new NotSupportedException(); } } /// /// /// /// public SelfTestResult PerformSelfTest() { throw new NotSupportedException(); } /// /// /// public void Reset() { IOWrite(_RESETCMD + "\n"); } /// /// /// public void Shutdown() { if (_tcpStream != null) { Reset(); _tcpStream.Dispose(); } } #endregion } }