escpos-vfd
escpos-vfd — Rust-библиотека для символьных VFD-дисплеев покупателя (customer display),
которые работают через serial-порт и понимают Epson/ESC/POS-совместимые команды.
Настройки порта и дисплея разделены: можно независимо задать скорость, геометрию,
кодировку, аппаратную таблицу символов и яркость. Для проверенного 20×2 дисплея с CP866
есть готовый пресет Preset::Epson20x2Cp866.

Установка
[]
= "0.2"
Tokio API подключается отдельным feature:
[]
= { = "0.2", = ["tokio"] }
Без feature tokio async-зависимости не подключаются.
Быстрый старт
Для 20×2 дисплея с 9600 8N1, CP866 и таблицей ESC t 6 достаточно готового пресета:
use ;
Полный пример: examples/preset_sync.rs.
Что выбрать
| Задача | API |
|---|---|
| Запустить проверенный 20×2 CP866 дисплей | VfdConfig::preset(...) |
| Настроить другой дисплей | SerialSettings + DisplaySettings |
| Писать напрямую из текущего потока | Vfd |
| Отправлять команды из нескольких потоков | VfdWorker + VfdHandle |
| Писать напрямую из Tokio task | tokio::AsyncVfd |
| Отправлять команды из нескольких Tokio tasks | tokio::AsyncVfdWorker |
| Отправить нестандартную команду | write_raw(...) |
Настройка другого дисплея
Пресет не обязателен. Параметры serial-порта и дисплея можно задать вручную:
use ;
use ;
use Duration;
Полный пример: examples/manual_sync.rs.
Serial-порт
SerialSettings::new(port, baud_rate) использует обычные значения 8N1, без flow
control, с тайм-аутом 100 ms. На Unix порт по умолчанию открывается эксклюзивно.
Все эти параметры можно изменить через поля SerialSettings.
Дисплей
DisplaySettings::new(columns, rows, encoding) задаёт геометрию и текстовую кодировку.
Размеры должны быть в диапазоне 1..=255.
Дополнительно можно настроить:
code_table— аппаратную таблицу символов черезESC t n;reset_on_open— отправкуESC @при открытии;brightness— допустимый диапазон яркости;brightness_settle— паузу после изменения яркости.
VfdConfig также содержит queue_capacity для worker API. По умолчанию очередь вмещает
32 команды; значение 0 запрещено.
Кодировка и таблица символов
Кодировка текста и таблица символов самого дисплея — разные настройки.
TextEncoding определяет, как Rust-строка превращается в байты:
| Значение | Назначение |
|---|---|
Cp866 |
CP866 / IBM866 |
Windows1251 |
Windows-1251 / CP1251 |
Ascii |
только ASCII, остальные символы заменяются на ? |
Utf8 |
UTF-8 без перекодирования |
code_table отвечает за команду ESC t n. Например, конкретному CP866-дисплею могут
одновременно понадобиться:
let mut display = new;
display.code_table = Some;
Если таблица уже выбрана DIP-переключателями или устройство использует другой механизм,
оставьте code_table = None.
Перед обычным выводом библиотека заменяет некоторые типографские символы на более
безопасные для символьного VFD варианты: например, длинное тире на -, № на #, а
табуляцию на пробел.
Вывод текста
Все публичные координаты начинаются с 1:
vfd.print_line?;
vfd.print_at?;
print_line() обрезает слишком длинный текст и дополняет короткий пробелами до ширины
дисплея. Это позволяет полностью перезаписать строку без остатка предыдущего текста.
print_at() пишет с указанной позиции и обрезает текст по правому краю. Автоматического
переноса на следующую строку нет.
Неверные координаты возвращают VfdError::InvalidLine или
VfdError::InvalidCoordinate.
Worker и частичные обновления
VfdWorker владеет дисплеем в отдельном потоке, а VfdHandle можно клонировать и
передавать между потоками.
Очередь ограничена по размеру: если она заполнена, отправитель ждёт свободное место вместо неограниченного накопления команд. Вызов метода handle завершается после фактического выполнения команды или ошибки I/O.
use ;
print_line_diff() хранит кэш последнего содержимого строк. Если текст не изменился,
запись не выполняется; если изменился только фрагмент, worker отправляет только изменённые
смежные диапазоны. Это удобно для часов, статусов и других часто обновляемых значений.
Для нормального завершения используйте VfdWorker::shutdown().
Бегущая строка
Worker также умеет обновлять marquee по таймеру:
use Duration;
display.set_marquee_text?;
display.start_marquee?;
// ...
display.stop_marquee?;
cps задаёт скорость в символах в секунду, end_pause — паузу после полного прохода.
stop_marquee() останавливает анимацию, но не очищает уже отображённый текст.
Tokio
Feature tokio добавляет два варианта API:
AsyncVfd— прямой драйвер поверхAsyncWrite;AsyncVfdWorker— одна задача-писатель, bounded queue и клонируемыйAsyncVfdHandle.
use AsyncVfdWorker;
use ;
async
После попадания команды в очередь отмена ожидающего future не отменяет уже поставленную
запись в устройство. Для корректного завершения используйте
AsyncVfdWorker::shutdown().await.
Низкоуровневая запись
Если нужной команды нет в типизированном API, байты можно отправить напрямую:
vfd.write_raw?;
write_raw() не кодирует и не интерпретирует данные. В worker API такая запись также не
обновляет строковый кэш, поэтому после raw-команд, меняющих текст на экране, лучше
выполнить clear() или print_line().
Для нестандартных транспортов и диагностики доступен публичный
escpos_vfd::codec::EpsonCodec, который формирует байты команд без открытия serial-порта.
Ошибки
Библиотека использует escpos_vfd::Result<T> = Result<T, VfdError> и разделяет ошибки по
смыслу:
| Ошибка | Когда возникает |
|---|---|
VfdError::Config(...) |
неверная конфигурация |
VfdError::Serial(...) |
ошибка открытия или настройки serial-порта |
VfdError::Io(...) |
ошибка записи или flush |
VfdError::InvalidCoordinate |
координата вне дисплея |
VfdError::InvalidLine |
строка вне 1..=rows |
VfdError::UnsupportedBrightness |
неподдерживаемый уровень яркости |
VfdError::QueueClosed |
очередь worker-а закрыта |
VfdError::WorkerStopped |
worker остановился до подтверждения команды |
VfdError::WorkerPanicked |
sync worker завершился с panic |
VfdError::WorkerCancelled |
Tokio worker был отменён |
Примеры
В репозитории есть небольшие аппаратные примеры для основных сценариев:
| Пример | Что показывает |
|---|---|
preset_sync |
запуск с готовым пресетом |
manual_sync |
ручную конфигурацию |
tokio_worker |
Tokio worker |
clock |
частые diff-обновления |
marquee |
бегущую строку |
brightness |
яркость |
position |
позиционирование |
update_at |
частичные обновления |
blink |
повторную запись в позицию |
Например:
Проверка на реальном дисплее
Автоматические тесты проверяют формирование команд, кодировки, координаты, кэш строк, worker queue, marquee и async-поведение на тестовых транспортах. Конкретное устройство всё равно стоит проверить отдельно:
- Выставьте правильный serial/DIP-режим.
- Запустите
cargo run --example preset_sync -- <port>. - Проверьте очистку, строки, кириллицу и яркость.
- Проверьте
update_atиmarquee. - При использовании Tokio запустите пример
tokio_worker.
Разработка
RUSTDOCFLAGS='-D warnings -D missing_docs -D rustdoc::broken_intra_doc_links' \
Подробная документация публичного API: docs.rs/escpos-vfd.
Лицензия
escpos-vfd распространяется под двойной лицензией MIT OR Apache-2.0.