Initial commit
This commit is contained in:
parent
abed247bd9
commit
53c566e641
16
README.md
16
README.md
@ -1,3 +1,19 @@
|
|||||||
# pos-printer-server
|
# pos-printer-server
|
||||||
|
|
||||||
ESC/POS Thermal Printer Server
|
ESC/POS Thermal Printer Server
|
||||||
|
|
||||||
|
Prints logs.
|
||||||
|
|
||||||
|
Prints images, randomly-generated mazes.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [escposprinter Python library](https://github.com/Simonefardella/escposprinter)
|
||||||
|
- [RPi Maze Printer](https://github.com/mattiasjahnke/rpi-maze-printer)
|
||||||
|
|
||||||
|
21
maze/LICENSE
Normal file
21
maze/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 Engineerish
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
145
maze/mazy.py
Normal file
145
maze/mazy.py
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# import modules used here -- sys is a very standard one
|
||||||
|
import sys
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
import math
|
||||||
|
import random
|
||||||
|
|
||||||
|
class Cell:
|
||||||
|
walls = int('1111', 2)
|
||||||
|
visited = False
|
||||||
|
|
||||||
|
def __init__(self, x, y):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
|
||||||
|
def draw(self, draw):
|
||||||
|
global start, end, margin
|
||||||
|
|
||||||
|
if self.walls & 1 == 1:
|
||||||
|
draw.line([(margin + cellSize * self.x, margin + cellSize * self.y + cellSize), (margin + cellSize * self.x + cellSize, margin + cellSize * self.y + cellSize)], fill="black", width=3)
|
||||||
|
if (self.walls >> 1 & 1) == 1:
|
||||||
|
draw.line([(margin + cellSize * self.x + cellSize, margin + cellSize * self.y), (margin + cellSize * self.x + cellSize, margin + cellSize * self.y + cellSize)], fill="black", width=3)
|
||||||
|
if (self.walls >> 2 & 1) == 1:
|
||||||
|
draw.line([(margin + cellSize * self.x, margin + cellSize * self.y), (margin + cellSize * self.x + cellSize, margin + cellSize * self.y)], fill="black", width=3)
|
||||||
|
if (self.walls >> 3 & 1) == 1:
|
||||||
|
draw.line([(margin + cellSize * self.x, margin + cellSize * self.y), (margin + cellSize * self.x, margin + cellSize * self.y + cellSize)], fill="black", width=3)
|
||||||
|
|
||||||
|
if self.x == start[0] and self.y == start[1]:
|
||||||
|
draw.ellipse([margin + cellSize * self.x + cellSize / 4, margin + cellSize * self.y + cellSize / 4, margin + cellSize * self.x + cellSize / 4 + cellSize / 2, margin + cellSize * self.y + cellSize / 4 + cellSize / 2], fill="blue")
|
||||||
|
elif self.x == end[0] and self.y == end[1]:
|
||||||
|
draw.ellipse([margin + cellSize * self.x + cellSize / 4, margin + cellSize * self.y + cellSize / 4, margin + cellSize * self.x + cellSize / 4 + cellSize / 2, margin + cellSize * self.y + cellSize / 4 + cellSize / 2], fill="green")
|
||||||
|
|
||||||
|
rows = 0
|
||||||
|
cols = 0
|
||||||
|
#image = Image.new('RGB', (380, 400 * 2), (0, 0, 0))
|
||||||
|
image = Image.new('RGB', (500, 400 * 4), (0, 0, 0))
|
||||||
|
draw = ImageDraw.Draw(image)
|
||||||
|
cellSize = 20
|
||||||
|
margin = 10
|
||||||
|
|
||||||
|
matrix = []
|
||||||
|
stack = []
|
||||||
|
currentCell = None
|
||||||
|
biggestStack = 0
|
||||||
|
start = (0, 0)
|
||||||
|
end = (0, 0)
|
||||||
|
|
||||||
|
# Gather our code in a main() function
|
||||||
|
def main():
|
||||||
|
global matrix, stack, currentCell, start, rows, cols, cellSize, margin
|
||||||
|
# Setup
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
cellSize = int(sys.argv[1])
|
||||||
|
|
||||||
|
random.seed()
|
||||||
|
|
||||||
|
drawingWidth = image.width - margin * 2
|
||||||
|
drawingHeight = image.height - margin * 2
|
||||||
|
|
||||||
|
draw.rectangle([margin, margin, margin + drawingWidth, margin + drawingHeight], fill="white")
|
||||||
|
|
||||||
|
rows = int(math.floor(drawingHeight / cellSize))
|
||||||
|
cols = int(math.floor(drawingWidth / cellSize))
|
||||||
|
|
||||||
|
print(cellSize)
|
||||||
|
|
||||||
|
for y in range(rows):
|
||||||
|
for x in range(cols):
|
||||||
|
matrix.append(Cell(x, y))
|
||||||
|
|
||||||
|
currentCell = matrix[0]
|
||||||
|
start = (currentCell.x, currentCell.y)
|
||||||
|
|
||||||
|
while nrOfUnvisitedCells() > 0:
|
||||||
|
runMazeStep()
|
||||||
|
|
||||||
|
# Draw
|
||||||
|
for cell in matrix:
|
||||||
|
cell.draw(draw)
|
||||||
|
|
||||||
|
image.save("maze.png")
|
||||||
|
|
||||||
|
def runMazeStep():
|
||||||
|
global currentCell, stack, end, biggestStack
|
||||||
|
|
||||||
|
currentCell.visited = True
|
||||||
|
|
||||||
|
nei = []
|
||||||
|
|
||||||
|
if currentCell.x > 0:
|
||||||
|
cell = matrix[index(currentCell.x - 1, currentCell.y)]
|
||||||
|
if not cell.visited:
|
||||||
|
nei.append(cell)
|
||||||
|
if currentCell.y > 0:
|
||||||
|
cell = matrix[index(currentCell.x, currentCell.y - 1)]
|
||||||
|
if not cell.visited:
|
||||||
|
nei.append(cell)
|
||||||
|
if currentCell.x < cols - 1:
|
||||||
|
cell = matrix[index(currentCell.x + 1, currentCell.y)]
|
||||||
|
if not cell.visited:
|
||||||
|
nei.append(cell)
|
||||||
|
if currentCell.y < rows - 1:
|
||||||
|
cell = matrix[index(currentCell.x, currentCell.y + 1)]
|
||||||
|
if not cell.visited:
|
||||||
|
nei.append(cell)
|
||||||
|
|
||||||
|
if len(nei) > 0:
|
||||||
|
chosen = random.choice(nei)
|
||||||
|
stack.append(currentCell)
|
||||||
|
if len(stack) > biggestStack:
|
||||||
|
biggestStack = len(stack)
|
||||||
|
end = (chosen.x, chosen.y)
|
||||||
|
|
||||||
|
if chosen.x < currentCell.x:
|
||||||
|
chosen.walls &= ~(1 << 1)
|
||||||
|
currentCell.walls &= ~(1 << 3)
|
||||||
|
elif chosen.x > currentCell.x:
|
||||||
|
chosen.walls &= ~(1 << 3)
|
||||||
|
currentCell.walls &= ~(1 << 1)
|
||||||
|
elif chosen.y > currentCell.y:
|
||||||
|
chosen.walls &= ~(1 << 2)
|
||||||
|
currentCell.walls &= ~(1 << 0)
|
||||||
|
elif chosen.y < currentCell.y:
|
||||||
|
chosen.walls &= ~(1 << 0)
|
||||||
|
currentCell.walls &= ~(1 << 2)
|
||||||
|
|
||||||
|
currentCell = chosen
|
||||||
|
else:
|
||||||
|
currentCell = stack.pop()
|
||||||
|
|
||||||
|
|
||||||
|
def nrOfUnvisitedCells():
|
||||||
|
global matrix
|
||||||
|
res = len([cell for cell in matrix if not cell.visited])
|
||||||
|
return res
|
||||||
|
|
||||||
|
def index(x, y):
|
||||||
|
global cols
|
||||||
|
return y * cols + x
|
||||||
|
|
||||||
|
# Standard boilerplate to call the main() function to begin
|
||||||
|
# the program.
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
86
print_log.py
Executable file
86
print_log.py
Executable file
@ -0,0 +1,86 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
from escpos.printer import Usb
|
||||||
|
import getopt
|
||||||
|
import sys
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
TEXT_LIMIT=256
|
||||||
|
|
||||||
|
class PrintOptions:
|
||||||
|
title = None
|
||||||
|
text = None
|
||||||
|
verbose = False
|
||||||
|
image = None
|
||||||
|
|
||||||
|
def get_printer():
|
||||||
|
return Usb(0x0525, 0xa700) # <-- change based on your printer vendor and product ID
|
||||||
|
|
||||||
|
def do_print(options):
|
||||||
|
p = get_printer()
|
||||||
|
p.set(align='center')
|
||||||
|
p.text(str(datetime.datetime.now().strftime("%H:%M:%S")))
|
||||||
|
p.text(' ')
|
||||||
|
p.text(str(datetime.date.today()))
|
||||||
|
p.text('\n')
|
||||||
|
if (options.title):
|
||||||
|
p.set(align='center', text_type='B') # center bold
|
||||||
|
p.text(options.title + '\n')
|
||||||
|
p.set()
|
||||||
|
if len(options.text) > TEXT_LIMIT:
|
||||||
|
p.text(options.text[:TEXT_LIMIT] + '[...]\n(truncated)')
|
||||||
|
else:
|
||||||
|
p.text(options.text + '\n')
|
||||||
|
if options.image != None:
|
||||||
|
p.image(options.image)
|
||||||
|
p.cut()
|
||||||
|
|
||||||
|
def do_print_image(path):
|
||||||
|
p = get_printer()
|
||||||
|
p.image(path)
|
||||||
|
p.cut()
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
print(f'usage: {sys.argv[0]} [OPTIONS] TEXT...')
|
||||||
|
print(f' OPTIONS')
|
||||||
|
print(f' -v ... verbose')
|
||||||
|
print(f' -h ... help')
|
||||||
|
print(f' -t --title=X ... title to prepend')
|
||||||
|
print(f' -i --image=X ... image path')
|
||||||
|
print(f' TEXT is taken as the rest of argumenats if present,')
|
||||||
|
print(f' otherwise from STDIN (terminated by Ctrl+D).')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], "ht:i:v", ["help", "title=", "image="])
|
||||||
|
except getopt.GetoptError as err:
|
||||||
|
print(err)
|
||||||
|
usage()
|
||||||
|
sys.exit(2)
|
||||||
|
title = None
|
||||||
|
verbose = False
|
||||||
|
image = None
|
||||||
|
for o, a in opts:
|
||||||
|
if o == "-v":
|
||||||
|
verbose = True
|
||||||
|
elif o in ("-h", "--help"):
|
||||||
|
usage()
|
||||||
|
sys.exit()
|
||||||
|
elif o in ("-i", "--image"):
|
||||||
|
image = a
|
||||||
|
elif o in ("-t", "--title"):
|
||||||
|
title = a
|
||||||
|
else:
|
||||||
|
assert False, "unhandled option"
|
||||||
|
options = PrintOptions()
|
||||||
|
options.title = title
|
||||||
|
options.verbose = verbose
|
||||||
|
options.text = " ".join(args)
|
||||||
|
options.image = image
|
||||||
|
if len(options.text) <= 0:
|
||||||
|
for line in sys.stdin:
|
||||||
|
options.text = options.text + line
|
||||||
|
do_print(options)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
python_escpos
|
Loading…
Reference in New Issue
Block a user