From 92ec15435c1067fa63203940ec5ee94d0b2e5fc6 Mon Sep 17 00:00:00 2001 From: simonkuehling Date: Thu, 17 Oct 2024 20:09:27 +0200 Subject: [PATCH] migrate plugin to machine registry integration --- inventree_brother/brother_plugin.py | 219 ++++++++++++++-------------- 1 file changed, 106 insertions(+), 113 deletions(-) diff --git a/inventree_brother/brother_plugin.py b/inventree_brother/brother_plugin.py index 707dd71..6dd0374 100644 --- a/inventree_brother/brother_plugin.py +++ b/inventree_brother/brother_plugin.py @@ -10,127 +10,126 @@ from brother_ql.models import ALL_MODELS from brother_ql.labels import ALL_LABELS, FormFactor -# translation +from django.db import models from django.utils.translation import gettext_lazy as _ -# printing options -from rest_framework import serializers - from inventree_brother.version import BROTHER_PLUGIN_VERSION # InvenTree plugin libs +from report.models import LabelTemplate from plugin import InvenTreePlugin -from plugin.mixins import LabelPrintingMixin, SettingsMixin +from plugin.machine import BaseMachineType +from plugin.machine.machine_types import LabelPrinterBaseDriver, LabelPrinterMachine # Image library from PIL import ImageOps -def get_model_choices(): - """ - Returns a list of available printer models - """ - - return [(model.name, model.name) for model in ALL_MODELS] - - -def get_label_choices(): - """ - Return a list of available label types - """ - - return [(label.identifier, label.name) for label in ALL_LABELS] - - -def get_rotation_choices(): - """ - Return a list of available rotation angles - """ - - return [(f"{degree}", f"{degree}°") for degree in [0, 90, 180, 270]] - - -class BrotherLabelSerializer(serializers.Serializer): - """Custom serializer class for BrotherLabelPlugin. - - Used to specify printing parameters at runtime - """ - - copies = serializers.IntegerField( - default=1, - label=_('Copies'), - help_text=_('Number of copies to print'), - ) - - -class BrotherLabelPlugin(LabelPrintingMixin, SettingsMixin, InvenTreePlugin): +class BrotherLabelPlugin(InvenTreePlugin): + """Brother label printer driver plugin for InvenTree.""" AUTHOR = "Oliver Walters" DESCRIPTION = "Label printing plugin for Brother printers" VERSION = BROTHER_PLUGIN_VERSION + # Machine registry was added in InvenTree 0.14.0, use inventree-brother-plugin 0.9.0 for older versions + # Machine driver interface was fixed with 0.16.0 to work inside of inventree workers + MIN_VERSION = "0.16.0" + NAME = "Brother Labels" SLUG = "brother" TITLE = "Brother Label Printer" - PrintingOptionsSerializer = BrotherLabelSerializer - # Use background printing BLOCKING_PRINT = False + + +class BrotherLabelPrinterDriver(LabelPrinterBaseDriver): + """Brother label printing driver for InvenTree.""" + + SLUG = "brother" + NAME = "Brother Label Printer Driver" + DESCRIPTION = "Brother label printing driver for InvenTree" + + def __init__(self, *args, **kwargs): + """Initialize the BrotherLabelPrinterDriver.""" + self.MACHINE_SETTINGS = { + 'MODEL': { + 'name': _('Printer Model'), + 'description': _('Select model of Brother printer'), + 'choices': self.get_model_choices, + 'default': 'PT-P750W', + 'required': True, + }, + 'LABEL': { + 'name': _('Label Media'), + 'description': _('Select label media type'), + 'choices': self.get_label_choices, + 'default': '12', + 'required': True, + }, + 'IP_ADDRESS': { + 'name': _('IP Address'), + 'description': _('IP address of the brother label printer'), + 'default': '', + }, + 'USB_DEVICE': { + 'name': _('USB Device'), + 'description': _('USB device identifier of the label printer (VID:PID/SERIAL)'), + 'default': '', + }, + 'AUTO_CUT': { + 'name': _('Auto Cut'), + 'description': _('Cut each label after printing'), + 'validator': bool, + 'default': True, + 'required': True, + }, + 'ROTATION': { + 'name': _('Rotation'), + 'description': _('Rotation of the image on the label'), + 'choices': self.get_rotation_choices, + 'default': '0', + 'required': True, + }, + 'COMPRESSION': { + 'name': _('Compression'), + 'description': _('Enable image compression option (required for some printer models)'), + 'validator': bool, + 'default': False, + 'required': True, + }, + 'HQ': { + 'name': _('High Quality'), + 'description': _('Enable high quality option (required for some printers)'), + 'validator': bool, + 'default': True, + 'required': True, + }, + } - SETTINGS = { - 'MODEL': { - 'name': _('Printer Model'), - 'description': _('Select model of Brother printer'), - 'choices': get_model_choices, - 'default': 'PT-P750W', - }, - 'LABEL': { - 'name': _('Label Media'), - 'description': _('Select label media type'), - 'choices': get_label_choices, - 'default': '12', - }, - 'IP_ADDRESS': { - 'name': _('IP Address'), - 'description': _('IP address of the brother label printer'), - 'default': '', - }, - 'USB_DEVICE': { - 'name': _('USB Device'), - 'description': _('USB device identifier of the label printer (VID:PID/SERIAL)'), - 'default': '', - }, - 'AUTO_CUT': { - 'name': _('Auto Cut'), - 'description': _('Cut each label after printing'), - 'validator': bool, - 'default': True, - }, - 'ROTATION': { - 'name': _('Rotation'), - 'description': _('Rotation of the image on the label'), - 'choices': get_rotation_choices, - 'default': '0', - }, - 'COMPRESSION': { - 'name': _('Compression'), - 'description': _('Enable image compression option (required for some printer models)'), - 'validator': bool, - 'default': False, - }, - 'HQ': { - 'name': _('High Quality'), - 'description': _('Enable high quality option (required for some printers)'), - 'validator': bool, - 'default': True, - }, - } - - def print_label(self, **kwargs): - """ - Send the label to the printer - """ + super().__init__(*args, **kwargs) + + def get_model_choices(self, **kwargs): + """ Returns a list of available printer models """ + return [(model.name, model.name) for model in ALL_MODELS] + + def get_label_choices(self, **kwargs): + """ Return a list of available label types """ + return [(label.identifier, label.name) for label in ALL_LABELS] + + def get_rotation_choices(self, **kwargs): + """ Return a list of available rotation angles """ + return [(f"{degree}", f"{degree}°") for degree in [0, 90, 180, 270]] + + def init_machine(self, machine: BaseMachineType): + """Machine initialize hook.""" + # static dummy setting for now, should probably be actively checked for USB printers + # and maybe by running a simple ping test or similar for networked printers + machine.set_status(LabelPrinterMachine.MACHINE_STATUS.CONNECTED) + + def print_label(self, machine: LabelPrinterMachine, label: LabelTemplate, item: models.Model, **kwargs) -> None: + """ Send the label to the printer """ # TODO: Add padding around the provided image, otherwise the label does not print correctly # ^ Why? The wording in the underlying brother_ql library ('dots_printable') seems to suggest @@ -148,19 +147,13 @@ def print_label(self, **kwargs): options = kwargs.get('printing_options', {}) n_copies = int(options.get('copies', 1)) - # Look for png data in kwargs (if provided) - label_image = kwargs.get('png_file', None) - - if not label_image: - # Convert PDF to PNG - pdf_data = kwargs['pdf_data'] - label_image = self.render_to_png(label=None, pdf_data=pdf_data) + label_image = self.render_to_png(label, item) # Read settings - model = self.get_setting('MODEL') - ip_address = self.get_setting('IP_ADDRESS') - usb_device = self.get_setting('USB_DEVICE') - media_type = self.get_setting('LABEL') + model = machine.get_setting('MODEL', 'D') + ip_address = machine.get_setting('IP_ADDRESS', 'D') + usb_device = machine.get_setting('USB_DEVICE', 'D') + media_type = machine.get_setting('LABEL', 'D') # Get specifications of media type media_specs = None @@ -168,7 +161,7 @@ def print_label(self, **kwargs): if label_specs.identifier == media_type: media_specs = label_specs - rotation = int(self.get_setting('ROTATION')) + 90 + rotation = int(machine.get_setting('ROTATION', 'D')) + 90 rotation = rotation % 360 if rotation in [90, 180, 270]: @@ -204,10 +197,10 @@ def print_label(self, **kwargs): 'qlr': printer, 'images': [printable_image], 'label': media_type, - 'cut': self.get_setting('AUTO_CUT'), + 'cut': machine.get_setting('AUTO_CUT', 'D'), 'rotate': 0, - 'compress': self.get_setting('COMPRESSION'), - 'hq': self.get_setting('HQ'), + 'compress': machine.get_setting('COMPRESSION', 'D'), + 'hq': machine.get_setting('HQ', 'D'), 'red': red, }