Code Monkey home page Code Monkey logo

python-scpi's Introduction

scpi

New asyncio version. Only for Python 3.6 and above

Since all the other wrappers either require VISA binary or are not generic (and do not implement the device I need)

Basic idea here is to make transport-independent command sender/parser and a device baseclass that implements the common SCPI commands

A device specific implementation can then add the device-specific commands.

Pro tip for thos wishing to work on the code https://python-poetry.org/

## Usage

Install the package to your virtualenv with poetry or from pip

  • Instatiate a transport (for GPIB you will need GPIBDeviceTransport to be able to use the device helper class)
  • Instatiate SCPIProtocol with the transport (optional, see below)
  • Instantiate SCPIDevice with the protocol (or as a shorthand: with the transport directly)
  • Use the asyncio eventloop to run the device methods (all of which are coroutines)

Or if you're just playing around in the REPL use AIOWrapper to hide the eventloop handling for traditional non-concurrent approach.

See the examples directory for more.

TODO

Check Carrier-Detect for RS232 transport

in the RS232 transport check getCD to make sure the device is present before doing anything. CTS can also be checked even if hw flow control is not in use.

Basically wait for it for X seconds and abort if not found

python-scpi's People

Contributors

rambo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-scpi's Issues

Can't get a response from my generator

I have this class I can use it to set voltage, set frequencies, but it can't read the responses. I did upgrade from the non-async version to this async version since then I can't get the responses back.

class AG33250A(PowerSupply, MultiMeter):
    """Adds the Agilent 33250A specific SCPI commands as methods"""

    def __init__(self, transport, loop):
        """Initializes a device for the given transport"""
        super().__init__(transport, use_safe_variants=False)
        self._voltage = 0.1
        self._frequency = 1000.0
        self.max_voltage = 10
        self.loop = loop

    def identify(self):
        """
        Return the identification of the generator

        :returns: a list of string:  Agilent Technologies,33250A,0,m.mm-l.ll-f.ff-gg-p
        m.mm = Main firmware revision number
        l.ll = Loader firmware revision number
        f.ff = I/O processor firmware revision number
        gg = Gate array revision number
        p = Printed circuit board revision number
        """
        return self.loop.run_until_complete(super().identify())
.....

Since run_until_complete never finishes. It can't find a response then it hits the maximum recursion depth exceeded.

    return self.gen.send(None)
  File "/home/roussinm/.local/lib/python3.5/site-packages/scpi/scpi.py", line 196, in ask
    await self.check_error(command)
  File "/usr/lib/python3.5/asyncio/coroutines.py", line 109, in __next__
    return self.gen.send(None)
  File "/home/roussinm/.local/lib/python3.5/site-packages/scpi/scpi.py", line 162, in check_error
    code, errstr = await self.get_error()
  File "/usr/lib/python3.5/asyncio/coroutines.py", line 109, in __next__
    return self.gen.send(None)
  File "/home/roussinm/.local/lib/python3.5/site-packages/scpi/scpi.py", line 151, in get_error
    response = await self.ask('SYST:ERR?')
  File "/usr/lib/python3.5/asyncio/coroutines.py", line 109, in __next__
    return self.gen.send(None)
... 

python 3 and pip install fails

hi Eero,

hope you still maintain this repo...!?

I have a problem installing "scpi" via pip. Specifically I get the following error message:

georg@BueroPC:~$ sudo -H pip install scpi
Collecting scpi
Downloading scpi-0.6.5.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "/tmp/pip-build-tks6vbwf/scpi/setup.py", line 7
except subprocess.CalledProcessError,e:
^
SyntaxError: invalid syntax
----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-tks6vbwf/scpi/

Clearing cache and using pip3 don't solve the issue. Any idea what goes wrong here? I'm using Ubuntu 16.04. For your help - and your repo - thanks a lot!

Greetings from Germany,
Georg Icking-Konert

SCPIProtocol potential infinite recursion

In the command and ask methods there is a potential for infinite recursion/loop

except (asyncio.TimeoutError, asyncio.CancelledError) as err:
    # check for the actual error if available
    await self.check_error(command)
    if abort_on_timeout:
        self.abort_command()
    # re-raise the timeout if no other error found
    raise err
# other errors are allowed to bubble-up as-is

The self.check_error(command) calls self.get_error() which calls self.ask.

If transport.get_response times out or is cancelled (asyncio.TimeoutError or asyncio.CancelledError), this will result in self.check_error, and therefore self.ask, being called again and again. I discovered this because my transport layer was trying to read too many bytes and always timed out (think binary data read from a spectrum analyzer or network analyzer, or trying to clear the input buffers of excess data).

To create the issue, try adding the following to the transport layer's get_response.

with await self.lock:
    data = await self.reader.readline()
    await self.reader.read()
    return data

or in my case get_response takes nbytes as an argument and it will timeout if nbytes is larger then bytes in the buffer.

with await self.lock:
    data = await self.reader.read(n=nbytes)
    return data

My quick solution and not very pretty was to set and check a flag if errors were already being checked.

except (asyncio.TimeoutError, asyncio.CancelledError) as err:
    # check for the actual error if available
     if not self.checkingerror:
        self.checkingerror = True
        await self.check_error(cmd)
    self.checkingerror = False
    if abort_on_timeout:
        self.abort_command()
    # re-raise the timeout if no other error found
    raise err
# other errors are allowed to bubble-up as-is

Will this work with /dev/usbtmc5?

Hi,

I'm new to this and I don't want to break my brand new things :)

When I plug my IT6922A power supply I get a /dev/usbtmc5. I would have expected something more like /dev/ttyUSB0 or something.

Do you know if I can just use /dev/usbtmc5 with this lib as if it would be /dev/ttyUSB0?

Task cancellations are not handled gracefully

[2021-03-21T11:34:07.763Z][ERROR] datastreamservicelib.service (87257) /Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/datastreamservicelib/service.py:report_error_remove_tracking:163 | Task <Task finished name='mmtask' coro=<MCSCPIService.multimeter_task() done, defined at /Users/rambo/devel/miocoach/python/python-mcscpi/src/mcscpi/service.py:47> exception=RuntimeError('Recursion on get_error detected')> raised exception Recursion on get_error detected
[2021-03-21T11:34:07.763Z][ERROR] datastreamservicelib.service (87257) /Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/datastreamservicelib/service.py:default_exception_handler:80 | Unhandled in loop <_UnixSelectorEventLoop running=True closed=False debug=False>
Traceback (most recent call last):
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 201, in ask
    return await self.transport.get_response()
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/transports/gpib/base.py", line 78, in get_response
    return await self.lltransport.get_response()
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/transports/gpib/prologix.py", line 59, in get_response
    return await self.send_and_read("++read eoi")
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/transports/gpib/prologix.py", line 76, in send_and_read
    await asyncio.sleep(0)
  File "/Users/rambo/.pyenv/versions/3.8.6/lib/python3.8/asyncio/tasks.py", line 641, in sleep
    await __sleep0()
  File "/Users/rambo/.pyenv/versions/3.8.6/lib/python3.8/asyncio/tasks.py", line 635, in __sleep0
    yield
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/rambo/.pyenv/versions/3.8.6/lib/python3.8/asyncio/events.py", line 81, in _run
    self._context.run(self._callback, *self._args)
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/datastreamservicelib/service.py", line 164, in report_error_remove_tracking
    raise exc
  File "/Users/rambo/devel/miocoach/python/python-mcscpi/src/mcscpi/service.py", line 59, in multimeter_task
    response = await device.ask("MEAS:VOLT:DC? 1,0.0005")
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 215, in safe_ask
    await self.check_error(command)
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 171, in check_error
    code, errstr = await self.get_error()
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 158, in get_error
    response = await self.ask("SYST:ERR?")
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 205, in ask
    await self.check_error(command)
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 171, in check_error
    code, errstr = await self.get_error()
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 155, in get_error
    raise RuntimeError("Recursion on get_error detected")
RuntimeError: Recursion on get_error detected
[2021-03-21T11:34:07.765Z][DEBUG] datastreamservicelib.service (87257) /Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/datastreamservicelib/service.py:quit:52 | called with code=200
[2021-03-21T11:34:07.765Z][ERROR] datastreamservicelib.service (87257) /Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/datastreamservicelib/service.py:stop_lingering_tasks:238 | Task <Task finished name='mmtask' coro=<MCSCPIService.multimeter_task() done, defined at /Users/rambo/devel/miocoach/python/python-mcscpi/src/mcscpi/service.py:47> exception=RuntimeError('Recursion on get_error detected')> returned exception
Traceback (most recent call last):
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 201, in ask
    return await self.transport.get_response()
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/transports/gpib/base.py", line 78, in get_response
    return await self.lltransport.get_response()
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/transports/gpib/prologix.py", line 59, in get_response
    return await self.send_and_read("++read eoi")
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/transports/gpib/prologix.py", line 76, in send_and_read
    await asyncio.sleep(0)
  File "/Users/rambo/.pyenv/versions/3.8.6/lib/python3.8/asyncio/tasks.py", line 641, in sleep
    await __sleep0()
  File "/Users/rambo/.pyenv/versions/3.8.6/lib/python3.8/asyncio/tasks.py", line 635, in __sleep0
    yield
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/datastreamservicelib/service.py", line 235, in stop_lingering_tasks
    await self.stop_task_graceful(task)
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/datastreamservicelib/service.py", line 226, in stop_task_graceful
    return await task
  File "/Users/rambo/.pyenv/versions/3.8.6/lib/python3.8/asyncio/events.py", line 81, in _run
    self._context.run(self._callback, *self._args)
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/datastreamservicelib/service.py", line 164, in report_error_remove_tracking
    raise exc
  File "/Users/rambo/devel/miocoach/python/python-mcscpi/src/mcscpi/service.py", line 59, in multimeter_task
    response = await device.ask("MEAS:VOLT:DC? 1,0.0005")
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 215, in safe_ask
    await self.check_error(command)
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 171, in check_error
    code, errstr = await self.get_error()
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 158, in get_error
    response = await self.ask("SYST:ERR?")
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 205, in ask
    await self.check_error(command)
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 171, in check_error
    code, errstr = await self.get_error()
  File "/Users/rambo/.virtualenvs/mcscpi/lib/python3.8/site-packages/scpi/scpi.py", line 155, in get_error
    raise RuntimeError("Recursion on get_error detected")
RuntimeError: Recursion on get_error detected

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.