[plotter] fix and improve a bit the HPGL plotter emulator

Sun, 03 Jun 2018 18:04:11 +0200

author
David Douard <david.douard@logilab.fr>
date
Sun, 03 Jun 2018 18:04:11 +0200
changeset 98
4cbd3d410230
parent 97
3f123b64d367
child 99
12dbadb58b19

[plotter] fix and improve a bit the HPGL plotter emulator

at least, the mocked version now works again

pygpibtoolkit/plotter/gpib_plotter.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/gpib_plotter_mockup.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/qgpib_plotter.py file | annotate | diff | comparison | revisions
--- a/pygpibtoolkit/plotter/gpib_plotter.py	Fri May 18 01:07:28 2018 +0200
+++ b/pygpibtoolkit/plotter/gpib_plotter.py	Sun Jun 03 18:04:11 2018 +0200
@@ -33,11 +33,13 @@
         }
 
     def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                 address=5):
+                 address=5, started_cb=None):
         super().__init__(device, baudrate, timeout, address, mode=0)
+        self.plot_started_cb = started_cb
 
-    def plotStarted(self):
-        pass
+    def plot_started(self):
+        if callable(self.plot_started_cb):
+            self.plot_started_cb()
 
     def load_plot(self, wait_timeout=0):
         """
@@ -50,8 +52,11 @@
         """
         res = ""
         i = 0
+        # replies dict is modified in some cases, so make a copy
         replies = self._replies.copy()
-        if wait_timeout is not None and not isinstance(wait_timeout, (float, int)):
+
+        if wait_timeout is not None and not isinstance(
+                wait_timeout, (float, int)):
             raise TypeError("wait_timeout (%s:%s) has wrong type" % (
                 repr(wait_timeout), type(wait_timeout)))
         if wait_timeout < 0:
@@ -59,25 +64,27 @@
 
         self._cnx.timeout = wait_timeout
         firstloop = True
-        newdata = False
-        while i<self._retries:
-            l = self._cnx.readline().strip()
+        while i < self._retries:
+            l = self._cnx.readline().strip().decode()
             if l and firstloop:
                 self._cnx.timeout = self._timeout
                 firstloop = False
-                self.plotStarted()
-            if l == "":
+                self.plot_started()
+            if not l:
                 if i == 0:  # > (self._retries/2):
-                    # ie. we just received new stuffs (i is reset in the else block)
+                    # we just received new stuffs (i is reset in the else blk)
                     for k, v in replies.items():
                         # check wether we should reply smthg
                         eres = res.replace('\n', '').strip()
-                        if eres.endswith(k) or eres.endswith(k+';') or eres.endswith(k+';OE'):
-                            self._cnx.write("%s" % v)
+                        shouldreply = any(eres.endswith(k + sfx)
+                                          for sfx in ('', ';', ';OE'))
+                        if shouldreply:
+                            self._cnx.write(("%s" % v).encode())
                             if k == "OS":
+                                # don't remember why we need this...
                                 replies[k] = "16"
                             break
-                    self._cnx.write('\r')
+                    self._cnx.write(b'\r')
                     # time.sleep(0.1)
                 i += 1
             else:
@@ -94,26 +101,31 @@
 if __name__ == '__main__':
     import optparse
     opt = optparse.OptionParser(
-        'A simple HP7470A GPIB plotter emulator for USB-GPIB bundle (ProLogix)')
-    opt.add_option('-f', '--filename', default=None,
-                   dest='filename',
-                   help='Output filename. If not set, write to stdout')
-    opt.add_option('-d', '--device', default='/dev/ttyUSB0',
-                   dest='device',
-                   help='Device of the RS232 connection (default: /dev/ttyUSB0)',
-                   )
-    opt.add_option('-a', '--address', default=0,
-                   dest='address',
-                   help='GPIB address of the device',
-                   )
-    opt.add_option('-l', '--loop', default=False,
-                   action="store_true",
-                   dest="loop",
-                   help="Continuously wait for new plots. If set, filename must be set and files will be created with _n at the end")
-    opt.add_option('-v', '--verbose', default=False,
-                   action="store_true",
-                   dest="verbose",
-                   help="Verbose mode",)
+        'A simple HP7470A GPIB plotter emulator for '
+        'USB-GPIB bundle (ProLogix)')
+    opt.add_option(
+        '-f', '--filename', default=None,
+        dest='filename',
+        help='Output filename. If not set, write to stdout')
+    opt.add_option(
+        '-d', '--device', default='/dev/ttyUSB0',
+        dest='device',
+        help='Device of the RS232 connection (default: /dev/ttyUSB0)')
+    opt.add_option(
+        '-a', '--address', default=0,
+        dest='address',
+        help='GPIB address of the device')
+    opt.add_option(
+        '-l', '--loop', default=False,
+        action="store_true",
+        dest="loop",
+        help=("Continuously wait for new plots. If set, filename must be "
+              "set and files will be created with _n at the end"))
+    opt.add_option(
+        '-v', '--verbose', default=False,
+        action="store_true",
+        dest="verbose",
+        help="Verbose mode")
 
     options, argv = opt.parse_args(sys.argv)
 
@@ -125,13 +137,13 @@
     else:
         outf = sys.stdout
 
-
     try:
         plotter = GPIBplotter(
             device=options.device, address=int(options.address),
             timeout=0.06)
     except (gpib.SerialException, gpib.ConnectionError) as e:
-        sys.stderr.write('Connection error:\n\t' + '\n\t'.join([str(x) for x in e.args]) + '\n')
+        sys.stderr.write('Connection error:\n\t' + '\n\t'.join(
+            [str(x) for x in e.args]) + '\n')
         sys.stderr.write('Check your parameters\n')
         sys.exit(1)
     if options.verbose:
@@ -147,10 +159,11 @@
             outf.write(plot)
             if options.verbose:
                 sys.stderr.write('\n')
-            sys.stderr.write('Received a new plot (written to %s)\n'%outf.name)
+            sys.stderr.write(
+                'Received a new plot (written to %s)\n' % outf.name)
             if not options.loop:
                 loop = False
             else:
                 nloop += 1
                 fname, ext = os.path.splitext(options.filename)
-                outf = open(fname + "_%d"%nloop + ext, 'w')
+                outf = open(fname + "_%d" % nloop + ext, 'w')
--- a/pygpibtoolkit/plotter/gpib_plotter_mockup.py	Fri May 18 01:07:28 2018 +0200
+++ b/pygpibtoolkit/plotter/gpib_plotter_mockup.py	Sun Jun 03 18:04:11 2018 +0200
@@ -15,37 +15,39 @@
 """
 
 import glob
-import os
 import time
 import random
 
-class GPIBplotter:#(GPIB):
-    """
-    A mockup thet will find in a directory some HPGL files and feed them randomly
+
+class GPIBplotter:
+    """A mockup thet will find in a directory some HPGL files and feed them
+    randomly
+
     """
     def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                 address=5):
+                 address=5, started_cb=None):
         self._timeout = timeout
         self.filenames = glob.glob('examples/hpgl_plots/*.plt')
-        self._next = random.randint(10,50)
+        self._next = random.randint(10, 50)
         self._num = 0
+        self.plot_started_cb = started_cb
 
-    def plotStarted(self):
-        pass
-        
+    def plot_started(self):
+        if callable(self.plot_started_cb):
+            self.plot_started_cb()
+
     def load_plot(self, wait_timeout=0):
         if wait_timeout:
             time.sleep(wait_timeout)
         self._num += 1
         if self._num > self._next:
-            ret = open(random.choice(self.filenames)).read()
-            if len(ret)>0:
-                self.plotStarted()
+            with open(random.choice(self.filenames)) as fobj:
+                ret = fobj.read().strip()
+            if ret:
+                self.plot_started()
                 self._num = 0
-                self._next = random.randint(10,100)
-                time.sleep(random.randint(1,3))
+                self._next = random.randint(10, 100)
+                time.sleep(random.randint(1, 3))
                 return ret
             return None
         return None
-    
-        
--- a/pygpibtoolkit/plotter/qgpib_plotter.py	Fri May 18 01:07:28 2018 +0200
+++ b/pygpibtoolkit/plotter/qgpib_plotter.py	Sun Jun 03 18:04:11 2018 +0200
@@ -19,9 +19,10 @@
 import time
 
 from PyQt5 import QtWidgets, QtGui, QtCore, QtPrintSupport, uic
-from PyQt5.QtCore import Qt
+from PyQt5.QtCore import Qt, pyqtSignal
 
 from pygpibtoolkit.plotter.hpgl_qt import QHPGLPlotterWidget
+from pygpibtoolkit.plotter.gpib_plotter import GPIBplotter
 
 from pygpibtoolkit.qt5.qpreferences import IntItem, UnicodeItem, ColorItem
 from pygpibtoolkit.qt5.qpreferences import BoolItem
@@ -40,14 +41,10 @@
         os.path.join(HERE, "qhpgl_plotter.ui"),
         from_imports=True, import_from='pygpibtoolkit.plotter',)
 except Exception as e:
-    print(e)
-    from pygpibtoolkit.plotter.qhpgl_plotter_ui import Ui_MainWindow as form_class
+    from pygpibtoolkit.plotter.qhpgl_plotter_ui import (
+        Ui_MainWindow as form_class)
 
 
-if "-m" in sys.argv:
-    from pygpibtoolkit.plotter.gpib_plotter_mockup import GPIBplotter
-else:
-    from pygpibtoolkit.plotter.gpib_plotter import GPIBplotter
 
 
 class Preferences(AbstractPreferences):
@@ -97,7 +94,8 @@
     autodisplay = BoolItem(
         default=True,
         name="Auto display",
-        description="Automatically display a new plot as soon as it is received",
+        description=(
+            "Automatically display a new plot as soon as it is received"),
         group="Misc")
 
 
@@ -151,7 +149,8 @@
         self._plots_list = QtCore.QStringListModel()
         self.plotsView.setModel(self._plots_list)
         self.plotsView.activated.connect(self.currentPlotChanged)
-        self.plotsView.selectionModel().currentChanged.connect(self.currentPlotChanged)
+        self.plotsView.selectionModel().currentChanged.connect(
+            self.currentPlotChanged)
         self.setReceivingLed()
 
     def currentPlotChanged(self, index, old_index=None):
@@ -170,8 +169,8 @@
         self.close()
 
     def closeEvent(self, event):
+        # if self.promptForSave():
         if 1:
-        #if self.promptForSave():
             self._prefs._pos = self.pos()
             self._prefs._size = self.size()
             self._prefs._appState = self.saveState()
@@ -193,7 +192,6 @@
     def openFiles(self, filenames):
         ok = False
         for filename in filenames:
-            print('FNAE=', filename)
             if os.path.exists(filename):
                 data = open(filename).read()
                 name = os.path.basename(filename)
@@ -260,9 +258,10 @@
     def initializeGPIB(self):
         self._online = False
         try:
-            self.gpib_plotter = QGPIBplotter(device=self._prefs.device,
-                                             address=self._prefs.address,
-                                             )
+            self.gpib_plotter = GPIBplotter(
+                device=self._prefs.device,
+                address=self._prefs.address,
+            )
             self.captureThread = GPIBReceiver(self.gpib_plotter)
             self.captureThread.plotReceived.connect(self.plotReceived)
             self.captureThread.plotStarted.connect(self.plotStarted)
@@ -278,9 +277,9 @@
                 self.initializeGPIB()
                 if self.gpib_plotter is None:
                     QtWidgets.QMessageBox.critical(
-                        self, self.tr("GPIB error"),
-                        self.tr("<b>Unable to initialize GPIB connection</b>."
-                                "<br>Please check your GPIB dongle and settings."))
+                        self, "GPIB error",
+                        "<b>Unable to initialize GPIB connection</b>."
+                        "<br>Please check your GPIB dongle and settings.")
                     self._online = False
                     self.setCaptureLed()
                     return
@@ -308,57 +307,37 @@
         self.receivingButton.setIcon(icn)
 
 
-class QGPIBplotter(GPIBplotter):
-    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                 address=5):
-        super().__init__(device, baudrate, timeout, address)
-        self.emitter = None
-
-    def plotStarted(self):
-        if self.emitter:
-            self.emitter.emit(SIGNAL('plotStarted()'))
-            # self.emitter.msleep(1)
-
 
 class GPIBReceiver(QtCore.QThread):
+    plotStarted = pyqtSignal()
+    plotReceived = pyqtSignal(int)
+
     def __init__(self, cnx, parent=None):
         super().__init__(parent)
         self.gpibplotter = cnx
-        self.gpibplotter.emitter = self
+        self.gpibplotter.plot_started_cb = self.plotStarted.emit
 
-        self._cancelmutex = QtCore.QMutex()
         self._cancel = False
         # self._nreceived = 0
         self._plotsmutex = QtCore.QMutex()
         self._plots = []
-        self._startstopmutex = QtCore.QMutex()
-        self._startstop = QtCore.QWaitCondition()
         self._capturing = False
 
     def cancel(self):
-        self._cancelmutex.lock()
         self._cancel = True
-        self._cancelmutex.unlock()
 
     def startCapture(self):
-        self._startstop.wakeOne()
+        self._capturing = True
 
     def stopCapture(self):
-        self._startstopmutex.lock()
         self._capturing = False
-        self._startstopmutex.unlock()
 
     def run(self):
-        while 1:
-            self._cancelmutex.lock()
-            if self._cancel:
-                return
-            self._cancelmutex.unlock()
-            self._startstopmutex.lock()
+        while not self._cancel:
             if not self._capturing:
-                self._startstop.wait(self._startstopmutex)
-                self._capturing = True
-            self._startstopmutex.unlock()
+                self.msleep(100)
+                continue
+
             plot = self.gpibplotter.load_plot(wait_timeout=0.1)
             timestamp = time.time()
             if plot:
@@ -366,7 +345,8 @@
                 self._plots.append((plot, timestamp))
                 n = len(self._plots)
                 self._plotsmutex.unlock()
-                self.emit(SIGNAL('plotReceived(int)'), n-1)
+
+                self.plotReceived.emit(n - 1)
             self.msleep(10)
 
     def getPlot(self, num):
@@ -378,6 +358,8 @@
 
 
 def main():
+    global GPIBplotter
+
     import optparse
     opt = optparse.OptionParser(
         'A simple PyQt4 HP7470A GPIB plotter emulator for USB-GPIB bundle '
@@ -393,6 +375,8 @@
                    help="Verbose mode",)
 
     options, argv = opt.parse_args(sys.argv)
+    if options.mockup:
+        from pygpibtoolkit.plotter.gpib_plotter_mockup import GPIBplotter
 
     a = QtWidgets.QApplication(argv)
     w = QtHPGLPlotter()

mercurial