diff --git a/.gitignore b/.gitignore index c41e6d94..48c4ecc9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.pyc build +_build dist *.egg-info diff --git a/doc/exec.py b/doc/exec.py index 1d227ff7..984727b7 100644 --- a/doc/exec.py +++ b/doc/exec.py @@ -6,7 +6,7 @@ except ImportError: from io import StringIO -from sphinx.util.compat import Directive +from docutils.parsers.rst import Directive from docutils import nodes, statemachine class ExecDirective(Directive): diff --git a/ivi/interface/pyvisa.py b/ivi/interface/pyvisa.py index 97782281..b49310b4 100644 --- a/ivi/interface/pyvisa.py +++ b/ivi/interface/pyvisa.py @@ -62,10 +62,26 @@ class PyVisaInstrument: "PyVisa wrapper instrument interface client" def __init__(self, resource, *args, **kwargs): if type(resource) is str: - self.instrument = visa_instrument_opener(resource, *args, **kwargs) + i = visa_instrument_opener(resource, *args, **kwargs) + # Support for "TCPIPx::aaa.bbb.ccc.ddd::ppppp::SOCKET" resources: + # These have no separate control channel, thus a termination character + # is always needed. Default newline is good for most instruments. + if "socket" in resource.lower(): + if not hasattr(i, "read_termination") or not i.read_termination: + i.read_termination = "\n" + if not hasattr(i, "write_termination") or not i.write_termination: + i.write_termination = "\n" + # Setting up self.write_termination as a shortcut to the respetive + # VISA instrument class property value. This might speed up the + # self.write() method further below, although not sure by how much. + if hasattr(i, "write_termination"): + self.write_termination = i.write_termination + else: + self.write_termination = "" # For compatibility with old style PyVISA - if not hasattr(self.instrument, 'assert_trigger'): - self.instrument.assert_trigger = self.instrument.trigger + if not hasattr(i, 'assert_trigger'): + i.assert_trigger = i.trigger + self.instrument = i else: self.instrument = resource self.buffer = io.BytesIO() @@ -104,7 +120,12 @@ def write(self, message, encoding = 'utf-8'): for message_i in message: self.write(message_i, encoding) return - self.write_raw(str(message).encode(encoding)) + # Support "TCPIPx::::::SOCKET" resources, see __init__ + if self.write_termination: + message = str(message) + self.write_termination + else: + message = str(message) + self.write_raw(message.encode(encoding)) def read(self, num=-1, encoding = 'utf-8'): "Read string from instrument" diff --git a/ivi/ivi.py b/ivi/ivi.py index 5a64bdaa..c5176df1 100644 --- a/ivi/ivi.py +++ b/ivi/ivi.py @@ -334,7 +334,7 @@ def count(self): class IviContainer(PropertyCollection): def __init__(self, *args, **kwargs): - super(IviContainer, self).__init__(*args, **kwargs) + super(IviContainer, self).__init__() def _add_attribute(self, name, attr, doc = None): cur_obj = self @@ -1615,7 +1615,7 @@ def __init__(self, resource = None, id_query = False, reset = False, *args, **kw # process out args for initialize kw = {} for k in ('range_check', 'query_instr_status', 'cache', 'simulate', 'record_coercions', - 'interchange_check', 'driver_setup', 'prefer_pyvisa'): + 'interchange_check', 'driver_setup', 'prefer_pyvisa', 'pyvisa_opts'): if k in kwargs: kw[k] = kwargs.pop(k) @@ -1696,6 +1696,7 @@ def __init__(self, resource = None, id_query = False, reset = False, *args, **kw Example resource strings:: + 'TCPIP0::10.0.0.1::12345::SOCKET' where 12345 is a TCP port 'TCPIP::10.0.0.1::INSTR' 'TCPIP0::10.0.0.1::INSTR' 'TCPIP::10.0.0.1::gpib,5::INSTR' @@ -1753,6 +1754,8 @@ def __init__(self, resource = None, id_query = False, reset = False, *args, **kw +-------------------------+----------------------+---------------------+ | Prefer PyVISA | False | prefer_pyvisa | +-------------------------+----------------------+---------------------+ + | PyVISA Options | {} | pyvisa_opts | + +-------------------------+----------------------+---------------------+ Each IVI specific driver defines it own meaning and valid values for the Driver Setup attribute. Many specific drivers ignore the value of the @@ -1823,6 +1826,7 @@ def __del__(self): def _initialize(self, resource = None, id_query = False, reset = False, **keywargs): "Opens an I/O session to the instrument." + self._pyvisa_opts = {} # decode options for op in keywargs: val = keywargs[op] @@ -1842,6 +1846,8 @@ def _initialize(self, resource = None, id_query = False, reset = False, **keywar self._driver_operation_driver_setup = val elif op == 'prefer_pyvisa': self._prefer_pyvisa = bool(val) + elif op == 'pyvisa_opts': + self._pyvisa_opts.update(val) else: raise UnknownOptionException('Invalid option') @@ -1853,6 +1859,7 @@ def _initialize(self, resource = None, id_query = False, reset = False, **keywar elif type(resource) == str: # parse VISA resource string # valid resource strings: + # TCPIP0::10.0.0.1::12345::SOCKET # TCPIP::10.0.0.1::INSTR # TCPIP0::10.0.0.1::INSTR # TCPIP::10.0.0.1::gpib,5::INSTR @@ -1870,11 +1877,11 @@ def _initialize(self, resource = None, id_query = False, reset = False, **keywar # ASRL::COM1,9600,8n1::INSTR # ASRL::/dev/ttyUSB0,9600::INSTR # ASRL::/dev/ttyUSB0,9600,8n1::INSTR - m = re.match('^(?P(?PTCPIP|USB|GPIB|ASRL)\d*)(::(?P[^\s:]+))?(::(?P[^\s:]+(\[.+\])?))?(::(?P[^\s:]+))?(::(?P[^\s:]+))?(::(?PINSTR))$', resource, re.I) + m = re.match('^(?P(?PTCPIP|USB|GPIB|ASRL)\d*)(::(?P[^\s:]+))?(::(?P[^\s:]+(\[.+\])?))?(::(?P[^\s:]+))?(::(?P[^\s:]+))?(::(?PINSTR|SOCKET))$', resource, re.I) if m is None: if 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) else: raise IOException('Invalid resource string') else: @@ -1889,58 +1896,58 @@ def _initialize(self, resource = None, id_query = False, reset = False, **keywar # TCP connection if self._prefer_pyvisa and 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) elif 'vxi11' in globals(): # connect with VXI-11 self._interface = vxi11.Instrument(resource) elif 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) else: raise IOException('Cannot use resource type %s' % res_type) elif res_type == 'USB': # USB connection if self._prefer_pyvisa and 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) elif 'usbtmc' in globals(): # connect with USBTMC self._interface = usbtmc.Instrument(resource) elif 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) else: raise IOException('Cannot use resource type %s' % res_type) elif res_type == 'GPIB': # GPIB connection if self._prefer_pyvisa and 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) elif 'linuxgpib' in globals(): # connect with linux-gpib self._interface = linuxgpib.LinuxGpibInstrument(resource) elif 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) else: raise IOException('Cannot use resource type %s' % res_type) elif res_type == 'ASRL': # Serial connection if self._prefer_pyvisa and 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) elif 'pyserial' in globals(): # connect with PySerial self._interface = pyserial.SerialInstrument(resource) elif 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) else: raise IOException('Cannot use resource type %s' % res_type) elif 'pyvisa' in globals(): # connect with PyVISA - self._interface = pyvisa.PyVisaInstrument(resource) + self._interface = pyvisa.PyVisaInstrument(resource, **self._pyvisa_opts) else: raise IOException('Unknown resource type %s' % res_type)