ptouch-print-labels/barcodegen.py
2024-06-03 09:22:02 +03:00

107 lines
3.5 KiB
Python
Executable File

import argparse
import pathlib
import subprocess
import sys
import time
from textwrap import dedent
from PIL import Image, ImageOps, ImageDraw, ImageFont
from barcode import EAN13
from barcode.writer import ImageWriter
PRODUCT_TYPES = {
"comp": ("21", "инвентарный номер для компьютера"),
"mon": ("22", "инвентарный номер для монитора"),
"net": ("23", "инвентарный номер для сетевого оборудования"),
"token": ("24", "инвентарный номер для токена"),
"print": ("25", "инвентарный номер для принтера/МФУ"),
"flash": ("26", "инвентарный номер для флешки"),
"hid": ("27", "инвентарный номер для HID устройств"),
"ups": ("28", "инвентарный номер для UPS устройств"),
"other": ("29", "инвентарный номер для других устройств"),
}
BARCODES_PATH = pathlib.Path().absolute() / "barcodes"
def gen_ean13(ptype: str):
product_code = PRODUCT_TYPES[ptype][0]
digits = product_code + str(round(time.time()))
digits = [int(i) for i in digits]
checksum = (10 - (sum(digits[1::2]) * 3 + sum(digits[::2])) % 10) % 10
return "".join(str(i) for i in (digits + [checksum]))
def create_code_png(filename: str | pathlib.Path, code, text):
if not filename.parent.exists():
filename.parent.mkdir(parents=True)
my_code = EAN13(code, writer=ImageWriter())
image = my_code.render(
writer_options={
"module_height": 11.0,
"module_width": 0.3,
"dpi": 169,
"font_size": 0,
"text_distance": 1,
"write_text": None,
}
)
image = image.convert("1", dither=Image.Dither.NONE)
image = ImageOps.expand(image, border=17, fill=1)
draw = ImageDraw.Draw(image)
dst = "terminus.pil"
font = ImageFont.load(dst)
text_length = draw.textlength(text, font=font)
code_text_length = draw.textlength(code, font=font)
draw.text(((image.width - text_length) / 2, 3), text, fill="black", font=font)
draw.text(
((image.width - code_text_length) / 2, 100),
code,
fill="black",
font=font,
)
image.save(filename)
def parse_args():
help_for_text = """\
code is must be a 13 digit code
or one of the following:
"""
help_for_text = dedent(help_for_text) + "\n".join(
f"{code} - {desc[1]}" for code, desc in PRODUCT_TYPES.items()
)
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("code", type=str, help=help_for_text)
parser.add_argument(
"text", type=str, nargs="?", default="", help="Description for barcode"
)
parser.add_argument("--print", action=argparse.BooleanOptionalAction, default=True)
return parser.parse_args()
def main():
args = parse_args()
if args.code not in PRODUCT_TYPES:
if args.code.isdigit() and len(args.code) == 13:
barcode = args.code
else:
print("Invalid args")
sys.exit(1)
else:
barcode = gen_ean13(args.code)
filename = BARCODES_PATH / f"{barcode}.png"
print(f"Generated code: {barcode}")
create_code_png(filename, barcode, args.text)
if args.print:
subprocess.run(["ptouch-print", "--image", filename])
if __name__ == "__main__":
main()