Am laufenden Band (Linux-Magazin, Dezember 2015)

Etiketten bringen Ordnung in den Kabelverhau am Heim-Router und helfen beim Auffinden von in Kisten gelagertem Plunder. Der Dymo Labelwriter 450 Turbo druckt sogar unter Linux.

Schon seit Jahrzehnten beschrifte ich alle meine Netzwerkkabel mit dauerhaften Etiketten aus einem tragbaren Gerät der Firma Brother. Doch bei jedem gedruckten Papperl regt mich der verschwenderische Umgang des Geräts mit dem Rohmaterial auf, das der User in relativ teuren Kartuschen nachkaufen muss. Brother-Ingenieure haben das Gerät wohl absichtlich so dilletantisch konstruiert, dass es doppelt so viel Label-Band verbraucht wie notwendig, auf dass der Rohbandkassettenabsatz in die Höhe schnelle! Falls es tatsächlich eine Hölle gibt, erwarte ich definitiv, die verantwortlichen Produktmanager dort bald hinabfahren zu sehen.

Schneller als von Hand

Außerdem dauert es jedesmal eine Ewigkeit, Texte wie "192.168.0.1" auf der unorthodoxen Tastatur einzutippen, das ginge mit meinem Desktop-Rechner viel schneller. Auf Ebay fand ich einen Etikettendrucker, der sich mittels eines USB-Anschlusses an meinen Ubuntu-Desktop einstöpseln lässt. Das Modell "LabelWriter 450 Turbo" der Firma "Dymo" kostete gebraucht etwa 40 Dollar und funktionierte auf Anhieb. Die erforderliche Treibersoftware für das Linux-eigene Druckersystem CUPS liegt als Source-Code auf [2] bereit. Nach Installation einiger Zusatzpakete wie libcups2-dev und libcupsimage2-dev mit apt-get compiliert ./configure; make das Ganze ohne Murren und sudo make install installiert die CUPS-Dateien. Erst später fand ich heraus, dass die Ubuntu-Distro sogar ein einfach zu installierendes Paket bereithält: sudo apt-get install printer-driver-dymo erledigt alles in einem Rutsch.

Abbildung 1: Schnelle Diagnose dank Ordnungssystem: Die konfigurierte IP-Addresse und die Wifi-SSID auf dem Router.

Abbildung 2: Verschwendet teures Etikettenrohmaterial: Der tragbare Brother-Etikettendrucker.

Abbildung 3: Der Etikettendrucker Dymo Labelwriter 450 Turbo druckt auch unter Linux.

Nach der Installation der CUPS-Treiber erkennt Ubuntu den neuen Etikettendrucker ohne Umschweife. Der Aufruf

    $ lpstat -p -d
    printer LabelWriter-450-Turbo is idle.
    ...

zeigt alle verfügbaren Drucker und ihren Status an. Wer sich für die vom Treiber unterstützten Etikettengrößen interessiert, kann diese mit lpoptions -p LabelWriter-450-Turbo -l abfragen. Unter "Printers" in den Systemeinstellungen kommt dann wie in Abbildung 4 gezeigt ein Dialog hoch, in dessen Untermenü "Printer Options" sich die Abmessungen der verwendeten Etiketten einstellen lassen. Ich kaufte eine Rolle mit der Bezeichnung "30330" mit 500 Stück sogenannter "Return Address Labels", die Firmen, die viel Papierpost versenden, wohl als Absenderaufkleber verwenden. Mir sollte das recht sein, ich war lediglich am handlichen Format 19mm x 51mm interessiert. Die Etiketten kommen senkrecht aus dem Thermodrucker geschossen, also sollte deren Beschriftung ebenfalls in dieser Richtung erfolgen, also um 90 Grad gedreht im Querformat.

Abbildung 4: Ubuntu erkennt den Etikettendrucker und kann die Etikettengröße einstellen.

Drucker in Aktion

Wie schickt nun der Rechner den zu druckenden Text an das Gerät? Das CUPS-System bietet dazu den Befehl lpr an, der, wie in Listing 1 gezeigt, mit der Option -P LabelWriter-450-Turbo den Etikettendrucker auswählt, falls dieser nicht sowieso schon als Default-Drucker konfiguriert wurde. Die Abmessungen der Etiketten gibt die Option PageSize vor. Diese erwartet deren Länge und Breite nicht etwa in Millimetern oder gar Inches, sondern in Points. Eine kurze Google-Suche offenbart, dass Millimeter dazu etwa mit 1.8 multipliziert werden (Abbildung 5). Aus den 19mm x 51mm großen Etiketten werden so Rechtecke im Format 54 x 144.1 Points, und der Parameter PageSize=w54h144.1 definiert genau dies. Als letztes Kommandozeilenargument erwartet der lpr-Befehl schließlich den Namen der PDF-Datei, in der der gesetzte Drucktext liegt.

Abbildung 5: Laut Umrechnungstabelle entsprechen 19mm etwa 54 Points.

Listing 1: cmd-print

    1 lpr -P LabelWriter-450-Turbo -o PageSize=w54h144.1 label.pdf

Listing 2: label-format

    01 #!/usr/local/bin/perl -w
    02 use strict;
    03 use PDF::Create;
    04 use Encode qw( _utf8_on );
    05 
    06 my( $string ) = @ARGV;
    07 _utf8_on( $string );
    08 
    09 die "usage: $0 string" if !defined $string;
    10 
    11 my $pdf = PDF::Create->new(
    12   filename => 'label.pdf' );
    13 
    14 my $width     = 144;
    15 my $height    = 54;
    16 my $font_size = 20 / length( $string ) * 11;
    17 my $adjust    = $font_size/7;
    18 
    19 my $page = $pdf->new_page(
    20  'MediaBox' => [ 0, 0, $width, $height ] );
    21 
    22 my $f1 = $pdf->font(
    23   Subtype  => 'Type1',
    24   Encoding => 'WinAnsiEncoding',
    25   BaseFont => 'Helvetica' 
    26 );
    27 
    28 $page->stringc( $f1, 
    29   $font_size, 
    30   $width/2 + 10, 
    31   ($height - $font_size)/2 + $adjust, 
    32   $string );
    33 
    34 $pdf->close;
    35 
    36 system( "acroread label.pdf" );

Formatieren als PDF

Dieses Layout generiert Listing 2 mit Hilfe des CPAN-Moduls PDF::Create. Das Skript c<label-format> nimmt auf der Kommandozeile eine Zeichenkette wie zum Beispiel

     label-format "Hip-hip, hurra!"

entgegen und pflanzt sie in die Mitte eines PDF-Dokuments im Querformat mit den Maßen 144.1 mal 54 Punkt. Zu beachten ist, dass der Aufruf umschließende Anführungszeichen verlangt, falls die Zeichenkette Leerzeichen enthält. In manchen Shell-Dialekten müssen sogar Ausrufezeichen maskiert werden, da die Shell sie sonst als Aufrufe ihrer History-Funktion interpretiert. Die Formel

    20 / length( $string ) * 11;

in Zeile 16 von Listing 2 rührt daher, dass ein String mit 11 Zeichen bei einer Fontgröße von 20 Punkt beim Experimentieren genau die Länge des Labels ausfüllte. Längere Zeichenketten erfordern eine lineare Verkleinerung des Fonts, sodass auch diese auf das Etikett passen. Die einfache Formel funktioniert erstaunlich gut weil der gewählte Helvetica-Font keine Proportionalschrift schreibt sondern jedem Buchstaben gleich viel Platz im Dokument zuweist.

Die in Zeile 28 aufgerufene Methode stringc() platziert den als viertes Argument angegebenen String in die Mitte des PDF-Dokuments. Die Fontgröße kommt als zweiter Parameter herein, gefolgt von den X- und Y-Koordinaten der Stringmitte. Der X-Wert läuft vom linken Rand des Dokuments nach rechts, der Y-Wert vom unteren Rand nach oben. Aus unerklärlichen Gründen war der Textstring immer zu weit unten im Dokument, sodass die Variable $adjust in Zeile 17 ins Leben gerufen wurde, um den String um ein Siebtel der Fontgröße nach oben zu schieben.

Mit diesen einfachen Tricks positioniert der Etikettendrucker sowohl kurze als auch etwas längere Textzeilen bis etwa 25 Zeichen optimal in der Dokumentmitte und der nachfolgende Aufruf von cmd-print wirft den Drucker an und das Etikett kommt herausgeschossen.

Besonderes Augenmerk gilt der Verarbeitung von Umlauten. Da der von der Kommandozeile hereingereichte String bereits in utf-8 kodiert ist, Perl ihn aber in der Standardeinstellung als ASCII interpretiert, kämen ohne spezielle Verarbeitung statt Umlauten kryptische Zeichen aus dem Drucker. Die Funktion _utf8_on aus dem Modul Encode teilt dem Interpreter mit, dass es sich bei dem hereingereichten String bereits um utf8 handelt, und keinerlei Umkodierung mehr erforderlich ist.

QR-Barcodes

Das verwendete CPAN-Modul zum Erzeugen von PDF-Dokumenten kann aber nicht nur Strings auf weißem Hintergrund ablegen, sondern auch Bilder positionieren. Bei einem Thermodrucker, der nur Schwarz-Weiß ohne Grautöne kann, sind die Möglichkeiten in dieser Hinsicht natürlich eingeschränkt, aber wie wäre es mit selbstklebenden Etiketten, auf denen ein Barcode prangt?

Neumodische QR-Barcodes lassen sich mit jedem Smartphone scannen. Sie ließen sich zum Beispiel dazu verwenden, Inventarnummern an Elektrogeräte zu vergeben, diese als Etikett mit QR-Barcode aufzupappen und im Bedarfsfall einzuscannen und unter der dann vorliegenden Assetnummer in einer Datenbank oder einem Merksystem wie Evernote zu stöbern, nach, sagen wir, der eingescannten Bedienungsanleitung zum Beispiel? Listing 3 generiert aus dem ihm auf der Kommandozeile übergebenen Text mittels des CPAN-Moduls Image::PNG::QRCode den in Abbildung 6 sichtbaren QR-Barcode:

    dymo-qr "Hallo, Linux-Magazin!"

Abbildung 6: Das Scanprogramm sucht den QR-Code im Foto ...

Abbildung 7: ... erkennt ihn, und gibt den einkodierten Text aus.

Abbildung 7 zeigt, wie eine der vielen freien QR-Scanner-Apps, "QR Reader" auf einem iphone den QR-Code auf dem Etikett erkennt, das noch im Drucker steckt und noch nicht einmal abgetrennt wurde.

Da das CPAN-Modul zum Generieren des QR-Codes nur Bilder im PNG-Format schreiben kann, holt Listing 3 auch noch einen Klon des CPAN-Moduls Image::Magick zum einfachen Konvertieren von Bildformaten herein. Image::Magick lässt sich nicht ohne Handarbeit installieren, weil es allerlei Entwicklungspakete diverser Libraries braucht, aber zum Glück hat sich ein Ubuntu-Engel erbarmt und mit perlmagick ein Paket erzeugt, das mit Graphics::Magick die gleichen Funktionen bereitstellt.

Die mit File::Temp verwaltete temporäre PNG-Datei wandelt das Modul in eine JPG-Datei um, die wiederum PDF::Create aufschnappt und in ein PDF-Dokument einbaut. Das erzeugte label.pdf schiebt dann Listing 1 wie gewohnt zum Etikettendrucker.

Listing 3: dymo-qr

    01 #!/usr/local/bin/perl -w
    02 use strict;
    03 use Image::PNG::QRCode 'qrpng';
    04 use Graphics::Magick;
    05 use File::Temp qw( tempfile );
    06 use PDF::Create;
    07 
    08 my( $text ) = @ARGV;
    09 die "usage: $0 text" if !defined $text;
    10 
    11 my $width     = 144;
    12 my $height    = 54;
    13 my $pdffile   = "label.pdf";
    14 
    15 my( $fh, $pngfile ) = 
    16   tempfile( UNLINK => 1,
    17             SUFFIX => ".png" );
    18 
    19 ( my $jpgfile = $pngfile ) =~ 
    20   s/\.png$/.jpg/;
    21 
    22 qrpng ( text => $text,
    23         out  => $pngfile );
    24 
    25 my $img = Graphics::Magick->new;
    26 $img->Read( $pngfile );
    27 $img->Write( $jpgfile );
    28 
    29 my $pdf = PDF::Create->new(
    30   filename => $pdffile );
    31 
    32 my $jpg = $pdf->image( $jpgfile );
    33 
    34 my $page = $pdf->new_page(
    35  'MediaBox' => [ 0, 0, $width, $height ] );
    36 
    37 $page->image( 'image' => $jpg, 
    38     'xscale' => 0.5, 'yscale' => 0.5, 
    39     'xpos'   => 50,  'ypos'   => 0 );
    40 
    41 $pdf->close;

Der einzige Nachteil des verwendeten Etikettendruckers ist, dass es dafür keine stabilen Plastiketiketten wie für den tragbaren Brother-Drucker gibt, nur schwarzer Thermodruck auf weißem Papier oder durchsichtiger Folie, beides selbstklebend. Ein weiteres Modell, der teurere "LabelWriter Duo", scheint da mehr Optionen zu bieten. Vielleicht ergibt sich bald die Gelegenheit, auf Ebay wieder ein Schnäppchen zu machen!

Infos

[1]

Listings zu diesem Artikel: ftp://www.linux-magazin.de/pub/listings/magazin/2015/12/Perl

[2]

Linux-SDK für den Etikettendrucker: http://var.dymo.com/US/resources/sdk/linux/

[3]

"CUPS: Common UNIX Printing System", Michael Sweet, Sams Publishing, Sep 7, 2001

Michael Schilli

arbeitet als Software-Engineer in der San Francisco Bay Area in Kalifornien. In seiner seit 1997 laufenden Kolumne forscht er jeden Monat nach praktischen Anwendungen der Skriptsprache Perl. Unter mschilli@perlmeister.com beantwortet er gerne Ihre Fragen.