177 lines
6.4 KiB
Python
177 lines
6.4 KiB
Python
"""Instrument factory for creating configured instrument sets.
|
|
|
|
This module provides a factory pattern for creating sets of instruments
|
|
based on configuration. It abstracts away the choice between simulated
|
|
and real hardware, allowing test code to be written once and run against
|
|
either backend.
|
|
"""
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Literal
|
|
|
|
from py_dvt_ate.instruments.interfaces import IMultimeter, IPowerSupply, IThermalChamber
|
|
|
|
|
|
@dataclass
|
|
class InstrumentSet:
|
|
"""Container for a complete set of instruments.
|
|
|
|
Holds all instruments needed for DVT testing. All instruments implement
|
|
the interface protocols (IThermalChamber, IPowerSupply, IMultimeter),
|
|
allowing them to be simulated or real hardware.
|
|
|
|
Attributes:
|
|
chamber: Thermal chamber for temperature control.
|
|
psu: Programmable power supply for DUT power.
|
|
dmm: Digital multimeter for precision measurements.
|
|
"""
|
|
|
|
chamber: IThermalChamber
|
|
psu: IPowerSupply
|
|
dmm: IMultimeter
|
|
|
|
|
|
@dataclass
|
|
class InstrumentConfig:
|
|
"""Configuration for instrument connections.
|
|
|
|
Defines how to connect to instruments. The backend determines whether
|
|
to use simulated instruments (TCP connections to virtual instruments)
|
|
or real hardware (PyVISA connections).
|
|
|
|
Attributes:
|
|
backend: "simulator" for virtual instruments, "pyvisa" for real hardware.
|
|
|
|
Simulator Settings:
|
|
simulator_host: Hostname/IP of simulation server. Default "localhost".
|
|
chamber_port: TCP port for thermal chamber simulator. Default 5001.
|
|
psu_port: TCP port for power supply simulator. Default 5002.
|
|
dmm_port: TCP port for multimeter simulator. Default 5003.
|
|
|
|
PyVISA Settings (for real hardware):
|
|
chamber_visa: VISA resource string for thermal chamber (e.g., "TCPIP::192.168.1.10::INSTR").
|
|
psu_visa: VISA resource string for power supply.
|
|
dmm_visa: VISA resource string for multimeter.
|
|
"""
|
|
|
|
backend: Literal["simulator", "pyvisa"]
|
|
|
|
# Simulator settings
|
|
simulator_host: str = "localhost"
|
|
chamber_port: int = 5001
|
|
psu_port: int = 5002
|
|
dmm_port: int = 5003
|
|
|
|
# PyVISA settings (for real hardware)
|
|
chamber_visa: str | None = None
|
|
psu_visa: str | None = None
|
|
dmm_visa: str | None = None
|
|
|
|
|
|
class InstrumentFactory:
|
|
"""Factory for creating instrument sets from configuration.
|
|
|
|
This factory encapsulates the creation logic for instrument sets,
|
|
hiding the complexity of instantiating transports and drivers based
|
|
on the chosen backend.
|
|
|
|
Example:
|
|
>>> config = InstrumentConfig(backend="simulator")
|
|
>>> instruments = InstrumentFactory.create(config)
|
|
>>> instruments.chamber.set_temperature(85.0)
|
|
>>> instruments.psu.set_voltage(1, 3.3)
|
|
>>> voltage = instruments.dmm.measure_dc_voltage()
|
|
"""
|
|
|
|
@staticmethod
|
|
def create(config: InstrumentConfig) -> InstrumentSet:
|
|
"""Create instrument set based on configuration.
|
|
|
|
Args:
|
|
config: Configuration specifying backend and connection details.
|
|
|
|
Returns:
|
|
InstrumentSet containing all configured instruments.
|
|
|
|
Raises:
|
|
ValueError: If backend is unknown or configuration is invalid.
|
|
ConnectionError: If unable to connect to instruments.
|
|
"""
|
|
if config.backend == "simulator":
|
|
return InstrumentFactory._create_simulated(config)
|
|
elif config.backend == "pyvisa":
|
|
return InstrumentFactory._create_pyvisa(config)
|
|
else:
|
|
raise ValueError(f"Unknown backend: {config.backend}")
|
|
|
|
@staticmethod
|
|
def _create_simulated(config: InstrumentConfig) -> InstrumentSet:
|
|
"""Create simulated instruments connected via TCP.
|
|
|
|
Creates TCP transports for each virtual instrument and wraps them
|
|
in SCPI drivers. The simulation server must be running and listening
|
|
on the configured ports.
|
|
|
|
Args:
|
|
config: Configuration with simulator_host and port settings.
|
|
|
|
Returns:
|
|
InstrumentSet with simulated instruments.
|
|
|
|
Raises:
|
|
ConnectionError: If unable to connect to simulation server.
|
|
"""
|
|
from py_dvt_ate.instruments.drivers.chamber import ThermalChamberDriver
|
|
from py_dvt_ate.instruments.drivers.multimeter import MultimeterDriver
|
|
from py_dvt_ate.instruments.drivers.power_supply import PowerSupplyDriver
|
|
from py_dvt_ate.instruments.transport.tcp import TCPTransport
|
|
|
|
# Create transports for each instrument
|
|
chamber_transport = TCPTransport(config.simulator_host, config.chamber_port)
|
|
psu_transport = TCPTransport(config.simulator_host, config.psu_port)
|
|
dmm_transport = TCPTransport(config.simulator_host, config.dmm_port)
|
|
|
|
# Wrap transports in drivers
|
|
return InstrumentSet(
|
|
chamber=ThermalChamberDriver(chamber_transport),
|
|
psu=PowerSupplyDriver(psu_transport),
|
|
dmm=MultimeterDriver(dmm_transport),
|
|
)
|
|
|
|
@staticmethod
|
|
def _create_pyvisa(config: InstrumentConfig) -> InstrumentSet:
|
|
"""Create PyVISA instruments for real hardware.
|
|
|
|
Creates VISA transports for each real instrument and wraps them
|
|
in SCPI drivers. Requires PyVISA to be installed and VISA resource
|
|
strings to be configured.
|
|
|
|
Args:
|
|
config: Configuration with chamber_visa, psu_visa, dmm_visa settings.
|
|
|
|
Returns:
|
|
InstrumentSet with real hardware instruments.
|
|
|
|
Raises:
|
|
NotImplementedError: PyVISA backend not yet implemented.
|
|
ValueError: If required VISA resource strings are missing.
|
|
"""
|
|
# Future implementation would use pyvisa.ResourceManager
|
|
# to create VISA transports:
|
|
#
|
|
# import pyvisa
|
|
# from py_dvt_ate.instruments.transport.visa import VISATransport
|
|
#
|
|
# rm = pyvisa.ResourceManager()
|
|
# chamber_transport = VISATransport(rm.open_resource(config.chamber_visa))
|
|
# psu_transport = VISATransport(rm.open_resource(config.psu_visa))
|
|
# dmm_transport = VISATransport(rm.open_resource(config.dmm_visa))
|
|
#
|
|
# return InstrumentSet(
|
|
# chamber=ThermalChamberDriver(chamber_transport),
|
|
# psu=PowerSupplyDriver(psu_transport),
|
|
# dmm=MultimeterDriver(dmm_transport),
|
|
# )
|
|
|
|
raise NotImplementedError("PyVISA backend not yet implemented")
|