citizen_zpl_printer/models/printer_utils.py
2026-01-26 11:26:45 +07:00

83 lines
2.5 KiB
Python

import socket
import logging
_logger = logging.getLogger(__name__)
def send_zpl_to_printer(ip, port, zpl_data):
"""
Send ZPL data to a printer via socket.
:param ip: Printer IP address (str)
:param port: Printer Port (int)
:param zpl_data: ZPL content (str or bytes)
:return: True if successful, raises Exception otherwise
"""
if not ip:
raise ValueError("Printer IP is not configured.")
if not zpl_data:
return
try:
if isinstance(zpl_data, str):
zpl_data = zpl_data.encode('utf-8')
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.settimeout(5) # 5 seconds timeout
sock.connect((ip, int(port)))
sock.sendall(zpl_data)
_logger.info(f"Sent {len(zpl_data)} bytes to printer at {ip}:{port}")
return True
except Exception as e:
_logger.error(f"Failed to print to {ip}:{port}. Error: {e}")
raise e
def convert_to_zpl_hex(image_data, width_dots=100, height_dots=100):
"""
Convert image binary data to ZPL hex string (^GFA command).
:param image_data: Binary image data
:param width_dots: Max width in dots
:param height_dots: Max height in dots
:return: ZPL command string (^GFA...)
"""
if not image_data:
return ""
try:
from PIL import Image
import io
import binascii
image = Image.open(io.BytesIO(image_data))
# Resize preserving aspect ratio
image.thumbnail((width_dots, height_dots), Image.Resampling.LANCZOS)
# Convert to 1-bit monochrome (dithered)
# Convert to grayscale first, then 1-bit
image = image.convert('L')
image = image.convert('1')
width, height = image.size
row_bytes = (width + 7) // 8
total_bytes = row_bytes * height
# Get bit data
data = image.tobytes()
# Convert to hex
hex_data = binascii.hexlify(data).upper().decode('utf-8')
# Create ZPL command
# ^GFA,b,c,d,data
# a = compression type (A=ASCII)
# b = binary byte count
# c = graphic field count (total bytes)
# d = bytes per row
zpl_cmd = f"^GFA,{total_bytes},{total_bytes},{row_bytes},{hex_data}"
return zpl_cmd
except Exception as e:
_logger.error(f"Image conversion failed: {e}")
return ""