Skip to content

Commit

Permalink
Enable Virtual GPIB connections to supported instruments (#230)
Browse files Browse the repository at this point in the history
* Update dm_config_parser.py for gpib support

Signed-off-by: Shashank P <[email protected]>

* Update device_manager.py for vgpib support

Signed-off-by: Shashank P <[email protected]>

* Update constants_and_dataclasses.py

Signed-off-by: Shashank P <[email protected]>

* Update functions.py

Signed-off-by: Shashank P <[email protected]>

* test: Update test_config_parser.py

Signed-off-by: Shashank P <[email protected]>

* test: Update test_alternative_connection_addresses.py

Signed-off-by: Shashank P <[email protected]>

* test: Update test_helpers.py

Signed-off-by: Shashank P <[email protected]>

* fix: Update pyproject.toml

Signed-off-by: Shashank P <[email protected]>

* fix: Update .pre-commit-config.yaml

Signed-off-by: Shashank P <[email protected]>

* docs: Update configuration.md

Signed-off-by: Shashank P <[email protected]>

* Update devices.yaml

Signed-off-by: Shashank P <[email protected]>

* fix: Update CHANGELOG.md

Signed-off-by: Shashank P <[email protected]>

* Apply suggestions from code review

Signed-off-by: Nicholas Felt <[email protected]>

---------

Signed-off-by: Shashank P <[email protected]>
Signed-off-by: Nicholas Felt <[email protected]>
Co-authored-by: Nicholas Felt <[email protected]>
  • Loading branch information
u625355 and nfelt14 authored Jun 4, 2024
1 parent 2a5a6f2 commit fac1299
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Things to be included in the next release go here.
- Added signed build provenance attestations to workflow artifacts for the built package.
- Added signed build provenance attestations to the generated SBOMs.
- Documentation was added explaining how to verify the attestations on uploaded files.
- Enabled support for Virtual GPIB connections to supported devices.

### Removed

Expand Down
4 changes: 4 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ devices:
end_input: none
# gpib connection
- address: <gpib_address>
gpib_board_number: <gpib_board_number>
alias: <alias>
connection_type: GPIB
device_type: <device_type>
Expand Down Expand Up @@ -193,6 +194,9 @@ devices:
- `end_input:` Character(s) to indicate the end of a message transmission.
- Valid options: `termination_break`, `termination_char`, `last_bit`, or
`none`.
- `gpib_board_number`
- The GPIB board number (also referred to as a controller) that the device is connected to.
- If no board number is provided in the configuration, a board number of `0` is assumed.
- `device_driver`
- The name of the Python driver class to use for the device (see the
[`tm_devices.drivers`][] API reference for a complete list of all driver
Expand Down
4 changes: 4 additions & 0 deletions src/tm_devices/components/dm_config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ def add_device( # noqa: PLR0913
lan_port: Optional[int] = None,
serial_config: Optional[SerialConfig] = None,
device_driver: Optional[str] = None,
gpib_board_number: Optional[int] = None,
) -> Tuple[str, DeviceConfigEntry]:
"""Add a new device configuration entry.
Expand All @@ -169,6 +170,8 @@ def add_device( # noqa: PLR0913
lan_port: The port number to connect on, used for SOCKET/REST_API connections.
serial_config: A dataclass for holding serial connection info.
device_driver: A string indicating the specific Python device driver to use.
gpib_board_number: The GPIB board number (also referred to as a controller), only used
for GPIB connections. The default is 0.
Returns:
Tuple of the config entry name and the new DeviceConfigEntry
Expand All @@ -187,6 +190,7 @@ def add_device( # noqa: PLR0913
lan_port=lan_port,
serial_config=serial_config,
device_driver=device_driver,
gpib_board_number=gpib_board_number,
)
# Currently, USB connections when using the PyVISA-py backend are not supported.
if self.__options.standalone and new_entry.connection_type in {
Expand Down
41 changes: 41 additions & 0 deletions src/tm_devices/device_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ def add_afg(
connection_type: Optional[str] = None,
port: Optional[int] = None,
serial_config: Optional[SerialConfig] = None,
gpib_board_number: Optional[int] = None,
) -> AFGAlias:
"""Add an AFG to the DeviceManager.
Expand All @@ -273,6 +274,8 @@ def add_afg(
from the address string.
port: The port to use when creating a socket connection.
serial_config: Serial connection settings, only needed when connection_type="SERIAL".
gpib_board_number: The GPIB board number (also referred to as a controller) to be used
when making a GPIB connection (defaults to 0).
Returns:
The AFG device driver.
Expand All @@ -287,6 +290,7 @@ def add_afg(
connection_type=connection_type,
port=port,
serial_config=serial_config,
gpib_board_number=gpib_board_number,
),
)

Expand All @@ -298,6 +302,7 @@ def add_awg(
connection_type: Optional[str] = None,
port: Optional[int] = None,
serial_config: Optional[SerialConfig] = None,
gpib_board_number: Optional[int] = None,
) -> AWGAlias:
"""Add an AWG to the DeviceManager.
Expand All @@ -311,6 +316,8 @@ def add_awg(
from the address string.
port: The port to use when creating a socket connection.
serial_config: Serial connection settings, only needed when connection_type="SERIAL".
gpib_board_number: The GPIB board number (also referred to as a controller) to be used
when making a GPIB connection (defaults to 0).
Returns:
The AWG device driver.
Expand All @@ -325,6 +332,7 @@ def add_awg(
connection_type=connection_type,
port=port,
serial_config=serial_config,
gpib_board_number=gpib_board_number,
),
)

Expand All @@ -336,6 +344,7 @@ def add_daq(
connection_type: Optional[str] = None,
port: Optional[int] = None,
serial_config: Optional[SerialConfig] = None,
gpib_board_number: Optional[int] = None,
) -> DataAcquisitionSystemAlias:
"""Add a DAQ to the DeviceManager.
Expand All @@ -349,6 +358,8 @@ def add_daq(
from the address string.
port: The port to use when creating a socket connection.
serial_config: Serial connection settings, only needed when connection_type="SERIAL".
gpib_board_number: The GPIB board number (also referred to as a controller) to be used
when making a GPIB connection (defaults to 0).
Returns:
The DAQ device driver.
Expand All @@ -363,6 +374,7 @@ def add_daq(
connection_type=connection_type,
port=port,
serial_config=serial_config,
gpib_board_number=gpib_board_number,
),
)

Expand All @@ -374,6 +386,7 @@ def add_dmm(
connection_type: Optional[str] = None,
port: Optional[int] = None,
serial_config: Optional[SerialConfig] = None,
gpib_board_number: Optional[int] = None,
) -> DigitalMultimeterAlias:
"""Add a DMM to the DeviceManager.
Expand All @@ -387,6 +400,8 @@ def add_dmm(
from the address string.
port: The port to use when creating a socket connection.
serial_config: Serial connection settings, only needed when connection_type="SERIAL".
gpib_board_number: The GPIB board number (also referred to as a controller) to be used
when making a GPIB connection (defaults to 0).
Returns:
The DMM device driver.
Expand All @@ -401,6 +416,7 @@ def add_dmm(
connection_type=connection_type,
port=port,
serial_config=serial_config,
gpib_board_number=gpib_board_number,
),
)

Expand Down Expand Up @@ -445,6 +461,7 @@ def add_psu(
connection_type: Optional[str] = None,
port: Optional[int] = None,
serial_config: Optional[SerialConfig] = None,
gpib_board_number: Optional[int] = None,
) -> PowerSupplyUnitAlias:
"""Add a PSU to the DeviceManager.
Expand All @@ -458,6 +475,8 @@ def add_psu(
from the address string.
port: The port to use when creating a socket connection.
serial_config: Serial connection settings, only needed when connection_type="SERIAL".
gpib_board_number: The GPIB board number (also referred to as a controller) to be used
when making a GPIB connection (defaults to 0).
Returns:
The PSU device driver.
Expand All @@ -472,6 +491,7 @@ def add_psu(
connection_type=connection_type,
port=port,
serial_config=serial_config,
gpib_board_number=gpib_board_number,
),
)

Expand All @@ -483,6 +503,7 @@ def add_scope(
connection_type: Optional[str] = None,
port: Optional[int] = None,
serial_config: Optional[SerialConfig] = None,
gpib_board_number: Optional[int] = None,
) -> ScopeAlias:
"""Add a scope to the DeviceManager.
Expand All @@ -496,6 +517,8 @@ def add_scope(
from the address string.
port: The port to use when creating a socket connection.
serial_config: Serial connection settings, only needed when connection_type="SERIAL".
gpib_board_number: The GPIB board number (also referred to as a controller) to be used
when making a GPIB connection (defaults to 0).
Returns:
The scope device driver.
Expand All @@ -510,6 +533,7 @@ def add_scope(
connection_type=connection_type,
port=port,
serial_config=serial_config,
gpib_board_number=gpib_board_number,
),
)

Expand All @@ -521,6 +545,7 @@ def add_smu(
connection_type: Optional[str] = None,
port: Optional[int] = None,
serial_config: Optional[SerialConfig] = None,
gpib_board_number: Optional[int] = None,
) -> SourceMeasureUnitAlias:
"""Add a SMU to the DeviceManager.
Expand All @@ -534,6 +559,8 @@ def add_smu(
from the address string.
port: The port to use when creating a socket connection.
serial_config: Serial connection settings, only needed when connection_type="SERIAL".
gpib_board_number: The GPIB board number (also referred to as a controller) to be used
when making a GPIB connection (defaults to 0).
Returns:
The SMU device driver.
Expand All @@ -548,6 +575,7 @@ def add_smu(
connection_type=connection_type,
port=port,
serial_config=serial_config,
gpib_board_number=gpib_board_number,
),
)

Expand All @@ -558,6 +586,7 @@ def add_ss(
alias: Optional[str] = None,
connection_type: Optional[str] = None,
port: Optional[int] = None,
gpib_board_number: Optional[int] = None,
) -> SystemsSwitchAlias:
"""Add a SS to the DeviceManager.
Expand All @@ -570,6 +599,8 @@ def add_ss(
when the address is a visa resource expression since the connection type is parsed
from the address string.
port: The port to use when creating a socket connection.
gpib_board_number: The GPIB board number (also referred to as a controller) to be used
when making a GPIB connection (defaults to 0).
Returns:
The SS device driver.
Expand All @@ -583,6 +614,7 @@ def add_ss(
alias=alias,
connection_type=connection_type,
port=port,
gpib_board_number=gpib_board_number,
),
)

Expand Down Expand Up @@ -1020,6 +1052,7 @@ def _add_device( # noqa: PLR0913
port: Optional[int] = None,
serial_config: Optional[SerialConfig] = None,
device_driver: Optional[str] = None,
gpib_board_number: Optional[int] = None,
) -> Union[RESTAPIDevice, PIDevice]:
"""Add a device to the DeviceManager.
Expand All @@ -1035,6 +1068,8 @@ def _add_device( # noqa: PLR0913
port: The port to use when creating a socket connection.
serial_config: Serial connection settings, only needed when connection_type="SERIAL".
device_driver: A string indicating the specific Python device driver to use.
gpib_board_number: The GPIB board number (also referred to as a controller) to be used
when making a GPIB connection (defaults to 0).
Returns:
The created device.
Expand All @@ -1048,6 +1083,10 @@ def _add_device( # noqa: PLR0913
):
address = address_parts[0]
port = int(address_parts[1])
if connection_type.startswith(ConnectionTypes.GPIB.value):
with contextlib.suppress(ValueError):
gpib_board_number = int("".join(filter(lambda x: x.isdigit(), connection_type)))
connection_type = ConnectionTypes.GPIB.value

# Device Manager uses all caps for key mappings to device drivers and aliases
config_dict: dict[str, Optional[Union[str, int, SerialConfig]]] = {
Expand All @@ -1064,6 +1103,8 @@ def _add_device( # noqa: PLR0913
config_dict["serial_config"] = serial_config
if device_driver:
config_dict["device_driver"] = device_driver
if gpib_board_number:
config_dict["gpib_board_number"] = gpib_board_number
new_device_name, new_device_config = self.__config.add_device(**config_dict) # pyright: ignore[reportArgumentType]

return self.__create_device(new_device_name, new_device_config)
Expand Down
Loading

0 comments on commit fac1299

Please sign in to comment.