//! Демонстрирует мигание произвольного текста в выбранной позиции через `print_at`. mod common; use std::error::Error; use escpos_vfd::VfdWorker; fn main() -> Result<(), Box> { // Аргументы: // 1) port - serial-порт дисплея; // 2) width - ширина строки, нужна для проверки координат; // 3) delay_ms - пауза между состояниями "видно/пусто"; // 4) x - колонка от единицы; // 5) y - строка от единицы; // 6) text - текст, который мигает. let mut args = common::ExampleArgs::from_env()?; let delay_ms: u64 = args.parse_or(400); let x: u8 = args.parse_or(1); let y: u8 = args.parse_or(1); let text = args.string_or("BLINK"); let text_len = text.chars().count(); // Worker нужен, чтобы все команды шли в serial-порт последовательно. Даже в одном // потоке пример получает те же semantics, что и приложение с несколькими producer-ами. let worker = VfdWorker::start(args.config)?; let vfd = worker.handle(); vfd.clear()?; // Первая строка остаётся статичной, мигает только выбранная область. vfd.print_line_diff(1, "blink demo (print_at)")?; if y != 1 { // Пустая запись в начало строки полезна на некоторых дисплеях, которые лениво // переключают видимую строку только после позиционирования курсора. vfd.print_at(1, y, "")?; } // Стираем ровно столько символов, сколько было выведено. Так справа не остаются // хвосты при следующем включении текста. let blank = " ".repeat(text_len); let mut on = false; loop { // Все ошибки (`InvalidCoordinate`, I/O, закрытый worker) сразу выходят из main // через оператор `?`, что удобно для аппаратного smoke-test. if on { vfd.print_at(x, y, &blank)?; } else { vfd.print_at(x, y, &text)?; } on = !on; common::sleep_ms(delay_ms); } }