tag_test_example/tag-test-example.rs
1//! `tag-test-example`: set the RTC and report the clock error.
2//!
3//! Port of `host/commandline/test-example.cc`. Syncs the tag clock, waits
4//! two seconds, reads the tag's time and prints its offset from the host
5//! clock in seconds.
6//!
7//! Usage: `tag-test-example [-d] [-b BUS:DEVICE]`. A positive error means
8//! the tag clock is ahead of the host. The figure includes the latency of
9//! the status request.
10//!
11//! # Exit status
12//!
13//! 0 when the error was printed; 1 if no base matches, or the attach,
14//! `SetRtc` or `GetStatus` fails. Option errors exit 2 (clap).
15//!
16//! # Hardware side effects
17//!
18//! The attach resets the tag, and `SetRtc` overwrites its clock with the
19//! host's.
20
21use std::process::ExitCode;
22use std::thread::sleep;
23use std::time::{Duration, SystemTime, UNIX_EPOCH};
24
25use clap::Parser;
26use tag_tools::{BaseArgs, init_logging, select_base};
27use tagcore::Tag;
28use tagcore::textformat::format_g;
29
30/// sets the RTC
31#[derive(Parser)]
32#[command(name = "tag-test-example")]
33struct Cli {
34 /// The shared `--debug` and `--base` options.
35 #[command(flatten)]
36 base: BaseArgs,
37}
38
39/// Attaches, sets the clock, waits 2 s and prints the clock error in
40/// seconds.
41fn main() -> ExitCode {
42 let cli = Cli::parse();
43 init_logging(&cli.base);
44
45 let tag = Tag::new();
46 let dev = select_base::<Cli>(&tag, &cli.base);
47 if tag.attach(&dev) {
48 if tag.set_rtc().is_err() {
49 eprintln!("SetRtc failed: {}", tag.debug_message());
50 return ExitCode::FAILURE;
51 }
52 sleep(Duration::from_millis(2000));
53 // millis defaults to 0, which would report a clock error of about
54 // -1.8e9 seconds as though it were a measurement.
55 let status = match tag.status() {
56 Ok(status) => status,
57 Err(_) => {
58 eprintln!("GetStatus failed: {}", tag.debug_message());
59 return ExitCode::FAILURE;
60 }
61 };
62 let now_ms = SystemTime::now()
63 .duration_since(UNIX_EPOCH)
64 .unwrap_or_default()
65 .as_millis() as i64;
66 // std::ostream's default double format: %g, six significant digits.
67 let error = (status.millis - now_ms) as f64 / 1000.0;
68 println!("Clock Error: {}", format_g(error, 6, 6, |_| true));
69 } else {
70 eprintln!("Attach failed");
71 return ExitCode::FAILURE;
72 }
73 ExitCode::SUCCESS
74}