File: clear_input_buffer.rs

package info (click to toggle)
rust-serialport 4.8.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 844 kB
  • sloc: makefile: 2
file content (135 lines) | stat: -rw-r--r-- 3,945 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//
// Provides a way to test clearing and querying the size of the serial input buffer.
//
// USAGE:
//
// 1. Connect a serial device to your host computer. E.g. an Arduino loaded with the example sketch
//    given below
// 2. Run this example
// 3. Observe the output - it reports how many bytes have been received from the device and are
//    waiting to be read
// 4. Press the Return key to make the example clear the input buffer. You should see the number of
//    bytes queued to read momentarily drop to 0
// 5. Press Ctrl+D (Unix) or Ctrl+Z (Win) to quit
//
// The following Arduino firmware could be used to generate input:
//
// ```
// #include <Arduino.h>
//
// void setup() {
//     Serial.begin(9600);
//     while (!Serial); // wait for serial port to connect. Needed for native USB
// }
//
// int iter = 0;
//
// void loop() {
//     Serial.print(iter);
//     if (++iter == 10) {
//         Serial.println();
//         iter = 0;
//     }
//     delay(1000 / 20);
// }
// ```

use std::error::Error;
use std::io::{self, Read};
use std::panic::panic_any;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

use clap::{Arg, Command};

use serialport::ClearBuffer;

fn main() {
    let matches = Command::new("Serialport Example - Clear Input Buffer")
        .about("Reports how many bytes are waiting to be read and allows the user to clear the input buffer")
        .disable_version_flag(true)
        .arg(Arg::new("port")
             .help("The device path to a serial port")
             .use_value_delimiter(false)
             .required(true))
        .arg(Arg::new("baud")
             .help("The baud rate to connect at")
             .use_value_delimiter(false)
             .required(true))
        .get_matches();

    let port_name = matches.value_of("port").unwrap();
    let baud_rate = matches.value_of("baud").unwrap();

    let exit_code = match run(port_name, baud_rate) {
        Ok(_) => 0,
        Err(e) => {
            println!("Error: {}", e);
            1
        }
    };

    std::process::exit(exit_code);
}

fn run(port_name: &str, baud_rate: &str) -> Result<(), Box<dyn Error>> {
    let rate = baud_rate
        .parse::<u32>()
        .map_err(|_| format!("Invalid baud rate '{}' specified", baud_rate))?;

    let port = serialport::new(port_name, rate)
        .timeout(Duration::from_millis(10))
        .open()
        .map_err(|ref e| format!("Port '{}' not available: {}", &port_name, e))?;

    let chan_clear_buf = input_service();

    println!("Connected to {} at {} baud", &port_name, &baud_rate);
    println!("Ctrl+D (Unix) or Ctrl+Z (Win) to stop. Press Return to clear the buffer.");

    loop {
        println!(
            "Bytes available to read: {}",
            port.bytes_to_read().expect("Error calling bytes_to_read")
        );

        match chan_clear_buf.try_recv() {
            Ok(_) => {
                println!("------------------------- Discarding buffer ------------------------- ");
                port.clear(ClearBuffer::Input)
                    .expect("Failed to discard input buffer")
            }
            Err(mpsc::TryRecvError::Empty) => (),
            Err(mpsc::TryRecvError::Disconnected) => {
                println!("Stopping.");
                break;
            }
        }

        thread::sleep(Duration::from_millis(100));
    }

    Ok(())
}

fn input_service() -> mpsc::Receiver<()> {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let mut buffer = [0; 32];
        loop {
            // Block awaiting any user input
            match io::stdin().read(&mut buffer) {
                Ok(0) => {
                    drop(tx); // EOF, drop the channel and stop the thread
                    break;
                }
                Ok(_bytes_read) => tx.send(()).unwrap(), // Signal main to clear the buffer
                Err(e) => panic_any(e),
            }
        }
    });

    rx
}