Печать на принтере POS из переполнения стека

Мы ищем возможность печати на POS-принтере, подключенном там, где работает Apache. В связи с дизайном приложения и развертыванием печать должна производиться с сервера (он должен определять заказ и отправлять на разные принтеры и разные форматы печати … счета, заказы на кухню и т. Д.). По этой и другим причинам (например, например, приложение доступа с iPad) мы отказываемся от таких опций, как апплет QZ-Print, и должны печатать непосредственно на стороне сервера.

Мы много искали и обнаружили, что есть расширение, называемое php-printer, но оно устарело и работает только под Windows.

Мы следовали этому коду 🙁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);

И это работает, но это отправляет простой текст, и нам нужно отправить изображение (логотип) и отформатировать более симпатичный счет. Мы попытались создать PDF и «отправить» на принтер таким же образом, но просто печатали без изменений.

Я нашел библиотеку для работы с сетевыми принтерами (escpos-php на github), но нам нужно работать и с USB-принтерами, чтобы наши клиенты не могли менять оборудование.

Некоторые идеи, как этого добиться?

Заранее спасибо.

16

Решение

Автор escpos-PHP Вот.

Если ваши принтеры поддерживают ESC / POS (большинство тепловых чековых принтеров, похоже, используют некоторые их подмножества), то я думаю, что драйвер подойдет для вашего варианта использования: USB или сетевая печать, логотип, некоторое форматирование. Некоторые из них являются довольно недавними дополнениями.

USB печать

escpos-php печатает на указатель файла. В Linux вы можете сделать USB-принтер видимым в виде файла, используя usblp водитель, а потом просто fopen() Это (Пример получения с USB, сообщение в блоге об установке USB-принтера в Linux).

Таким образом, печать «Hello world» на USB-принтере незначительно отличается от печати на сетевом принтере:

<?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();

Или, более похоже на код, который вы в настоящее время успешно используете, вы можете записать во временный файл и скопировать его:

<?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);

Таким образом, в вашей системе POS вам потребуется функция, которая возвращает указатель на файл в зависимости от конфигурации вашего клиента и предпочтительного места назначения. Принтеры чеков отвечают довольно быстро, но если у вас есть несколько iPad-ов, делающих заказы, вы должны перенести операции на каждый принтер с блокировкой файлов (стадо()) чтобы избежать проблем, связанных с параллелизмом.

Также обратите внимание, что поддержка USB в Windows не проверена.

логотип & форматирование

После того, как вы выяснили, как вы планируете общаться с принтером, вы можете использовать полный набор команд форматирования и изображения.

Логотип можно распечатать из файла PNG следующим образом:

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

А для форматирования README.md и приведенный ниже пример поможет вам начать. Для большинства поступлений вам действительно нужно только:

  • selectPrintMode() изменить размеры шрифта.
  • setEmphasis() переключать жирным шрифтом.
  • setJustification() выравнивание по левому краю или центрирование текста или изображений.
  • cut() после каждой квитанции

Я также хотел бы предложить, где вы в настоящее время используете пример, который рисует коробки, как это:

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

Вы могли бы использовать символы в IBM Кодовая страница 437 которые предназначены для рисования коробок, которые поддерживаются многими принтерами — просто включите символы от 0xB3 до 0xDA в вывод. Они не идеальны, но выглядят гораздо менее «текстовыми».

$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);

Полный пример

Пример ниже также теперь включен с водителем. Я думаю, что это выглядит как довольно типичная квитанция магазина, с точки зрения форматирования, и может быть легко адаптирована к вашему кухонному сценарию.

Сканированный вывод:

Пример отформатированной квитанции с логотипом

Исходный код PHP для его генерации:

<?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";
}
}
46

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]