|
|
@ -7,9 +7,9 @@ import os.path
|
|
|
|
import random
|
|
|
|
import random
|
|
|
|
import string
|
|
|
|
import string
|
|
|
|
import subprocess
|
|
|
|
import subprocess
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import tempfile
|
|
|
|
import tempfile
|
|
|
|
import textwrap
|
|
|
|
import textwrap
|
|
|
|
|
|
|
|
#import traceback
|
|
|
|
import threading
|
|
|
|
import threading
|
|
|
|
|
|
|
|
|
|
|
|
import lmdb
|
|
|
|
import lmdb
|
|
|
@ -60,6 +60,19 @@ def add_api(apistr, name=""):
|
|
|
|
return decorator
|
|
|
|
return decorator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#def log_traceback(func):
|
|
|
|
|
|
|
|
# """ this is a decorator that catches tracebacks for logging"""
|
|
|
|
|
|
|
|
# def wrapper(*args):
|
|
|
|
|
|
|
|
# my_bureau = args[0]
|
|
|
|
|
|
|
|
# try:
|
|
|
|
|
|
|
|
# func(*args)
|
|
|
|
|
|
|
|
# except Exception as e:
|
|
|
|
|
|
|
|
# my_bureau.log.error("CRASH TRACE: {0}".format(my_bureau.name),
|
|
|
|
|
|
|
|
# exc_info=e)
|
|
|
|
|
|
|
|
# raise
|
|
|
|
|
|
|
|
# return wrapper
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LogPrinter(logging.Handler):
|
|
|
|
class LogPrinter(logging.Handler):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
LogPrinter prints logs on a receipt printer for screenless debugging.
|
|
|
|
LogPrinter prints logs on a receipt printer for screenless debugging.
|
|
|
@ -151,11 +164,6 @@ class Bureau(object):
|
|
|
|
self.api = {}
|
|
|
|
self.api = {}
|
|
|
|
|
|
|
|
|
|
|
|
modpath = os.path.dirname(__file__)
|
|
|
|
modpath = os.path.dirname(__file__)
|
|
|
|
#slimerjs = os.path.join(modpath, "..", "lib", "slimerjs", "slimerjs")
|
|
|
|
|
|
|
|
#renderer = os.path.join(modpath, "..", "slimerjs", "rasterize.js")
|
|
|
|
|
|
|
|
#self.slimerjs = os.path.abspath(slimerjs)
|
|
|
|
|
|
|
|
#self.html2pdf = self.slimerjs + " --headless " + \
|
|
|
|
|
|
|
|
# os.path.abspath(renderer) + " "
|
|
|
|
|
|
|
|
mypath = inspect.getfile(self.__class__)
|
|
|
|
mypath = inspect.getfile(self.__class__)
|
|
|
|
self.mdir = os.path.dirname(mypath)
|
|
|
|
self.mdir = os.path.dirname(mypath)
|
|
|
|
|
|
|
|
|
|
|
@ -181,7 +189,6 @@ class Bureau(object):
|
|
|
|
log_format = logging.Formatter('LOG ${levelname} $name: $message', style='$')
|
|
|
|
log_format = logging.Formatter('LOG ${levelname} $name: $message', style='$')
|
|
|
|
log_printer.setFormatter(log_format)
|
|
|
|
log_printer.setFormatter(log_format)
|
|
|
|
self.log.addHandler(log_printer)
|
|
|
|
self.log.addHandler(log_printer)
|
|
|
|
sys.excepthook = self._log_exception
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# setup a dir to store files and data
|
|
|
|
# setup a dir to store files and data
|
|
|
|
self.datadir = os.path.join(basepath, self.prefix)
|
|
|
|
self.datadir = os.path.join(basepath, self.prefix)
|
|
|
@ -200,9 +207,9 @@ class Bureau(object):
|
|
|
|
self.log.debug("commands: ")
|
|
|
|
self.log.debug("commands: ")
|
|
|
|
self.log.debug(str(self.commands))
|
|
|
|
self.log.debug(str(self.commands))
|
|
|
|
|
|
|
|
|
|
|
|
def _log_exception(typ, value, tb):
|
|
|
|
# def _log_exception(typ, value, tb):
|
|
|
|
self.log.error("CRASH TRACE: {0}".format(str(value)), exc_info=(typ, value, tb))
|
|
|
|
# self.log.error("CRASH TRACE: {0}".format(str(value)), exc_info=(typ, value, tb))
|
|
|
|
sys.__excepthook__(typ, value, tb)
|
|
|
|
# sys.__excepthook__(typ, value, tb)
|
|
|
|
|
|
|
|
|
|
|
|
def open_db(self, name):
|
|
|
|
def open_db(self, name):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
@ -346,10 +353,15 @@ class Bureau(object):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
# TODO: make printer id/width configured and easy
|
|
|
|
# TODO: make printer id/width configured and easy
|
|
|
|
prn = printer.Usb(0x416, 0x5011, in_ep=0x81, out_ep=0x03)
|
|
|
|
prn = printer.Usb(0x416, 0x5011, in_ep=0x81, out_ep=0x03)
|
|
|
|
im = PIL.Image.open(img)
|
|
|
|
|
|
|
|
|
|
|
|
if type(img) is PIL.Image.Image:
|
|
|
|
|
|
|
|
im = img
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
im = PIL.Image.open(img)
|
|
|
|
|
|
|
|
|
|
|
|
# NOTE: might be worth tring to push up brightness
|
|
|
|
# NOTE: might be worth tring to push up brightness
|
|
|
|
im = PIL.ImageOps.equalize(im) # stretch histogram for nicer dither
|
|
|
|
im = PIL.ImageOps.equalize(im) # stretch histogram for nicer dither
|
|
|
|
im.thumbnail((576, 576), PIL.Image.ANTIALIAS) # resize to fit printer
|
|
|
|
im.thumbnail((576, 1024), PIL.Image.ANTIALIAS) # resize to fit printer
|
|
|
|
prn.image(im, impl="bitImageColumn") # not using this impl crashes ??
|
|
|
|
prn.image(im, impl="bitImageColumn") # not using this impl crashes ??
|
|
|
|
|
|
|
|
|
|
|
|
@add_command("test")
|
|
|
|
@add_command("test")
|
|
|
@ -361,6 +373,16 @@ class Bureau(object):
|
|
|
|
print(("hi! testing. " + self.name + " bureau seems to work!"))
|
|
|
|
print(("hi! testing. " + self.name + " bureau seems to work!"))
|
|
|
|
return "seems to work."
|
|
|
|
return "seems to work."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _run_io(self):
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
wrapper for run_io so that we can catch threaded exceptions and log
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
self.run_io()
|
|
|
|
|
|
|
|
except Exception as err:
|
|
|
|
|
|
|
|
self.log.exception("%s CRASHED with %s\n", self.name, err)
|
|
|
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
def run_io(self):
|
|
|
|
def run_io(self):
|
|
|
|
"""process hardware or timed input
|
|
|
|
"""process hardware or timed input
|
|
|
|
|
|
|
|
|
|
|
@ -375,6 +397,16 @@ class Bureau(object):
|
|
|
|
pass
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
def run(self):
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
wrapper running the main loop and logging all exceptions
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
self._run()
|
|
|
|
|
|
|
|
except Exception as err:
|
|
|
|
|
|
|
|
self.log.exception("%s CRASHED with %s\n", self.name, err)
|
|
|
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _run(self):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
main loop for processing messages
|
|
|
|
main loop for processing messages
|
|
|
|
|
|
|
|
|
|
|
@ -382,7 +414,7 @@ class Bureau(object):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
# start the hardware input handler
|
|
|
|
# start the hardware input handler
|
|
|
|
io_handler = threading.Thread(target=self.run_io)
|
|
|
|
io_handler = threading.Thread(target=self._run_io)
|
|
|
|
io_handler.start()
|
|
|
|
io_handler.start()
|
|
|
|
|
|
|
|
|
|
|
|
# register commands and api methods
|
|
|
|
# register commands and api methods
|
|
|
@ -398,10 +430,6 @@ class Bureau(object):
|
|
|
|
msg = self._recv.recv_string(flags=zmq.NOBLOCK)
|
|
|
|
msg = self._recv.recv_string(flags=zmq.NOBLOCK)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
# msg = self._recv.recv_string(flags=zmq.NOBLOCK)
|
|
|
|
|
|
|
|
#except zmq.ZMQError:
|
|
|
|
|
|
|
|
# time.sleep(0.05) # don't waste CPU
|
|
|
|
|
|
|
|
# continue
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
self.log.debug("got message:" + msg)
|
|
|
|
self.log.debug("got message:" + msg)
|
|
|
|
dot = msg.find(".")
|
|
|
|
dot = msg.find(".")
|
|
|
@ -411,7 +439,6 @@ class Bureau(object):
|
|
|
|
self.log.debug("dot at %d", dot)
|
|
|
|
self.log.debug("dot at %d", dot)
|
|
|
|
# TODO: maybe trim off the trailing "." for convenience
|
|
|
|
# TODO: maybe trim off the trailing "." for convenience
|
|
|
|
data = msg[dot + 1:]
|
|
|
|
data = msg[dot + 1:]
|
|
|
|
# data = str(data) # force to be a string
|
|
|
|
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
data = None
|
|
|
|
data = None
|
|
|
|
self.log.debug("data: " + str(data))
|
|
|
|
self.log.debug("data: " + str(data))
|
|
|
|