Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Virtual GPIB connections to supported instruments #230

Merged
merged 13 commits into from
Jun 4, 2024
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ repos:
always_run: true
args: [audit, --json, --ignore-code=CVE-2019-8341]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.7
rev: v0.4.5
nfelt14 marked this conversation as resolved.
Show resolved Hide resolved
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
Expand Down
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
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ pre-commit = [
pre-commit-update = "^0.3.0"
pyclean = "^3.0.0"
pylint = "3.2.2"
pyright = "1.1.365"
pyright = "1.1.364"
nfelt14 marked this conversation as resolved.
Show resolved Hide resolved
pyroma = "^4.2"
python-semantic-release = "^9.6.0"
ruff = "0.4.7"
ruff = "0.4.5"
nfelt14 marked this conversation as resolved.
Show resolved Hide resolved
safety = "^3.2.0"
toml-sort = "^0.23.0"
tox = "^4.0"
Expand Down Expand Up @@ -159,7 +159,7 @@ pytest-env = "^1.1.3"
pytest-github-report = "^0.0.1"
pytest-html = "^4.1.1"
pytest-order = "^1.2.1"
ruff = "0.4.7"
ruff = "0.4.5"
nfelt14 marked this conversation as resolved.
Show resolved Hide resolved
tomli = "^2.0.1"

[tool.poetry.scripts]
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
Loading