Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/paper config #9

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 82 additions & 24 deletions phomeme/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from enum import Enum, auto
from io import BytesIO
from multiprocessing import Lock
from typing import Optional
import os
import pathlib
import socket
Expand All @@ -8,12 +10,8 @@
from flask import Flask, request, make_response, redirect, jsonify
from flask_cors import CORS

DEVICE = os.environ.get("PHOMEMO_BT_MAC", None)
if not DEVICE:
CHARDEV = '/dev/phomemo'
if not pathlib.Path(CHARDEV).is_char_device():
raise Exception('No valid printer target configured (envvar PHOMEMO_BT_MAC unset and %s is not a character device)' % CHARDEV)
PAPER_SIZE = os.environ.get("PHOMEMO_PAPER_SIZE", None)
from . import config


app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 40 * 1024 * 1024
Expand All @@ -32,50 +30,95 @@ def static_helper(static):
return app.send_static_file(static)


@app.route("/papersize")
def paper_size():
if PAPER_SIZE:
return jsonify(PAPER_SIZE)
else:
return "No default paper size configured", 404


@app.route("/printers")
def printers():
return jsonify(config.printers)


@app.route("/print", methods=["POST"])
def handle_image():
printer_name = request.args.get("printer")

try:
f = request.files["image"]
file_length = f.seek(0, os.SEEK_END)
f.seek(0, os.SEEK_SET)
width = int(float(request.form.get("width")))
height = int(float(request.form.get("height")))
print('Received image with length %d bytes and intended print size %dx%d' % (file_length, width, height))
print(
f"Received image with length {file_length} bytes and intended print size {width}x{height}"
)
img = Image.open(f)
except Exception as e:
print(e)
return f"Error loading image: {e}", 500

try:
print_image = PrintImage(img, offset=True, resize=(width, height))
print_image.print()
printer = Printer(
device=(
config.printers[0]["address"] if printer_name is None else printer_name
)
)
printer.print(print_image)
except Exception as e:
print(e)
return f"Error printing image: {e}", 500

return jsonify("ok")


class DeviceType(Enum):
BLUETOOTH = auto()
CHARDEV = auto()


class PrinterDevice:
path: Optional[str]
device_type: DeviceType

def __init__(
self, path: Optional[str] = None, device_type: Optional[DeviceType] = None
):
if path is None:
self.path = "/dev/phomemo"

if device_type is None:
self.device_type = DeviceType.CHARDEV

if not pathlib.Path(self.path).is_char_device():
raise Exception(
f"No valid printer target configured (envvar PHOMEMO_BT_MAC unset and {CHARDEV} is not a character device)"
)
else:
self.path = path

if device_type is None:
self.device_type = DeviceType.BLUETOOTH

@property
def address(self):
return self.path

@address.setter
def address(self, value):
self.path = value


class PrintImage:
image: Image

def __init__(self, image: Image, offset=True, resize=(323, 240)):
self.image = image
print('Original image size:', image.size)
print("Original image size:", image.size)
if resize:
self._resize(resize[0], resize[1])
print('Image size after resize:', self.image.size)
print("Image size after resize:", self.image.size)
if offset:
self._offset()
print('Image size after offset:', self.image.size)
print("Image size after offset:", self.image.size)

def _resize(self, target_width, target_height):
img = self.image
Expand Down Expand Up @@ -103,8 +146,23 @@ def _offset(self):
imgborder.paste(self.image, (horizontal_offset, 0))
self.image = imgborder

def _print(self):
img = self.image.convert("1")

class Printer:
name: str
device: PrinterDevice

def __init__(
self,
device: Optional[str] = None,
name: Optional[str] = None,
):
self.device = PrinterDevice(path=device)

if name is None:
self.name = self.device.address

def _print(self, image: PrintImage):
img = image.image.convert("1")

buf = []
buf += [0x1B, 0x40]
Expand All @@ -127,19 +185,19 @@ def _print(self):
buf += ibuf

# -- send
if DEVICE:
if self.device.device_type == DeviceType.BLUETOOTH:
sock = socket.socket(
socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM
)
sock.bind((socket.BDADDR_ANY, 1))
sock.connect((DEVICE, 1))
sock.connect((self.device.address, 1))
sock.sendall(bytes(buf))
sock.recv(1024)
sock.close()
else:
with open(CHARDEV, 'wb') as f:
with open(self.device.path, "wb") as f:
f.write(bytes(buf))

def print(self):
def print(self, image: PrintImage):
with app.printlock:
self._print()
self._print(image)
16 changes: 16 additions & 0 deletions phomeme/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import json
import os

config_path = os.path.join(os.path.dirname(__file__), "config")

printers = []
paper = None

with open(os.path.join(config_path, "printer.json"), 'r') as file:
printers = json.load(file)

with open(os.path.join(config_path, "paper.json"), 'r') as file:
paper = json.load(file)

for printer in printers:
printer["paper"] = paper[printer["paper"]]
58 changes: 58 additions & 0 deletions phomeme/config/paper.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"rect_40_30": {
"name": "rect_40_30",
"shape": "rectangular",
"width": 40,
"height": 30,
"dpi": 204
},
"rect_50_20": {
"name": "rect_50_20",
"shape": "rectangular",
"width": 50,
"height": 20,
"dpi": 204
},
"rect_30_20": {
"name": "rect_30_20",
"shape": "rectangular",
"width": 30,
"height": 20,
"dpi": 204
},
"rect_40_40": {
"name": "rect_40_40",
"shape": "rectangular",
"width": 40,
"height": 40,
"dpi": 204
},
"rect_50_50": {
"name": "rect_50_50",
"shape": "rectangular",
"width": 50,
"height": 50,
"dpi": 204
},
"circ_40": {
"name": "circ_40",
"shape": "circular",
"width": 40,
"height": 40,
"dpi": 204
},
"circ_50": {
"name": "circ_50",
"shape": "circular",
"width": 50,
"height": 50,
"dpi": 204
},
"split_42_10": {
"name": "split_42_10",
"shape": "split",
"width": 42,
"height": 10,
"dpi": 204
}
}
7 changes: 7 additions & 0 deletions phomeme/config/printer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"address": "qwertz",
"paper": "circ_50",
"name": "printer1"
}
]
Loading
Loading