Skip to content

Commit

Permalink
Merge branch 'release/0.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
sam159 committed Dec 28, 2023
2 parents c7862fd + b61158e commit 5644e29
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 21 deletions.
9 changes: 9 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"cSpell.words": [
"barcodes",
"Datamatrix",
"Grocy",
"libdmtx",
"venv"
]
}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 0.3.0

- Added support for using QR codes instead of Datamatrix

# 0.2.0

- Scaling barcode by 2x or 4x space permitting
Expand Down
27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

<img src="example.png" alt="Example Label" width="348" height="135">

This project is intended to be a webhook target for [Grocy](https://github.com/grocy/grocy) to print labels to a brother QL label printer. Datamatrix barcodes are used instead of QR or linear barcodes, this matches what Grocy uses by default.
This project is intended to be a webhook target for [Grocy](https://github.com/grocy/grocy) to print labels to a brother QL label printer.

Datamatrix or QR codes can be used with Datamatrix being the default. Datamatrix will fit better in smaller labels but I've found aren't as easily read by the Grocy
barcode reader or by the [Android App](https://github.com/patzly/grocy-android).

Only die-cut labels are supported as I don't have any endless rolls to test with.

Expand All @@ -18,23 +21,23 @@ Once you have this running somewhere update your config at `app/data/config.php`
Setting('LABEL_PRINTER_HOOK_JSON', false);
Setting('FEATURE_FLAG_LABEL_PRINTER', true);
```

## Environment Variables

The label size and printer are configured via environmental variables. You can also create a `.env` file instead.

| Variable | Default | Description |
| -------- | ------- | ----------- |
| LABEL_SIZE | 62x29 | See the [brother_ql](https://github.com/pklaus/brother_ql) readme for the names of the labels |
| PRINTER_MODEL | QL-500 | The printer model, ie `QL-500`. One of the values accepted by brother_ql |
| PRINTER_PATH | file:///dev/usb/lp1 | Where the printer is found on the system. For network printers use `tcp://printer.address` |
| NAME_FONT | NotoSerif-Regular.ttf | The file name of the font in the fonts directory |
| NAME_FONT_SIZE | 48 | The size of that font |
| NAME_MAX_LINES | 4 | The maximum number of lines to use for the name |
| DUE_DATE_FONT | NotoSerif-Regular.ttf | NotoSerif-Regular.ttf | The file name of the font in the fonts directory |
| DUE_DATE_FONT_SIZE | 30 | The size of that font |
| Variable | Default | Description |
| ------------------ | --------------------- | --------------------------------------------------------------------------------------------- |
| LABEL_SIZE | 62x29 | See the [brother_ql](https://github.com/pklaus/brother_ql) readme for the names of the labels |
| PRINTER_MODEL | QL-500 | The printer model. One of the values accepted by brother_ql |
| PRINTER_PATH | file:///dev/usb/lp1 | Where the printer is found on the system. For network printers use `tcp://printer.address` |
| BARCODE_FORMAT | Datamatrix | `Datamatrix` or `QRCode` |
| NAME_FONT | NotoSerif-Regular.ttf | The file name of the font in the fonts directory |
| NAME_FONT_SIZE | 48 | The size of that font |
| NAME_MAX_LINES | 4 | The maximum number of lines to use for the name |
| DUE_DATE_FONT | NotoSerif-Regular.ttf | The file name of the font in the fonts directory |
| DUE_DATE_FONT_SIZE | 30 | The size of that font |

Included fonts are `NotoSans-Regular.ttf` and `NotoSerif-Regular.ttf`

Expand Down
11 changes: 6 additions & 5 deletions app.py → app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
from brother_ql.labels import ALL_LABELS
from brother_ql import BrotherQLRaster, create_label
from brother_ql.backends import guess_backend, backend_factory
from imaging import createBarcode, createLabelImage
from app.imaging import createBarcode, createLabelImage

load_dotenv()

LABEL_SIZE = getenv("LABEL_SIZE", "62x29")
PRINTER_MODEL = getenv("PRINTER_MODEL", "QL-500")
PRINTER_PATH = getenv("PRINTER_PATH", "file:///dev/usb/lp1")
BARCODE_FORMAT = getenv("BARCODE_FORMAT", "Datamatrix")
NAME_FONT = getenv("NAME_FONT", "NotoSerif-Regular.ttf")
NAME_FONT_SIZE = int(getenv("NAME_FONT_SIZE", "48"))
NAME_MAX_LINES = int(getenv("NAME_MAX_LINES", "4"))
Expand All @@ -25,8 +26,8 @@
label_spec = next(x for x in ALL_LABELS if x.identifier == LABEL_SIZE)

thisDir = path.dirname(path.abspath(__file__))
nameFont = ImageFont.truetype(path.join(thisDir, "fonts", NAME_FONT), NAME_FONT_SIZE)
ddFont = ImageFont.truetype(path.join(thisDir, "fonts", DUE_DATE_FONT), DUE_DATE_FONT_SIZE)
nameFont = ImageFont.truetype(path.join(thisDir, "..", "fonts", NAME_FONT), NAME_FONT_SIZE)
ddFont = ImageFont.truetype(path.join(thisDir, "..", "fonts", DUE_DATE_FONT), DUE_DATE_FONT_SIZE)

app = Flask(__name__)

Expand Down Expand Up @@ -56,7 +57,7 @@ def get_params():
def print_route():
(name, barcode, dueDate) = get_params();

label = createLabelImage(label_spec.dots_printable, name, nameFont, NAME_MAX_LINES, createBarcode(barcode), dueDate, ddFont)
label = createLabelImage(label_spec.dots_printable, name, nameFont, NAME_MAX_LINES, createBarcode(barcode, BARCODE_FORMAT), dueDate, ddFont)

buf = BytesIO()
label.save(buf, format="PNG")
Expand All @@ -69,7 +70,7 @@ def print_route():
def test():
(name, barcode, dueDate) = get_params();

img = createLabelImage(label_spec.dots_printable, name, nameFont, NAME_MAX_LINES, createBarcode(barcode), dueDate, ddFont)
img = createLabelImage(label_spec.dots_printable, name, nameFont, NAME_MAX_LINES, createBarcode(barcode, BARCODE_FORMAT), dueDate, ddFont)
buf = BytesIO()
img.save(buf, format="PNG")
buf.seek(0)
Expand Down
18 changes: 15 additions & 3 deletions imaging.py → app/imaging.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
from pylibdmtx.pylibdmtx import encode
import qrcode
from PIL import Image, ImageColor, ImageFont, ImageDraw

def createBarcode(text: str):
def createDatamatrix(text: str):
encoded = encode(text.encode('utf8'), "Ascii", "ShapeAuto")
barcode = Image.frombytes('RGB', (encoded.width, encoded.height), encoded.pixels)
return barcode

def createQRCode(text: str):
return qrcode.make(text, box_size = 1)

def createBarcode(text: str, type: str):
match type:
case "QRCode":
return createQRCode(text)
case "DataMatrix":
return createDatamatrix(text)
case _:
return createDatamatrix(text)

def createLabelImage(labelSize : tuple, text : str, textFont : ImageFont, textMaxLines : int, barcode : Image, dueDate : str, dueDateFont : ImageFont):
# increase the size of the barcode if space permits
if (barcode.size[1] * 4) < labelSize[1]:
Expand All @@ -14,6 +27,7 @@ def createLabelImage(labelSize : tuple, text : str, textFont : ImageFont, textMa
barcode = barcode.resize((barcode.size[0] * 2, barcode.size[1] * 2), Image.Resampling.NEAREST)

label = Image.new("RGB", labelSize, ImageColor.getrgb("#FFF"))
# vertically align barcode
barcode_padding = [0, (int)((label.size[1] / 2) - (barcode.size[1] / 2))]
label.paste(barcode, barcode_padding)

Expand All @@ -23,8 +37,6 @@ def createLabelImage(labelSize : tuple, text : str, textFont : ImageFont, textMa
nameMaxWidth = label.size[0] - barcode.size[0]
nameLeftMargin = (nameMaxWidth - nameTextWidth) / 2

print((nameTextWidth, nameMaxWidth, nameLeftMargin))

draw.multiline_text(
[barcode.size[0] + nameLeftMargin, 0],
nameText,
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ brother_ql >= 0.9, <= 1.0
Pillow == 10.*
pylibdmtx == 0.1.*
python-dotenv == 1.*
gunicorn
gunicorn
qrcode[pil] == 7.4.*

0 comments on commit 5644e29

Please sign in to comment.