Initial commit, state from 36C3
This commit is contained in:
commit
e1be1c5f08
4 changed files with 134 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*.pyc
|
||||||
|
**/__pycache__
|
14
escpos.service
Normal file
14
escpos.service
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[Unit]
|
||||||
|
Description=ESC/POS Print Job Submission Web Interface
|
||||||
|
After=multi-user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Environment=PYTHONUNBUFFERED=1
|
||||||
|
ExecStart=/home/escpos/escpos/venv/bin/python3 /home/escpos/escpos/__main__.py
|
||||||
|
User=escpos
|
||||||
|
WorkingDirectory=-/home/escpos/escpos
|
||||||
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
0
escpos/__init__.py
Normal file
0
escpos/__init__.py
Normal file
118
escpos/__main__.py
Normal file
118
escpos/__main__.py
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
from bottle import run, get, post, request
|
||||||
|
from threading import Lock, Event, Thread
|
||||||
|
from queue import Queue
|
||||||
|
import serial
|
||||||
|
import cgi
|
||||||
|
import copy
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
# Version 2, December 2004
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019, SPiNNiX
|
||||||
|
# Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
# copies of this license document, and changing it is allowed as long
|
||||||
|
# as the name is changed.
|
||||||
|
#
|
||||||
|
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
#
|
||||||
|
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||||
|
|
||||||
|
lock = Lock()
|
||||||
|
queue = Queue()
|
||||||
|
stop_event = Event()
|
||||||
|
|
||||||
|
|
||||||
|
TEMPLATE='''
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Toilet Paper as a Service</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>TPaaS - Toilet Paper as a Service</h1>
|
||||||
|
<h2>Submit Print Job</h2>
|
||||||
|
<form action="/" method="post">
|
||||||
|
Give your print job a name: <input name="printjob" /><br/>
|
||||||
|
<textarea name="txt" cols="44" rows="22"></textarea><br/><br/>
|
||||||
|
<input name="action" value="wrap" type="submit" />
|
||||||
|
<input name="action" value="cut" type="submit" />
|
||||||
|
<input name="action" value="test" type="submit" />
|
||||||
|
</form><br/>
|
||||||
|
A single line on toilet paper is up to 44 characters long.<br/>
|
||||||
|
There are three print modes:
|
||||||
|
<ul>
|
||||||
|
<li><tt>wrap</tt>: Lines longer than 44 characters are wrapped.</li>
|
||||||
|
<li><tt>cut</tt>: Only the first 44 characters of each line are printed.</li>
|
||||||
|
<li><tt>test</tt>: Prints a special test message.</li>
|
||||||
|
</ul>
|
||||||
|
Pick up your print at <a href="https://36c3.c3nav.de/l/c:0:482.75:484.16/">CCC-CH assembly</a>.
|
||||||
|
<h2>Print Queue</h2>
|
||||||
|
<ol>
|
||||||
|
{printqueue}
|
||||||
|
</ol>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@get('/')
|
||||||
|
def home():
|
||||||
|
with queue.mutex:
|
||||||
|
q = copy.copy(queue.queue)
|
||||||
|
items = [f'{" "*12}<li>{x[0]}</li>\n' for x in q]
|
||||||
|
return TEMPLATE.format(printqueue=''.join(items))
|
||||||
|
|
||||||
|
@post("/")
|
||||||
|
def web():
|
||||||
|
action = 'wrap'
|
||||||
|
if request.forms.action in ['wrap', 'cut', 'test']:
|
||||||
|
action = request.forms.action
|
||||||
|
content = request.forms.get("txt") or ''
|
||||||
|
name = cgi.html.escape(request.forms.get("printjob") or '')
|
||||||
|
queue.put((name, content, action))
|
||||||
|
return home()
|
||||||
|
|
||||||
|
|
||||||
|
def prt():
|
||||||
|
with serial.Serial("/dev/ttyUSB0", 19200, xonxoff=True) as s:
|
||||||
|
print('tty opened', file=sys.stderr)
|
||||||
|
while not stop_event.is_set():
|
||||||
|
name, content, action = queue.get()
|
||||||
|
print(f'now printing: {name}', file=sys.stderr)
|
||||||
|
if action == 'wrap':
|
||||||
|
output = ''
|
||||||
|
for line in content.split("\r\n"):
|
||||||
|
while len(line) > 44:
|
||||||
|
l, line = line[0:44], line[44:]
|
||||||
|
l = l or ' '
|
||||||
|
output += f'{" "*22}{l}\n'
|
||||||
|
line = line or ' '
|
||||||
|
output += f'{" "*22}{line}\n'
|
||||||
|
nln = len([1 for x in output.split("\n")])
|
||||||
|
print(f'Printing {nln} lines in wrap mode', file=sys.stderr)
|
||||||
|
s.write(output.encode('cp437', errors='ignore'))
|
||||||
|
elif action == 'cut':
|
||||||
|
output = ''
|
||||||
|
for line in content.split("\r\n"):
|
||||||
|
line = line or ' '
|
||||||
|
output += f'{" "*22}{line[0:44]}\n'
|
||||||
|
nln = len([1 for x in output.split("\n")])
|
||||||
|
print(f'Printing {nln} lines in wrap mode', file=sys.stderr)
|
||||||
|
s.write(output.encode('cp437', errors='ignore'))
|
||||||
|
elif action == 'test':
|
||||||
|
print('Printing hello world', file=sys.stderr)
|
||||||
|
s.write(f'{" "*22}HELLO, 36C3 - TOILET PAPER EXHAUSTION\n'.encode('cp437', errors='ignore'))
|
||||||
|
|
||||||
|
def main():
|
||||||
|
t = Thread(target=prt)
|
||||||
|
t.start()
|
||||||
|
run(host='0.0.0.0', port=80, debug=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in a new issue