Metadata-Version: 2.5
Name: sqidevice
Version: 2.0.3
Summary: Python interface for communicating with Santec Quantum Instrument devices
Project-URL: Homepage, https://inst.santec.com/products/quantum-instruments
Author: Santec Australia
License: MIT
License-File: LICENSE.txt
Keywords: ddlc,ethernet,fzw,instrument,ldd,mlc,mwm,qrf,quantum,santec,usb,xrf
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Instrument Drivers
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.8
Requires-Dist: pyserial>=3.0
Description-Content-Type: text/markdown

# SQIDevice: Simple interface to Santec Quantum Instruments

The `SQIDevice` class provides a simple interface for interacting with Santec Quantum Instruments over a USB or ETH connection.

Supported devices include:
- Laser controllers, such as DDLC, MLC and LDD
- Wavemeters, such as FZW and MWM
- RF synthesizers, such as XRF and QRF

The device class handles end-of-message termination, concatenating multi-component responses, and converts error messages into exceptions to simplify error handling in the application.

Helper functions are provided for common operations, such as `ask_val()` for querying a numerical value and converting SI units, and `ask_list()` to transform comma-separated values into a `list`.


## Overview

The `SQIDevice` class is instantiated with a string defining the connection instance, for example:
```
# TCP connection by specifying IP address and optionally server port
SQIDevice("10.1.1.122")
SQIDevice("10.1.1.122:7802")
SQIDevice("10.1.1.122", port=7802)

# USB connection via virtual COM port
SQIDevice("COM3")
SQIDevice("USB", port=3)
```

The primary functions for communicating with the device are:
* `ask(query)`: Send the provided `query` string and return the response as a string.
        Intended as the main mechanism for _reading_ values from the device.
        If `query` is bytes, the return value is also bytes.
* `ask_val(query)`: Calls `ask(query)` and performs type conversion on the response string; to `float` by default.
        Also performs simple SI-units conversion of the response, when units are provided.
        Recommended for querying measured values from the device, instead of type-casting the response string directly.
* `ask_dict(query)`: Calls `ask(query)` and parses the response string into a python dictionary.
        Intended for parsing compound responses such as `VER` and `REPORT`.
        Does not perform type conversion of the values.
* `ask_list(query)`: Calls `ask(query)` and parses the response as a comma-separated list of values.
        Optionally performs unit conversion and type conversion.
* `cmd(command)`: Send the provided command string to the device and wait for a response.
        Commands are different from queries in that they induce an action and hence are expected to respond with an `OK` string.
        Intended to be used when _writing_ values to the device.
        Failing to respond in this way raises a `DeviceError`.
* `reconnect()`: Close the connection (if applicable) and reconnect with the same parameters.
        Recommended for handling disconnection or reboot events.


The queries and commands are product-specific, and can be found in the appropriate Appendix of the relevant product manual.


### Example
The following simple example demonstrates connecting to a device via Ethernet, querying some information about the device type,
reading the temperature as a floating-point value, and raising an exception if sent an unknown command:
```
>>> from sqidevice import SQIDevice
>>> dev = SQIDevice('10.2.1.169')
>>> dev.ask('INFO')
'MCC B5110-R6 0.3.6  A06002'
>>> dev['type']
'MCC'
>>> dev.ask_val('MCC,TEMP')
54.0
>>> dev.ask('CMDNOTEXIST')
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    dev.ask('CMDNOTEXIST')
  File "[...]\sqidevice.py", line 616, in ask
    raise DeviceError(resp, cmd, self)
sqidevice.DeviceError: Unknown command "CMDNOTEXIST"
```


## Properties
The `INFO` query is common across compatible devices to help identify the product at a glance.
The `SQIDevice` parses this query at connection and stores the results as a `dict` which can be accessed directly by indexing the device instance via `__getitem__()`.

The dictionary contains at least the following keys:
- `type`: Product name string (e.g. "DDLC" or "FZW").
- `rev`: Mainboard PCB revision, to help identify firmware compatibility.
- `ver`: Primary version numbers for the UC (and FPGA if applicable). See also the `VER` query for additional information.
- `serial`: Serial number of the unit.
- `name`: User-defined name for the unit, as set with the `DEVNAME` command, or the serial number when a custom name is not set.
- `iap`: Identifies that the devices is in firmware-update (IAP) mode.


## Error handling
The command and query functions of the `SQIDevice` class raise exceptions to handle error scenarios, that should be caught at the application level.

### DeviceError
A response was successfully received from the device, but that response is an error message.
This raises an instance of `DeviceError` containing both the request that failed and the response error message.

### USBError
Particularly on the Windows(tm) operating system, the error messages raised by `pyserial` are often unintuitive and it is unclear how to resolve them.

The `USBError` class is a subclass of `OSError` that translates the most common error messages into a clearer form.

### TimeoutError
Raised if no response was received, or an incomplete response was received before the timeout period elapsed.

### OSError
Typically any error at the transport level will result in a subclass of `OSError` being raised by the underlying `socket` or `serial` class instances.
Usually this indicates that the device has been disconnected, rebooted, or powered off, and needs to be reconnected.

Examples include `TimeoutError` and `USBError`.

### AssertionError
If an attempt is made to communicate with the device after closing the connection, it will cause `AssertionError` to be raised.
