Skip to main content

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}