-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
711 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
name: CI | ||
|
||
on: | ||
push: | ||
pull_request: | ||
release: | ||
types: [published] | ||
|
||
jobs: | ||
style-python: | ||
name: "💄 Style: python" | ||
if: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) }} | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # [email protected] | ||
|
||
- name: Setup python | ||
uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # [email protected] | ||
with: | ||
python-version: "3.10" | ||
|
||
- name: Install style check dependencies | ||
run: | | ||
pip install flake8==7.0.0 | ||
pip install pep8-naming==0.13.3 | ||
- name: Check style | ||
run: | | ||
flake8 . | ||
publish: | ||
if: github.event_name == 'release' && github.event.action == 'published' | ||
needs: [style-python] | ||
name: 📦 Publish to PyPi | ||
runs-on: ubuntu-latest | ||
environment: | ||
name: release | ||
url: https://pypi.org/p/inventree-dymo-plugin | ||
permissions: | ||
id-token: write | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # [email protected] | ||
|
||
- name: Setup python | ||
uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # [email protected] | ||
with: | ||
python-version: "3.10" | ||
|
||
- name: Install build dependencies | ||
run: pip install --upgrade wheel setuptools twine build | ||
|
||
- name: Build pip package | ||
run: python3 -m build | ||
|
||
- name: Publish package to PyPI | ||
uses: pypa/gh-action-pypi-publish@f8c70e705ffc13c3b4d1221169b84f12a75d6ca8 # [email protected] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,34 @@ | ||
# inventree-dymo-plugin | ||
Dymo Label printer driver plugin for InvenTree. | ||
|
||
[![License: ](https://img.shields.io/badge/License-GPLv3-yellow.svg)](https://opensource.org/licenses/MIT) | ||
![CI](https://github.com/wolflu05/inventree-dymo-plugin/actions/workflows/ci.yml/badge.svg) | ||
|
||
A label printer driver plugin for [InvenTree](https://inventree.org/), which provides support for Dymo Label Writer® printers. | ||
|
||
## Compatibility | ||
|
||
The following printers are already supported by the driver: | ||
|
||
- DYMO Label Writer 450 | ||
- DYMO Label Writer 450 Duo (Tape is not supported currently) | ||
- DYMO Label Writer 450 Turbo | ||
- DYMO Label Writer 450 Twin Turbo | ||
|
||
## Requirements | ||
|
||
Currently only printing over network is supported, so an RAW network socket server needs to be connected to the printer. A raspberry pi zero w is just enough for that job. | ||
|
||
The easiest way to set this up, is using cups and configure a RAW printer device in combination with `xinetd` like described in this [blog post](https://nerdig.es/labelwriter-im-netz-teil1/). | ||
|
||
## Installation | ||
|
||
> [!IMPORTANT] | ||
> This plugin is only compatible with InvenTree>=0.14 because this uses the new label printer driver interface. | ||
Goto "Admin Center > Plugins > Install Plugin" and enter `inventree-dymo-plugin` as package name. | ||
|
||
Then goto "Admin Center > Machines" and create a new machine using this driver. | ||
|
||
## Technical working | ||
|
||
This driver implements the RAW Dymo LabelWriter® 450 Series commands like described in the [technical reference manual](https://download.dymo.com/dymo/technical-data-sheets/LW%20450%20Series%20Technical%20Reference.pdf) to send the label data to the printer. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import socket | ||
from django.db.models.query import QuerySet | ||
from rest_framework.request import Request | ||
from django.utils.translation import gettext_lazy as _ | ||
from django.core.validators import MinValueValidator, MaxValueValidator | ||
|
||
from plugin import InvenTreePlugin | ||
from plugin.base.label.mixins import LabelItemType | ||
from plugin.machine.machine_types import LabelPrinterBaseDriver, LabelPrinterMachine | ||
from label.models import LabelTemplate | ||
|
||
from .version import DYMO_PLUGIN_VERSION | ||
from .dymo import DymoLabel, RoleSelect, PrintDensity | ||
|
||
|
||
class InvenTreeDymoPlugin(InvenTreePlugin): | ||
AUTHOR = "wolflu05" | ||
DESCRIPTION = "InvenTree Dymo plugin" | ||
VERSION = DYMO_PLUGIN_VERSION | ||
|
||
# Machine driver registry is only available in InvenTree 0.14.0 and later | ||
MIN_VERSION = "0.14.0" | ||
|
||
TITLE = "InvenTree Dymo Plugin" | ||
SLUG = "inventree-dymo-plugin" | ||
NAME = "InvenTreeDymoPlugin" | ||
|
||
|
||
class DymoLabelPrinterDriver(LabelPrinterBaseDriver): | ||
"""Label printer driver for Dymo printers.""" | ||
|
||
SLUG = "dymo-driver" | ||
NAME = "Dymo Driver" | ||
DESCRIPTION = "Dymo label printing drive for InvenTree" | ||
|
||
def __init__(self, *args, **kwargs): | ||
self.MACHINE_SETTINGS = { | ||
'SERVER': { | ||
'name': _('Server'), | ||
'description': _('IP/Hostname of the Dymo print server'), | ||
'default': 'localhost', | ||
'required': True, | ||
}, | ||
'PORT': { | ||
'name': _('Port'), | ||
'description': _('Port number of the Dymo print server'), | ||
'validator': int, | ||
'default': 9100, | ||
'required': True, | ||
}, | ||
'SELECT_ROLL': { | ||
'name': _('Select Roll'), | ||
'description': _('Select the roll to use for printing'), | ||
'choices': [(a.name, a.label) for a in RoleSelect], | ||
'default': 'AUTOMATIC', | ||
'required': True, | ||
}, | ||
'DENSITY': { | ||
'name': _('Print Density'), | ||
'description': _('Set the print density'), | ||
'choices': [(a.name, a.label) for a in PrintDensity], | ||
'default': 'NORMAL', | ||
'required': True, | ||
}, | ||
'PRINT_MODE': { | ||
'name': _('Print Mode'), | ||
'description': _('Set the print mode'), | ||
'choices': [('TEXT', _('Text (300x300dpi)')), ('GRAPHIC', _('Graphic (300x600dpi)'))], | ||
'default': 'TEXT', | ||
'required': True, | ||
}, | ||
'LABEL_LENGTH': { | ||
'name': _('Label Length'), | ||
'description': _('Set the label length in dots between the holes + 10mm tolerance (e.g: (<distance> mm + 10mm)/25.4inch*300dpi)'), | ||
'validator': int, | ||
'default': 3058, | ||
'required': True, | ||
}, | ||
'THRESHOLD': { | ||
'name': _('Threshold'), | ||
'description': _('Set the threshold for converting grayscale to BW (0-255)'), | ||
'validator': [int, MinValueValidator(0), MaxValueValidator(255)], | ||
'default': 200, | ||
'required': True, | ||
}, | ||
'ROTATE': { | ||
'name': _('Rotate'), | ||
'description': _('Rotate the label'), | ||
'choices': [(f"{a}", f"{a}°") for a in [0, 90, 180, 270]], | ||
'default': "0", | ||
'required': False, | ||
}, | ||
} | ||
|
||
super().__init__(*args, **kwargs) | ||
|
||
def print_labels(self, machine: LabelPrinterMachine, label: LabelTemplate, items: QuerySet[LabelItemType], request: Request, **kwargs): | ||
"""Print labels using a Dymo label printer.""" | ||
printing_options = kwargs.get('printing_options', {}) | ||
|
||
dymo_label = DymoLabel( | ||
label_length=machine.get_setting('LABEL_LENGTH', 'D'), | ||
mode=machine.get_setting('PRINT_MODE', 'D'), | ||
density=PrintDensity[machine.get_setting('DENSITY', 'D')], | ||
role_select=RoleSelect[machine.get_setting('SELECT_ROLL', 'D')], | ||
rotate=int(machine.get_setting('ROTATE', 'D')), | ||
threshold=machine.get_setting('THRESHOLD', 'D'), | ||
) | ||
|
||
for item in items: | ||
dpi = {"TEXT": 300, "GRAPHIC": 600}[dymo_label.mode] | ||
png = self.render_to_png(label, item, request, dpi=dpi) | ||
|
||
for _copies in range(printing_options.get('copies', 1)): | ||
dymo_label.add_label(png) | ||
|
||
data = dymo_label.get_data() | ||
|
||
ip_addr = machine.get_setting('SERVER', 'D') | ||
port = machine.get_setting('PORT', 'D') | ||
|
||
try: | ||
print_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
print_socket.connect((ip_addr, port)) | ||
print_socket.send(data) | ||
print_socket.close() | ||
except Exception as e: | ||
raise ConnectionError(f"Error connection to network printer: {e}") |
Empty file.
Oops, something went wrong.