У нас, айтишников, часто возникает задача напечатать что-то простое и одноразовое – например, логин и пароль новому сотруднику, тикет для монтажника или что-то в этом роде. Тратить бумагу и картридж на подобное очень дорого. При этом есть принтеры с ультрадешёвой скоростной печатью, про которые редко кто вспоминает, хотя видим мы их все каждый день по много раз. Речь про чековые термопринтеры.

Начну, пожалуй, с демки, чтобы вы могли оценить скорость печати – 20 см. в секунду:
(На видео принтер замедляется пару раз в секунду из-за того, что мой скрипт не успевает достаточно быстро засылать команды. Спасибо Тому Скотту за вдохновение 🙂 )
Этот принтер я добыл на Авито за полторы тысячи рублей. Модель Citizen CT-S2000, умеет печатать на лентах разной стандартной ширины – от 58 мм до 80 мм. Принтер имел на корпусе следы долгой работы на, кажется, ресторанной кухне, которые удалось оттереть мылом и спиртом. Впрочем, этот принтер фиг убьешь: если термоголовка и отрезной нож исправны, он вам ещё послужит, ломаться там больше особо нечему (а он еще и водостойкий!).
Рулон ленты шириной 80 мм и длиной до ста метров обойдётся вам меньше чем в сто рублей. Ленты 58 мм стоят ещё меньше. Также, т.к. этот принтер печатает нагревая бумагу в определенных местах, ему не нужны картриджи.

Термопринтеры обычно работают по COM-интерфейсу (нативному или эмуляцией через USB), дорогие варианты имеют на борту Ethernet, WiFi или даже Bluetooth, но они слишком дорогие.
На сайте Citizen был богатый набор вариантов подключения – от нативного драйвера под Windows, PPD для CUPS, и до библиотек для Java. Нам с вами это всё не понадобится, потому что для максимальной простоты и скорости мы не будем рендерить задания на печать на сервере, а лишь будем слать команды принтеру на стандартном языке команд «ESC/POS».
Но сначала нам нужно один раз провести настройку принтера. Citizen предлагает настроить принтер через меню, которое он вам печатает (!) – экрана-то у него нет, или воспользоваться утилитой под Windows.
У моего принтера имеются интерфейсы USB и COM на 25 pin, под который не удалось быстро найти переходник с 9 pin – поэтому пользуемся USB. Драйвер под Windows установил виртуальный COM-порт, который мы выбираем в утилите настройки.
Внимательно просмотрите все параметры – нужно проверить тип бумаги (наклейки или обычная) и указать ширину заправленной в принтер ленты. Остальные настройки, типа яркости печати, тона встроенной пищалки и прочего – на ваш вкус.

Чтобы не забивать себе голову синтаксисом языка ESC/POS, воспользуемся Python-библиотекой python-escpos . В моём случае принтером управляет одноплатный компьютер Orange PI PC с Debian, но настройки в любой ОС будут идентичны.
Командой lsusb узнаём ID принтера, в моём случае это был 2730:0fff:
# lsusb Bus 006 Device 002: ID 2730:0fff Citizen
Также нам нужно выяснить USB endpoints, для этого подставляем ID в команду:
# lsusb -v -d 2730:0fff | grep bEndpointAddress bEndpointAddress 0x81 EP 1 IN bEndpointAddress 0x02 EP 2 OUT
Запоминаем полученные значения и создаём тестовый скрипт на Python:
from escpos import Usb p = printer.Usb(0x2730, 0x0fff, 0, 0x81, 0x02)
Если ваш принтер есть в списке явно поддерживаемых библиотекой, например, Epson TM-T88III, то можно применить его профиль, где авторы явно прописали, что из возможностей поддерживается, а что — нет. Почитать документацию по подключению принтеров можно тут.
Пользование библиотекой – тривиально, она полностью избавляет вас от изучения ESC/POS:
""" Выбор встроенного шрифта, выравнивания, размера """ p.set(font='a', align=u'left', height=3) """ Печать картинки (помните про ширину ленты и DPI!) """ p.image('/home/test/example.png') """ Вывод текста (кириллицей-только если поддерживает принтер, иначе лучше напечатать текст на картинке и печатать ее) """ p.text("Hello, world!\n") """ Генерация QR-кода """ p.qr("https://gbougakov.dev", size=5, center=True) """ Генерация бар-кода (читайте Википедию, чтобы правильно вычислить checksum) """ p.barcode('1324354657687','EAN13') p.barcode('123456', 'CODE39') """ Программная генерация бар-кода – если ваш принтер не умеет генерировать нужный тип аппаратно """ p.soft_barcode('code39', '123456') """ Надрезать ленту: """ p.cut(mode='PART') """ или отрубить напечатанный кусок целиком: """ p.cut() """ послать напряжение на разъём для денежного ящика кассы (обычно под них выведено два контакта в разъёме RJ-25): """ p.cashdraw(2) p.cashdraw(5)
Про последнюю команду – чуть поподробнее. На всех чековых принтерах выведен разъём, который отвечает за то, что сразу после выбивания чека у кассира сам открывается ящик, куда он складывает полученные от вас деньги. Стандартное напряжение – 24 вольта, ток – до одного ампера.

Не пытайтесь от него запитать Raspberry Pi или что-то подобное – в момент печати принтер обесточивает разъём. Так что для того, чтобы запитать, например, стрелку из светодиодов «возьми чек тут!» — сойдёт, но не более.
Напоследок – пример применения. В прошедшие выходные моя школа праздновала свой очередной день рождения (аж 143-й), и по традиции старшеклассники устраивали разные конкурсы и развлечения для младших классов и выпускников. Я отвечал за «Бинго» — мой принтер по нажатию кнопки печатал билеты для игроков, а на доску выводились цифры. QR-код на билете позволял проверить, правильно ли игрок вычеркнул цифры в процессе игры:

Для вандалоустойчивости Orange Pi был упрятан в фанерный подиум, накрепко прикрученный к принтеру, а команда на печать билетов была выведена на кнопки, подключённые к GPIO. Для подстраховки был добавлен I2C-экран, на который выводился IP-адрес Orange Pi, чтобы в случае чего знать, как зайти на него по SSH.
ссылка на оригинал статьи https://habr.com/ru/post/486998/
Добавить комментарий