Rust serialport お試し①

はじめに

Rust でシリアル通信したくなったので、serialport クレートを使ってみます。

docs.rs

serialport クレート

serialport クレートはクロスプラットフォームで使えるシリアルポートライブラリです。 各プラットフォーム固有の API も提供しています。

using blocking I/O with serial ports

とあるので、async には対応していなさそうです。

環境

open

シリアルポートの open はビルダーで行います。デバイスパスとボーレートを指定して SerialPortBuilder オブジェクトを取得し、シリアルポートの設定を行います。

    let mut port = serialport::new("/dev/ttyUSB0", 115200)
        .stop_bits(serialport::StopBits::One)
        .data_bits(serialport::DataBits::Eight)
        .timeout(Duration::from_millis(10))
        .open()
        .unwrap_or_else(|e| {
            eprintln!("Failed to open \"{}\". Error: {}", "/dev/ttyUSB", e);
            ::std::process::exit(1);
    });

new() は下の通りなので、ストップビットとデータビットはデフォルト値で良いのですが、お試しのために設定しています。

serialport/src/lib.rs
pub fn new<'a>(path: impl Into<std::borrow::Cow<'a, str>>, baud_rate: u32) -> SerialPortBuilder {
    SerialPortBuilder {
        path: path.into().into_owned(),
        baud_rate,
        data_bits: DataBits::Eight,
        flow_control: FlowControl::None,
        parity: Parity::None,
        stop_bits: StopBits::One,
        timeout: Duration::from_millis(0),
    }
}

大体普通のシリアルポート設定が SerialPortBuilder でできます。受信時のタイムアウトtimeout() で設定できます。

serialport/src/lib.rs
    /// Set the amount of time to wait to receive data before timing out
    pub fn timeout(mut self, timeout: Duration) -> Self {
        self.timeout = timeout;
        self
    }

open() の代わりに open_native() すると、プラットフォーム固有のシリアルポートオブジェクトが取得できます。

serialport/src/lib.rs
    /// Open a platform-specific interface to the port with the specified settings
    #[cfg(unix)]
    pub fn open_native(self) -> Result<TTYPort> {
        posix::TTYPort::open(&self)
    }

    /// Open a platform-specific interface to the port with the specified settings
    #[cfg(windows)]
    pub fn open_native(self) -> Result<COMPort> {
        windows::COMPort::open(&self)
    }

read

手元のマイコンボードから送信された Hello World を受信してみます (とりあえずエラーは無視しています) 。

    let mut serial_buf: Vec<u8> = vec![0; 1000];
    loop {
        match port.read(serial_buf.as_mut_slice()) {
            Ok(t) => io::stdout().write_all(&serial_buf[..t]).unwrap(),
            Err(_e) => {},
        }
    }
$ cargo run
# マイコンボードをリセットします
hello world

お、ええやん。