Как ноутбук увидел принтер там, где был ридер

09.09.2026 · 5 мин

Читаю статью и ловлю себя на мысли: вот человек купил электронную книжку с e-ink дисплеем, а потом решил сделать из неё принтер. Не принтер для книги — а принтер как устройство. Который принимает задания на печать от MacBook через стандартный диалог Print.

Идея: если выглядит как бумага — пусть и работает как бумага

Автор — Nishant Joshi — купил Xteink X3, электронную книгу с программируемым дисплеем. Поставил свою прошивку CrossPoint и добавил несколько фишек: анимацию при загрузке, виртуальные кости и QR-код для LinkedIn.

Но загружать контент было неудобно: нужно было подключаться к хотспоту ридера и открывать веб-интерфейс. Тогда автор подумал: раз дисплей выглядит как бумага, почему бы не сделать так, чтобы на него можно было печатать?

Как заставить ноутбук увидеть «принтер»

Чтобы Mac увидел устройство как принтер, автор ушёл в Internet Printing Protocol, или IPP. Это стандарт, который позволяет компьютеру:

IPP работает поверх HTTP — того же протокола, что браузеры используют для сайтов. Это удобно: не нужно изобретать велосипед.

Автор объявил, что его «принтер» поддерживает монохромную печать с разрешением 300 dpi, понимает форматы Apple raster и PWG raster, знает размеры A5 и Letter и называется penguin.

Оставалось сделать так, чтобы ноутбук вообще нашёл это устройство в сети.

Служба обнаружения: bonjour и mdns

Чтобы Mac увидел принтер без драйверов, нужно было объявить о нём через Bonjour — систему автоматического обнаружения сервисов в локальной сети от Apple. Внутри она использует mDNS: устройство рассылает сигнал «я тут!», и компьютеры его слышат.

Нужно было зарегистрировать сервис _ipp._tcp с подтипом _universal. Автор пишет, что стандартная Arduino-обёртка для mDNS не давала доступа к этой функции, поэтому пришлось вызывать API ESP-IDF напрямую.

После этого в диалоге печати на MacBook появился penguin. Оставалась одна маленькая проблема: 400 килобайт оперативной памяти.

Проблема: как распечатать страницу, не имея памяти для страницы

Вот в чём загвоздка. Страница формата Letter при разрешении 300 dpi — это 2550 на 3300 пикселей. Если хранить каждый пиксель как один байт, получается около 8,4 мегабайта. Устройство в сумме имеет 400 КБ, часть из которых занята кэшем и Wi-Fi. После инициализации сетевого стека и буфера изображения остаётся всего 6,8 КБ.

Классический подход — принять всю страницу в память, потом её отобразить — здесь невозможен.

Решение оказалось элегантным: использовать оперативную память дисплея как хранилище для страницы. Дисплей уже содержит в памяти изображение, которое показывает. Значит, страницу можно строить прямо там, по мере поступления пикселей.

ПОТОК ДАННЫХ ПРИ ПЕЧАТИ
────────────────────────
MacBook ──HTTP/IPP──▶ ESP32-C3
                          │
                          ▼
              ┌───────────────────────┐
              │ Декодер (построчно)   │
              │  • Расшифровка потока │
              │  • Масштабирование    │
              │  • Dithering (ч/б)    │
              └───────────┬───────────┘
                          │ готовая строка
                          ▼
              ┌───────────────────────┐
              │ RAM дисплея E-ink     │
              │ (вместо буфера в RAM) │
              │ ─────────────────────│
              │ ▓▓▓░░▓▓░░▓▓▓░░▓▓░░▓▓▓ │
              │ ░▓▓░░▓▓▓░░▓▓░░▓▓▓░░▓▓ │
              │ ... весь экран ...    │
              └───────────────────────┘
                          │
                          ▼
                    E-ink display
Страница собирается прямо в буфере дисплея, строка за строкой. Экономия: 113 КБ → 62 КБ

Декодер уже умел работать построчно. Автор добавил возможность сразу отправлять готовые строки в буфер экрана, минуя промежуточное хранилище. Параллельно шло масштабирование — картинка с ноутбука больше, чем экран ридера, — и дизеринг, то есть преобразование градаций серого в чёрно-белые точки по алгоритму Флойда-Стейнберга.

Изначально автор показывал страницу полосами, как настоящий принтер выдаёт бумагу. Но каждая промежуточная отрисовка занимала полсекунды, и результат раздражал. В итоге он переключился на мгновенный показ готовой страницы.

Результат

Первая тестовая печать — страница манги. Открыл Preview на MacBook, выбрал penguin в списке принтеров, нажал Print. Через секунду картинка появилась на экране ридера.

РАСПРЕДЕЛЕНИЕ ПАМЯТИ ESP32-C3
─────────────────────────────
До оптимизации:
┌──────────┬───────────────────┬──────────┐
│  Wi-Fi   │    Изображение    │  Сеть    │
│  стек    │    (8.4 MB →      │  буферы  │
│  ~200 KB │    не влезает)    │  ~80 KB  │
└──────────┴───────────────────┴──────────┘
              ❌ Недостаточно RAM

После (потоковая обработка):
┌──────────┬──────────┬────────────────────┐
│  Wi-Fi   │  Сеть    │   E-ink буфер      │
│  стек    │  буферы  │   (встроен в       │
│  ~200 KB │  ~62 KB  │    дисплей)        │
└──────────┴──────────┴────────────────────┘
              ✅ 6.8 KB на работу
Ключевая идея: использовать RAM дисплея вместо RAM процессора

Распечатки сохраняются на SD-карту как BMP-файлы — автор шутит, что у его принтера всё-таки есть выходной лоток. Это папка.

Принтер может подключиться к существующей Wi-Fi сети или создать свою точку доступа — literate-penguin. Исходный код доступен в форке CrossPoint на GitHub.

Моя оценка

Это не инженерный подвиг в классическом смысле. Здесь нет сложной механики, навороченных деталей или космического бюджета. Есть переосмысление: дисплей выглядит как бумага — значит, должен вести себя как бумага. Остальное — следствие этого решения.

Меня зацепило другое. Автор не стал покупать 3D-принтер или делать что-то «правильное». Он взял существующее устройство и заставил его решать задачу, для которой оно формально не предназначено. IPP, Bonjour, потоковая обработка — всё это существующие решения, просто никто не складывал их так.

Практический вывод простой: если ты застрял на «правильном» способе сделать что-то, попробуй спросить себя: а что если это уже и есть принтер?

Ссылки

Дмитрий Полухин — продуктовый дизайнер. Пишу про разработку, AI и дизайн интерфейсов. Обо мне, контакты и профили.