// examples/clock_ru.rs use anyhow::Result; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use m::vfd::VfdConfig; use m::worker::VfdWorker; fn run_date(args: &[&str]) -> Option { let out = std::process::Command::new("date") .args(args) .output() .ok()?; if !out.status.success() { return None; } Some(String::from_utf8_lossy(&out.stdout).trim().to_string()) } fn local_datetime_ddmmyyyy_hhmmss() -> String { // 28.01.2006 12:03:34 run_date(&["+%d.%m.%Y %H:%M:%S"]).unwrap_or_else(|| "??.??.???? ??:??:??".to_string()) } fn local_weekday_num_1_7() -> u8 { // 1..7 (Mon..Sun) run_date(&["+%u"]) .and_then(|s| s.parse::().ok()) .unwrap_or(1) } fn weekday_ru_full(n: u8) -> &'static str { match n { 1 => "Понедельник", 2 => "Вторник", 3 => "Среда", 4 => "Четверг", 5 => "Пятница", 6 => "Суббота", 7 => "Воскресенье", _ => "Понедельник", } } fn weekday_ru_short(n: u8) -> &'static str { match n { 1 => "Пн", 2 => "Вт", 3 => "Ср", 4 => "Чт", 5 => "Пт", 6 => "Сб", 7 => "Вс", _ => "Пн", } } fn time_of_day_ru(hour: u8) -> &'static str { match hour { 5..=10 => "утро", 11..=16 => "день", 17..=22 => "вечер", _ => "ночь", } } fn extract_hour(datetime: &str) -> u8 { // ожидаем "DD.MM.YYYY HH:MM:SS" // берём HH как 2 символа после пробела datetime .split_whitespace() .nth(1) .and_then(|t| t.get(0..2)) .and_then(|hh| hh.parse::().ok()) .unwrap_or(12) } fn fit_to_width(s: &str, width: usize) -> String { // простое “обрезать по символам”, чтобы кириллицу не порвать let mut out = String::new(); for (i, ch) in s.chars().enumerate() { if i >= width { break; } out.push(ch); } out } fn main() -> Result<()> { // args: // 1) port (default: /dev/cu.usbmodem101) // 2) width (default: 20) // 3) brightness 1..4 (default: 2) let port_name = std::env::args() .nth(1) .unwrap_or("/dev/cu.usbmodem101".into()); let width: usize = std::env::args() .nth(2) .as_deref() .unwrap_or("20") .parse() .unwrap_or(20); let brightness: u8 = std::env::args() .nth(3) .as_deref() .unwrap_or("2") .parse() .unwrap_or(2); let cfg = VfdConfig::new(port_name).with_width(width); let worker = VfdWorker::start(cfg)?; let vfd = worker.handle(); vfd.clear(); vfd.set_brightness(brightness); loop { let dt = local_datetime_ddmmyyyy_hhmmss(); let wd = local_weekday_num_1_7(); let hour = extract_hour(&dt); let tod = time_of_day_ru(hour); // 1 строка: "28.01.2006 12:03:34" let line1 = fit_to_width(&dt, width); // 2 строка: "Понедельник сейчас день" // но если не влазит — "Пн сейчас день" let full = format!("{} сейчас {}", weekday_ru_full(wd), tod); let mut line2 = full; if line2.chars().count() > width { line2 = format!("{} сейчас {}", weekday_ru_short(wd), tod); } line2 = fit_to_width(&line2, width); vfd.print_line_diff(1, line1)?; vfd.print_line_diff(2, line2)?; // чтобы обновлялось ровно раз в секунду (плюс/минус), можно “привязать” к UNIX time let now = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default() .as_millis(); let ms_to_next = 1000 - (now % 1000) as u64; std::thread::sleep(Duration::from_millis(ms_to_next)); } }