#!/usr/bin/env python3 """ This is a small python webserver intended to run on a testing network resource where the lf_kinstall.pl script can post build machine information to. A useful place to install this script would be on an APU2 being used as a VPN gateway. Use these commands to install LaTeX and html2ps apt install perlmagick libwww-perl libhtml-parser-perl libpaper-utils ghostscript weblint-perl texlive-base postscript-viewer xhtml2ps html2ps Consider these commands to install printer drivers: Dymo LabelWriter-450: apt install printer-driver-dymo Brother QL-800: # apt install brother-cups-wrapper-common brother-cups-wrapper-extra brother-lpr-drivers-common brother-lpr-drivers-extra Download drivers here: https://support.brother.com/g/b/downloadtop.aspx?c=us&lang=en&prod=lpql800eus * download driver * install driver using $ sudo dpkg -i dymo*.dpkg Use these commands to install the script: $ sudo cp label-printer.py /usr/local/bin $ sudo chmod a+x /usr/local/bin/label-printer.py $ sudo cp label-printer.service /lib/systemd/system $ sudo systemctl add-wants multi-user.target label-printer.service $ sudo systemctl daemon-reload $ sudo systemctl restart label-printer.service At this point, if you use `ss -ntlp` you should see this script listening on port 8082. If you are running ufw on your label-printer host, please use this command to allow traffice to port 8082: $ sudo ufw allow 8082/tcp $ sudo ufw reload Using kinstall to print labels: Dymo LabelWriter: $ ./lf_kinstall.pl --print-label http://192.168.9.1:8082/ --printer LabelWriter-450 Brother QL-800: $ ./lf_kinstall.pl --print-label http://192.168.9.1:8082/ --printer QL800 """ import os import logging import math from datetime import datetime from http import server from http.server import HTTPServer, BaseHTTPRequestHandler from ssl import wrap_socket from urllib.parse import urlparse, parse_qs import pprint from pprint import pprint class LabelPrinterRequestHandler(BaseHTTPRequestHandler): def do_HEAD(self): self.send_response(200); self.send_header("Content-type", "text/html") self.end_headers() def do_GET(self): self.send_response(200); self.send_header("Content-type", "text/html") self.end_headers() def popstr(self, param): #print ("""TYPE : "%s" """%type(param)) #print ("""TYPE0: "%s" """%type(param[0])) if type(param) is list: #print("""LIST: "%s", """%param[0]) return str(param[0]) return str(param) def do_POST(self): html_filename = "/tmp/label.html" printer = "" hostname = ""; mac_address = ""; model = ""; serial = ""; length = int(self.headers['Content-Length']) field_data = self.rfile.read(length).decode("utf-8") print("Field_data: %s\n"%field_data); fields = parse_qs(field_data) #pprint(fields) #for name in fields: # print("""key %s: "%s" %s""" % (name, self.popstr(fields[name]), type(fields[name]))) if "printer" in fields: printer = self.popstr(fields["printer"]) if (printer is None) or ("" == printer): err_msg = "printer empty or unset" self.send_resonse(400) self.send_header("X-Error", err_msg) self.end_headers() self.wfile.write(b"
  • %s\n"%err_msg) return else: err_msg = "printer not submitted" self.send_response(400) self.send_header("X-Error", err_msg) self.end_headers(); self.wfile.write(b"
  • %s\n" % err_msg); return if "mac" in fields: mac_address = self.popstr(fields["mac"]) if (mac_address is None) or ("" == mac_address): err_msg = "mac address empty or unset" self.send_resonse(400) self.send_header("X-Error", err_msg) self.end_headers() self.wfile.write(b"
  • %s\n"%err_msg) return else: err_msg = "mac address not submitted" self.send_response(400) self.send_header("X-Error", err_msg) self.end_headers(); self.wfile.write(b"
  • %s\n" % err_msg); return if "model" in fields: model = self.popstr(fields["model"]) if (model is None) or (model == ""): err_msg = "model name not submitted" self.send_reponse(400) self.send_header("X-Error", err_msg) self.end_headers() self.wfile.write(b"
  • %s\n"%err_msg) return else: err_msg = "model name not submitted" self.send_response(400) self.send_header("X-Error", err_msg) self.wfile.write(b"
  • %s\n" % err_msg); return if "hostname" in fields: hostname = self.popstr(fields["hostname"]) else: suffix = mac_address[-5:].replace(":", "") hostname = "%s-%s"%(model, suffix) if "serial" in fields: serial = self.popstr(fields["serial"]) else: serial = hostname now = datetime.now() datestr = now.strftime("%Y-%m") self.send_response(200); self.send_header("Content-type", "text/html") self.end_headers() label_html = self.html_template(model_=model, mac_=mac_address, hostname_=hostname, serial_=serial, datestr_=datestr) if os.path.exists(html_filename): try: os.remove(html_filename) except: err_msg = "unable to remove html file" self.send_response(400) self.send_header("X-Error", err_msg) self.wfile.write(b"
  • %s\n" % err_msg); return try: file = open(html_filename, "w") file.write(label_html) file.close() except: err_msg = "unable to write html file" self.send_response(400) self.send_header("X-Error", err_msg) self.wfile.write(b"
  • %s\n" % err_msg); return self.print_pdf(printer=printer, html=html_filename) self.wfile.write(b"Success\n") def html_template(self, model_="unset", mac_="unset", hostname_="unset", serial_="unset", datestr_="unset"): template = """
    Model: %s (%s)
    MAC: %s
    Hostname: %s
    Serial: #%s
    """ % (model_, datestr_, mac_, hostname_, serial_) return template def print_pdf(self, printer, html ): """ :param printer: :param html: :return: """ """ Below is shell script that worked: w_inches="3.45" h_inches="1.125" w_points=`echo "scale=0; ($w_inches * 72)/1" | bc -l` w_px=`echo "scale=0; ($w_inches * 720)/1" | bc -l` h_points=`echo "scale=0; ($h_inches * 72)/1" | bc -l` h_px=`echo "scale=0; ($h_inches * 720)/1" | bc -l` echo "Page size in Points: $w_points x $h_points" echo "Page size in pixels: $w_px x $h_px" rm -f label.pdf set -x html2ps -L label.html \ | gs -o label.pdf \ -g${h_px}x${w_px} \ -sDEVICE=pdfwrite \ -dFIXEDMEDIA \ -dPDFFitPage \ -dFitPage \ -c '<> setpagedevice' \ -f - """ w_inches = 3.45 h_inches = 1.125 w_points = math.floor(w_inches * 72) w_px = math.floor(w_inches * 720) h_points = math.floor(h_inches * 72) h_px = math.floor(h_inches * 720) pdf_file = "/tmp/label.pdf" pageoffset = "<> setpagedevice" geometry = "-g{}x{}".format(h_px, w_px) if os.path.exists(pdf_file): try: os.remove(pdf_file) except: err_msg = "unable to remove html file" self.send_response(400) self.send_header("X-Error", err_msg) self.wfile.write(b"
  • %s\n" % err_msg); return cmd = """html2ps -L "%s" | gs -o "%s" %s -sDEVICE=pdfwrite -dFIXEDMEDIA -dPDFFitPage -dFitPage -c '%s' -f -""" \ % (html, pdf_file, geometry, pageoffset) print("CMD: "+cmd) try: os.system(cmd) os.system("""lp -d "%s" -- "%s" """%(printer, pdf_file)) except: err_msg = "trouble printing pdf" self.send_response(500) self.send_header("X-Error", err_msg) self.wfile.write(b"
  • %s\n" % err_msg); return def __main__(): logging.info("Main Method. Creating CGI Handler") httpd = HTTPServer(('', 8082), LabelPrinterRequestHandler) print("Starting LabelPrinter service...") httpd.serve_forever() if __name__ == "__main__": __main__()