From fca62dbc833f325552bf11384bb042a16288d34a Mon Sep 17 00:00:00 2001 From: Ruben van de Ven Date: Fri, 1 Nov 2019 17:18:28 +0100 Subject: [PATCH] WIP locking & parking of plotter/scanner --- sorteerhoed/central_management.py | 50 +++++++++++++++---------------- sorteerhoed/plotter.py | 30 ++++++++++++++----- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/sorteerhoed/central_management.py b/sorteerhoed/central_management.py index a5fcee0..0f9a2b5 100644 --- a/sorteerhoed/central_management.py +++ b/sorteerhoed/central_management.py @@ -36,6 +36,7 @@ class CentralManagement(): self.eventQueue = Queue() self.isRunning = threading.Event() self.isScanning = threading.Event() + self.scanLock = threading.Lock() def loadConfig(self, filename): @@ -77,7 +78,7 @@ class CentralManagement(): sqsThread.start() # the plotter itself - self.plotter = Plotter(self.config, self.eventQueue, self.isRunning) + self.plotter = Plotter(self.config, self.eventQueue, self.isRunning, self.scanLock) plotterThread = threading.Thread(target=self.plotter.start, name='plotter') plotterThread.start() @@ -130,9 +131,9 @@ class CentralManagement(): self.server.statusPage.set('state', self.currentHit.getStatus()) self.makeHit() elif signal.name == 'scan.start': - self.isScanning.set() + pass elif signal.name == 'scan.finished': - self.isScanning.clear() + pass elif signal.name == 'hit.info': if signal.params['hit_id'] != self.currentHit.id: self.logger.warning(f"hit.info hit_id != currenthit.id: {signal}") @@ -279,14 +280,15 @@ class CentralManagement(): self.logger.debug(notification_info) def cleanDrawing(self): - self.eventQueue.put(Signal('scan.start')) - # Scan to reset - cmd = [ - 'sudo', 'scanimage', '-d', 'epkowa' - ] - proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE) - # opens connection to scanner, but only starts scanning when output becomes ready: - o, e = proc.communicate(80) + with self.scanLock: + self.eventQueue.put(Signal('scan.start')) + # Scan to reset + cmd = [ + 'sudo', 'scanimage', '-d', 'epkowa' + ] + proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE) + # opens connection to scanner, but only starts scanning when output becomes ready: + _, e = proc.communicate(80) if e: self.logger.critical(f"Scanner caused: {e.decode()}") @@ -302,20 +304,18 @@ class CentralManagement(): """ Run scanimage on scaner and returns a string with the filename """ - if self.isScanning.is_set(): - raise Exception("Already scanning!") - - self.eventQueue.put(Signal('scan.start')) - cmd = [ - 'sudo', 'scanimage', '-d', 'epkowa', '--format', 'jpeg', - '--resolution=100', '-l','20','-t','30','-x',str(self.config['scanner']['height']), - '-y',str(self.config['scanner']['width']) - ] - self.logger.info(f"{cmd}") - filename = self.currentHit.getImagePath() - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - # opens connection to scanner, but only starts scanning when output becomes ready: - o, e = proc.communicate(80) + with self.scanLock: + self.eventQueue.put(Signal('scan.start')) + cmd = [ + 'sudo', 'scanimage', '-d', 'epkowa', '--format', 'jpeg', + '--resolution=100', '-l','20','-t','30','-x',str(self.config['scanner']['height']), + '-y',str(self.config['scanner']['width']) + ] + self.logger.info(f"{cmd}") + filename = self.currentHit.getImagePath() + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + # opens connection to scanner, but only starts scanning when output becomes ready: + o, e = proc.communicate(80) if e: self.logger.critical(f"Scanner caused: {e.decode()}") #TODO: should clear self.isRunning.clear() ? diff --git a/sorteerhoed/plotter.py b/sorteerhoed/plotter.py index b9dc46b..22c91e4 100644 --- a/sorteerhoed/plotter.py +++ b/sorteerhoed/plotter.py @@ -2,12 +2,12 @@ import queue import logging from pyaxidraw import axidraw from queue import Queue -from threading import Event +from threading import Event, Lock from sorteerhoed.Signal import Signal import time class Plotter: - def __init__(self, config, eventQ: Queue, runningEvent: Event): + def __init__(self, config, eventQ: Queue, runningEvent: Event, scannerLock: Lock): #TODO: scanningEvent -> CentralManagement.isScanning -> prevent plotter move during scan, failsafe self.config = config self.eventQ = eventQ @@ -21,13 +21,15 @@ class Plotter: self.xPadding = self.config['scanner']['left_padding'] / 10 / 2.54; self.yPadding = self.config['scanner']['top_padding'] / 10 / 2.54; self.logger.info(f"Paddings x: {self.xPadding} inch y: {self.yPadding} inch") + self.scannerLock = scannerLock + self.goPark = False + self.locked = False + self.ad = None def park(self): self.logger.info("Queue to park plotter") - - if self.config['dummy_plotter']: - # TODO: find a nice way to park the axidraw in the 0 position - self.q.put([(-1/2.54)/self.plotWidth,0,0]) + self.goPark = True + self.q.put([(-1/2.54)/self.plotWidth,0,0]) def start(self): try: @@ -60,13 +62,19 @@ class Plotter: finally: self.logger.warning("Close Axidraw connection") if self.ad: - self.ad.moveto(0,0) - self.ad.disconnect() + with self.scannerLock: + self.ad.moveto(0,0) + self.ad.disconnect() # send shutdown signal (if not already set) self.isRunning.clear() def draw_segments(self, segments = []): + if not self.locked: + # acquire lock if not already done so + self.scannerLock.acquire() + self.locked = True + coordinates = [] for segment in segments: coordinate = [ @@ -140,6 +148,12 @@ class Plotter: elif plotterRan: plotterRan = False self.eventQ.put(Signal('plotter.finished')) + if self.goPark: + self.eventQ.put(Signal('plotter.parked')) + if self.locked: + self.scannerLock.release() + self.locked = False + self.goPark = False # else: # time.sleep(.05) # self.logger.debug(f'Plotter move: {move}')