项目需要对频谱仪远程操作,因此初步写了几个功能,不完善,有空继续添加
罗德频谱仪相关
"""An SignalAnalyzer class and some helper functions.
NOTE: The ROHDE&SCHWARZ SignalAnalzer's port is 5025, different from Aglinet's port 5023
Only tested on Agilent N9000A CXA Signal Analyzer.
Example:
>>> from signalanalyzerlib import SA
>>> sa = SA('192.168.1.3', 5023) # connect to the signal analyzer, using port 5023
>>> sa.getwelcome() # check if connect success
'Welcome to A-N9000A-10507'
>>> sa.set_freq_cent(440, 'M') # set center freq to 440MHz
True
>>> # call other functions ...
>>> sa.close()
>>>
Note:
It's user's responsibility adding delay between calling these helper functions
Here is a nice test:
python signalanalyzerlib.py 192.168.1.3 5023
"""
#
# Create by zhuzhenyu @ 2012.12.27
#
import sys
import os
try:
import SOCKS; socket = SOCKS; del SOCKS
except ImportError:
import socket
__all__ = ["SA"]
__version__ = '0.1'
# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF)
CRLF = '\r\n'
# The class itself
class SA:
'''An Signal Analyzer connection class.
To create a connection, call the class using these arguments:
host, port
'''
debugging = 0
host = ''
port = 0
sock = None
file = None
welcome = None
# Initialization method (called by class instantiation).
def __init__(self, host='', port=0):
if host:
self.connect(host, port)
def connect(self, host='', port=0):
'''Connect to host(SA). Arguments are:
- host: hostname to connect to (string)
- port: port to connect to (integer)'''
if host != '':
self.host = host
if port > 0:
self.port = port
self.sock = socket.create_connection((self.host, self.port))
self.file = self.sock.makefile('rb')
#self.welcome = self.getresp()
#return self.welcome
def getwelcome(self):
'''Get the welcome messgage from the analyzer.
(this is read and squirreled away by connect())'''
if self.debugging:
print '*welcome*', repr(self.welcome)
return self.welcome
def set_debuglevel(self, level):
'''Set the debugging level.
The required argument level means:
0: no debugging output(default)
1: print commands and responses but not body text etc.
2: also print raw lines read and sent before stripping CR/LF'''
self.debugging = level
debug = set_debuglevel
# Internal: return one line from the analyzer, stripping CRLF.
# Raise EOFError if the connection is closed.
def getline(self):
line = self.file.readline()
if self.debugging > 1:
print '*get*', repr(line)
if not line: raise EOFError
if line[-2:] == CRLF: line = line[:-2]
elif line[-1:] in CRLF: line = line[:-1]
return line
# Internal: get a response from the analyzer, which may possibly
# consist of multiple lines. Return a single string with no
# trailing CRLF. If the response consists of multiple lines,
# these are separated by '\n' characters in the string
def getmultiline(self):
line = self.getline()
if '?' in line: # query cmd contains a '?', so does the response
nextline = self.getline()
line = line + ('\n' + nextline)
return line
# Internal: get a response from the analyzer.
def getresp(self):
resp = self.getmultiline()
if self.debugging: print '*resp*', repr(resp)
return resp
# Internal: send one line to the analyzer, appending CRLF
def putline(self, line):
line = line + CRLF
if self.debugging > 1: print '*put*', repr(line)
self.sock.sendall(line)
# Internal: send one command to the analyzer (through putline())
def putcmd(self, line):
if self.debugging: print '*cmd*', repr(line)
self.putline(line)
def sendcmd(self, cmd):
'''Send a command and return the response.'''
self.putcmd(cmd)
return self.getresp()
# Internal: skip 'SCPI>' prompt in the response and strip
def skipprompt(self, s):
if s[:6] == 'SCPI> ' or s[:6] == 'scpi> ':
s = s[6:]
# FIXME: Don't know why such strange bytes always in the first response
if '\xff\xfb\x01\xff\xfb\x03' == s[:6]:
s = s[6:]
return s.strip()
# Internal: get result from multiline response
def extractresult(self, s):
return s
def voidcmd(self, cmd):
'''Send a command and expect a response equal with the command.'''
self.putcmd(cmd)
#self.skipprompt(self.getresp()) == cmd)
def resultcmd(self, cmd):
'''Send a command and expect a response which is a number.'''
self.putcmd(cmd)
return self.extractresult(self.skipprompt(self.getresp()))
def close(self):
'''Close the connection without assuming anything about it.'''
if self.file:
self.file.close()
self.sock.close()
self.file = self.sock = None
# Check "Agilent X-Series Signal Analyzer User's and Programmer's Reference"
# for the details of the following helper functions
def freq_cent(self, freq, unit='M'):
cmd = 'FREQ:CENT ' + str(freq) + unit + 'Hz'
self.voidcmd(cmd)
def freq_span(self, span, unit='M'):
cmd = 'FREQ:SPAN ' + str(span) + unit + 'Hz'
self.voidcmd(cmd)
def disp_wind_trac_y_rlev(self, lev):
cmd = 'DISP:WIND:TRAC:Y:RLEV ' + str(lev) + 'dBm'
self.voidcmd(cmd)
def band(self, width, unit='K'):
cmd = 'BAND ' + str(width) + unit + 'Hz'
self.voidcmd(cmd)
def band_vid(self, width, unit='K'):
cmd = 'BAND:VID ' + str(width) + unit + 'Hz'
self.voidcmd(cmd)
def calc_mark_mode_pos(self):
cmd = 'CALC:MARK:MODE POS'
self.voidcmd(cmd)
def calc_mark_max(self):
cmd = 'CALC:MARK:MAX'
self.voidcmd(cmd)
def set_harm_num(self, num):
cmd = 'CALC:MARK:FUNC:HARM:NHAR ' + str(num)
self.voidcmd(cmd)
def set_harm_on_off(self, switch):
if switch == 'ON':
cmd = 'CALC:MARK:FUNC:HARM:STAT ' + switch
self.voidcmd(cmd)
elif switch == 'OFF':
cmd = 'CALC:MARK:FUNC:HARM:STAT ' + switch
self.voidcmd(cmd)
else:
pass
def read_harm_value(self):
cmd = 'CALC:MARK:FUNC:HARM:LIST?'
return self.resultcmd(cmd)
def calc_mark_x(self):
cmd = 'CALC:MARK:X?'
return self.resultcmd(cmd)
def calc_mark_y(self):
cmd = 'CALC:MARK:Y?'
return self.resultcmd(cmd)
def calc_mark_aoff(self):
cmd = 'CALC:MARK:AOFF'
self.voidcmd(cmd)
# TODO: add other functions here
def test():
'''Test program.
Usage: sa [-d] host port
-d debug
This test program will set the analyzer's center freq to 456MHz,
set the freq span to 20MHz... and output measured freq and power.
'''
import time
if len(sys.argv) < 3:
print test.__doc__
sys.exit(0)
debugging = 0
while sys.argv[1] == '-d':
debugging = debugging + 1
del sys.argv[1]
host = sys.argv[1]
port = sys.argv[2]
sa = SA(host, port)
sa.set_debuglevel(debugging)
#print sa.getwelcome()
sa.freq_cent(456, 'M')
sa.freq_span(20, 'M')
sa.disp_wind_trac_y_rlev(20)
sa.band(10, 'K')
sa.band_vid(10, 'K')
sa.calc_mark_mode_pos()
# must sleep here after calc_mark_mode_pos and calc_mark_max
time.sleep(2)
sa.calc_mark_max()
time.sleep(5)
currentfreq = sa.calc_mark_x()
currentpower = sa.calc_mark_y()
sa.calc_mark_aoff()
sa.close()
print 'Current Freq:', currentfreq
print 'Current Power:', currentpower
if __name__ == '__main__':
test()