Add instrument factory
This commit is contained in:
@@ -8,6 +8,11 @@ This package provides everything needed to communicate with lab instruments:
|
|||||||
- Factory for creating configured instrument sets
|
- Factory for creating configured instrument sets
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from py_dvt_ate.instruments.factory import (
|
||||||
|
InstrumentConfig,
|
||||||
|
InstrumentFactory,
|
||||||
|
InstrumentSet,
|
||||||
|
)
|
||||||
from py_dvt_ate.instruments.interfaces import (
|
from py_dvt_ate.instruments.interfaces import (
|
||||||
IMultimeter,
|
IMultimeter,
|
||||||
IPowerSupply,
|
IPowerSupply,
|
||||||
@@ -18,4 +23,7 @@ __all__ = [
|
|||||||
"IThermalChamber",
|
"IThermalChamber",
|
||||||
"IPowerSupply",
|
"IPowerSupply",
|
||||||
"IMultimeter",
|
"IMultimeter",
|
||||||
|
"InstrumentSet",
|
||||||
|
"InstrumentConfig",
|
||||||
|
"InstrumentFactory",
|
||||||
]
|
]
|
||||||
|
|||||||
176
src/py_dvt_ate/instruments/factory.py
Normal file
176
src/py_dvt_ate/instruments/factory.py
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
"""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")
|
||||||
Reference in New Issue
Block a user