/*------------------------------------------------------------------------- // UNCLASSIFIED /*------------------------------------------------------------------------- RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON COMPANY. THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT. UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. -------------------------------------------------------------------------*/ using NLog; using Raytheon.Common; using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Raytheon.Instruments.PowerSupplies { /// /// Class to simulate any power supply module /// class KeysightN67xxPowerModule : PowerSupplyModule { private List _groupedModules; private List _coupledModules; private string _powerSupplySystemName; private EthernetSockets.TcpClient _tcpClient; IConfigurationFile _config; private ILogger _logger; /// /// Constructor /// public KeysightN67xxPowerModule(string iniFilePath, string powerSupplySystemName) { _logger = LogManager.GetCurrentClassLogger(); _powerSupplySystemName = powerSupplySystemName; _config = new ConfigurationFile(iniFilePath); string ipAddress = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.ETHERNET_ADDRESS.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue); int port = 0; Int32.TryParse(_config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.ETHERNET_PORT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out port); string moduleDef = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.MODULE_DEFINITION.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue); string coupledModules = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.COUPLED_MODULES.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue); string groupedModules = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.GROUPED_MODULES.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue); List powerModules = moduleDef.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); _coupledModules = coupledModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); _groupedModules = groupedModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); _tcpClient = new EthernetSockets.TcpClient(ipAddress, port); _tcpClient.Initialize(); _tcpClient.Connect(); ResetPowerSupplySystem(); bool systemRebooted = false; if (_groupedModules.Count() > 1) GroupModules(_groupedModules, out systemRebooted); else if (_coupledModules.Count() > 1) CoupleModules(_coupledModules); if (systemRebooted) { _tcpClient.Disconnect(); _tcpClient.Connect(); } if (_groupedModules.Count() > 1) { powerModules.Clear(); // since modules are grouped, we pick the first module as the representative module powerModules.Add(_groupedModules[0]); } // build the power module map string moduleIndex = ""; double ovp = 0.0; double ocp = 0.0; double voltageSetPoint = 0.0; double voltageSlewRate = -1.0; double minVoltage = 0.0; double maxVoltage = 0.0; double minCurrent = 0.0; double maxCurrent = 0.0; for (int i = 0; i < powerModules.Count(); i++) { string moduleName = powerModules[i]; moduleIndex = _config.ReadValue(moduleName, PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue); Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.OCP.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out ocp); Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.OVP.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out ovp); Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SETPOINT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out voltageSetPoint); Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SLEW_RATE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out voltageSlewRate); Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_VOLTAGE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out minVoltage); Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_VOLTAGE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out maxVoltage); Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_CURRENT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out minCurrent); Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_CURRENT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out maxCurrent); PowerModuleInfoDict[moduleName] = new Raytheon.Instruments.PowerSupplies.PowerSupplyModuleInfo(moduleIndex, ocp, ovp, voltageSetPoint, voltageSlewRate, minVoltage, maxVoltage, minCurrent, maxCurrent); ActivePowerModule = moduleName; SetConstantVoltageMode(); SetAndConfirmOvp(); SetAndConfirmOcp(); SetAndConfirmVoltageSetpoint(); SetAndConfirmVoltageSlewRate(); } } /// /// Enable or Disable Front Panel /// /// /// public override bool DisplayEnabled { set { SemObj?.Release(); } } /// /// Enable or disable Front Panel /// /// /// public override bool FrontPanelEnabled { get { SemObj?.Release(); throw new NotImplementedException(); } set { string command; try { lock (SyncObj) { if (value) command = KeysightPowerSupplyScpiCommands.SET_FRONTPANEL_ENABLE_CMD + "\n"; else command = KeysightPowerSupplyScpiCommands.SET_FRONTPANEL_DISABLE_CMD + "\n"; SendCommand(command); } } finally { SemObj?.Release(); } } } /// /// Turn on power module's output /// /// /// public override void On() { try { lock (SyncObj) { CheckActivePowerModuleValidity(); string command = KeysightPowerSupplyScpiCommands.SET_OUTPUT_ENABLE_CMD + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; SendCommand(command); } } finally { SemObj?.Release(); } } /// /// Turn off power module's output /// /// /// public override void Off() { try { lock (SyncObj) { CheckActivePowerModuleValidity(); string command = KeysightPowerSupplyScpiCommands.SET_OUTPUT_DISABLE_CMD + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; SendCommand(command); } } finally { SemObj?.Release(); } } /// /// Perform self test /// /// /// public override SelfTestResult PerformSelfTest() { try { lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.SELFTEST_CMD + "\n"; string rsp = SendCommandAndGetResponse(command); string[] stringVec = rsp.Split(','); int status = -1; Int32.TryParse(stringVec[0], out status); if (status != 0) { SelfTestResult = SelfTestResult.Fail; throw new Exception($"{_powerSupplySystemName}'s self-test failed with error code: {status}"); } else SelfTestResult = SelfTestResult.Pass; } } finally { SemObj?.Release(); } return SelfTestResult; } /// /// Set constant voltage mode /// /// /// private void SetConstantVoltageMode() { lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.SET_CONSTANT_VOLTAGE_CMD + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; SendCommand(command); } } /// /// Set and Confirm OVP /// /// /// private void SetAndConfirmOvp() { lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.SET_OVP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; SendCommand(command); command = KeysightPowerSupplyScpiCommands.READ_OVP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; string rsp = SendCommandAndGetResponse(command); double ovp = 0.0; Double.TryParse(rsp, out ovp); if (ovp != PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_) throw new Exception($"Unable to set OVP. Expected OVP: {PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_}. Actual: {ovp}"); } } /// /// Set and Confirm OCP /// /// /// private void SetAndConfirmOcp() { lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.SET_OCP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; SendCommand(command); command = KeysightPowerSupplyScpiCommands.READ_OCP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; string rsp = SendCommandAndGetResponse(command); double ocp = 0.0; Double.TryParse(rsp, out ocp); if (ocp != PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_) throw new Exception($"Unable to set OCP. Expected OCP: {PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_}. Actual: {ocp}"); } } /// /// Set and Confirm Voltage Setpoint /// /// /// private void SetAndConfirmVoltageSetpoint() { lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.SET_VOLTAGE_SETPOINT_CMD + " " + PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; SendCommand(command); command = KeysightPowerSupplyScpiCommands.READ_VOLTAGE_SETPOINT_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; string rsp = SendCommandAndGetResponse(command); double voltage = 0.0; Double.TryParse(rsp, out voltage); if (voltage != PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_) throw new Exception($"Unable to set Voltage Setpoint. Expected Voltage Setpoint: {PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_}. Actual: {voltage}"); } } /// /// Set and Confirm Slew Rate /// /// /// private void SetAndConfirmVoltageSlewRate() { lock (SyncObj) { if (PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_ > 0.0) { string command = KeysightPowerSupplyScpiCommands.SET_VOLTAGE_SLEW_RATE_CMD + " " + PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; SendCommand(command); command = KeysightPowerSupplyScpiCommands.READ_VOLTAGE_SLEW_RATE_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; string rsp = SendCommandAndGetResponse(command); double voltageSlewRate = 0.0; Double.TryParse(rsp, out voltageSlewRate); if (voltageSlewRate != PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_) throw new Exception($"Unable to set Voltage Slew Rate. Expected Voltage Slew Rate: {PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_}. Actual: {voltageSlewRate}"); } } } /// /// Get error code /// /// /// protected override string GetErrorCode(out int errorCode) { errorCode = 0; string rtn = ""; lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.READ_ERROR_CODE_CMD + "\n"; string rsp = SendCommandAndGetResponse(command); string[] stringVec = rsp.Split(','); Int32.TryParse(stringVec[0], out errorCode); if (stringVec.Length > 1) { rtn = stringVec[1]; } } return rtn; } /// /// Read voltage /// /// /// protected override double ReadVoltage() { double val = 0.0; lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.READ_VOLTAGE_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; string rsp = SendCommandAndGetResponse(command); Double.TryParse(rsp, out val); } return val; } /// /// Read current /// /// /// protected override double ReadCurrent() { double val = 0.0; lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.READ_CURRENT_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; string rsp = SendCommandAndGetResponse(command); Double.TryParse(rsp, out val); } return val; } /// /// Read protection status /// /// /// protected override int ReadProtectionStatus() { int val = -1; lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.READ_PROTECTION_STATUS_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; string rsp = SendCommandAndGetResponse(command); Int32.TryParse(rsp, out val); } return val; } /// /// Determine if module's output is on /// /// /// protected override bool IsOutputOn() { bool isOn = false; lock (SyncObj) { string command = KeysightPowerSupplyScpiCommands.READ_OUTPUT_STATUS_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n"; string rsp = SendCommandAndGetResponse(command); int status = -1; Int32.TryParse(rsp, out status); if (status == 1) { isOn = true; } } return isOn; } /// /// When modules are grouped, they act as one module /// /// /// private void GroupModules(List moduleList, out bool systemRebooted) { // 1. Group the channels string groupListToDefine = "(@"; string groupListToQuery = ""; string moduleNumber = ""; systemRebooted = false; for (int i = 0; i < moduleList.Count; i++) { moduleNumber = _config.ReadValue(moduleList[i], PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue); groupListToDefine += moduleNumber; groupListToQuery += moduleNumber; // add a ',' if this is not the final element in the list if (i < moduleList.Count() - 1) { groupListToDefine += ","; groupListToQuery += ","; } else { groupListToDefine += ")"; } } groupListToQuery = "\"" + groupListToQuery + "\"\n"; // see if channels are grouped string queryGroupCommand = KeysightPowerSupplyScpiCommands.QUERY_GROUP_CHANNELS + "\n"; for (int i = 1; i <= 2; i++) { string respStr = SendCommandAndGetResponse(queryGroupCommand); // if modules are not grouped if (respStr != groupListToQuery) { groupListToDefine += "\n"; string groupCommand = KeysightPowerSupplyScpiCommands.SET_GROUP_DEFINE_CMD + " " + groupListToDefine; SendCommand(groupCommand); } else if (i == 1) { break; } else { string command = KeysightPowerSupplyScpiCommands.REBOOT_CMD + "\n"; // after grouping the modules, need to reboot system for it to take effect SendCommand(command); // wait 20 seconds for reboot Thread.Sleep(20000); systemRebooted = true; } } } /// /// When modules are coupled, they turned on and off in unison /// i.e turn on/off one module, all other coupled modules will automatically turn on/off /// /// /// private void CoupleModules(List moduleList) { string coupleListToDefine = ""; string moduleNumber = ""; for (int i = 0; i < moduleList.Count(); i++) { moduleNumber = _config.ReadValue(moduleList[i], PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue); coupleListToDefine += moduleNumber; // add a ',' if this is not the final element in the list if (i < moduleList.Count() - 1) { coupleListToDefine += ","; } } coupleListToDefine += "\n"; // see if channels are grouped string queryCoupleChannelCommand = KeysightPowerSupplyScpiCommands.QUERY_COUPLE_CHANNELS + "\n"; for (int i = 1; i <= 2; i++) { string respStr = SendCommandAndGetResponse(queryCoupleChannelCommand); string queryCoupleStateCommand = KeysightPowerSupplyScpiCommands.QUERY_COUPLE_STATE + "\n"; string respStr2 = SendCommandAndGetResponse(queryCoupleStateCommand); if (coupleListToDefine != respStr || respStr2 == "0\n") { // send command to couple modules string command = KeysightPowerSupplyScpiCommands.SET_COUPLE_CHANNELS_CMD + " " + coupleListToDefine; SendCommand(command); // turn coupling on command = KeysightPowerSupplyScpiCommands.SET_COUPLE_ON_CMD + "\n"; SendCommand(command); // output protection on command = KeysightPowerSupplyScpiCommands.SET_COUPLE_OUTPUT_PROTECT_ON_CMD + "\n"; SendCommand(command); } else if (i == 1) break; } } /// /// Reset Power Supply System /// /// /// private void ResetPowerSupplySystem() { // send the command string command = KeysightPowerSupplyScpiCommands.RESET_CMD + "\n"; SendCommand(command); } /// /// Send command /// /// /// private void SendCommand(string command) { lock (SyncObj) { byte[] msg = Encoding.ASCII.GetBytes(command); _tcpClient.Write(msg, (uint)msg.Length); } } /// /// Send command and get response /// /// /// private string SendCommandAndGetResponse(string command) { lock (SyncObj) { byte[] readBuf = new byte[100]; _tcpClient.SetReadTimeout(2000); int bytesRec = 0; SendCommand(command); try { bytesRec = (int)_tcpClient.Read(ref readBuf); } catch (SocketException ex) { throw new Exception("SocketException Error Code: " + ex.ErrorCode + $" ({((SocketError)ex.ErrorCode).ToString()})"); } return Encoding.ASCII.GetString(readBuf, 0, bytesRec); } } } }