This commit is contained in:
Кобелев Андрей Андреевич
2026-01-28 01:36:35 +05:00
commit 446a710e01
11 changed files with 1191 additions and 0 deletions

150
examples/clock.rs Normal file
View File

@@ -0,0 +1,150 @@
// 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<String> {
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::<u8>().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::<u8>().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));
}
}