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