1# Lint as: python2, python3 2# Copyright (c) 2018 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6from autotest_lib.client.common_lib import error 7from autotest_lib.server.cros.network import telnet_helper 8 9 10class Attenuator(object): 11 """Represents a minicircuits telnet-controlled 4-channel variable 12 attenuator.""" 13 14 def __init__(self, host, num_atten=0): 15 self._tnhelper = telnet_helper.TelnetHelper( 16 tx_cmd_separator="\r\n", rx_cmd_separator="\r\n", prompt="") 17 self.host = host 18 self.num_atten = num_atten 19 self.open(host) 20 21 22 def __del__(self): 23 if self.is_open(): 24 self.close() 25 26 def open(self, host, port=22): 27 """Opens a telnet connection to the attenuator and queries basic 28 information. 29 30 @param host: Valid hostname 31 @param port: Optional port number, defaults to 22 32 33 """ 34 self._tnhelper.open(host, port) 35 36 if self.num_atten == 0: 37 self.num_atten = 1 38 39 config_str = self._tnhelper.cmd("MN?") 40 41 if config_str.startswith("MN="): 42 config_str = config_str[len("MN="):] 43 44 self.properties = dict(list(zip(['model', 'max_freq', 'max_atten'], 45 config_str.split("-", 2)))) 46 self.max_atten = float(self.properties['max_atten']) 47 self.min_atten = 0 48 49 def is_open(self): 50 """Returns true if telnet connection to attenuator is open.""" 51 return bool(self._tnhelper.is_open()) 52 53 def reopen(self, host, port=22): 54 """Close and reopen telnet connection to the attenuator.""" 55 self._tnhelper.close() 56 self._tnhelper.open(host, port) 57 58 def close(self): 59 """Closes the telnet connection.""" 60 self._tnhelper.close() 61 62 def set_atten(self, channel, value): 63 """Set attenuation of the attenuator for given channel (0-3). 64 65 @param channel: Zero-based attenuator channel to set attenuation (0-3) 66 @param value: Floating point value for attenuation to be set 67 """ 68 if not self.is_open(): 69 raise error.TestError("Connection not open!") 70 71 if channel >= self.num_atten: 72 raise error.TestError("Attenuator channel out of range! Requested " 73 "%d; max available %d" % 74 (channel, self.num_atten)) 75 76 if not (self.min_atten <= value <= self.max_atten): 77 raise error.TestError("Requested attenuator value %d not in range " 78 "(%d - %d)" % 79 (value, self.min_atten, self.max_atten)) 80 # The actual device uses one-based channel for channel numbers. 81 if (int(self._tnhelper.cmd("CHAN:%d:SETATT:%d" % 82 (channel + 1, value))) != 1): 83 raise error.TestError("Error while setting attenuation on %d" % 84 channel) 85 86 def get_atten(self, channel): 87 """Returns current attenuation of the attenuator for given channel. 88 89 @param channel: Attenuator channel 90 @returns the current attenuation value as a float 91 """ 92 if not self.is_open(): 93 raise error.TestError("Connection not open!") 94 95 if channel >= self.num_atten or channel < 0: 96 raise error.TestError("Attenuator channel out of range! Requested " 97 "%d; should be between 0 and max available " 98 "%d" % (channel, self.num_atten)) 99 100 return float(self._tnhelper.cmd("CHAN:%d:ATT?" % (channel + 1))) 101