145 lines
4.4 KiB
Python
Executable File
145 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import sys
|
|
import os
|
|
import json
|
|
import base64
|
|
from io import BytesIO
|
|
from random import randint
|
|
import argparse
|
|
|
|
# Dependency Check
|
|
MISSING_DEPS = []
|
|
try:
|
|
import requests
|
|
except ImportError:
|
|
MISSING_DEPS.append("requests")
|
|
try:
|
|
from PIL import Image as PILImg, ImageOps
|
|
except ImportError:
|
|
MISSING_DEPS.append("Pillow (PIL)")
|
|
|
|
if MISSING_DEPS:
|
|
print(f"Error: Missing dependencies: {', '.join(MISSING_DEPS)}")
|
|
print("Please install them using: pip install " + " ".join(["requests", "Pillow"]))
|
|
sys.exit(1)
|
|
|
|
# Default IP for Moritz's Memobird
|
|
DEFAULT_HOST = "192.168.10.165"
|
|
|
|
def to_byte_array(img):
|
|
imgByteArr = BytesIO()
|
|
img.save(imgByteArr, format='bmp')
|
|
return imgByteArr.getvalue()
|
|
|
|
class MemobirdSender:
|
|
def __init__(self, host=DEFAULT_HOST, port='80'):
|
|
self.host = host
|
|
self.port = port
|
|
self.uri = f"http://{self.host}:{self.port}/sys/printer"
|
|
|
|
def send(self, text_list, print_id=None):
|
|
print_id = print_id or randint(1, 10**6)
|
|
payload = {
|
|
'command': 3,
|
|
'content': {
|
|
'textList': text_list
|
|
},
|
|
'encryptFlag': 0,
|
|
'hasHead': 0,
|
|
'hasSignature': 0,
|
|
'hasTail': 0,
|
|
'isFromDirectPrint': False,
|
|
'msgType': 1,
|
|
'pkgCount': 1,
|
|
'pkgNo': 1,
|
|
'printID': print_id,
|
|
'priority': 0,
|
|
'result': 0,
|
|
'scripType': 3
|
|
}
|
|
|
|
try:
|
|
resp = requests.post(self.uri, json=payload, timeout=10)
|
|
resp.raise_for_status()
|
|
return resp.status_code
|
|
except requests.exceptions.ConnectTimeout:
|
|
print(f"Error: Connection to Memobird at {self.host} timed out.")
|
|
print("Check if the printer is powered on and on the same network.")
|
|
sys.exit(1)
|
|
except requests.exceptions.ConnectionError:
|
|
print(f"Error: Could not connect to Memobird at {self.host}.")
|
|
print("Verify the IP address and network connectivity.")
|
|
sys.exit(1)
|
|
except Exception as e:
|
|
print(f"Error sending to Memobird: {e}")
|
|
sys.exit(1)
|
|
|
|
def create_text_element(text, big=False, bold=False, underline=False):
|
|
if not text.endswith('\n'):
|
|
text += '\n'
|
|
return {
|
|
'encodeType': 0,
|
|
'printType': 1,
|
|
'basetext': base64.b64encode(text.encode("GBK")).decode(),
|
|
'fontSize': 1 + big,
|
|
'bold': 1 * bold,
|
|
'underline': 1 * underline
|
|
}
|
|
|
|
def create_image_element(path):
|
|
img = PILImg.open(path)
|
|
img = img.convert(mode='L')
|
|
img = ImageOps.flip(img)
|
|
img = img.convert(mode='1')
|
|
return {
|
|
'encodeType': 0,
|
|
'printType': 5,
|
|
'basetext': base64.b64encode(to_byte_array(img)).decode()
|
|
}
|
|
|
|
def create_line_element(linetype='THICK'):
|
|
codes = {'THICK': 41, 'THIN': 42, 'DASH': 43}
|
|
return {
|
|
'encodeType': 0,
|
|
'printType': 4,
|
|
'iconID': codes.get(linetype, 41)
|
|
}
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Print to Memobird")
|
|
parser.add_argument("--text", help="Text to print")
|
|
parser.add_argument("--image", help="Path to image to print")
|
|
parser.add_argument("--ip", default=DEFAULT_HOST, help=f"Memobird IP (default: {DEFAULT_HOST})")
|
|
parser.add_argument("--big", action="store_true", help="Use big font")
|
|
parser.add_argument("--bold", action="store_true", help="Use bold font")
|
|
parser.add_argument("--underline", action="store_true", help="Use underline")
|
|
parser.add_argument("--line", choices=['THICK', 'THIN', 'DASH'], help="Print a separator line")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if not args.text and not args.image and not args.line:
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
sender = MemobirdSender(host=args.ip)
|
|
elements = []
|
|
|
|
if args.line:
|
|
elements.append(create_line_element(args.line))
|
|
|
|
if args.text:
|
|
elements.append(create_text_element(args.text, big=args.big, bold=args.bold, underline=args.underline))
|
|
|
|
if args.image:
|
|
if os.path.exists(args.image):
|
|
elements.append(create_image_element(args.image))
|
|
else:
|
|
print(f"Error: Image not found: {args.image}")
|
|
sys.exit(1)
|
|
|
|
status = sender.send(elements)
|
|
print(f"Success! Printer returned {status}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|