def power_output(self, c, pow=None): """Turn output power on or off, or query state.""" dev = self.selectedDevice(c) if pow is None: resp = yield dev.query('OUTP?') pow = bool(int(resp)) else: if pow: yield dev.write('OUTP ON') else: yield dev.write('OUTP OFF') returnValue(pow) @setting(602, 'Center Frequency', cfreq='v[Hz]', returns='v[Hz]') def center_frequency(self, c, cfreq=None): """Set or get the sweep center frequency.""" dev = self.selectedDevice(c) if cfreq is None: resp = yield dev.query('SENSe1:FREQuency:CENTer?') cfreq = float(resp) * units.Hz else: yield dev.write('SENSe1:FREQuency:CENTer %i' %cfreq['Hz']) returnValue(cfreq) @setting(603, 'Frequency Span', span='v[Hz]', returns='v[Hz]') def frequency_span(self, c, span=None): """Set or get the sweep center frequency.""" dev = self.selectedDevice(c) if span is None: resp = yield dev.query('SENSe1:FREQuency:SPAN') span = float(resp) * units.Hz else: yield dev.write('SENSe1:FREQuency:SPAN %i' %span['Hz']) returnValue(cfreq)
def power(self, c): """ Get the current power. """ dev = self.selectedDevice(c) resp = yield dev.query('FETC:POW:AC?') returnValue(float(resp))
def _doIdentifyDevice(): for identifier in list(self.identFunctions.keys()): name = yield self.tryIdentFunc(server, channel, idn, identifier) if name is not None: returnValue(name) returnValue(UNKNOWN)
def tryIdentFunc(self, server, channel, idn, identifier): """Try calling one registered identification function. If the identification succeeds, returns the new name, otherwise returns None. """ if identifier in self.identFunctions: s = self.client[identifier] setting, context = self.identFunctions[identifier] print("Trying to identify device " + str(server) + " " + str(channel) + " on server " + str(identifier)) try: if idn is None: resp = yield s[setting](server, channel, context=context) else: resp = yield s[setting](server, channel, idn, context=context) except Exception: print('Error while attempting to identify a device') returnValue(UNKNOWN) if resp is not None and resp != UNKNOWN: print("Server " + str(identifier) + ' identified device ' + str(server) + ' ' + str(channel) + ' as ' + str(resp)) returnValue(resp) else: print("Server " + str(identifier) + ' could not identify device ' + str(server) + ' ' + str(channel))
def lookupDeviceName(self, server, channel): """Try to send a *IDN? or an alternative query to lookup info about a device. Returns the name of the device and the actual response string to the identification query. If the response cannot be parsed or the query fails, the name will be listed as '<unknown>'. """ for cls_cmd, idn_cmd in [('*CLS', '*IDN?'), ('', 'ID?'), ('CS', 'OI')]: resp = None name = UNKNOWN p = self.client.servers[server].packet() p.address(channel).timeout(Value(1, 's')) p.write(cls_cmd).query(idn_cmd) srv_ch = ''.join([str(server), " ", str(channel)]) print("Sending '%s' to %s" % (idn_cmd, srv_ch)) try: resp = (yield p.send()).query except LRError as e: if 'VisaIOError' in e.msg: resp = '' print("No response to '%s' from %s" % (idn_cmd, srv_ch)) continue except Exception: print("No response to '%s' from %s" % (idn_cmd, srv_ch)) continue # Workaround for old-style devices. if idn_cmd in ('*IDN?', 'ID?') and resp.find(',') == -1: continue name = parseIDNResponse(resp, idn_cmd) if name != UNKNOWN: print("%s '%s' response: '%s'" % (srv_ch, idn_cmd, resp)) print("%s device name: '%s'" % (srv_ch, name)) break returnValue((name, resp))
def sweep_points(self, c, points=None): """Set or get the number of points in the sweep.""" dev = self.selectedDevice(c) if points is None: resp = yield dev.query('SENSe1:SWEep:POINts?') points = int(float(resp)) else: yield dev.write('SENSe1:SWEep:POINts %i'%points) returnValue(points)
def temperatures(self): if time.time() - self._temperatures_time > CACHE_TIME: keys = 'TEMP_TNTH_DEG', 'TEMP_TNTH_DEG_MINS', 'TEMP_TNTH_DEG_MAXES' ts = yield self.readArrays(keys, 4, toTemp) #if [t for t in ts if t[0]['K'] >= ALLOWED_TEMPERATURE_RANGE[0] and t[0]['K'] <= ALLOWED_TEMPERATURE_RANGE[1]]: #if all([t[0]['K'] >= ALLOWED_TEMPERATURE_RANGE[0] and t[0]['K'] <= ALLOWED_TEMPERATURE_RANGE[1] for t in ts]): self._temperatures = ts self._temperatures_time = time.time() returnValue(self._temperatures)
def voltage(self, c, v=None): """Get or set the voltage.""" dev = self.selectedDevice(c) if v is None: resp = yield dev.query('MEAS:VOLT?') v = float(resp) * units.V else: yield dev.write('VOLT %f' % v['V']) returnValue(v)
def if_bandwidth(self, c, bw=None): """Set or get the IF bandwidth.""" dev = self.selectedDevice(c) if bw is None: resp = yield dev.query('SENSe1:BANDwidth?') bw = float(resp) * units.Hz else: yield dev.write('SENSe1:BANDwidth %i' %bw['Hz']) returnValue(type)
def frequency(self, c, f=None): """ Get or set the calibration frequency. """ dev = self.selectedDevice(c) if f is not None: yield dev.write('SENS:FREQ %fHz' %f) resp = yield dev.query('SENS:FREQ?') returnValue(float(resp))
def stop_frequency(self, c, stop=None): """Set or get sweep stop frequency.""" dev = self.selectedDevice(c) if stop is None: resp = yield dev.query('SENSe1:FREQuency:STOP?') stop = float(resp) * units.Hz else: yield dev.write('SENSe1:FREQuency:STOP %i' %stop['Hz']) returnValue(stop)
def read(self, key, index=0): """Read a data value from the compressor.""" if key not in READABLE: raise Exception('Cannot read key "%s".' % (key,)) p = self.packet() p.write(read(HASHCODES[key], index=index)) p.read_line('\r') ans = yield p.send() returnValue(getValue(ans.read_line))
def current(self, c, cur=None): """Get or set the current.""" dev = self.selectedDevice(c) if cur is None: resp = yield dev.query('MEAS:CURR?') cur = float(resp) * units.A else: yield dev.write('CURR %f' % cur['A']) returnValue(cur)
def source_power(self, c, pow=None): """Set or get source RF power.""" dev = self.selectedDevice(c) if pow is None: resp = yield dev.query('SOURce:POWer?') pow = float(resp) * units.dBm else: yield dev.write('SOURce:POW1 %f' %pow['dBm']) returnValue(pow)
def current(self, c, cur=None): """Get or set the current.""" dev = self.selectedDevice(c) if cur is None: resp = yield dev.query('MEAS:CURR?') cur = float(resp)*units.A else: yield dev.write('CURR %f' % cur['A']) returnValue(cur)
def voltage(self, c, v=None): """Get or set the voltage.""" dev = self.selectedDevice(c) if v is None: resp = yield dev.query('MEAS:VOLT?') v = float(resp)*units.V else: yield dev.write('VOLT %f' % v['V']) returnValue(v)
def output_state(self, c, os=None): """Get or set the output state, on or off.""" dev = self.selectedDevice(c) if os is None: resp = yield dev.query('OUTP?') os = bool(int(resp)) else: yield dev.write('OUTP %d' % int(os)) returnValue(os)
def frequency(self, c, f=None): """ Get or set the calibration frequency. """ dev = self.selectedDevice(c) if f is not None: yield dev.write('SENS:FREQ %fHz' % f) resp = yield dev.query('SENS:FREQ?') returnValue(float(resp))
def get_channel( self ): # found that when stringing together commands in the serial server, need about a 20ms delay between write and read for the mux board to operate properly. Either add a delay or change the baud rate self.write('?') # this command is currently not working properly read_chan = yield self.read() print read_chan returnValue( ord(read_chan) - ord('A') ) # queries received from RF Mux are in ASCII, channel 0 = 'A', channel 1 = 'B' etc
def read(self, key, index=0): """Read a data value from the compressor.""" if key not in READABLE: raise Exception('Cannot read key "%s".' % (key, )) p = self.packet() p.write(read(HASHCODES[key], index=index)) p.read_line('\r') ans = yield p.send() returnValue(getValue(ans.read_line))
def center_frequency(self, c, freq=None): """Set or get the center frequency of the trace.""" dev = self.selectedDevice(c) if freq is None: resp = yield dev.query('CF?') freq = float(resp) * units.Hz else: yield dev.write('CF %i' %freq['Hz']) returnValue(freq)
def frequency_span(self, c, span=None): """Set or get the sweep center frequency.""" dev = self.selectedDevice(c) if span is None: resp = yield dev.query('SENSe1:FREQuency:SPAN') span = float(resp) * units.Hz else: yield dev.write('SENSe1:FREQuency:SPAN %i' %span['Hz']) returnValue(cfreq)
def center_frequency(self, c, cfreq=None): """Set or get the sweep center frequency.""" dev = self.selectedDevice(c) if cfreq is None: resp = yield dev.query('SENSe1:FREQuency:CENTer?') cfreq = float(resp) * units.Hz else: yield dev.write('SENSe1:FREQuency:CENTer %i' %cfreq['Hz']) returnValue(cfreq)
def averagingOnOff(self, c, onoff=None): """ Turn averaging on or off. If onoff is not specified, determine if averaging is on or off. """ dev = self.selectedDevice(c) if onoff is not None: yield dev.write('SENS:AVER %d' % int(onoff)) resp = yield dev.query('SENS:AVER?') returnValue(bool(int(resp)))
def cpu_temp(self, c): """Get the CPU temperature.""" dev = self.selectedDevice(c) if time.time() - dev.cpu_temp_time > CACHE_TIME: ans = yield dev.read('CPU_TEMP') t = toTemp(ans) if t >= ALLOWED_TEMPERATURE_RANGE[0] and t <= ALLOWED_TEMPERATURE_RANGE[1]: dev.cpu_temp = t dev.cpu_temp_time = time.time() returnValue(dev.cpu_temp)
def motor_current(self, c): """Get the motor current draw.""" dev = self.selectedDevice(c) if time.time() - dev.motor_current_time > CACHE_TIME: ans = yield dev.read('MOTOR_CURR_A') t = float(ans) * A if t >= ALLOWED_CURRENT_RANGE[0] and t <= ALLOWED_CURRENT_RANGE[1]: dev.motor_current = t dev.motor_current_time = time.time() returnValue(dev.motor_current)
def averagingLength(self, c, num=None): """ Get or set the averaging length. Allowable values between 1 and 1024. """ dev = self.selectedDevice(c) if num is not None: yield dev.write('SENS:AVER:COUN %d' % num) resp = yield dev.query('SENS:AVER:COUN?') returnValue(int(resp))
def averagingOnOff(self, c, onoff=None): """ Turn averaging on or off. If onoff is not specified, determine if averaging is on or off. """ dev = self.selectedDevice(c) if onoff is not None: yield dev.write('SENS:AVER %d' %int(onoff)) resp = yield dev.query('SENS:AVER?') returnValue(bool(int(resp)))
def units(self, c, units=None): """ Get or set the power units. Must be either 'DBM' or 'W'. """ dev = self.selectedDevice(c) if units is not None: yield dev.write('UNIT:POW ' + units) resp = yield dev.query('UNIT:POW?') returnValue(resp)
def averagingLength(self, c, num=None): """ Get or set the averaging length. Allowable values between 1 and 1024. """ dev = self.selectedDevice(c) if num is not None: yield dev.write('SENS:AVER:COUN %d' %num) resp = yield dev.query('SENS:AVER:COUN?') returnValue(int(resp))
def output_state(self, c, os=None): """Get or set the output state, on or off.""" dev = self.selectedDevice(c) if os is None: resp = yield dev.query('OUTP?') os = bool(int(resp)) else: print 'OUTP %i' % int(os) yield dev.write('OUTP %i' % int(os)) returnValue(os)
def units(self, c, units=None): """ Get or set the power units. Must be either 'DBM' or 'W'. """ dev = self.selectedDevice(c) if units is not None: yield dev.write('UNIT:POW '+units) resp = yield dev.query('UNIT:POW?') returnValue(resp)
def cpu_temp(self, c): """Get the CPU temperature.""" dev = self.selectedDevice(c) if time.time() - dev.cpu_temp_time > CACHE_TIME: ans = yield dev.read('CPU_TEMP') t = toTemp(ans) if t >= ALLOWED_TEMPERATURE_RANGE[ 0] and t <= ALLOWED_TEMPERATURE_RANGE[1]: dev.cpu_temp = t dev.cpu_temp_time = time.time() returnValue(dev.cpu_temp)
def average_points(self, c, count=None): """ Set or get the number of measurements to combine for an average. """ dev = self.selectedDevice(c) if count is None: resp = yield dev.query('SENSe1:AVER:COUN?') count = int(float(resp)) else: yield dev.write('SENSe1:AVER:COUN %d' %count) returnValue(count)
def readArrays(self, keys, length, processFunc): """Read arrays from the compressor, returning processed results.""" p = self.packet() for i in range(length): for key in keys: p.write(read(HASHCODES[key], i)) p.read_line('\r', key=(i, key)) ans = yield p.send() vals = [[processFunc(getValue(ans[i, key])) for key in keys] for i in range(length)] returnValue(vals)
def average_mode(self, c, avg=None): """Turn sweep averaging on or off, or query state.""" dev = self.selectedDevice(c) if avg is None: resp = yield dev.query('SENSe1:AVERage?') avg = bool(int(resp)) else: if avg: yield dev.write('SENSe1:AVERage ON') else: yield dev.write('SENSe1:AVERage OFF') returnValue(avg)
def get_s2p(self, c, ports=(1, 2)): """Get the scattering parameters from the network analyzer in the S2P format. The input parameter should be a tuple that specifies two network analyzer ports, e.g. (1, 2). Available ports are 1, 2, 3, and 4. The data are returned as a list of tuples in the following format: *(frequency, S[ports[0],ports[0]], Phase[ports[0], ports[0]], S[ports[1],ports[0]], Phase[ports[1], ports[0]], S[ports[0],ports[1]], Phase[ports[0], ports[1]], S[ports[1],ports[1]], Phase[ports[0], ports[1]]). """ if len(ports) != 2: raise Exception("Two and only two ports should be " + "specified.") for port in ports: if port < 1 or port > 4: raise Exception("Port number could be only '1', '2', " + "'3', or '4'.") if ports[0] == ports[1]: raise Exception("Port numbers should not be equal.") dev = self.selectedDevice(c) meas = yield dev.query('SYST:ACT:MEAS?') yield dev.write('CALC:PAR:SEL %s' %meas) yield dev.write('FORM ASCii,0') avgMode = yield self.average_mode(c) if avgMode: avgCount = yield self.average_points(c) yield self.restart_averaging(c) yield dev.write('SENS:SWE:GRO:COUN %i' %avgCount) yield dev.write('SENS:SWE:MODE GRO') else: yield dev.write('ABORT;:INITIATE:IMMEDIATE') # Wait for the measurement to finish. yield dev.query('*OPC?') ascii_data = yield dev.query("CALC:DATA:SNP:PORT? '%i, %i'" %ports) data = numpy.array([x for x in ascii_data.split(',')], dtype=float) length = numpy.size(data) / 9 data = data.reshape(9, length) data = [(data[0, k] * units.Hz, data[1, k] * units.dB, data[2, k] * units.deg, data[3, k] * units.dB, data[4, k] * units.deg, data[5, k] * units.dB, data[6, k] * units.deg, data[7, k] * units.dB, data[8, k] * units.deg) for k in range(length)] returnValue(data)
def findDevices(self): """Find available devices from list stored in the registry.""" devs = [] for name, port in self.serialLinks: if name not in self.client.servers: continue server = self.client[name] ports = yield server.list_serial_ports() if port not in ports: continue devName = '%s - %s' % (name, port) devs += [(devName, (server, port))] returnValue(devs)
def findDevices(self): """Find available devices from list stored in the registry.""" devs = [] for name, port in self.serialLinks: if name not in self.client.servers: continue # The serial server of the appropriate computer server = self.client[name] ports = yield server.list_serial_ports() # Checks that expected arduinos are plugged in. if port not in ports: continue devName = '%s - %s' % (name, port) devs += [(devName, (server, port))] returnValue(devs)
def sweep_type(self, c, stype=None): """ Set or get the frequency sweep type. 'LIN' - for linear, 'CW' - for single frequency. """ dev = self.selectedDevice(c) if stype is None: stype = yield dev.query('SENSe1:SWEep:TYPE?') else: if (stype.upper() != 'CW') and (stype.upper() != 'LIN'): raise ValueError('Unknown sweep type: ' + str(stype) + '. Please use "LIN" or "CW".') else: yield dev.write('SENSe1:SWEep:TYPE ' + stype) returnValue(stype)
def lookupDeviceName(self, server, channel): """Try to send a *IDN? query to lookup info about a device. Returns the name of the device and the actual response string to the identification query. If the response cannot be parsed or the query fails, the name will be listed as '<unknown>'. """ for k in range(0,2): p = self.client.servers[server].packet() p.address(channel).timeout(Value(1,'s')).write('*CLS').write('*IDN?').read() print('Sending *IDN? to', server, channel) resp = None try: resp = (yield p.send()).read name = parseIDNResponse(resp) except Exception as e: print('Error sending *IDN? to', server, channel + ':', e) name = UNKNOWN returnValue((name, resp))
def getFrequency(self, chan): output = '/I' + str(chan) + 'R0e' yield self.write(output) data = yield self.read() try : data = data.split(',') data = data[2][14:-6] data = data.replace(' ','') data = int(data, 16) returnValue(W(data, 'MHz')) except: time.sleep(0.1) output = '/I' + str(chan) + 'R0e' yield self.write(output) data = yield self.read() data = data.split(',') data = data[2][14:-6] data = data.replace(' ','') data = (int(data, 16) * 500)/2147483647.0 returnValue(W(data, 'MHz'))
def getFrequency(self, chan): output = '/I' + str(chan) + 'R0e' yield self.write(output) data = yield self.read() try: data = data.split(',') data = data[2][14:-6] data = data.replace(' ', '') data = int(data, 16) returnValue(W(data, 'MHz')) except: time.sleep(0.1) output = '/I' + str(chan) + 'R0e' yield self.write(output) data = yield self.read() data = data.split(',') data = data[2][14:-6] data = data.replace(' ', '') data = (int(data, 16) * 500) / 2147483647.0 returnValue(W(data, 'MHz'))
def tryIdentFunc(self, server, channel, idn, identifier): """Try calling one registered identification function. If the identification succeeds, returns the new name, otherwise returns None. """ try: #yield self.client.refresh() s = self.client[identifier] setting, context = self.identFunctions[identifier] print('Trying to identify device', server, channel, end=' ') print('on server', identifier, end=' ') print('with *IDN?:', repr(idn)) if idn is None: resp = yield s[setting](server, channel, context=context) else: resp = yield s[setting](server, channel, idn, context=context) if resp is not None: data = (identifier, server, channel, resp) print('Server %s identified device %s %s as "%s"' % data) returnValue(resp) except Exception as e: print('Error during ident:', str(e))
def tryIdentFunc(self, server, channel, idn, identifier): """Try calling one registered identification function. If the identification succeeds, returns the new name, otherwise returns None. """ try: #yield self.client.refresh() s = self.client[identifier] setting, context = self.identFunctions[identifier] print 'Trying to identify device', server, channel, print 'on server', identifier, print 'with *IDN?:', repr(idn) if idn is None: resp = yield s[setting](server, channel, context=context) else: resp = yield s[setting](server, channel, idn, context=context) if resp is not None: data = (identifier, server, channel, resp) print 'Server %s identified device %s %s as "%s"' % data returnValue(resp) except Exception, e: print 'Error during ident:', str(e)
def getOpsReg(self, c): """Get the operating mode.""" dev = self.selectedDevice(c) returnedVal = yield dev.query('STAT:OPER:COND?') #.strip('\x00')) opCode = int(returnedVal) codeList = [int(x) for x in "{0:016b}".format(opCode)] codeList.reverse() CAL = bool(codeList[0]) WTG = bool(codeList[5]) CV = bool(codeList[8]) CC = bool(codeList[10]) if CV: returnValue('CV Mode') elif CC: returnValue('CC Mode') else: returnValue('OutputOff')
def getAmplitude(self, chan): output = '/I' + str(chan) + 'R0e' yield self.write(output) data = yield self.read() try: data = data.split(',') data = data[2][8:14] data = data.replace(' ', '') data = int(data, 16) * 0.276376 returnValue(W(data, 'MHz')) except: time.sleep(0.1) output = '/I' + str(chan) + 'R0e' yield self.write(output) data = yield self.read() data = data.split(',') data = data[2][8:14] data = data.replace(' ', '') volts = ((int(data, 16) * 0.276376) / 16383) + 0.00022387211 if volts == 0: returnValue(W(-63, 'dbm')) else: amp = 20 * np.log10(volts) + 10 returnValue(W(amp, 'dbm'))
def pressures(self): if time.time() - self._pressures_time > CACHE_TIME: keys = 'PRES_TNTH_PSI', 'PRES_TNTH_PSI_MINS', 'PRES_TNTH_PSI_MAXES' self._pressures = yield self.readArrays(keys, 2, toPress) self._pressures_time = time.time() returnValue(self._pressures)
def compressorStatus(self): if time.time() - self.status_time > CACHE_TIME: ans = yield self.read('COMP_ON') self.status = bool(ans) self.status_time = time.time() returnValue(self.status)
def elapsed_time(self, c): """Get the elapsed running time of the compressor.""" dev = self.selectedDevice(c) ans = yield dev.read('COMP_MINUTES') returnValue(float(ans) * minutes)
def read_raw(self, c, hashcode, index=0): dev = self.selectedDevice(c) ans = yield dev.read_raw(hashcode, index) returnValue(ans)
def read(self): """Read data from the arduino""" p = self.packet() p.read() ans = yield p.send() returnValue(ans.read)
class GPIBDeviceManager(LabradServer): """Manages autodetection and identification of GPIB devices. The device manager listens for "GPIB Device Connect" and "GPIB Device Disconnect" messages coming from GPIB bus servers. It attempts to identify the connected devices and forward the messages on to servers interested in particular devices. For devices that cannot be identified by *IDN? in the usual way, servers can register an identification setting to be called by the device manager to properly identify the device. """ name = 'GPIB Device Manager' @inlineCallbacks def initServer(self): """Initialize the server after connecting to LabRAD.""" self.knownDevices = {} # maps (server, channel) to (name, idn) self.deviceServers = { } # maps device name to list of interested servers self.identFunctions = {} # maps server to (setting, ctx) for ident self.identLock = DeferredLock() # named messages are sent with source ID first, which we ignore connect_func = lambda c, (s, payload): self.gpib_device_connect( *payload) disconnect_func = lambda c, (s, payload): self.gpib_device_disconnect( *payload) mgr = self.client.manager self._cxn.addListener(connect_func, source=mgr.ID, ID=10) self._cxn.addListener(disconnect_func, source=mgr.ID, ID=11) yield mgr.subscribe_to_named_message('GPIB Device Connect', 10, True) yield mgr.subscribe_to_named_message('GPIB Device Disconnect', 11, True) # do an initial scan of the available GPIB devices yield self.refreshDeviceLists() @inlineCallbacks def refreshDeviceLists(self): """Ask all GPIB bus servers for their available GPIB devices.""" servers = [s for n, s in self.client.servers.items() if (('GPIB Bus' in n) or ('gpib_bus' in n)) and \ (('List Devices' in s.settings) or \ ('list_devices' in s.settings))] names = [s.name for s in servers] print 'Pinging servers:', names resp = yield DeferredList([s.list_devices() for s in servers]) for name, (success, addrs) in zip(names, resp): if not success: print 'Failed to get device list for:', name else: print 'Server %s has devices: %s' % (name, addrs) for addr in addrs: self.gpib_device_connect(name, addr) @inlineCallbacks def gpib_device_connect(self, server, channel): """Handle messages when devices connect.""" print 'Device Connect:', server, channel if (server, channel) in self.knownDevices: return device, idnResult = yield self.lookupDeviceName(server, channel) if device == UNKNOWN: device = yield self.identifyDevice(server, channel, idnResult) self.knownDevices[server, channel] = (device, idnResult) # forward message if someone cares about this device if device in self.deviceServers: self.notifyServers(device, server, channel, True) def gpib_device_disconnect(self, server, channel): """Handle messages when devices connect.""" print 'Device Disconnect:', server, channel if (server, channel) not in self.knownDevices: return device, idnResult = self.knownDevices[server, channel] del self.knownDevices[server, channel] # forward message if someone cares about this device if device in self.deviceServers: self.notifyServers(device, server, channel, False) @inlineCallbacks def lookupDeviceName(self, server, channel): """Try to send a *IDN? query to lookup info about a device. Returns the name of the device and the actual response string to the identification query. If the response cannot be parsed or the query fails, the name will be listed as '<unknown>'. """ p = self.client.servers[server].packet() p.address(channel).timeout(1).write('*IDN?').read() print 'Sending *IDN? to', server, channel resp = None try: resp = (yield p.send()).read name = parseIDNResponse(resp) except Exception, e: print 'Error sending *IDN? to', server, channel + ':', e name = UNKNOWN returnValue((name, resp))