Pure Python implementation of a VISA library for instrument communication.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Network-based instrument communication supporting multiple protocols including VXI-11, HiSLIP (High-Speed LAN Instrument Protocol), VICP (VISA over IP), and raw TCP sockets. PyVISA-py provides comprehensive Ethernet instrument support with automatic protocol detection and network discovery capabilities.
Main dispatcher for TCP/IP instrument communication that automatically creates the appropriate protocol-specific session (VXI-11 or HiSLIP) based on the resource string format.
class TCPIPInstrSession:
"""Dispatcher that creates VXI-11 or HiSLIP sessions based on resource string."""
def __new__(cls, resource_manager_session, resource_name, parsed, open_timeout):
"""
Create appropriate TCP/IP session based on resource string.
Args:
resource_manager_session (VISARMSession): Parent RM session
resource_name (str): TCP/IP resource name
parsed (rname.ResourceName): Parsed resource name
open_timeout (int): Connection timeout in milliseconds
Returns:
TCPIPInstrVxi11 or TCPIPInstrHiSLIP: Protocol-specific session instance
"""
@staticmethod
def list_resources():
"""
List available TCP/IP instruments via network discovery.
Returns:
List[str]: Combined list from VXI-11 and HiSLIP discovery
"""VXI-11 protocol implementation for standard Ethernet instrument communication.
class TCPIPInstrVxi11:
"""TCP/IP session using VXI-11 protocol for network instruments."""
def __init__(self, resource_manager_session, resource_name, parsed, open_timeout):
"""
Initialize VXI-11 session.
Args:
resource_manager_session (VISARMSession): Parent RM session
resource_name (str): TCP/IP resource name
parsed (rname.ResourceName): Parsed resource name
open_timeout (int): Connection timeout in milliseconds
"""
def read(self, count):
"""
Read data via VXI-11 protocol.
Args:
count (int): Maximum number of bytes to read
Returns:
Tuple[bytes, StatusCode]: Data read and operation status
"""
def write(self, data):
"""
Write data via VXI-11 protocol.
Args:
data (bytes): Data to transmit
Returns:
Tuple[int, StatusCode]: Number of bytes written and status
"""
def clear(self):
"""
Clear instrument via VXI-11 device clear.
Returns:
StatusCode: Operation result
"""
@staticmethod
def list_resources():
"""
Discover VXI-11 instruments via broadcast.
Returns:
List[str]: List of VXI-11 instrument resource strings
"""HiSLIP (High-Speed LAN Instrument Protocol) implementation for high-performance Ethernet communication.
class TCPIPInstrHiSLIP:
"""TCP/IP session using HiSLIP protocol for high-speed instruments."""
def __init__(self, resource_manager_session, resource_name, parsed, open_timeout):
"""
Initialize HiSLIP session.
Args:
resource_manager_session (VISARMSession): Parent RM session
resource_name (str): HiSLIP resource name
parsed (rname.ResourceName): Parsed resource name
open_timeout (int): Connection timeout in milliseconds
"""
def read(self, count):
"""
Read data via HiSLIP protocol.
Args:
count (int): Maximum number of bytes to read
Returns:
Tuple[bytes, StatusCode]: Data read and operation status
"""
def write(self, data):
"""
Write data via HiSLIP protocol.
Args:
data (bytes): Data to transmit
Returns:
Tuple[int, StatusCode]: Number of bytes written and status
"""
def clear(self):
"""
Clear instrument via HiSLIP device clear.
Returns:
StatusCode: Operation result
"""
@staticmethod
def list_resources():
"""
Discover HiSLIP instruments via mDNS.
Returns:
List[str]: List of HiSLIP instrument resource strings
"""VICP (VISA over IP) protocol implementation for LeCroy/Teledyne oscilloscopes.
class TCPIPInstrVicp:
"""TCP/IP session using VICP protocol for LeCroy oscilloscopes."""
def __init__(self, resource_manager_session, resource_name, parsed, open_timeout):
"""
Initialize VICP session.
Args:
resource_manager_session (VISARMSession): Parent RM session
resource_name (str): VICP resource name
parsed (rname.ResourceName): Parsed resource name
open_timeout (int): Connection timeout in milliseconds
"""
def read(self, count):
"""
Read data via VICP protocol.
Args:
count (int): Maximum number of bytes to read
Returns:
Tuple[bytes, StatusCode]: Data read and operation status
"""
def write(self, data):
"""
Write data via VICP protocol.
Args:
data (bytes): Data to transmit
Returns:
Tuple[int, StatusCode]: Number of bytes written and status
"""Provides raw TCP socket communication for instruments using proprietary protocols or simple socket-based communication.
class TCPIPSocketSession:
"""Session for raw TCP socket communication."""
def __init__(self, resource_manager_session, resource_name, parsed, open_timeout):
"""
Initialize TCP socket session.
Args:
resource_manager_session (VISARMSession): Parent RM session
resource_name (str): TCP socket resource name
parsed (rname.ResourceName): Parsed resource name
open_timeout (int): Connection timeout in milliseconds
"""
def read(self, count):
"""
Read data from TCP socket.
Args:
count (int): Maximum number of bytes to read
Returns:
Tuple[bytes, StatusCode]: Data read and operation status
"""
def write(self, data):
"""
Write data to TCP socket.
Args:
data (bytes): Data to transmit
Returns:
Tuple[int, StatusCode]: Number of bytes written and status
"""
def close(self):
"""
Close TCP socket connection.
Returns:
StatusCode: Operation result
"""Internal protocol implementations that handle the low-level communication details for each network protocol.
class TCPIPInstrVxi11:
"""VXI-11 protocol implementation for network instruments."""
class TCPIPInstrHiSLIP:
"""HiSLIP protocol implementation for high-speed network instruments."""
class TCPIPInstrVicp:
"""VICP protocol implementation for LeCroy oscilloscopes."""import pyvisa
# Use PyVISA-py backend
rm = pyvisa.ResourceManager('@py')
# VXI-11 is the default protocol for TCPIP::hostname::INSTR
try:
# Open VXI-11 instrument
inst = rm.open_resource("TCPIP::192.168.1.100::INSTR")
# Configure timeout
inst.timeout = 5000 # 5 seconds
# Standard SCPI communication
idn = inst.query("*IDN?")
print("Instrument ID:", idn.strip())
# Device reset and configuration
inst.write("*RST")
inst.write("*CLS") # Clear status
# Read measurement
inst.write("MEAS:VOLT:DC?")
voltage = float(inst.read())
print(f"Measured voltage: {voltage} V")
except pyvisa.VisaIOError as e:
print(f"VXI-11 communication error: {e}")
finally:
inst.close()
rm.close()# HiSLIP provides faster communication than VXI-11
# Resource format: TCPIP::hostname::hislip[session]::INSTR
try:
# Open HiSLIP instrument (session 0 is default)
inst = rm.open_resource("TCPIP::192.168.1.101::hislip0::INSTR")
# HiSLIP supports larger messages and faster transfer
inst.timeout = 10000 # 10 seconds for large data
# Query instrument capabilities
options = inst.query("*OPT?")
print("Instrument options:", options)
# Request large data block
inst.write("DATA:CAPTURE?") # Request waveform data
waveform_data = inst.read_bytes(1000000) # Read 1MB of data
print(f"Received {len(waveform_data)} bytes of waveform data")
except pyvisa.VisaIOError as e:
print(f"HiSLIP communication error: {e}")
finally:
inst.close()# Raw TCP socket for proprietary protocols
# Resource format: TCPIP::hostname::port::SOCKET
try:
# Open raw TCP socket
socket_inst = rm.open_resource("TCPIP::192.168.1.102::5025::SOCKET")
# Set socket-specific options
socket_inst.timeout = 3000
socket_inst.read_termination = '\\n'
socket_inst.write_termination = '\\n'
# Send raw commands
socket_inst.write("GET_STATUS")
status = socket_inst.read()
print("Device status:", status.strip())
# Binary protocol example
command = b'\\x02\\x01\\x00\\x04DATA\\x03' # Custom binary command
socket_inst.write_raw(command)
response = socket_inst.read_raw(128)
print(f"Binary response: {response.hex()}")
except pyvisa.VisaIOError as e:
print(f"TCP socket error: {e}")
finally:
socket_inst.close()# VICP is used by LeCroy/Teledyne oscilloscopes
# Requires pyvicp package: pip install pyvisa-py[vicp]
try:
# Open VICP instrument
scope = rm.open_resource("VICP::192.168.1.103::INSTR")
# LeCroy-specific commands
idn = scope.query("*IDN?")
print("Oscilloscope:", idn.strip())
# Configure timebase
scope.write("TIME_DIV 1E-6") # 1 µs/div
# Capture and read waveform
scope.write("ARM")
scope.write("WAIT") # Wait for trigger
# Read waveform data
scope.write("C1:WAVEFORM?")
waveform = scope.read_raw(10000000) # Read up to 10MB
print(f"Waveform size: {len(waveform)} bytes")
except pyvisa.VisaIOError as e:
print(f"VICP communication error: {e}")
finally:
scope.close()# Discover instruments on the network
def discover_network_instruments():
"""Discover instruments using various methods."""
rm = pyvisa.ResourceManager('@py')
# Method 1: List all TCPIP resources (includes discovered devices)
tcpip_resources = rm.list_resources('TCPIP?*::INSTR')
print("Discovered TCPIP instruments:", tcpip_resources)
# Method 2: List socket resources
socket_resources = rm.list_resources('TCPIP?*::SOCKET')
print("Available socket connections:", socket_resources)
# Method 3: List HiSLIP resources (if zeroconf available)
hislip_resources = rm.list_resources('TCPIP?*::hislip?*::INSTR')
print("HiSLIP instruments:", hislip_resources)
# Method 4: List VICP resources (if pyvicp and zeroconf available)
vicp_resources = rm.list_resources('VICP?*::INSTR')
print("VICP instruments:", vicp_resources)
rm.close()
return tcpip_resources + socket_resources + hislip_resources + vicp_resources
# Run discovery
instruments = discover_network_instruments()# Configure TCP keepalive for reliable connections
inst = rm.open_resource("TCPIP::192.168.1.100::INSTR")
try:
# Enable TCP keepalive (PyVISA-py specific attribute)
inst.set_visa_attribute(pyvisa.constants.VI_ATTR_TCPIP_KEEPALIVE, True)
# Configure keepalive parameters (if supported by platform)
inst.set_visa_attribute(pyvisa.constants.VI_ATTR_TCPIP_ADDR, "192.168.1.100")
# Set large timeout for long operations
inst.timeout = 30000 # 30 seconds
# Perform long-running operation
inst.write("SYSTEM:PRESET") # May take time to complete
inst.query("*OPC?") # Wait for operation complete
except Exception as e:
print(f"Keepalive configuration error: {e}")
finally:
inst.close()TCP/IP resource strings support multiple formats:
TCPIP::[board]::hostname[::lan_device_name]::INSTRTCPIP::192.168.1.100::INSTR - Basic VXI-11TCPIP0::scope.local::inst0::INSTR - With board and device nameTCPIP::[board]::hostname::hislip[session]::INSTRTCPIP::192.168.1.101::hislip0::INSTR - HiSLIP session 0TCPIP::analyzer.lab.com::hislip::INSTR - Default sessionTCPIP::[board]::hostname::port::SOCKETTCPIP::192.168.1.102::5025::SOCKET - SCPI portTCPIP0::device.local::8080::SOCKET - Custom portVICP::[board]::hostname::INSTRVICP::192.168.1.103::INSTR - LeCroy oscilloscopeNetwork communication errors and troubleshooting:
from pyvisa import VisaIOError
from pyvisa.constants import StatusCode
import socket
try:
inst = rm.open_resource("TCPIP::192.168.1.100::INSTR")
except VisaIOError as e:
if e.error_code == StatusCode.error_resource_not_found:
print("Host not reachable - check IP address and network")
elif e.error_code == StatusCode.error_timeout:
print("Connection timeout - device may not support VXI-11")
elif e.error_code == StatusCode.error_connection_lost:
print("Network connection lost")
else:
print(f"Network error: {e}")
# Handle protocol-specific errors
try:
response = inst.query("*IDN?", timeout=5000)
except VisaIOError as e:
if e.error_code == StatusCode.error_timeout:
print("Command timeout - check if device supports SCPI")
elif e.error_code == StatusCode.error_io:
print("I/O error - network communication failed")
# Check network connectivity
def test_network_connectivity(hostname, port=111): # VXI-11 uses port 111
"""Test if host is reachable on specified port."""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(3)
result = sock.connect_ex((hostname, port))
sock.close()
return result == 0
except Exception:
return False
if not test_network_connectivity("192.168.1.100"):
print("Host not reachable on VXI-11 port")TCP/IP communication has optional dependencies for enhanced functionality:
# Install all TCP/IP features
pip install pyvisa-py[psutil,hislip-discovery,vicp]
# Individual packages:
pip install psutil # Enhanced network interface discovery
pip install zeroconf # HiSLIP and VICP device discovery
pip install pyvicp # VICP protocol support| Protocol | Speed | Features | Use Case |
|---|---|---|---|
| VXI-11 | Medium | Standard, reliable | General instruments |
| HiSLIP | High | Fast, efficient | High-throughput data |
| VICP | High | LeCroy-specific | LeCroy oscilloscopes |
| Raw TCP | Variable | Custom protocols | Proprietary devices |
Install with Tessl CLI
npx tessl i tessl/pypi-pyvisa-py