Files
lx-d02/README.md
T
Alex CubeandClaude Opus 5.5 9e06f3ebd0 LX-D02 BLE thermal printer: PC, Windows printer, Home Assistant
- printer.py: protocol with flow control (pause / resend / done)
- lxd02.py: print text or pictures from the command line
- windows/: POS-58 driver + local ESC/POS server = a regular Windows printer,
  Explorer menu for pictures
- custom_components/lxd02: Home Assistant integration with a persistent queue

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 16:56:45 +03:00

9.7 KiB
Raw Blame History

lx-d02

Печать на Bluetooth-термопринтере LX-D02 (он же Funny Print, Xiqi, DOLEWA и другие бренды) без приложения на смартфоне:

  • как на обычном принтере Windows: из Блокнота, браузера, Word, из меню «Печать»;
  • картинки правым кликом в проводнике, растянутые на всю ширину ленты;
  • из командной строки: python lxd02.py "Привет";
  • из Home Assistant: действие lxd02.print_text с очередью, которая переживает выключенный принтер и перезапуск HA.

Принтер работает только по BLE (Bluetooth Low Energy): USB-порт у него лишь для зарядки, и Windows без этого проекта его как принтер не видит.

Протокол разобран в ValdikSS/printer-driver-funnyprint, управление потоком сделано по образцу klimromanyuk/funnyprint. Подробный рассказ, как это сделано: блог «Доктор Лексиум».

Что нужно

  • Python 3.9+ и Bluetooth на компьютере.
  • pip install -r requirements.txt
  • Принтер включён и не подключён к телефону: LX-D02 держит только одно соединение, и пока открыто Funny Print, компьютер его не найдёт.

Проверка: python lxd02.py "Привет" должен напечатать строку.

На Python 3.9 bleak 1.x падает при импорте, поэтому в requirements.txt стоит bleak<1.0. На более новом Python ограничение можно снять.

Печать из командной строки

python lxd02.py "Первая строка" "Вторая строка"
python lxd02.py фото.jpg скриншот.png

Текст печатается шрифтом DejaVu Sans (кириллица есть). Картинки растягиваются на ширину ленты (48 мм, 384 точки), альбомные поворачиваются вдоль ленты, чтобы выйти крупнее, полутона передаются растром.

Принтер ищется по имени LX-D02. Чтобы не тратить на поиск несколько секунд, задайте MAC: set LXD02_MAC=AA:BB:CC:DD:EE:FF (MAC покажет любой BLE-сканер, например nRF Connect на телефоне).

Принтер в Windows

Как это устроено: Windows печатает на принтер с драйвером POS-58 (стандартный драйвер 58-мм чековых принтеров), драйвер раскладывает страницу на ленту 58 мм и отдаёт её командами ESC/POS в порт 127.0.0.1:9100. Там их принимает windows/print_server.py и печатает по Bluetooth.

Почему не встроенные драйверы Windows: «Microsoft Print to PDF» знает только офисные форматы, и лист A4, ужатый до 48 мм, нечитаем. IPP Class Driver принимает только стандартные названия бумаги, самое узкое из которых A6.

Драйвер

Драйвер POS-58 обычно идёт с любым дешёвым 58-мм чековым принтером, ищите «POS-58 driver» на сайте Xprinter или продавца. Проверено с POS-58 11.2.0.0 (Zjiang, pos58.inf). Сам принтер POS-58 не нужен, нужен только драйвер.

Установка

В PowerShell от имени администратора:

Set-ExecutionPolicy -Scope Process Bypass
.\windows\install.ps1

Скрипт:

  • добавляет принтер LX-D02 на драйвере POS-58 и порту 127.0.0.1:9100;
  • ставит в Планировщик задание «LX-D02 print server» (сервер стартует при входе в систему);
  • добавляет в меню картинок пункт «Print on LX-D02» и ярлык в «Отправить».

Удаление: .\windows\install.ps1 -Uninstall. Журнал: windows\print_server.log.

Советы

  • Бумага. У драйвера по умолчанию лента 3276 мм. Пусть вас не пугает превью: сервер срезает белое сверху и снизу и сжимает пустые промежутки до 6 мм. Для удобного превью выберите в настройках печати размер 58×210.
  • Поля. Ставьте поля «Минимальные» (в браузере) или 0 (в редакторах). Левое поле сервер убирает сам, но правое срежет драйвер: печатная полоса 48 мм начинается от левого края листа, а браузер с обычными полями сдвигает текст вправо.
  • Картинки лучше печатать правым кликом, а не из браузера или «Фотографий»: те раскладывают картинку по листу, и она выходит мелкой или обрезанной.
  • Странный результат? Последнее задание сохраняется в windows\last_job.bin, python windows\print_server.py --test windows\last_job.bin покажет его картинкой.

Home Assistant

Нужен Bluetooth на хосте HA (встроенный адаптер или прокси ESPHome).

Скопируйте custom_components/lxd02 в /config/custom_components/, добавьте в configuration.yaml и перезапустите HA:

lxd02:
  mac: AA:BB:CC:DD:EE:FF

Действие:

action: lxd02.print_text
data:
  text: "Привет из Home Assistant"
  size: 28         # размер шрифта, 10..120
  density: 3       # плотность, 0..7
  feed: 40         # прогон ленты после текста
  separator: true  # линия под текстом

Задания попадают в очередь на диске (/config/.storage/lxd02). Если принтер выключен, вне зоны или занят телефоном, задание ждёт, и очередь печатается, как только HA снова увидит принтер. Пока очередь не пуста, HA пробует раз в минуту. Действие не падает, если принтера нет: ищите LX-D02 в журнале HA.

Пример: чат MeshCore на ленте

Печатает входящие сообщения канала my_channel из интеграции MeshCore: отправитель и время, ниже текст, под ним черта. Свои исходящие пропускаются: интеграция присылает их заново на каждое обновление статуса доставки.

triggers:
- trigger: event
  event_type: meshcore_message
  event_data:
    message_type: channel
conditions:
- condition: template
  value_template: "{{ trigger.event.data.channel | lower == 'my_channel' and not trigger.event.data.outgoing | default(false) }}"
actions:
- action: lxd02.print_text
  continue_on_error: true
  data:
    size: 24
    separator: true
    text: "{{ trigger.event.data.sender_name }} · {{ now().strftime('%d.%m %H:%M') }}\n{{ trigger.event.data.message }}"
mode: queued
max: 20

Если Bluetooth на хосте зависает

На ТВ-приставках встроенный чип раз в несколько недель может зависнуть (hci0: Opcode 0x0c03 failed: -110 в dmesg, HA пишет NotReady). Помогает перепривязать чип к драйверу. Пример сторожа на systemd для чипа на UART (hci_uart_bcm):

#!/bin/sh
# /usr/local/sbin/bt-watchdog.sh: run every minute by bt-watchdog.timer
D=/sys/bus/serial/drivers/hci_uart_bcm
up() { hciconfig hci0 2>/dev/null | grep -q "UP RUNNING"; }
up && exit 0
sleep 20  # HA/BlueZ may be resetting the adapter itself
up && exit 0
logger -t bt-watchdog "hci0 down, rebinding serial0-0"
echo serial0-0 > $D/unbind 2>/dev/null
sleep 2
echo serial0-0 > $D/bind
sleep 8
timeout 5 bluetoothctl power on >/dev/null 2>&1

Имена драйвера и устройства у вас могут отличаться: смотрите /sys/bus/serial/drivers/.

Протокол коротко

Имя в BLE-рекламе LX-D02
Сервис / запись / уведомления FFE6 / FFE1 / FFE2
Ширина печати 384 точки, 48 байт на строку, по две строки в пакете из 96 байт
Рукопожатие принтер шлёт вызов 5a0a, ответ 5a0b + байт CRC16 от MAC × 10
Управление потоком 5a08 пауза (буфер полон), 5a05 + номер строки (дослать с неё), 5a06 готово

Весь протокол: custom_components/lxd02/printer.py, самопроверка python printer.py.

Лицензия

MIT, см. LICENSE.