web-dev-qa-db-de.com

Drucken auf einem POS-Drucker von PHP

Wir möchten auf einem POS-Drucker drucken, der mit Apache verbunden ist. Aufgrund des Designs der Anwendung und der Bereitstellung sollte der Druck vom Server aus erfolgen (er sollte die Bestellung erkennen und an verschiedene Drucker und verschiedene Druckformate senden ... Rechnung, Küchenbestellungen usw.). Aus diesem Grund und anderen Gründen (wie zum Beispiel dem Zugriff auf Anwendungen von einem iPad aus) verwerfen wir Optionen wie das QZ-Print-Applet und müssen direkt auf dem Server drucken.

Wir haben viel gesucht und festgestellt, dass es eine Erweiterung namens php-printer gibt, die aber veraltet zu sein scheint und nur unter Windows funktioniert.

Wir folgten diesem Code: ( http://mocopat.wordpress.com/2012/01/18/php-direct-printing-printer-dot-matrix-lx-300/ )

$tmpdir = sys_get_temp_dir();   # ambil direktori temporary untuk simpan file.
$file =  tempnam($tmpdir, 'ctk');  # nama file temporary yang akan dicetak
$handle = fopen($file, 'w');
$condensed = Chr(27) . Chr(33) . Chr(4);
$bold1 = Chr(27) . Chr(69);
$bold0 = Chr(27) . Chr(70);
$initialized = chr(27).chr(64);
$condensed1 = chr(15);
$condensed0 = chr(18);
$corte = Chr(27) . Chr(109);
$Data  = $initialized;
$Data .= $condensed1;
$Data .= "==========================\n";
$Data .= "|     ".$bold1."OFIDZ MAJEZTY".$bold0."      |\n";
$Data .= "==========================\n";
$Data .= "Ofidz Majezty is here\n";
$Data .= "We Love PHP Indonesia\n";
$Data .= "We Love PHP Indonesia\n";
$Data .= "We Love PHP Indonesia\n";
$Data .= "We Love PHP Indonesia\n";
$Data .= "We Love PHP Indonesia\n";
$Data .= "--------------------------\n";
$Data .= $corte;
fwrite($handle, $Data);
fclose($handle);
copy($file, "//localhost/KoTickets");  # Lakukan cetak
unlink($file);

Und es funktioniert, aber dies sendet einfachen Text, und wir müssen ein Bild (Logo) senden und eine niedlichere Rechnung formatieren. Wir haben versucht, ein PDF und "Senden" an den Drucker auf die gleiche Weise zu erstellen, drucken jedoch nur leer.

Ich habe eine Bibliothek gefunden, die mit Netzwerkdruckern funktioniert (escpos-php auf github), aber wir müssen auch mit USB-Druckern arbeiten, um zu vermeiden, dass unsere Kunden die Hardware wechseln.

Einige Ideen, wie dies erreicht werden kann?

Danke im Voraus.

17
Giu

Autor von escpos-php hier.

Wenn Ihre Drucker ESC/POS unterstützen (die meisten Thermobondrucker verwenden anscheinend einen Teil davon), wird der Treiber Ihrem Anwendungsfall gerecht: USB- oder Netzwerkdruck, Logo, einige Formatierungen. Einige davon sind ziemlich neu hinzugekommen.

USB-Druck

escpos-php druckt auf einen Dateizeiger. Unter Linux können Sie den USB-Drucker mithilfe des Treibers usblp als Datei anzeigen und dann einfach fopen() it ( Beispiel für USB-Empfang , Blogbeitrag über die Installation eines USB-Druckers unter Linux ).

Das Drucken von "Hello world" auf einem USB-Drucker unterscheidet sich also nur geringfügig vom Drucken auf einem Netzwerkdrucker:

<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
use Mike42\Escpos\Printer;
$connector = new FilePrintConnector("/dev/usb/lp0");
$printer = new Printer($connector);

$printer -> text("Hello World!\n");
$printer -> cut();

$printer -> close();

Oder Sie können, eher wie der Code, den Sie derzeit erfolgreich verwenden, in eine temporäre Datei schreiben und diese kopieren:

<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
use Mike42\Escpos\Printer;

/* Open file */
$tmpdir = sys_get_temp_dir();
$file =  tempnam($tmpdir, 'ctk');

/* Do some printing */
$connector = new FilePrintConnector($file);
$printer = new Printer($connector);
$printer -> text("Hello World!\n");
$printer -> cut();

$printer -> close();

/* Copy it over to the printer */
copy($file, "//localhost/KoTickets");
unlink($file);

In Ihrem Kassensystem benötigen Sie daher eine Funktion, die einen Dateizeiger zurückgibt, der auf Ihrer Kundenkonfiguration und Ihrem bevorzugten Ziel basiert. Belegdrucker reagieren recht schnell, aber wenn Sie ein paar iPads bestellen, sollten Sie die Vorgänge mit einer Dateisperre ( flock () ) auf jeden Drucker übertragen, um Probleme im Zusammenhang mit der Parallelität zu vermeiden.

Beachten Sie auch, dass die USB-Unterstützung unter Windows nicht getestet wurde.

Logo-Formatierung

Sobald Sie herausgefunden haben, wie Sie mit dem Drucker kommunizieren möchten, können Sie die gesamte Palette der Formatierungs- und Bildbefehle verwenden.

Ein Logo kann wie folgt aus einer PNG-Datei gedruckt werden:

use Mike42\Escpos\EscposImage;
$logo = EscposImage::load("foo.png");
$printer -> graphics($logo);

Und zum Formatieren sollten Sie mit README.md und dem folgenden Beispiel beginnen. Für die meisten Belege benötigen Sie nur wirklich:

  • selectPrintMode() zum Ändern der Schriftgröße.
  • setEmphasis() um fett zu schalten.
  • setJustification() um Text oder Bilder nach links auszurichten oder zu zentrieren.
  • cut() nach jedem Empfang.

Ich würde auch vorschlagen, dass Sie ein Beispiel verwenden, das Kästchen wie das folgende zeichnet:

=========
|       |
=========

Sie können die Zeichen in IBM Codepage 437 verwenden, die für Zeichenfelder vorgesehen sind, die von vielen Druckern unterstützt werden. Fügen Sie lediglich die Zeichen 0xB3 bis 0xDA in die Ausgabe ein. Sie sind nicht perfekt, aber es sieht viel weniger nach "Text" aus.

$box = "\xda".str_repeat("\xc4", 10)."\xbf\n";
$box .= "\xb3".str_repeat(" ", 10)."\xb3\n";
$box .= "\xc0".str_repeat("\xc4", 10)."\xd9\n";
$printer -> textRaw($box);

Vollständiges Beispiel

Das folgende Beispiel ist ebenfalls jetzt enthalten mit dem Treiber. Ich denke, es sieht aus wie ein ziemlich typischer Ladenbeleg, formatiert und kann leicht an Ihr Küchenszenario angepasst werden.

Gescannte Ausgabe:

Example formatted receipt including logo

PHP-Quellcode, um es zu generieren:

<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42\Escpos\Printer;
use Mike42\Escpos\EscposImage;
use Mike42\Escpos\PrintConnectors\FilePrintConnector;

/* Open the printer; this will change depending on how it is connected */
$connector = new FilePrintConnector("/dev/usb/lp0");
$printer = new Printer($connector);

/* Information for the receipt */
$items = array(
    new item("Example item #1", "4.00"),
    new item("Another thing", "3.50"),
    new item("Something else", "1.00"),
    new item("A final item", "4.45"),
);
$subtotal = new item('Subtotal', '12.95');
$tax = new item('A local tax', '1.30');
$total = new item('Total', '14.25', true);
/* Date is kept the same for testing */
// $date = date('l jS \of F Y h:i:s A');
$date = "Monday 6th of April 2015 02:56:25 PM";

/* Start the printer */
$logo = EscposImage::load("resources/escpos-php.png", false);
$printer = new Printer($connector);

/* Print top logo */
$printer -> setJustification(Printer::JUSTIFY_CENTER);
$printer -> graphics($logo);

/* Name of shop */
$printer -> selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
$printer -> text("ExampleMart Ltd.\n");
$printer -> selectPrintMode();
$printer -> text("Shop No. 42.\n");
$printer -> feed();

/* Title of receipt */
$printer -> setEmphasis(true);
$printer -> text("SALES INVOICE\n");
$printer -> setEmphasis(false);

/* Items */
$printer -> setJustification(Printer::JUSTIFY_LEFT);
$printer -> setEmphasis(true);
$printer -> text(new item('', '$'));
$printer -> setEmphasis(false);
foreach ($items as $item) {
    $printer -> text($item);
}
$printer -> setEmphasis(true);
$printer -> text($subtotal);
$printer -> setEmphasis(false);
$printer -> feed();

/* Tax and total */
$printer -> text($tax);
$printer -> selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
$printer -> text($total);
$printer -> selectPrintMode();

/* Footer */
$printer -> feed(2);
$printer -> setJustification(Printer::JUSTIFY_CENTER);
$printer -> text("Thank you for shopping at ExampleMart\n");
$printer -> text("For trading hours, please visit example.com\n");
$printer -> feed(2);
$printer -> text($date . "\n");

/* Cut the receipt and open the cash drawer */
$printer -> cut();
$printer -> Pulse();

$printer -> close();

/* A wrapper to do organise item names & prices into columns */
class item
{
    private $name;
    private $price;
    private $dollarSign;

    public function __construct($name = '', $price = '', $dollarSign = false)
    {
        $this -> name = $name;
        $this -> price = $price;
        $this -> dollarSign = $dollarSign;
    }

    public function __toString()
    {
        $rightCols = 10;
        $leftCols = 38;
        if ($this -> dollarSign) {
            $leftCols = $leftCols / 2 - $rightCols / 2;
        }
        $left = str_pad($this -> name, $leftCols) ;

        $sign = ($this -> dollarSign ? '$ ' : '');
        $right = str_pad($sign . $this -> price, $rightCols, ' ', STR_PAD_LEFT);
        return "$left$right\n";
    }
}
48
mike42