频谱仪远程操作Python类

来源:互联网 发布:日语口语网络课程 编辑:程序博客网 时间:2024/05/22 13:47

项目需要对频谱仪远程操作,因此初步写了几个功能,不完善,有空继续添加

罗德频谱仪相关

"""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()



原创粉丝点击