diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a99545a --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.vscode/ +.vs/ +.VSCodeCounter/ +.idea/ +.venv/ +venv/ +__pycache__/ + +pkgs/* +*.pyc +media/* +dist/* +temp/* + diff --git a/PrintAgent.py b/PrintAgent.py new file mode 100644 index 0000000..1537b99 --- /dev/null +++ b/PrintAgent.py @@ -0,0 +1,190 @@ +""" +@time:2024-07018 +@author:zhang +@param:pdf_file +PDF文件打印 + +""" +import win32print +import win32api +import os +import threading +from flask import Flask, request, jsonify +from PyPDF2 import PdfWriter, PdfReader +from flask_cors import CORS +import io +import ctypes + +import os +import pystray +import threading +from PIL import Image +from pystray import MenuItem +import time +# import requests +from datetime import datetime +import json +from configparser import ConfigParser +import socket +import glob + +import os +import logging +from logging.handlers import RotatingFileHandler +import configparser + + +CUR_DIR = os.path.dirname(os.path.abspath(__file__)) +log_path = os.path.join(CUR_DIR, 'printer.log') + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +formatter = logging.Formatter('[%(asctime)s] [%(filename)s:%(lineno)d] [%(levelname)s]- %(message)s') + +file_hander = RotatingFileHandler(log_path, maxBytes=1024*1024*10, backupCount=1) +file_hander.setFormatter(formatter) +file_hander.setLevel(logging.INFO) + +console_handler = logging.StreamHandler() +console_handler.setFormatter(formatter) +console_handler.setLevel(logging.DEBUG) + +logger.addHandler(file_hander) +logger.addHandler(console_handler) + +log_command = f'start "" powershell -Command "Get-Content -Path \'{log_path}\' -Tail 10 -Wait"' + + + +# 创建一个Flask应用 +app = Flask(__name__) +CORS(app, supports_credentials=True) +app.json.ensure_ascii = False + + +class SnPost: + + def __init__(self, server, port) -> None: + self.is_one_instance = False + self.is_working = False + self.icon = None # 下标 + self.server = server + self.port = port + self.check_one_instance() + + + def check_one_instance(self): + try: + global s + s = socket.socket() + host = socket.gethostname() + s.bind((host, 8080)) + self.is_one_instance = True + except Exception: + self.is_one_instance = False + + def close(self): + self.is_working = False + self.icon.stop() + + def log(self): + os.system(log_command) + + def run(self): + if not self.is_one_instance: + return + + menu = (MenuItem('退出', self.close), MenuItem('查看日志', self.log)) + image = Image.open("favicon.ico") + title = "打印机" + self.icon = pystray.Icon(title, image, "打印机", menu) + threading.Thread(target=self.icon.run, daemon=True).start() + + +@app.route('/print/', methods=['POST', 'OPTIONS']) +def pdf_printer(): + if request.method == 'OPTIONS': # 跨域请求预检 + return jsonify({"message": "OK"}), 200 + # if 'file' not in request.files: + # return jsonify({"error_message": "No file part", "error_code": 400}), 400 + file = request.files['file'] + printer_name = request.form.get('printer_name', None) + # Save the file temporarily + temp_pdf_path = os.path.join(os.path.dirname(__file__), 'temp_pdf.pdf') + + try: + # Read the PDF binary + file.save(temp_pdf_path) + if printer_name: + win32print.OpenPrinter(printer_name) + win32print.SetDefaultPrinter(printer_name) + win32print.GetDefaultPrinter() + + win32api.ShellExecute( + 0, + "print", + temp_pdf_path, + None, + ".", + 0 + ) + except Exception as e: + import traceback + print(traceback.format_exc()) + return jsonify({"error_message": str(e), "error_code": "print_failed"}), 500 + finally: + t = threading.Thread(target=del_file, args=(temp_pdf_path,)) + t.start() + # # 清除打印文件 + return jsonify({}), 200 + +def del_file(path): + import time + time.sleep(5) + if os.path.exists(path): + os.remove(path) + +def save_pdf_from_binary(pdf_binary, file_path): + """将二进制数据写入 PDF 文件""" + with open(file_path, 'wb') as file: + file.write(pdf_binary) + + +@app.route('/prints/', methods=['POST', 'OPTIONS']) +def str_printer(): + if request.method == 'OPTIONS': # 跨域请求预检 + return jsonify({"message": "OK"}), 200 + print_commands = request.json.get('print_commands', None) + print_name = request.json.get('print_name', None) + print(print_commands) + tsclibrary = ctypes.WinDLL(".//TSCLIB.dll") + if print_name: + tsclibrary.openportW(print_name) + else: + print_name = win32print.GetDefaultPrinter() + tsclibrary.openportW(print_name) + tsclibrary.clearbuffer() + for item in print_commands: + if 'WINTEXT' in item: + item_list = item.replace('WINTEXT ', '').split(',') + tsclibrary.windowsfontW( + item_list[0], + item_list[1], + item_list[2], + item_list[3], + item_list[4], + item_list[5], + item_list[6], + item_list[7]) + else: + tsclibrary.sendcommandW(item) + print(item, "33333") + tsclibrary.closeport() + + return jsonify({}), 200 + + +if __name__ == '__main__': + obj = SnPost(server='localhost', port=8080) + obj.run() + app.run(port=8080, debug=True, host='0.0.0.0') diff --git a/PrintAgent.spec b/PrintAgent.spec new file mode 100644 index 0000000..5c9adfe --- /dev/null +++ b/PrintAgent.spec @@ -0,0 +1,38 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['PrintAgent.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='PrintAgent', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/TSCLIB.dll b/TSCLIB.dll new file mode 100644 index 0000000..d03d33d Binary files /dev/null and b/TSCLIB.dll differ diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..f6f458e Binary files /dev/null and b/favicon.ico differ diff --git a/printer.log b/printer.log new file mode 100644 index 0000000..e69de29 diff --git a/test_.py b/test_.py new file mode 100644 index 0000000..001ca63 --- /dev/null +++ b/test_.py @@ -0,0 +1,29 @@ +import ctypes +# wintext x,y,height,rotation,type(0,1,2,3),line(0,1,2),fontname(Arial),text +print_commands = """SIZE 70 mm,90 mm\r\n +GAP 2 mm,0 mm\r\n +CLS\r\n +TEXT 100,100,"4",0,1,1,"DEMO FOR TEXT"\r\n +WINTEXT 100,200,36,0,0,0,Simhei,中国制造2025\r\n +BARCODE 100,300,"128",108,0,0,2,4,"3474598772242444288"\r\n +QRCODE 100,500,L,6,A,0,"www.baidu.com"\r\n +PRINT 1""" +tsclibrary = ctypes.WinDLL(".//TSCLIB.dll") +tsclibrary.openportW("GP-3150TN") +tsclibrary.clearbuffer() +print_commands_list = print_commands.split("\r\n\n") +for item in print_commands_list: + if 'WINTEXT' in item: + item_list = item.replace('WINTEXT ', '').split(',') + tsclibrary.windowsfontW( + item_list[0], + item_list[1], + item_list[2], + item_list[3], + item_list[4], + item_list[5], + item_list[6], + item_list[7]) + else: + tsclibrary.sendcommandW(item) +tsclibrary.closeport()