gpio-cdevクレートがバージョンアップしてtokio 1.x系で扱えるようになった。

本記事で以前の記事のコードを書き直す。 環境と準備は同様なので割愛する。

コード

Cargo.toml

[dependencies]
futures = "0.3.25"
tokio = {version = "1", features = ["time", "sync", "rt", "macros"]}
gpio-cdev = {version = "0.5", features=["async-tokio"]}

tokioクレートとgpio-cdevクレートのバージョン修正のみ。

main.rs

use futures::stream::StreamExt;
use gpio_cdev::{AsyncLineEventHandle, Chip, EventRequestFlags, LineRequestFlags};
use std::error::Error;

async fn async_main() -> Result<(), Box<dyn Error>> {
    //使用するGPIOキャラクターデバイスを指定する
    let mut chip = Chip::new("/dev/gpiochip0")?;

    //使用するピン番号のハンドルを取得する
    let lines = [chip.get_line(0)?, chip.get_line(2)?, chip.get_line(3)?];

    //対応するピン番号のイベントハンドルを取得する
    //どの状態変化を検出するかを引数で指定する
    let events = lines
        .iter()
        .map(|line| {
            line.events(
                LineRequestFlags::INPUT,       //入力として使用する
                EventRequestFlags::BOTH_EDGES, //ボタンが押されたときと、ボタンから手を離したときを検知する
                "gpioevents",
            )
        })
        .collect::<Result<Vec<_>, _>>()?;

    //イベントを非同期で受け取れるようにする
    let handles = events
        .into_iter()
        .map(AsyncLineEventHandle::new)
        .collect::<Result<Vec<_>, _>>()?;

    let (mut handle1, mut handle2, mut handle3) = {
        let mut iter = handles.into_iter();
        (
            iter.next().unwrap(),
            iter.next().unwrap(),
            iter.next().unwrap(),
        )
    };

    loop {
        //どれか1つのボタンが押されたときに標準出力へ出力する
        let (name, event) = tokio::select! {
            Some(Ok(e)) = handle1.next() => {
                ("F1", e.event_type())
            },
            Some(Ok(e))  = handle2.next() => {
                ("F2", e.event_type())
            },
            Some(Ok(e))  = handle3.next() => {
                ("F3", e.event_type())
            },
            else => break,
        };
        println!("{}: {:?}", name, event);
    }
    Ok(())
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    async_main().await
}

特記事項

  • 基本は以前の記事と同じ
  • tokio::mainアトリビュートはflavorの指定が必要