Logging added

This commit is contained in:
Balthasar Reuter
2018-05-14 21:13:56 +02:00
parent e341fbc052
commit 5e2739bec8
13 changed files with 122 additions and 75 deletions

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import configparser, os
import configparser, os, logging
class Config:
@@ -29,16 +29,20 @@ class Config:
def defaults(self):
self._cfg.read(os.path.join(os.path.dirname(__file__), 'defaults.cfg'))
filename = os.path.join(os.path.dirname(__file__), 'defaults.cfg')
logging.info('Reading config file "%s"', filename)
self._cfg.read(filename)
def read(self):
logging.info('Reading config file "%s"', self._filename)
self._cfg.read(self._filename)
def write(self):
logging.info('Writing config file "%s"', self._filename)
with open(self._filename, 'w') as configfile:
self._cfg.write(configfile)

View File

@@ -1,16 +1,15 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# from time import time, localtime, strftime
import logging
from PIL import Image, ImageOps
from .PictureList import PictureList
from .PictureDimensions import PictureDimensions
from . import gui
from.Worker import PictureSaver
from .Worker import PictureSaver
class TeardownException(Exception):
@@ -40,30 +39,35 @@ class Photobooth:
self._cap = camera
self._pic_dims = PictureDimensions(config, self._cap.getPicture().size)
# picture_basename = strftime(config.get('Picture', 'basename'), localtime())
# self._pic_list = PictureList(picture_basename)
# self._get_next_filename = self._pic_list.getNext
if ( config.getBool('Photobooth', 'show_preview')
and self._cap.hasPreview ):
logging.info('Countdown with preview activated')
self._show_counter = self.showCounterPreview
else:
logging.info('Countdown without preview activated')
self._show_counter = self.showCounterNoPreview
def initGpio(self, config):
if config.getBool('Gpio', 'enable'):
lamp_pin = config.getInt('Gpio', 'lamp_pin')
trigger_pin = config.getInt('Gpio', 'trigger_pin')
exit_pin = config.getInt('Gpio', 'exit_pin')
logging.info('GPIO enabled (lamp_pin=%d, trigger_pin=%d, exit_pin=%d)',
lamp_pin, trigger_pin, exit_pin)
from Gpio import Gpio
self._gpio = Gpio()
lamp = self._gpio.setLamp(config.getInt('Gpio', 'lamp_pin'))
lamp = self._gpio.setLamp(lamp_pin)
self._lampOn = lambda : self._gpio.lampOn(lamp)
self._lampOff = lambda : self._gpio.lampOff(lamp)
self._gpio.setButton(config.getInt('Gpio', 'trigger_pin'), self.gpioTrigger)
self._gpio.setButton(config.getInt('Gpio', 'exit_pin'), self.gpioExit)
self._gpio.setButton(triger_pin, self.gpioTrigger)
self._gpio.setButton(exit_pin, self.gpioExit)
else:
self._lampOn = lambda : None
self._lampOff = lambda : None
@@ -71,7 +75,7 @@ class Photobooth:
def teardown(self):
print('Camera teardown')
logging.info('Teardown of camera')
self.triggerOff()
self.setCameraIdle()
@@ -83,7 +87,7 @@ class Photobooth:
try:
event_idx = expected.index(str(event))
except ValueError:
print('Photobooth: Unknown event received: ' + str(event))
logging.error('Unknown event received: %s', str(event))
raise ValueError('Unknown event received', str(event))
return event_idx
@@ -94,7 +98,7 @@ class Photobooth:
events = ['ack', 'cancel', 'teardown']
if self.recvEvent(events) != 0:
print('Teardown of Photobooth requested')
logging.info('Teardown of camera requested')
raise TeardownException()
@@ -103,16 +107,10 @@ class Photobooth:
events = ['triggered', 'teardown']
if self.recvEvent(events) != 0:
print('Teardown of Photobooth requested')
logging.info('Teardown of camera requested')
raise TeardownException()
# @property
# def getNextFilename(self):
# return self._get_next_filename
@property
def showCounter(self):
@@ -140,7 +138,7 @@ class Photobooth:
try:
self.trigger()
except RuntimeError as e:
print('Camera error: ' + str(e))
logging.error('Camera error: %s', str(e))
self._conn.send( gui.ErrorState('Camera error', str(e)) )
self.recvAck()
@@ -175,7 +173,6 @@ class Photobooth:
self._conn.send(gui.CountdownState())
self.recvAck()
print('ack received')
def showPose(self):
@@ -209,11 +206,13 @@ class Photobooth:
def enqueueWorkerTasks(self, picture):
for task in self._worker_list:
self._queue.put(( task.do, (picture, ) ))
self._queue.put(task.get(picture))
def trigger(self):
logging.info('Photobooth triggered')
self._conn.send(gui.GreeterState())
self.triggerOff()
self.setCameraActive()
@@ -224,7 +223,6 @@ class Photobooth:
self._conn.send(gui.AssembleState())
img = self.assemblePictures(pics)
# img.save(self.getNextFilename(), 'JPEG')
self._conn.send(gui.PictureState(img))
self.enqueueWorkerTasks(img)

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import os, logging
from glob import glob
@@ -43,11 +43,13 @@ class PictureList:
else:
pictures.sort()
last_picture = pictures[-1]
self.counter = int(last_picture[-(self.count_width+len(self.suffix)):-len(self.suffix)])
self.counter = int(last_picture[
-(self.count_width+len(self.suffix)):-len(self.suffix)])
# Print initial infos
print('Info: Number of last existing file: ' + str(self.counter))
print('Info: Saving assembled pictures as: ' + self.basename + (self.count_width * 'X') + '.jpg')
logging.info('Number of last existing file: %d', self.counter)
logging.info('Saving assembled pictures as "%s%s.%s"', self.basename,
self.count_width * 'X', 'jpg')
def getFilename(self, count):

View File

@@ -1,6 +1,8 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
from time import localtime, strftime
from .PictureList import PictureList
@@ -13,7 +15,7 @@ class WorkerTask:
assert not kwargs
def do(self, picture):
def get(self, picture):
raise NotImplementedError()
@@ -25,21 +27,20 @@ class PictureSaver(WorkerTask):
super().__init__()
picture_basename = strftime(config.get('Picture', 'basename'), localtime())
self._pic_list = PictureList(picture_basename)
self._get_next_filename = self._pic_list.getNext
basename = strftime(config.get('Picture', 'basename'), localtime())
self._pic_list = PictureList(basename)
@property
def getNextFilename(self):
@staticmethod
def do(picture, filename):
return self._get_next_filename
logging.info('Saving picture as %s', filename)
picture.save(filename, 'JPEG')
def do(self, picture):
def get(self, picture):
print('saving picture')
picture.save(self.getNextFilename(), 'JPEG')
return (self.do, (picture, self._pic_list.getNext()))
@@ -52,7 +53,7 @@ class Worker:
def run(self):
for func, args in iter(self._queue.get, ('teardown', None)):
for func, args in iter(self._queue.get, 'teardown'):
func(*args)
return 0

View File

@@ -20,6 +20,8 @@ class CameraGphoto2(Camera):
self.hasIdle = False
self._isActive = False
logging.info('Using python-gphoto2 bindings')
self._setupLogging()
self._setupCamera()
@@ -27,14 +29,10 @@ class CameraGphoto2(Camera):
def cleanup(self):
self._cap.exit(self._ctxt)
# self.setIdle()
def _setupLogging(self):
logging.basicConfig(
format='%(levelname)s: %(name)s: %(message)s',
level=logging.ERROR)
gp.check_result(gp.use_python_logging())
@@ -67,9 +65,7 @@ class CameraGphoto2(Camera):
# self.setActive()
text = self._cap.get_summary(self._ctxt)
print('Summary')
print('=======')
print(str(text))
logging.info('Camera summary: %s', str(text))
# self.setIdle()

View File

@@ -19,10 +19,7 @@ class CameraGphoto2Cffi(Camera):
self.hasPreview = True
self.hasIdle = True
# Avoid output cluttered
logging.basicConfig(
format='%(levelname)s: %(name)s: %(message)s',
level=logging.CRITICAL)
logging.info('Using gphoto2-cffi bindings')
self._setupCamera()
@@ -30,7 +27,7 @@ class CameraGphoto2Cffi(Camera):
def _setupCamera(self):
self._cap = gp.Camera()
print(self._cap.supported_operations)
logging.info('Supported operations: %s', self._cap.supported_operations)
if 'raw' in self._cap.config['imgsettings']['imageformat'].value.lower():
raise RuntimeError('Camera file format is set to RAW')

View File

@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
from PIL import Image
import os, subprocess
import os, subprocess, logging
from . import Camera
@@ -15,9 +15,13 @@ class CameraGphoto2CommandLine(Camera):
self.hasPreview = False
self.hasIdle = False
logging.info('Using gphoto2 via command line')
if os.access('/dev/shm', os.W_OK):
logging.debug('Storing temp files to "/dev/shm/photobooth.jpg"')
self._tmp_filename = '/dev/shm/photobooth.jpg'
else:
logging.debug('Storing temp files to "/tmp/photobooth.jpg"')
self._tmp_filename = '/tmp/photobooth.jpg'
self.setActive()

View File

@@ -1,6 +1,8 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
from PIL import Image
import cv2
@@ -16,6 +18,8 @@ class CameraOpenCV(Camera):
self.hasPreview = True
self.hasIdle = True
logging.info('Using OpenCV')
self._cap = cv2.VideoCapture()

View File

@@ -1,6 +1,8 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
from PyQt5.QtWidgets import QMessageBox
from .. import printer
@@ -19,6 +21,11 @@ class GuiPostprocess:
raise NotImplementedError()
def confirm(self, picture):
raise NotImplementedError()
class PrintPostprocess(GuiPostprocess):
@@ -33,17 +40,15 @@ class PrintPostprocess(GuiPostprocess):
def get(self, picture):
return PrintState(lambda : self.do(picture))
return PrintState(lambda : self.do(picture), False)
# reply = QMessageBox.question(parent, 'Print?',
# 'Do you want to print the picture?',
# QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
# if reply == QMessageBox.Yes:
# self._printer.print(picture)
def confirm(self, picture):
return PrintState(lambda : None, True)
def do(self, picture):
print('Printing')
logging.info('Printing picture')
self._printer.print(picture)

View File

@@ -147,11 +147,12 @@ class TeardownState(GuiState):
class PrintState(GuiState):
def __init__(self, handler, **kwargs):
def __init__(self, handler, confirmed, **kwargs):
super().__init__(**kwargs)
self.handler = handler
self.confirmed = confirmed
@property
@@ -166,4 +167,19 @@ class PrintState(GuiState):
if not callable(handler):
raise ValueError('handler must be callable')
self._handler = handler
self._handler = handler
@property
def confirmed(self):
return self._confirmed
@confirmed.setter
def confirmed(self, confirmed):
if not isinstance(confirmed, bool):
raise ValueError('confirmed status must be bool')
self._confirmed = confirmed

View File

@@ -3,6 +3,7 @@
import multiprocessing as mp
import queue
import logging
from PIL import ImageQt
@@ -141,7 +142,6 @@ class PyQt5Gui(Gui):
elif isinstance(state, PictureState):
img = ImageQt.ImageQt(state.picture)
self._p.setCentralWidget(PyQt5PictureMessage('', img))
# QTimer.singleShot(cfg.getInt('Photobooth', 'display_time') * 1000, self.sendAck)
QTimer.singleShot(cfg.getInt('Photobooth', 'display_time') * 1000,
lambda : self.postprocessPicture(state.picture))
@@ -179,6 +179,8 @@ class PyQt5Gui(Gui):
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
task.handler()
QMessageBox.information(self._p, 'Printing',
'Picture sent to printer.', QMessageBox.Ok)
else:
raise ValueError('Unknown task')
@@ -217,9 +219,9 @@ class PyQt5Gui(Gui):
def showError(self, title, message):
print('ERROR: ' + title + ': ' + message)
reply = QMessageBox.warning(self._p, title, message, QMessageBox.Close | QMessageBox.Retry,
QMessageBox.Retry)
logging.error('%s: %s', title, message)
reply = QMessageBox.warning(self._p, title, message,
QMessageBox.Close | QMessageBox.Retry, QMessageBox.Retry)
if reply == QMessageBox.Retry:
self.sendAck()
self._lastState()

View File

@@ -7,8 +7,9 @@ try:
except DistributionNotFound:
__version__ = 'unknown'
import multiprocessing as mp
import sys
import multiprocessing as mp
import logging
from . import camera, gui
from .Config import Config
@@ -44,7 +45,7 @@ class CameraProcess(mp.Process):
if str(event) in ('cancel', 'ack'):
return 123
else:
print('Unknown event received: ' + str(event))
logging.error('Unknown event received: %s', str(event))
raise RuntimeError('Unknown event received', str(event))
@@ -56,10 +57,11 @@ class CameraProcess(mp.Process):
event = self.conn.recv()
if str(event) != 'start':
logging.warning('Unknown event received: %s', str(event))
continue
status_code = self.run_camera()
print('Camera exit: ', str(status_code))
logging.info('Camera exited with status code %d', status_code)
sys.exit(status_code)
@@ -100,13 +102,16 @@ class GuiProcess(mp.Process):
def run(argv):
print('Photobooth version:', __version__)
logging.info('Photobooth version: %s', __version__)
# Load configuration
config = Config('photobooth.cfg')
# Create communication objects
gui_conn, camera_conn = mp.Pipe()
worker_queue = mp.SimpleQueue()
# Initialize processes
camera_proc = CameraProcess(config, camera_conn, worker_queue)
camera_proc.start()
@@ -116,11 +121,13 @@ def run(argv):
gui_proc = GuiProcess(argv, config, gui_conn, worker_queue)
gui_proc.start()
# Close endpoints
gui_conn.close()
camera_conn.close()
gui_proc.join()
worker_queue.put(('teardown', None))
# Wait for processes to finish
gui_proc.join()
worker_queue.put('teardown')
worker_proc.join()
camera_proc.join(5)
return gui_proc.exitcode
@@ -128,6 +135,9 @@ def run(argv):
def main(argv):
logging.basicConfig(filename='photobooth.log', level=logging.INFO)
logging.getLogger().addHandler(logging.StreamHandler())
known_status_codes = {
999: 'Initializing photobooth',
123: 'Restarting photobooth and reloading config'
@@ -136,8 +146,10 @@ def main(argv):
status_code = 999
while status_code in known_status_codes:
print(known_status_codes[status_code])
logging.info(known_status_codes[status_code])
status_code = run(argv)
logging.info('Exiting photobooth with status code %d', status_code)
return status_code

View File

@@ -1,6 +1,8 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
from PIL import ImageQt
from PyQt5.QtCore import Qt, QPoint, QSizeF
@@ -18,8 +20,11 @@ class PrinterPyQt5(Printer):
self._printer = QPrinter(QPrinter.HighResolution)
self._printer.setPageSize(QPageSize(QSizeF(*page_size), QPageSize.Millimeter))
logging.info('Using printer "%s"', self._printer.printerName())
self._print_pdf = print_pdf
if self._print_pdf:
logging.info('Using PDF printer')
self._counter = 0
self._printer.setOutputFormat(QPrinter.PdfFormat)
self._printer.setFullPage(True)
@@ -32,7 +37,8 @@ class PrinterPyQt5(Printer):
self._counter += 1
img = ImageQt.ImageQt(picture)
img = img.scaled(self._printer.pageRect().size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
img = img.scaled(self._printer.pageRect().size(), Qt.KeepAspectRatio,
Qt.SmoothTransformation)
printable_size = self._printer.pageRect(QPrinter.DevicePixel)
origin = ( (printable_size.width() - img.width()) // 2,