11 KiB
title | description | date | draft | tags | categories | featured_image | lastmod | telegram_entry_id | type | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Изучаем протокол принтеров Niimbot | Изучаем протокол принтеров Niimbot и печатаем этикетки, отправляя пакеты | 2024-06-29T21:10:28+03:00 | false |
|
|
miniature.jpg | 2024-07-28T14:07:39+03:00 | default |
После того, как поигрались с niimprint, захотелось чего-то большего. У меня появилась идея написать полноценный веб-интерфейс для печати, в котором можно будет и рисовать этикетки, и печатать. Для этого я решил изучить протокол принтеров.
Структура пакета
Сейчас в моём владении два принтера D110 и B1.
Вооружившись Wireshark и Android телефоном, снял дампы обмена данными с принтером по bluetooth. Для этого нужно было включить опцию "Bluetooth HCI Snoop Log" в настройках разработчика, а потом на компьютере после печати запустить adb bugreport <filename>
.
Изучив пакеты и сверившись с другими открытыми источниками, получилась такая структура пакета:
- Prefix – префикс
0x03
, присутствующий только при одной команде - Connect. - Head – всегда 2 байта
0x55
0x55
. - Command – ID команды (пакета).
- Data length – количество байтов данных, идущих далее.
- Data – непосредственно данные в количестве Data length.
- Checksum – вычисляется с помощью XOR всех байтов от Command до последнего байта Data.
- Tail – всегда 2 байта
0xAA
0xAA
.
Типы пакетов
На данный момент мне удалось идентифицировать следующие типы пакетов:
ID команды | Наименование | Описание | ID ответа |
---|---|---|---|
0x01 | PrintStart | 0x02 | |
0x03 | PageStart | 0x04 | |
0x05 | PrinterLog | 0x06 | |
0x0b | AntiFake | 0x0c | |
0x13 | SetPageSize | 0x14 | |
0x15 | PrintQuantity | 0x16 | |
0x1a | RfidInfo | 0x1b | |
0x1c | RfidInfo2 | 0x1d | |
0x20 | PrintClear | 0x30 | |
0x21 | SetDensity | 0x31 | |
0x23 | SetLabelType | 0x33 | |
0x27 | SetAutoShutdownTime | 0x37 | |
0x28 | PrinterReset | 0x38 | |
0x40 | PrinterInfo | 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e | |
0x54 | RfidSuccessTimes | 0x64 | |
0x58 | SoundSettings | 0x68 | |
0x70 | GetVolumeLevel / WriteRFID | 0x71 | |
0x83 | PrintBitmapRowIndexed | ⚠ Без ответа | |
0x84 | PrintEmptyRow | ⚠ Без ответа | |
0x85 | PrintBitmapRow | ⚠ Без ответа | |
0x8e | LabelPositioningCalibration | 0x8f | |
0xa3 | PrintStatus | 0xb3 | |
0xa5 | PrinterStatusData | 0xb5 | |
0xaf | PrinterConfig | 0xbf | |
0xc1 | Connect | 0xc2 | |
0xda | CancelPrint | 0xd0 | |
0xdc | Heartbeat (GetPrinterInfo) | 0xde | |
0xe3 | PageEnd | 0xe4 | |
0xf3 | PrintEnd | 0xf4 |
Важно знать
Протокол обмена данным варьируется между разными моделями
В основном это касается набора пакетов при непосредственно печати. Изучив код приложения, можно сделать вывод, что есть пять вариаций протокола + вариации для самих моделей.
Вероятно, протокол обмена данными может варьироваться даже в пределах ревизий одной модели
Это можно увидеть в декомпилированном коде приложения:
Принтер искусственно занижает плотность печати при использовании неправильной или отсутствующей RFID метке
Вот тут довольно интересно. Принтеры и приложения ведут себя по разному.
Метки нет вообще:
- Niimbot Android
- Этикетку создать невозможно в принципе.
- Niimbot Windows
- D110 - не поддерживается, хоть и может печатать по usb.
- B1 - печатать можно, игнорируя предупреждения, плотность очень низкая.
- Сторонние проекты
- D110 - печатает без проблем с нужной плотностью.
- B1 - печатает с низкой плотностью.
Метка есть, но от бумаги размером, который не поддерживается принтером:
- Niimbot Android
- D110 - печатать можно, игнорируя предупреждения, плотность очень низкая (подлость самого приложения).
- B1 - аналогично с D110.
- Niimbot Windows
- D110 - печатать можно, игнорируя предупреждения, плотность очень низкая.
- B1 - печатать можно, игнорируя предупреждения, плотность очень низкая.
- Сторонние проекты
- D110 - печатает без проблем с нужной плотностью.
- B1 - аналогично с D110.
Что касаемо самой метки - считывание происходит при закрытии крышки. Принтер видит метку даже если она снаружи корпуса. Так что можно просто приложить метку снаружи, закрыть корпус и печатать на чём попало.
Источники
-
Тут и тут нашлась библиотека jcprintersdk для Java. Библиотека обфусцирована.
-
kjy00302/niimprint - утилита на Python для печати изображений на принтерах niimbot.
-
AndBondStyle/niimprint - доработанный форк niimprint. Также благодаря автору и человеку с неизвестным мне ником удалось получить актуальную версию jcprintersdk с низкой обфускацией путём декомпиляции Android приложения.
-
ayufan/niimprint-web - малофункциональный, но полезный проект печати через браузер.