
Defining an instrument class
------------------------------

an instrument class is a subclass derived from the
:class:`Instrument<srsgui.inst.instrument.Instrument>` class.
Minimum requirement is to have **_IdString** to check if a connected
instrument is a correct instrument  that can be used with the class.

.. code-block::

    from srsgui import Instrument
    class CG635(Instrument):
        _IdString = 'CG635'
        _term_char = b'\r'  # Add this line if the carriage return is the termination character
                            # of the instrument, instead of the line feed (ASCII: 0x10, b'\n').


If the instrument has:
    1. the **\*IDN?** remote command
    2. either RS232 serial communication or Ethernet TCPIP communication port available,

the instrument can be connected and used in task scripts and in the terminal,
with 4 lines of definition like above. If it does not have the \*IDN? remote command,
:meth:`check_id()<srsgui.inst.instrument.Instrument.check_id>` method in Instrument
class needs to be reimplemented.

Available_interfaces
^^^^^^^^^^^^^^^^^^^^^

`Available_interface` defines what kind of communication is available for the instrument,
the base :class:`Instrument<srsgui.inst.instrument.Instrument>` class has the following
definition for serial and TCPIP communication interfaces:

.. code-block::

    available_interfaces = [
        [   SerialInterface,
            {
                'port': FindListInput(),
                'baud_rate': IntegerListInput([9600, 115200]),
                'hardware_flow_control': BoolInput(['Off', 'On'])
            }
        ],
        [   TcpipInterface,
            {
                'ip_address': Ip4Input('192.168.1.10'),
                'port': IntegerInput(23)
            }
        ]
    ]

If your instrument needs other than serial and TCPIP interfaces, ``srsgui`` allows to add
other communication classes derived from
:class:`Interface <srsgui.inst.communication.interface.Interface>` class.
Currently there are two external communication interfaces are available from
`srsinst.sr860`_ package: ``Vxi11Interface`` and ``VisaInterface``,
which covers for VXI11_, GPIB_ and USB-TMC_. You can import the interface modules
from `srsinst.sr860`_ .

Available_interfaces in SSR865 class is define as following:

.. code-block::

    available_interfaces = [
        [   Vxi11Interface,
            {
                'ip_address': Ip4Input('192.168.1.10'),
            }
        ],
        [   VisaInterface,
            {
                'resource': FindListInput(),
            }
        ],
        [   TcpipInterface,
            {
                'ip_address': Ip4Input('192.168.1.10'),
                'port': 23
            }
        ],
        [   SerialInterface,
            {
                'port': FindListInput(),
                'baud_rate': IntegerListInput([9600, 19200, 38400, 115200,
                                               230400, 460800], 3)
            }
        ],
    ]

The definition of available_interfaces is all you need to do to get a customized
dialog box opened for the instrument in ``srsgui`` application.

.. figure:: ./_static/connect-dialog-box-capture.png
    :align: center
    :figclass: align-center

For ``VisaInterface``, you have to get PyVISA_ working before running ``srsgui`` application.
It involves installation of the PyVISA package and its backend library.
Refer to PyVISA_ documentation for installation detail.

From Python interpreter, you can connect and use a instrument, once its ``Instrument`` class is defined.

.. code-block::

    C:\srsgui>python
    Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>>
    >>> from srsinst.sr860 import SR860
    >>> from srsgui import SerialInte
    >>> SerialInterface.find()
    ['COM3', 'COM4', 'COM256']
    >>> lia = SR860('serial','COM4',115200, False)
    >>> lia.query_text('*idn?')
    'Stanford_Research_Systems,SR865A,002725,v1.34'
    >>> lia.disconnect()
    >>>
    >>> from srsinst.sr860 import VisaInterface
    >>> VisaInterface.find()
    ['USB0::0xB506::0x2000::002725::INSTR', 'GPIB0::4::INSTR']
    >>> lia.connect('visa', 'USB0::0xB506::0x2000::002725::INSTR')
    >>> lia.query_text('*idn?')
    'Stanford_Research_Systems,SR865A,002725,v1.34\n'
    >>>

Well, these operations are what you can do with PyVISA_ itself. Defining an instrument class,
adding it in a .taskconfig file, and opening it in ``srsgui`` application let you
use the terminal to interact with multiple instrument at once, and use high level ``Instrument``
class attributes and methods.

Below is an image of terminal captured with the example project opened.
As you can see, you can interact with the clock generator and oscilloscope in many ways.
There are two commands for osc: \*idn?, sara? used, and two commands for cg:
\*idn?, freq(?) used in the terminal.

.. figure:: ./_static/terminal-with-example.png
    :align: center
    :figclass: align-center

|


Component, Commands and IndexCommands
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

:class:`Instrument <srsgui.inst.instrument.Instrument>` class uses
:class:`Component <srsgui.inst.component.Component>` class,
:mod:`Command <srsgui.inst.commands>` classes and
:mod:`IndexCommand <srsgui.inst.indexcommands>` classes
to organize the functionality of an instrument.

If you have to deal with hundreds of remote commands to use an instrument remotely,
organizing them in a manageable way is crucial. `Srsinst.sr860`_ package shows how these
convenience classes are used to organize a large set of remote commands.


.. _PyVisa: https://pyvisa.readthedocs.io/en/latest/
.. _srsinst.sr860: https://pypi.org/project/srsinst.sr860/
.. _VXI11: https://www.lxistandard.org/About/VXI-11-and-LXI.aspx
.. _GPIB: https://en.wikipedia.org/wiki/IEEE-488
.. _USB-TMC: https://www.testandmeasurementtips.com/remote-communication-with-usbtmc-faq/
.. _thread: https://realpython.com/intro-to-python-threading/
.. _QThread: https://doc.qt.io/qt-6/qthread.html
